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 8import json 9import ssl 10 11# Third party imports 12from qtpy.QtCore import QObject, Signal 13 14# Local imports 15from spyder import __version__ 16from spyder.config.base import _ 17from spyder.py3compat import PY3 18from spyder.utils.programs import check_version, is_stable_version 19 20 21if PY3: 22 from urllib.request import urlopen 23 from urllib.error import URLError, HTTPError 24else: 25 from urllib2 import urlopen, URLError, HTTPError 26 27 28class WorkerUpdates(QObject): 29 """ 30 Worker that checks for releases using the Github API without blocking the 31 Spyder user interface, in case of connections issues. 32 """ 33 sig_ready = Signal() 34 35 def __init__(self, parent, startup): 36 QObject.__init__(self) 37 self._parent = parent 38 self.error = None 39 self.latest_release = None 40 self.startup = startup 41 42 def check_update_available(self, version, releases): 43 """Checks if there is an update available. 44 45 It takes as parameters the current version of Spyder and a list of 46 valid cleaned releases in chronological order (what github api returns 47 by default). Example: ['2.3.4', '2.3.3' ...] 48 """ 49 if is_stable_version(version): 50 # Remove non stable versions from the list 51 releases = [r for r in releases if is_stable_version(r)] 52 53 latest_release = releases[0] 54 55 if version.endswith('dev'): 56 return (False, latest_release) 57 58 return (check_version(version, latest_release, '<'), latest_release) 59 60 def start(self): 61 """Main method of the WorkerUpdates worker""" 62 self.url = 'https://api.github.com/repos/spyder-ide/spyder/releases' 63 self.update_available = False 64 self.latest_release = __version__ 65 66 error_msg = None 67 68 try: 69 if hasattr(ssl, '_create_unverified_context'): 70 # Fix for issue # 2685 [Works only with Python >=2.7.9] 71 # More info: https://www.python.org/dev/peps/pep-0476/#opting-out 72 context = ssl._create_unverified_context() 73 page = urlopen(self.url, context=context) 74 else: 75 page = urlopen(self.url) 76 try: 77 data = page.read() 78 79 # Needed step for python3 compatibility 80 if not isinstance(data, str): 81 data = data.decode() 82 83 data = json.loads(data) 84 releases = [item['tag_name'].replace('v', '') for item in data] 85 version = __version__ 86 87 result = self.check_update_available(version, releases) 88 self.update_available, self.latest_release = result 89 except Exception: 90 error_msg = _('Unable to retrieve information.') 91 except HTTPError: 92 error_msg = _('Unable to retrieve information.') 93 except URLError: 94 error_msg = _('Unable to connect to the internet. <br><br>Make ' 95 'sure the connection is working properly.') 96 except Exception: 97 error_msg = _('Unable to check for updates.') 98 99 # Don't show dialog when starting up spyder and an error occur 100 if not (self.startup and error_msg is not None): 101 self.error = error_msg 102 self.sig_ready.emit() 103