Repository: nvaccess/nvda

Issue:
Update check/Python 3: update check fails due to incomplete urllib package imports
### Steps to reproduce:
In order to test this, a binary version of Python 3 staging snapshot is ideal:

1. Run the latest Python 3 staging snapshot.
2. Check for updates.

### Actual behavior:
Errors such as a traceback that says no function.

### Expected behavior:
Update check succeeds.

### System configuration
#### NVDA installed/portable/running from source:
Source and portable

#### NVDA version:
Py3 staging 17843

#### Windows version:
Windows 10 Version 1903

#### Name and version of other software in use when reproducing the issue:
None

#### Other information about your system:
None

### Other questions
#### Does the issue still occur after restarting your PC?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
Yes- no i8ssues with Python 2 version.

### Cause:
Caused by incomplete urllib package import (such as not importing urllib.request/parse).

Thanks.


Discussion:
Hi,

Note that if one imports just urllib, urllib.request/parse won't be imported. The solution is to import at least urllib.request, which will then import other parts of this package.

Thanks.

Resolving patch:
diff --git a/source/updateCheck.py b/source/updateCheck.py
--- a/source/updateCheck.py
+++ b/source/updateCheck.py
@@ -24,7 +24,9 @@
 import threading
 import time
 import pickle
-import urllib
+# #9818: one must import at least urllib.request in Python 3 in order to use full urllib functionality.
+import urllib.request
+import urllib.parse
 import tempfile
 import hashlib
 import ctypes.wintypes
@@ -119,16 +121,16 @@ def checkForUpdate(auto=False):
 			"outputBrailleTable":config.conf['braille']['translationTable'] if brailleDisplayClass else None,
 		}
 		params.update(extraParams)
-	url = "%s?%s" % (CHECK_URL, urllib.urlencode(params))
+	url = "%s?%s" % (CHECK_URL, urllib.parse.urlencode(params))
 	try:
-		res = urllib.urlopen(url)
+		res = urllib.request.urlopen(url)
 	except IOError as e:
 		if isinstance(e.strerror, ssl.SSLError) and e.strerror.reason == "CERTIFICATE_VERIFY_FAILED":
 			# #4803: Windows fetches trusted root certificates on demand.
 			# Python doesn't trigger this fetch (PythonIssue:20916), so try it ourselves
 			_updateWindowsRootCertificates()
 			# and then retry the update check.
-			res = urllib.urlopen(url)
+			res = urllib.request.urlopen(url)
 		else:
 			raise
 	if res.code != 200:
@@ -610,13 +612,12 @@ def _bg(self):
 		self._guiExec(self._downloadSuccess)
 
 	def _download(self, url):
-		remote = urllib.urlopen(url)
-		if remote.code != 200:
-			raise RuntimeError("Download failed with code %d" % remote.code)
 		# #2352: Some security scanners such as Eset NOD32 HTTP Scanner
 		# cause huge read delays while downloading.
 		# Therefore, set a higher timeout.
-		remote.fp._sock.settimeout(120)
+		remote = urllib.request.urlopen(url, timeout=120)
+		if remote.code != 200:
+			raise RuntimeError("Download failed with code %d" % remote.code)
 		size = int(remote.headers["content-length"])
 		with open(self.destPath, "wb") as local:
 			if self.fileHash:
@@ -807,7 +808,7 @@ def _updateWindowsRootCertificates():
 	crypt = ctypes.windll.crypt32
 	# Get the server certificate.
 	sslCont = ssl._create_unverified_context()
-	u = urllib.urlopen("https://www.nvaccess.org/nvdaUpdateCheck", context=sslCont)
+	u = urllib.request.urlopen("https://www.nvaccess.org/nvdaUpdateCheck", context=sslCont)
 	cert = u.fp._sock.getpeercert(True)
 	u.close()
 	# Convert to a form usable by Windows.


Test patch: