internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: sopel-irc/sopel

Issue:
reminder: allow a user to reset its reminders
For some reason I set a bad reminder. I'd like a way to reset these reminders for myself. I don't have a clear interface in mind right now (`.reminder <action> <arg>` for example?), but I think this feature is worth the time.


Discussion:

Resolving patch:
diff --git a/sopel/modules/remind.py b/sopel/modules/remind.py
--- a/sopel/modules/remind.py
+++ b/sopel/modules/remind.py
@@ -503,3 +503,73 @@ def remind_at(bot, trigger):
         bot.reply('Okay, will remind at %s' % human_time)
     else:
         bot.reply('Okay, will remind in %s secs' % duration)
+
+
+@plugin.command('reminders')
+@plugin.example('.reminders forget *', user_help=True)
+@plugin.example('.reminders count #channel', user_help=True)
+@plugin.example('.reminders count', user_help=True)
+def manage_reminders(bot, trigger):
+    """Count or forget your reminders in the current channel.
+
+    Use a subcommand "count" (default) or "forget". The second argument is
+    optional and can be either a channel name, your nick, or * (for all).
+    """
+    owner = trigger.nick
+    action = trigger.group(3) or trigger.sender
+    target = trigger.group(4)
+
+    if action not in ['count', 'forget'] and not target:
+        # assume `.reminders` or `.reminders #channel`
+        # in that case, invalid action will just count 0 reminder
+        action, target = 'count', action
+
+    if action == 'count':
+        tpl = 'You have {count} reminders for all channels.'
+        nick_reminders = (
+            (timestamp, channel, nick, message)
+            for timestamp, reminders in bot.rdb.items()
+            for channel, nick, message in reminders
+            if nick == owner
+        )
+        if target and target != '*':
+            tpl = 'You have {count} reminders in {target}.'
+            nick_reminders = (
+                (timestamp, channel, nick, message)
+                for timestamp, channel, nick, message in nick_reminders
+                if channel == target
+            )
+
+        count = sum(1 for __ in nick_reminders)
+
+        if target == owner:
+            target = 'private'
+
+        bot.reply(tpl.format(count=count, target=target))
+
+    elif action == 'forget':
+        bot.rdb = {
+            timestamp: [
+                (channel, nick, message)
+                for channel, nick, message in reminders
+                if not (
+                    nick == owner
+                    and (target == '*' or target == channel)
+                )
+            ]
+            for timestamp, reminders in bot.rdb.items()
+        }
+        dump_database(bot.rfn, bot.rdb)
+
+        if not target or target == '*':
+            bot.reply('I forgot all your reminders.')
+        elif target == owner:
+            bot.reply('I forgot your private reminders.')
+        else:
+            bot.reply('I forgot your reminders in %s' % target)
+
+    else:
+        bot.reply(
+            'Unrecognized action. '
+            'Usage: {}reminders [count|forget [nickname|channel|*]]'
+            .format(bot.config.core.help_prefix))


Test patch:
Repository: sopel-irc/sopel

Issue:
Error messages were removed from `.title` command
In #1510, the error feedback Sopel used to output if it couldn't find a title for one or more URL given to the `.title` command got removed. This is kind of regression-y, and was shipped already in 7.0.x before someone mentioned it. Here's how it looked: https://github.com/sopel-irc/sopel/blob/806f296fdb74f197397bcdd6eb5464cd07a638cc/sopel/modules/url.py#L132-L137 Might not be practical to do exactly the same thing now due to use of generators, but something similar would be enough.


Discussion:

Resolving patch:
diff --git a/sopel/modules/url.py b/sopel/modules/url.py
--- a/sopel/modules/url.py
+++ b/sopel/modules/url.py
@@ -174,16 +174,30 @@ def title_command(bot, trigger):
         else:
             urls = [bot.memory['last_seen_url'][trigger.sender]]
     else:
-        urls = web.search_urls(
-            trigger,
-            exclusion_char=bot.config.url.exclusion_char)
-
+        urls = list(  # needs to be a list so len() can be checked later
+            web.search_urls(
+                trigger,
+                exclusion_char=bot.config.url.exclusion_char
+            )
+        )
+
+    result_count = 0
     for url, title, domain, tinyurl in process_urls(bot, trigger, urls):
         message = '%s | %s' % (title, domain)
         if tinyurl:
             message += ' ( %s )' % tinyurl
         bot.reply(message)
         bot.memory['last_seen_url'][trigger.sender] = url
+        result_count += 1
+
+    expected_count = len(urls)
+    if result_count < expected_count:
+        if expected_count == 1:
+            bot.reply("Sorry, fetching that title failed. Make sure the site is working.")
+        elif result_count == 0:
+            bot.reply("Sorry, I couldn't fetch titles for any of those.")
+        else:
+            bot.reply("I couldn't get all of the titles, but I fetched what I could!")
 
 
 @plugin.rule(r'(?u).*(https?://\S+).*')


Test patch:
Repository: sopel-irc/sopel

Issue:
find_updates: Unexpected error (local variable 'info' referenced before assignment)
### Description
An error is logged, errors shouldn't happen.

### Reproduction steps
Seen in log channel, unknown, run the bot for long enough???

### Expected behavior
No error

### Logs
```
[2021-03-31 22:00:24,531] sopel.tools.jobs     ERROR    - Error while processing job: local variable 'info' referenced before assignment
[2021-03-31 22:00:24,538] sopel.bot            ERROR    - Unexpected error (local variable 'info' referenced before assignment)
Traceback (most recent call last):
  File "/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/tools/jobs.py", line 191, in _call
    job.execute(self.manager)
  File "/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/tools/jobs.py", line 463, in execute
    return self._handler(manager)
  File "/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/modules/find_updates.py", line 86, in check_version
    latest = info['version']
UnboundLocalError: local variable 'info' referenced before assignment

```

### Environment
- Sopel `.version`: https://github.com/sopel-irc/sopel/commit/96c55aff852bf40bca56de49b2bc30378bf1c819
- Sopel installed via: pip/wheel
- Python version: 3.7.3
- Operating system: Debian 10.9
- IRCd `/version`: freenode
- Relevant plugins: find_updates



Discussion:

Resolving patch:
diff --git a/sopel/modules/find_updates.py b/sopel/modules/find_updates.py
--- a/sopel/modules/find_updates.py
+++ b/sopel/modules/find_updates.py
@@ -67,8 +67,14 @@ def check_version(bot):
     except ValueError:
         # TODO: use JSONDecodeError when dropping Pythons < 3.5
         _check_failed(bot)
+        success = False
 
-    if not success and bot.memory.get('update_failures', 0) > 4:
+    if not success:
+        if bot.memory.get('update_failures', 0) <= 4:
+            # not enough failures to worry; silently ignore this one
+            return
+
+        # too many failures to ignore; notify owner
         bot.say(
             "[update] I haven't been able to check for updates in a while. "
             "Please verify that {} is working and I can reach it."


Test patch:
Repository: sopel-irc/sopel

Issue:
Support 2-pronoun sets in the pronoun module 
### The problem

Setting pronouns in the pronouns module can be unintuitive because the bot accepts either a 1-pronoun "object" command (`.setpronouns she`) or a long 5-pronouns "subject/object/possessive-determiner/possessive-pronoun/reflexive" commnad (`.setpronouns she/her/her/hers/herself`). However, in my experience most people are used to the 2-pronoun convention of "subject/object" `.setpronouns she/her`). 

### The solution

Supporting 2-word version of pronouns. 

### Alternatives

An alternative would be to improve the message for unrecognised pronoun sets by adding explicit instructions to use either 1- or 5-pronoun sets. 





Discussion:
(I think this might be a relatively easy fix: just add the two-word combos to the list on [these lines](https://github.com/sopel-irc/sopel/blob/master/sopel/modules/pronouns.py#L17-L30). 

If this is a desirable feature, I can send a PR in that fashion. 
> If this is a desirable feature, I can send a PR in that fashion.

Yes it is, and I think your idea is a good one: adding all the variations (`he/him`, `she/her`, etc.) in the mapping should do it, I think.

Resolving patch:
diff --git a/sopel/modules/pronouns.py b/sopel/modules/pronouns.py
--- a/sopel/modules/pronouns.py
+++ b/sopel/modules/pronouns.py
@@ -19,14 +19,21 @@
     'ze/hir': 'ze/hir/hir/hirs/hirself',
     'ze/zir': 'ze/zir/zir/zirs/zirself',
     'they': 'they/them/their/theirs/themselves',
+    'they/them': 'they/them/their/theirs/themselves',
     'they/.../themselves': 'they/them/their/theirs/themselves',
     'they/.../themself': 'they/them/their/theirs/themself',
     'she': 'she/her/her/hers/herself',
+    'she/her': 'she/her/her/hers/herself',
     'he': 'he/him/his/his/himself',
+    'he/him': 'he/him/his/his/himself',
     'xey': 'xey/xem/xyr/xyrs/xemself',
+    'xey/xem': 'xey/xem/xyr/xyrs/xemself',
     'sie': 'sie/hir/hir/hirs/hirself',
+    'sie/hir': 'sie/hir/hir/hirs/hirself',
     'it': 'it/it/its/its/itself',
-    'ey': 'ey/em/eir/eirs/eirslef',
+    'it/it': 'it/it/its/its/itself',
+    'ey': 'ey/em/eir/eirs/eirself',
+    'ey/em': 'ey/em/eir/eirs/eirself',
 }
 
 
@@ -71,8 +78,8 @@ def say_pronouns(bot, nick, pronouns):
 @plugin.command('setpronouns')
 @plugin.example('.setpronouns they/them/their/theirs/themselves')
 def set_pronouns(bot, trigger):
-    pronouns = trigger.group(2)
     """Set your pronouns."""
+    pronouns = trigger.group(2)
     if not pronouns:
         bot.reply('What pronouns do you use?')
         return


Test patch:
Repository: sopel-irc/sopel

Issue:
`sopel-plugins` CLI doesn't show broken plugin source
One of the main utilities our `sopel-plugins` CLI tool provides is showing what plugins are available, and where they come from (a file, a folder, a package). It works great for plugins that can load as valid Python modules, but shows only "unknown" for the source location if loading generates an error of any kind—meaning there is a mistake in the plugin code:

```
$ sopel-plugins list
...
broken/unknown Error: name 'bot' is not defined (unknown) [error]
...
$ sopel-plugins show broken
Plugin: broken
Status: error
Type: unknown
Source: unknown
Label: Error: name 'bot' is not defined
Loading failed
```

Ideally, even if loading fails, `sopel-plugins` would be able to at least show the type and source of a broken plugin so the user can easily go fix the problem and/or report it to the author.

This isn't just my random idea; it came from a long troubleshooting session on IRC yesterday, followed by @Exirel's later reflection that `sopel-plugins list` helped confirm that there _existed_ a problem, but not _where_.

Note: My `broken.py` plugin file was literally one line, very easy to test.
`bot.say("This can't ever work.")`


Discussion:

Resolving patch:
diff --git a/sopel/cli/plugins.py b/sopel/cli/plugins.py
--- a/sopel/cli/plugins.py
+++ b/sopel/cli/plugins.py
@@ -211,12 +211,15 @@ def handle_list(options):
                 else:
                     description['name'] = utils.red(name)
         except Exception as error:
-            label = ('%s' % error) or 'unknown loading exception'
+            description.update(plugin.get_meta_description())
+
+            meta_label = description.get('label') or '(error)'
+            error_label = ('%s' % error) or 'unknown loading exception'
+            label = '%s (error: %s)' % (meta_label, error_label)
             error_status = 'error'
+
             description.update({
-                'label': 'Error: %s' % label,
-                'type': 'unknown',
-                'source': 'unknown',
+                'label': label,
                 'status': error_status,
             })
             if not no_color:
@@ -267,12 +270,15 @@ def handle_show(options):
         description.update(plugin.get_meta_description())
         loaded = True
     except Exception as error:
-        label = ('%s' % error) or 'unknown loading exception'
+        description.update(plugin.get_meta_description())
+
+        meta_label = description.get('label') or '(error)'
+        error_label = ('%s' % error) or 'unknown loading exception'
+        label = '%s (error: %s)' % (meta_label, error_label)
         error_status = 'error'
+
         description.update({
-            'label': 'Error: %s' % label,
-            'type': 'unknown',
-            'source': 'unknown',
+            'label': label,
             'status': error_status,
         })
 


Test patch:
Repository: sopel-irc/sopel

Issue:
Add `.clearpronouns` command
### The problem
Users might set their pronouns by mistake or just to test the functionality and then they are stuck.

### The solution

Add an "unsetpronouns" that deletes pronoun information for the nick. 
Something like this might work. 

```python
@plugin.command('unsetpronouns')
def unset_pronouns(bot, trigger):
        bot.db.delete_nick_value(trigger.nick, 'pronouns')
```



Discussion:

Resolving patch:
diff --git a/sopel/modules/pronouns.py b/sopel/modules/pronouns.py
--- a/sopel/modules/pronouns.py
+++ b/sopel/modules/pronouns.py
@@ -120,3 +120,10 @@ def set_pronouns(bot, trigger):
     bot.reply(
         "Thanks for telling me! I'll remember you use {}.{}".format(pronouns, disambig)
     )
+
+
+@plugin.command('clearpronouns')
+def unset_pronouns(bot, trigger):
+    """Clear pronouns for the given user."""
+    bot.db.delete_nick_value(trigger.nick, 'pronouns')
+    bot.reply("Okay, I'll forget your pronouns.")


Test patch:
Repository: sopel-irc/sopel

Issue:
translate: mangle is a bit useless due to rate limit
<!-- Before reporting a bug, please search both open *and closed* issues to
see if it has already been reported. If you can, try to reproduce the problem
on an unmodified copy of the `master` branch first, as sometimes bugs are found
and fixed without a report. If the problem is unreported and persists in
`master`, please help us fix it quickly by filling out as much of this
information as you can. Thanks! -->

### Description
Mangle ends up just saying 'None' a lot after using it more than once or twice within a minute or so due to what seems to be a rate limit

### Reproduction steps
1. Start a basic, stock sopel up
2. Use mangle a few times within a minute or so
3. It returns None

### Expected behavior
It either back off and respond when it is successful or error nicely. @rate (I think) might be useful here

### Logs
```
If applicable, add logs to help us figure out what's happening. Raw logs are
super helpful! Logs are usually found in ~/.sopel/logs, depending on your
configuration.
```

### Environment
- Sopel `.version`: lastest on PyPi
- Sopel installed via: pip 
- Python version: 3.7
- Operating system: Debian Buster
- IRCd `/version`: freenode's
- Relevant plugins: mangle

### Notes
https://cloud.google.com/translate/quotas



Discussion:
I had to spam a `.mangle` command over 20 times in a minute for it to stop responding.

Low priority issue, patches welcome, yadda-yadda.

Resolving patch:
diff --git a/sopel/modules/translate.py b/sopel/modules/translate.py
--- a/sopel/modules/translate.py
+++ b/sopel/modules/translate.py
@@ -230,9 +230,11 @@ def mangle(bot, trigger):
     """Repeatedly translate the input until it makes absolutely no sense."""
     long_lang_list = ['fr', 'de', 'es', 'it', 'no', 'he', 'la', 'ja', 'cy', 'ar', 'yi', 'zh', 'nl', 'ru', 'fi', 'hi', 'af', 'jw', 'mr', 'ceb', 'cs', 'ga', 'sv', 'eo', 'el', 'ms', 'lv']
     lang_list = []
+
     for __ in range(0, 8):
         lang_list = get_random_lang(long_lang_list, lang_list)
     random.shuffle(lang_list)
+
     if trigger.group(2) is None:
         try:
             phrase = (bot.memory['mangle_lines'][trigger.sender], '')
@@ -241,9 +243,11 @@ def mangle(bot, trigger):
             return
     else:
         phrase = (trigger.group(2).strip(), '')
+
     if phrase[0] == '':
         bot.reply("What do you want me to mangle?")
         return
+
     for lang in lang_list:
         backup = phrase
         try:
@@ -264,6 +268,12 @@ def mangle(bot, trigger):
             phrase = backup
             break
 
+    if phrase[0] is None:
+        # translate() returns (None, None) if an error happens,
+        # usually because the bot has exceeded a rate limit
+        bot.reply("Translation rate limit reached. Try again later.")
+        return
+
     bot.say(phrase[0])
 
 


Test patch:
Repository: sopel-irc/sopel

Issue:
wikipedia: parse error for template link with fragment
### Description
If someone links a template URL with a section fragment, Sopel outputs an unexpected error.

### Logs
```
[2021-07-24 17:12:47,036] sopel.bot            ERROR    - Unexpected error ('parse') from dgw at 2021-07-24
22:12:47.036637. Message was: https://en.wikipedia.org/wiki/Template:Infobox_company#TemplateData
Traceback (most recent call last):
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/bot.py", line 757, in call_rule
    rule.execute(sopel, trigger)
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/plugins/rules.py", line 1057,
  in execute
    exit_code = self._handler(bot, trigger)
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/plugins/rules.py", line 1608,
  in execute_handler
    return handler(bot, trigger, match=trigger)
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/modules/wikipedia.py", line 256,
  in mw_info
    say_section(bot, trigger, match.group(1), unquote(match.group(2)), unquote(match.group(3)))
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/modules/wikipedia.py", line 204,
  in say_section
    snippet = mw_section(server, query, section)
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/sopel/modules/wikipedia.py", line 240,
  in mw_section
    parser.feed(data['parse']['text']['*'])
KeyError: 'parse'
```

### Environment
- Sopel `.version`: 7.1.2
- Sopel installed via: pip
- Python version: 3.9.6
- Operating system: Termux (but was first reported by @RhinosF1 on a different platform)
- IRCd `/version`: plexus-4(hybrid-8.1.20)(20200510_0-610). irc.rizon.ca TS6ow
- Relevant plugins: wikipedia

### Notes
The same template URL with no fragment yields a perfectly functional, but useless, empty snippet.

```irc
<SopelTest> [wikipedia] Template:Infobox company | ""
```


Discussion:

Resolving patch:
diff --git a/sopel/modules/wikipedia.py b/sopel/modules/wikipedia.py
--- a/sopel/modules/wikipedia.py
+++ b/sopel/modules/wikipedia.py
@@ -214,6 +214,11 @@ def mw_section(server, query, section):
     for entry in sections['parse']['sections']:
         if entry['anchor'] == section:
             section_number = entry['index']
+            # Needed to handle sections from transcluded pages properly
+            # e.g. template documentation (usually pulled in from /doc subpage).
+            # One might expect this prop to be nullable because in most cases it
+            # will simply repeat the requested page title, but it's always set.
+            fetch_title = quote(entry['fromtitle'])
             break
 
     if not section_number:
@@ -221,7 +226,7 @@ def mw_section(server, query, section):
 
     snippet_url = ('https://{0}/w/api.php?format=json&redirects'
                    '&action=parse&page={1}&prop=text'
-                   '&section={2}').format(server, query, section_number)
+                   '&section={2}').format(server, fetch_title, section_number)
 
     data = get(snippet_url).json()
 


Test patch:
Repository: sopel-irc/sopel

Issue:
reddit: comment links also output submission info
One of the bug fixes in 7.1.3 removed an anchor (`&`) from the end of post URLs. While it's now possible for Sopel to pick up reddit post links with e.g. `?sort=confidence` tacked on (the intended result), that also means Sopel will happily output the post info along with comments (unintended side effect).

The link matching for posts needs to exclude anything that looks like a comment ID, but still match on anything else.


Discussion:

Resolving patch:
diff --git a/sopel/modules/reddit.py b/sopel/modules/reddit.py
--- a/sopel/modules/reddit.py
+++ b/sopel/modules/reddit.py
@@ -27,10 +27,13 @@
 
 domain = r'https?://(?:www\.|old\.|pay\.|ssl\.|[a-z]{2}\.)?reddit\.com'
 subreddit_url = r'%s/r/([\w-]+)/?$' % domain
-post_url = r'%s/r/\S+?/comments/([\w-]+)(?:/[\w%%]+)?/?' % domain
+post_or_comment_url = (
+    domain +
+    r'/r/\S+?/comments/(?P<submission>[\w-]+)'
+    r'(?:/?(?:[\w%]+/(?P<comment>[\w-]+))?)'
+)
 short_post_url = r'https?://redd\.it/([\w-]+)'
 user_url = r'%s/u(?:ser)?/([\w-]+)' % domain
-comment_url = r'%s/r/\S+?/comments/\S+?/\S+?/([\w-]+)' % domain
 image_url = r'https?://i\.redd\.it/\S+'
 video_url = r'https?://v\.redd\.it/([\w-]+)'
 gallery_url = r'https?://(?:www\.)?reddit\.com/gallery/([\w-]+)'
@@ -107,18 +110,25 @@ def video_info(bot, trigger, match):
         timeout=(10.0, 4.0)).headers['Location']
     try:
         return say_post_info(
-            bot, trigger, re.match(post_url, url).group(1), False, True)
+            bot, trigger, re.match(post_or_comment_url, url).group('submission'), False, True
+        )
     except AttributeError:
         # Fail silently if we can't map the video link to a submission
         return plugin.NOLIMIT
 
 
-@plugin.url(post_url)
+@plugin.url(post_or_comment_url)
 @plugin.url(short_post_url)
 @plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)
-def rpost_info(bot, trigger, match):
+def post_or_comment_info(bot, trigger, match):
     match = match or trigger
-    return say_post_info(bot, trigger, match.group(1))
+    comment = match.group('comment')
+
+    if comment:
+        say_comment_info(bot, trigger, comment)
+        return
+
+    say_post_info(bot, trigger, match.group('submission'))
 
 
 @plugin.url(gallery_url)
@@ -205,12 +215,9 @@ def say_post_info(bot, trigger, id_, show_link=True, show_comments_link=False):
         return plugin.NOLIMIT
 
 
-@plugin.url(comment_url)
-@plugin.output_prefix(PLUGIN_OUTPUT_PREFIX)
-def comment_info(bot, trigger, match):
-    """Shows information about the linked comment"""
+def say_comment_info(bot, trigger, id_):
     try:
-        c = bot.memory['reddit_praw'].comment(match.group(1))
+        c = bot.memory['reddit_praw'].comment(id_)
     except prawcore.exceptions.NotFound:
         bot.reply('No such comment.')
         return plugin.NOLIMIT


Test patch: