prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <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
  
  
  </issue>
  <code>
  [start of sopel/modules/find_updates.py]
  1 # coding=utf-8
  2 """
  3 find_updates.py - Sopel Update Check Plugin
  4 This is separated from version.py, so that it can be easily overridden by
  5 distribution packagers, and they can check their repositories rather than the
  6 Sopel website.
  7 Copyright 2014, Elsie Powell, embolalia.com
  8 Licensed under the Eiffel Forum License 2.
  9 
  10 https://sopel.chat
  11 """
  12 from __future__ import absolute_import, division, print_function, unicode_literals
  13 
  14 import requests
  15 
  16 from sopel import (
  17     __version__ as current_version,
  18     _version_info,
  19     plugin,
  20     tools,
  21     version_info,
  22 )
  23 
  24 
  25 wait_time = 24 * 60 * 60  # check once per day
  26 version_url = 'https://sopel.chat/latest.json'
  27 stable_message = (
  28     'A new Sopel version, {}, is available; I am running {}. Please update '
  29     'me. Full release notes at {}'
  30 )
  31 unstable_message = (
  32     'A new pre-release version, {}, is available; I am running {}. Please '
  33     'update me.{}'
  34 )
  35 
  36 
  37 @plugin.event(tools.events.RPL_LUSERCLIENT)
  38 def startup_version_check(bot, trigger):
  39     if not bot.memory.get('update_startup_check_run', False):
  40         bot.memory['update_startup_check_run'] = True
  41         check_version(bot)
  42 
  43 
  44 def _check_succeeded(bot):
  45     bot.memory['update_failures'] = 0
  46 
  47 
  48 def _check_failed(bot):
  49     bot.memory['update_failures'] = 1 + bot.memory.get('update_failures', 0)
  50 
  51 
  52 @plugin.interval(wait_time)
  53 def check_version(bot):
  54     version = version_info
  55     success = False
  56 
  57     try:
  58         r = requests.get(version_url, timeout=(5, 5))
  59     except requests.exceptions.RequestException:
  60         _check_failed(bot)
  61     else:
  62         success = True
  63 
  64     try:
  65         if success:
  66             info = r.json()
  67     except ValueError:
  68         # TODO: use JSONDecodeError when dropping Pythons < 3.5
  69         _check_failed(bot)
  70 
  71     if not success and bot.memory.get('update_failures', 0) > 4:
  72         bot.say(
  73             "[update] I haven't been able to check for updates in a while. "
  74             "Please verify that {} is working and I can reach it."
  75             .format(version_url), bot.config.core.owner)
  76         bot.say(
  77             "[update] If this issue persists, please alert the Sopel dev team "
  78             "in #sopel on freenode, or open a GitHub issue: "
  79             "https://github.com/sopel-irc/sopel/issues",
  80             bot.config.core.owner)
  81         return
  82 
  83     _check_succeeded(bot)
  84 
  85     if version.releaselevel == 'final':
  86         latest = info['version']
  87         notes = info['release_notes']
  88         message = stable_message
  89     else:
  90         latest = info['unstable']
  91         notes = info.get('unstable_notes', '')
  92         if notes:
  93             notes = ' Full release notes at ' + notes
  94         message = unstable_message
  95     latest_version = _version_info(latest)
  96 
  97     if version < latest_version:
  98         msg = message.format(latest, current_version, notes)
  99         bot.say('[update] ' + msg, bot.config.core.owner)
  100
  [end of sopel/modules/find_updates.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: 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 @@
       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."
  
verification_info: {"golden_diff": "diff --git a/sopel/modules/find_updates.py b/sopel/modules/find_updates.py\n--- a/sopel/modules/find_updates.py\n+++ b/sopel/modules/find_updates.py\n@@ -67,8 +67,14 @@\n     except ValueError:\n         # TODO: use JSONDecodeError when dropping Pythons < 3.5\n         _check_failed(bot)\n+        success = False\n \n-    if not success and bot.memory.get('update_failures', 0) > 4:\n+    if not success:\n+        if bot.memory.get('update_failures', 0) <= 4:\n+            # not enough failures to worry; silently ignore this one\n+            return\n+\n+        # too many failures to ignore; notify owner\n         bot.say(\n             \"[update] I haven't been able to check for updates in a while. \"\n             \"Please verify that {} is working and I can reach it.\"\n", "issue": "find_updates: Unexpected error (local variable 'info' referenced before assignment)\n### Description\r\nAn error is logged, errors shouldn't happen.\r\n\r\n### Reproduction steps\r\nSeen in log channel, unknown, run the bot for long enough???\r\n\r\n### Expected behavior\r\nNo error\r\n\r\n### Logs\r\n```\r\n[2021-03-31 22:00:24,531] sopel.tools.jobs     ERROR    - Error while processing job: local variable 'info' referenced before assignment\r\n[2021-03-31 22:00:24,538] sopel.bot            ERROR    - Unexpected error (local variable 'info' referenced before assignment)\r\nTraceback (most recent call last):\r\n  File \"/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/tools/jobs.py\", line 191, in _call\r\n    job.execute(self.manager)\r\n  File \"/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/tools/jobs.py\", line 463, in execute\r\n    return self._handler(manager)\r\n  File \"/srv/sopelbots/devvenv/lib/python3.7/site-packages/sopel/modules/find_updates.py\", line 86, in check_version\r\n    latest = info['version']\r\nUnboundLocalError: local variable 'info' referenced before assignment\r\n\r\n```\r\n\r\n### Environment\r\n- Sopel `.version`: https://github.com/sopel-irc/sopel/commit/96c55aff852bf40bca56de49b2bc30378bf1c819\r\n- Sopel installed via: pip/wheel\r\n- Python version: 3.7.3\r\n- Operating system: Debian 10.9\r\n- IRCd `/version`: freenode\r\n- Relevant plugins: find_updates\r\n\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"\nfind_updates.py - Sopel Update Check Plugin\nThis is separated from version.py, so that it can be easily overridden by\ndistribution packagers, and they can check their repositories rather than the\nSopel website.\nCopyright 2014, Elsie Powell, embolalia.com\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport requests\n\nfrom sopel import (\n    __version__ as current_version,\n    _version_info,\n    plugin,\n    tools,\n    version_info,\n)\n\n\nwait_time = 24 * 60 * 60  # check once per day\nversion_url = 'https://sopel.chat/latest.json'\nstable_message = (\n    'A new Sopel version, {}, is available; I am running {}. Please update '\n    'me. Full release notes at {}'\n)\nunstable_message = (\n    'A new pre-release version, {}, is available; I am running {}. Please '\n    'update me.{}'\n)\n\n\n@plugin.event(tools.events.RPL_LUSERCLIENT)\ndef startup_version_check(bot, trigger):\n    if not bot.memory.get('update_startup_check_run', False):\n        bot.memory['update_startup_check_run'] = True\n        check_version(bot)\n\n\ndef _check_succeeded(bot):\n    bot.memory['update_failures'] = 0\n\n\ndef _check_failed(bot):\n    bot.memory['update_failures'] = 1 + bot.memory.get('update_failures', 0)\n\n\n@plugin.interval(wait_time)\ndef check_version(bot):\n    version = version_info\n    success = False\n\n    try:\n        r = requests.get(version_url, timeout=(5, 5))\n    except requests.exceptions.RequestException:\n        _check_failed(bot)\n    else:\n        success = True\n\n    try:\n        if success:\n            info = r.json()\n    except ValueError:\n        # TODO: use JSONDecodeError when dropping Pythons < 3.5\n        _check_failed(bot)\n\n    if not success and bot.memory.get('update_failures', 0) > 4:\n        bot.say(\n            \"[update] I haven't been able to check for updates in a while. \"\n            \"Please verify that {} is working and I can reach it.\"\n            .format(version_url), bot.config.core.owner)\n        bot.say(\n            \"[update] If this issue persists, please alert the Sopel dev team \"\n            \"in #sopel on freenode, or open a GitHub issue: \"\n            \"https://github.com/sopel-irc/sopel/issues\",\n            bot.config.core.owner)\n        return\n\n    _check_succeeded(bot)\n\n    if version.releaselevel == 'final':\n        latest = info['version']\n        notes = info['release_notes']\n        message = stable_message\n    else:\n        latest = info['unstable']\n        notes = info.get('unstable_notes', '')\n        if notes:\n            notes = ' Full release notes at ' + notes\n        message = unstable_message\n    latest_version = _version_info(latest)\n\n    if version < latest_version:\n        msg = message.format(latest, current_version, notes)\n        bot.say('[update] ' + msg, bot.config.core.owner)\n", "path": "sopel/modules/find_updates.py"}]}