prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  4.0beta1 is offered as an update when using a development version and a virtualenv
  We need to avoid showing beta versions when checking for updates
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `spyder/workers/updates.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 #
  3 # Copyright © Spyder Project Contributors
  4 # Licensed under the terms of the MIT License
  5 # (see spyder/__init__.py for details)
  6 
  7 # Standard library imports
  8 import json
  9 import os
  10 import ssl
  11 import sys
  12 
  13 # Third party imports
  14 from qtpy.QtCore import QObject, Signal
  15 
  16 # Local imports
  17 from spyder import __version__
  18 from spyder.config.base import _
  19 from spyder.py3compat import PY3
  20 from spyder.config.utils import is_anaconda
  21 from spyder.utils.programs import check_version, is_stable_version
  22 
  23 
  24 if PY3:
  25     from urllib.request import urlopen
  26     from urllib.error import URLError, HTTPError
  27 else:
  28     from urllib2 import urlopen, URLError, HTTPError
  29 
  30 
  31 class WorkerUpdates(QObject):
  32     """
  33     Worker that checks for releases using either the Anaconda
  34     default channels or the Github Releases page without
  35     blocking the Spyder user interface, in case of connection
  36     issues.
  37     """
  38     sig_ready = Signal()
  39 
  40     def __init__(self, parent, startup, version=""):
  41         QObject.__init__(self)
  42         self._parent = parent
  43         self.error = None
  44         self.latest_release = None
  45         self.startup = startup
  46         self.version = version
  47 
  48     def check_update_available(self, version, releases, github=False):
  49         """Checks if there is an update available.
  50 
  51         It takes as parameters the current version of Spyder and a list of
  52         valid cleaned releases in chronological order.
  53         Example: ['2.3.2', '2.3.3' ...] or with github ['2.3.4', '2.3.3' ...]
  54         """
  55         if is_stable_version(version):
  56             # Remove non stable versions from the list
  57             releases = [r for r in releases if is_stable_version(r)]
  58 
  59         if github:
  60             latest_release = releases[0]
  61         else:
  62             latest_release = releases[-1]
  63 
  64         if version.endswith('dev'):
  65             return (False, latest_release)
  66 
  67         return (check_version(version, latest_release, '<'), latest_release)
  68 
  69     def start(self):
  70         """Main method of the WorkerUpdates worker"""
  71         if is_anaconda():
  72             self.url = 'https://repo.anaconda.com/pkgs/main'
  73             if os.name == 'nt':
  74                 self.url += '/win-64/repodata.json'
  75             elif sys.platform == 'darwin':
  76                 self.url += '/osx-64/repodata.json'
  77             else:
  78                 self.url += '/linux-64/repodata.json'
  79         else:
  80             self.url = ('https://api.github.com/repos/'
  81                         'spyder-ide/spyder/releases')
  82         self.update_available = False
  83         self.latest_release = __version__
  84 
  85         error_msg = None
  86 
  87         try:
  88             if hasattr(ssl, '_create_unverified_context'):
  89                 # Fix for issue # 2685 [Works only with Python >=2.7.9]
  90                 # More info: https://www.python.org/dev/peps/pep-0476/#opting-out
  91                 context = ssl._create_unverified_context()
  92                 page = urlopen(self.url, context=context)
  93             else:
  94                 page = urlopen(self.url)
  95             try:
  96                 data = page.read()
  97 
  98                 # Needed step for python3 compatibility
  99                 if not isinstance(data, str):
  100                     data = data.decode()
  101 
  102                 data = json.loads(data)
  103                 if not self.version:
  104                     self.version = __version__
  105 
  106                 if is_anaconda():
  107                     releases = []
  108                     for item in data['packages']:
  109                         if 'spyder' in item and 'spyder-kernels' not in item:
  110                             releases.append(item.split('-')[1])
  111                     result = self.check_update_available(self.version,
  112                                                          releases)
  113                 else:
  114                     releases = [item['tag_name'].replace('v', '')
  115                                 for item in data]
  116                     result = self.check_update_available(self.version,
  117                                                          releases,
  118                                                          github=True)
  119                 self.update_available, self.latest_release = result
  120             except Exception:
  121                 error_msg = _('Unable to retrieve information.')
  122         except HTTPError:
  123             error_msg = _('Unable to retrieve information.')
  124         except URLError:
  125             error_msg = _('Unable to connect to the internet. <br><br>Make '
  126                           'sure the connection is working properly.')
  127         except Exception:
  128             error_msg = _('Unable to check for updates.')
  129 
  130         # Don't show dialog when starting up spyder and an error occur
  131         if not (self.startup and error_msg is not None):
  132             self.error = error_msg
  133             self.sig_ready.emit()
  134
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/spyder/workers/updates.py b/spyder/workers/updates.py
  --- a/spyder/workers/updates.py
  +++ b/spyder/workers/updates.py
  @@ -7,6 +7,7 @@
   # Standard library imports
   import json
   import os
  +import re
   import ssl
   import sys
   
  @@ -37,34 +38,41 @@
       """
       sig_ready = Signal()
   
  -    def __init__(self, parent, startup, version=""):
  +    def __init__(self, parent, startup, version="", releases=None):
           QObject.__init__(self)
           self._parent = parent
           self.error = None
           self.latest_release = None
           self.startup = startup
  -        self.version = version
  +        self.releases = releases
   
  -    def check_update_available(self, version, releases, github=False):
  +        if not version:
  +            self.version = __version__
  +        else:
  +            self.version = version
  +
  +    def check_update_available(self):
           """Checks if there is an update available.
   
           It takes as parameters the current version of Spyder and a list of
           valid cleaned releases in chronological order.
           Example: ['2.3.2', '2.3.3' ...] or with github ['2.3.4', '2.3.3' ...]
           """
  -        if is_stable_version(version):
  -            # Remove non stable versions from the list
  -            releases = [r for r in releases if is_stable_version(r)]
  +        # Don't perform any check for development versions
  +        if 'dev' in self.version:
  +            return (False, latest_release)
   
  -        if github:
  -            latest_release = releases[0]
  +        # Filter releases
  +        if is_stable_version(self.version):
  +            releases = [r for r in self.releases if is_stable_version(r)]
           else:
  -            latest_release = releases[-1]
  +            releases = [r for r in self.releases
  +                        if not is_stable_version(r) or r in self.version]
   
  -        if version.endswith('dev'):
  -            return (False, latest_release)
  +        latest_release = releases[-1]
   
  -        return (check_version(version, latest_release, '<'), latest_release)
  +        return (check_version(self.version, latest_release, '<'),
  +                latest_release)
   
       def start(self):
           """Main method of the WorkerUpdates worker"""
  @@ -98,24 +106,23 @@
                   # Needed step for python3 compatibility
                   if not isinstance(data, str):
                       data = data.decode()
  -
                   data = json.loads(data)
  -                if not self.version:
  -                    self.version = __version__
   
                   if is_anaconda():
  -                    releases = []
  -                    for item in data['packages']:
  -                        if 'spyder' in item and 'spyder-kernels' not in item:
  -                            releases.append(item.split('-')[1])
  -                    result = self.check_update_available(self.version,
  -                                                         releases)
  +                    if self.releases is None:
  +                        self.releases = []
  +                        for item in data['packages']:
  +                            if ('spyder' in item and
  +                                    not re.search(r'spyder-[a-zA-Z]', item)):
  +                                self.releases.append(item.split('-')[1])
  +                    result = self.check_update_available()
                   else:
  -                    releases = [item['tag_name'].replace('v', '')
  -                                for item in data]
  -                    result = self.check_update_available(self.version,
  -                                                         releases,
  -                                                         github=True)
  +                    if self.releases is None:
  +                        self.releases = [item['tag_name'].replace('v', '')
  +                                         for item in data]
  +                        self.releases = list(reversed(self.releases))
  +
  +                result = self.check_update_available()
                   self.update_available, self.latest_release = result
               except Exception:
                   error_msg = _('Unable to retrieve information.')
  
verification_info: {"golden_diff": "diff --git a/spyder/workers/updates.py b/spyder/workers/updates.py\n--- a/spyder/workers/updates.py\n+++ b/spyder/workers/updates.py\n@@ -7,6 +7,7 @@\n # Standard library imports\n import json\n import os\n+import re\n import ssl\n import sys\n \n@@ -37,34 +38,41 @@\n     \"\"\"\n     sig_ready = Signal()\n \n-    def __init__(self, parent, startup, version=\"\"):\n+    def __init__(self, parent, startup, version=\"\", releases=None):\n         QObject.__init__(self)\n         self._parent = parent\n         self.error = None\n         self.latest_release = None\n         self.startup = startup\n-        self.version = version\n+        self.releases = releases\n \n-    def check_update_available(self, version, releases, github=False):\n+        if not version:\n+            self.version = __version__\n+        else:\n+            self.version = version\n+\n+    def check_update_available(self):\n         \"\"\"Checks if there is an update available.\n \n         It takes as parameters the current version of Spyder and a list of\n         valid cleaned releases in chronological order.\n         Example: ['2.3.2', '2.3.3' ...] or with github ['2.3.4', '2.3.3' ...]\n         \"\"\"\n-        if is_stable_version(version):\n-            # Remove non stable versions from the list\n-            releases = [r for r in releases if is_stable_version(r)]\n+        # Don't perform any check for development versions\n+        if 'dev' in self.version:\n+            return (False, latest_release)\n \n-        if github:\n-            latest_release = releases[0]\n+        # Filter releases\n+        if is_stable_version(self.version):\n+            releases = [r for r in self.releases if is_stable_version(r)]\n         else:\n-            latest_release = releases[-1]\n+            releases = [r for r in self.releases\n+                        if not is_stable_version(r) or r in self.version]\n \n-        if version.endswith('dev'):\n-            return (False, latest_release)\n+        latest_release = releases[-1]\n \n-        return (check_version(version, latest_release, '<'), latest_release)\n+        return (check_version(self.version, latest_release, '<'),\n+                latest_release)\n \n     def start(self):\n         \"\"\"Main method of the WorkerUpdates worker\"\"\"\n@@ -98,24 +106,23 @@\n                 # Needed step for python3 compatibility\n                 if not isinstance(data, str):\n                     data = data.decode()\n-\n                 data = json.loads(data)\n-                if not self.version:\n-                    self.version = __version__\n \n                 if is_anaconda():\n-                    releases = []\n-                    for item in data['packages']:\n-                        if 'spyder' in item and 'spyder-kernels' not in item:\n-                            releases.append(item.split('-')[1])\n-                    result = self.check_update_available(self.version,\n-                                                         releases)\n+                    if self.releases is None:\n+                        self.releases = []\n+                        for item in data['packages']:\n+                            if ('spyder' in item and\n+                                    not re.search(r'spyder-[a-zA-Z]', item)):\n+                                self.releases.append(item.split('-')[1])\n+                    result = self.check_update_available()\n                 else:\n-                    releases = [item['tag_name'].replace('v', '')\n-                                for item in data]\n-                    result = self.check_update_available(self.version,\n-                                                         releases,\n-                                                         github=True)\n+                    if self.releases is None:\n+                        self.releases = [item['tag_name'].replace('v', '')\n+                                         for item in data]\n+                        self.releases = list(reversed(self.releases))\n+\n+                result = self.check_update_available()\n                 self.update_available, self.latest_release = result\n             except Exception:\n                 error_msg = _('Unable to retrieve information.')\n", "issue": "4.0beta1 is offered as an update when using a development version and a virtualenv\nWe need to avoid showing beta versions when checking for updates\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n#\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n# Standard library imports\nimport json\nimport os\nimport ssl\nimport sys\n\n# Third party imports\nfrom qtpy.QtCore import QObject, Signal\n\n# Local imports\nfrom spyder import __version__\nfrom spyder.config.base import _\nfrom spyder.py3compat import PY3\nfrom spyder.config.utils import is_anaconda\nfrom spyder.utils.programs import check_version, is_stable_version\n\n\nif PY3:\n    from urllib.request import urlopen\n    from urllib.error import URLError, HTTPError\nelse:\n    from urllib2 import urlopen, URLError, HTTPError\n\n\nclass WorkerUpdates(QObject):\n    \"\"\"\n    Worker that checks for releases using either the Anaconda\n    default channels or the Github Releases page without\n    blocking the Spyder user interface, in case of connection\n    issues.\n    \"\"\"\n    sig_ready = Signal()\n\n    def __init__(self, parent, startup, version=\"\"):\n        QObject.__init__(self)\n        self._parent = parent\n        self.error = None\n        self.latest_release = None\n        self.startup = startup\n        self.version = version\n\n    def check_update_available(self, version, releases, github=False):\n        \"\"\"Checks if there is an update available.\n\n        It takes as parameters the current version of Spyder and a list of\n        valid cleaned releases in chronological order.\n        Example: ['2.3.2', '2.3.3' ...] or with github ['2.3.4', '2.3.3' ...]\n        \"\"\"\n        if is_stable_version(version):\n            # Remove non stable versions from the list\n            releases = [r for r in releases if is_stable_version(r)]\n\n        if github:\n            latest_release = releases[0]\n        else:\n            latest_release = releases[-1]\n\n        if version.endswith('dev'):\n            return (False, latest_release)\n\n        return (check_version(version, latest_release, '<'), latest_release)\n\n    def start(self):\n        \"\"\"Main method of the WorkerUpdates worker\"\"\"\n        if is_anaconda():\n            self.url = 'https://repo.anaconda.com/pkgs/main'\n            if os.name == 'nt':\n                self.url += '/win-64/repodata.json'\n            elif sys.platform == 'darwin':\n                self.url += '/osx-64/repodata.json'\n            else:\n                self.url += '/linux-64/repodata.json'\n        else:\n            self.url = ('https://api.github.com/repos/'\n                        'spyder-ide/spyder/releases')\n        self.update_available = False\n        self.latest_release = __version__\n\n        error_msg = None\n\n        try:\n            if hasattr(ssl, '_create_unverified_context'):\n                # Fix for issue # 2685 [Works only with Python >=2.7.9]\n                # More info: https://www.python.org/dev/peps/pep-0476/#opting-out\n                context = ssl._create_unverified_context()\n                page = urlopen(self.url, context=context)\n            else:\n                page = urlopen(self.url)\n            try:\n                data = page.read()\n\n                # Needed step for python3 compatibility\n                if not isinstance(data, str):\n                    data = data.decode()\n\n                data = json.loads(data)\n                if not self.version:\n                    self.version = __version__\n\n                if is_anaconda():\n                    releases = []\n                    for item in data['packages']:\n                        if 'spyder' in item and 'spyder-kernels' not in item:\n                            releases.append(item.split('-')[1])\n                    result = self.check_update_available(self.version,\n                                                         releases)\n                else:\n                    releases = [item['tag_name'].replace('v', '')\n                                for item in data]\n                    result = self.check_update_available(self.version,\n                                                         releases,\n                                                         github=True)\n                self.update_available, self.latest_release = result\n            except Exception:\n                error_msg = _('Unable to retrieve information.')\n        except HTTPError:\n            error_msg = _('Unable to retrieve information.')\n        except URLError:\n            error_msg = _('Unable to connect to the internet. <br><br>Make '\n                          'sure the connection is working properly.')\n        except Exception:\n            error_msg = _('Unable to check for updates.')\n\n        # Don't show dialog when starting up spyder and an error occur\n        if not (self.startup and error_msg is not None):\n            self.error = error_msg\n            self.sig_ready.emit()\n", "path": "spyder/workers/updates.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n#\n# Copyright \u00a9 Spyder Project Contributors\n# Licensed under the terms of the MIT License\n# (see spyder/__init__.py for details)\n\n# Standard library imports\nimport json\nimport os\nimport re\nimport ssl\nimport sys\n\n# Third party imports\nfrom qtpy.QtCore import QObject, Signal\n\n# Local imports\nfrom spyder import __version__\nfrom spyder.config.base import _\nfrom spyder.py3compat import PY3\nfrom spyder.config.utils import is_anaconda\nfrom spyder.utils.programs import check_version, is_stable_version\n\n\nif PY3:\n    from urllib.request import urlopen\n    from urllib.error import URLError, HTTPError\nelse:\n    from urllib2 import urlopen, URLError, HTTPError\n\n\nclass WorkerUpdates(QObject):\n    \"\"\"\n    Worker that checks for releases using either the Anaconda\n    default channels or the Github Releases page without\n    blocking the Spyder user interface, in case of connection\n    issues.\n    \"\"\"\n    sig_ready = Signal()\n\n    def __init__(self, parent, startup, version=\"\", releases=None):\n        QObject.__init__(self)\n        self._parent = parent\n        self.error = None\n        self.latest_release = None\n        self.startup = startup\n        self.releases = releases\n\n        if not version:\n            self.version = __version__\n        else:\n            self.version = version\n\n    def check_update_available(self):\n        \"\"\"Checks if there is an update available.\n\n        It takes as parameters the current version of Spyder and a list of\n        valid cleaned releases in chronological order.\n        Example: ['2.3.2', '2.3.3' ...] or with github ['2.3.4', '2.3.3' ...]\n        \"\"\"\n        # Don't perform any check for development versions\n        if 'dev' in self.version:\n            return (False, latest_release)\n\n        # Filter releases\n        if is_stable_version(self.version):\n            releases = [r for r in self.releases if is_stable_version(r)]\n        else:\n            releases = [r for r in self.releases\n                        if not is_stable_version(r) or r in self.version]\n\n        latest_release = releases[-1]\n\n        return (check_version(self.version, latest_release, '<'),\n                latest_release)\n\n    def start(self):\n        \"\"\"Main method of the WorkerUpdates worker\"\"\"\n        if is_anaconda():\n            self.url = 'https://repo.anaconda.com/pkgs/main'\n            if os.name == 'nt':\n                self.url += '/win-64/repodata.json'\n            elif sys.platform == 'darwin':\n                self.url += '/osx-64/repodata.json'\n            else:\n                self.url += '/linux-64/repodata.json'\n        else:\n            self.url = ('https://api.github.com/repos/'\n                        'spyder-ide/spyder/releases')\n        self.update_available = False\n        self.latest_release = __version__\n\n        error_msg = None\n\n        try:\n            if hasattr(ssl, '_create_unverified_context'):\n                # Fix for issue # 2685 [Works only with Python >=2.7.9]\n                # More info: https://www.python.org/dev/peps/pep-0476/#opting-out\n                context = ssl._create_unverified_context()\n                page = urlopen(self.url, context=context)\n            else:\n                page = urlopen(self.url)\n            try:\n                data = page.read()\n\n                # Needed step for python3 compatibility\n                if not isinstance(data, str):\n                    data = data.decode()\n                data = json.loads(data)\n\n                if is_anaconda():\n                    if self.releases is None:\n                        self.releases = []\n                        for item in data['packages']:\n                            if ('spyder' in item and\n                                    not re.search(r'spyder-[a-zA-Z]', item)):\n                                self.releases.append(item.split('-')[1])\n                    result = self.check_update_available()\n                else:\n                    if self.releases is None:\n                        self.releases = [item['tag_name'].replace('v', '')\n                                         for item in data]\n                        self.releases = list(reversed(self.releases))\n\n                result = self.check_update_available()\n                self.update_available, self.latest_release = result\n            except Exception:\n                error_msg = _('Unable to retrieve information.')\n        except HTTPError:\n            error_msg = _('Unable to retrieve information.')\n        except URLError:\n            error_msg = _('Unable to connect to the internet. <br><br>Make '\n                          'sure the connection is working properly.')\n        except Exception:\n            error_msg = _('Unable to check for updates.')\n\n        # Don't show dialog when starting up spyder and an error occur\n        if not (self.startup and error_msg is not None):\n            self.error = error_msg\n            self.sig_ready.emit()\n", "path": "spyder/workers/updates.py"}]}