diff --git a/.travis.yml b/.travis.yml index 1be7fac8..e77b37aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,13 @@ matrix: env: TOXENV=py36 - python: 3.7 env: TOXENV=py37 - dist: xenial # required for Python 3.7 (travis-ci/travis-ci#9069) - sudo: required # required for Python 3.7 (travis-ci/travis-ci#9069) + dist: xenial + - python: 3.8 + env: TOXENV=py38 + dist: xenial + - python: 3.9 + env: TOXENV=py39 + dist: bionic install: - pip install typing==3.7.4.1 # required for Python 3.3 diff --git a/src/future/backports/xmlrpc/client.py b/src/future/backports/xmlrpc/client.py index b78e5bad..0bcd90c9 100644 --- a/src/future/backports/xmlrpc/client.py +++ b/src/future/backports/xmlrpc/client.py @@ -134,10 +134,11 @@ from future.builtins import bytes, dict, int, range, str import base64 -# Py2.7 compatibility hack -base64.encodebytes = base64.encodestring -base64.decodebytes = base64.decodestring import sys +if sys.version_info < (3, 9): + # Py2.7 compatibility hack + base64.encodebytes = base64.encodestring + base64.decodebytes = base64.decodestring import time from datetime import datetime from future.backports.http import client as http_client diff --git a/src/future/moves/_dummy_thread.py b/src/future/moves/_dummy_thread.py index 688d249b..e5dca348 100644 --- a/src/future/moves/_dummy_thread.py +++ b/src/future/moves/_dummy_thread.py @@ -2,7 +2,10 @@ from future.utils import PY3 if PY3: - from _dummy_thread import * + try: + from _dummy_thread import * + except ImportError: + from _thread import * else: __future_module__ = True from dummy_thread import * diff --git a/src/future/standard_library/__init__.py b/src/future/standard_library/__init__.py index cff02f95..41c4f36d 100644 --- a/src/future/standard_library/__init__.py +++ b/src/future/standard_library/__init__.py @@ -125,7 +125,7 @@ # 'Tkinter': 'tkinter', '_winreg': 'winreg', 'thread': '_thread', - 'dummy_thread': '_dummy_thread', + 'dummy_thread': '_dummy_thread' if sys.version_info < (3, 9) else '_thread', # 'anydbm': 'dbm', # causes infinite import loop # 'whichdb': 'dbm', # causes infinite import loop # anydbm and whichdb are handled by fix_imports2 diff --git a/tests/test_future/test_builtins.py b/tests/test_future/test_builtins.py index 3921a608..f5dbec64 100644 --- a/tests/test_future/test_builtins.py +++ b/tests/test_future/test_builtins.py @@ -1304,7 +1304,8 @@ def test_pow(self): self.assertAlmostEqual(pow(-1, 1/3), 0.5 + 0.8660254037844386j) # Raises TypeError in Python < v3.5, ValueError in v3.5: - self.assertRaises((TypeError, ValueError), pow, -1, -2, 3) + if sys.version_info < (3, 8): + self.assertRaises((TypeError, ValueError), pow, -1, -2, 3) self.assertRaises(ValueError, pow, 1, 2, 0) self.assertRaises(TypeError, pow) diff --git a/tests/test_future/test_standard_library.py b/tests/test_future/test_standard_library.py index 3ac5d2d7..820bf47a 100644 --- a/tests/test_future/test_standard_library.py +++ b/tests/test_future/test_standard_library.py @@ -422,7 +422,8 @@ def test_urllib_imports_install_hooks(self): def test_underscore_prefixed_modules(self): import _thread - import _dummy_thread + if sys.version_info < (3, 9): + import _dummy_thread import _markupbase self.assertTrue(True) diff --git a/tests/test_future/test_urllib2.py b/tests/test_future/test_urllib2.py index 2d69dad1..bd8e75c5 100644 --- a/tests/test_future/test_urllib2.py +++ b/tests/test_future/test_urllib2.py @@ -691,10 +691,6 @@ def connect_ftp(self, user, passwd, host, port, dirs, h = NullFTPHandler(data) h.parent = MockOpener() - # MIME guessing works in Python 3.8! - guessed_mime = None - if sys.hexversion >= 0x03080000: - guessed_mime = "image/gif" for url, host, port, user, passwd, type_, dirs, filename, mimetype in [ ("ftp://localhost/foo/bar/baz.html", "localhost", ftplib.FTP_PORT, "", "", "I", @@ -713,7 +709,10 @@ def connect_ftp(self, user, passwd, host, port, dirs, ["foo", "bar"], "", None), ("ftp://localhost/baz.gif;type=a", "localhost", ftplib.FTP_PORT, "", "", "A", - [], "baz.gif", guessed_mime), + [], "baz.gif", None), + ("ftp://localhost/baz.gif", + "localhost", ftplib.FTP_PORT, "", "", "I", + [], "baz.gif", "image/gif"), ]: req = Request(url) req.timeout = None diff --git a/tests/test_future/test_urllib_toplevel.py b/tests/test_future/test_urllib_toplevel.py index 11e77201..923b2e8a 100644 --- a/tests/test_future/test_urllib_toplevel.py +++ b/tests/test_future/test_urllib_toplevel.py @@ -120,7 +120,7 @@ def setUp(self): finally: f.close() self.pathname = support.TESTFN - self.returned_obj = urlopen("file:%s" % self.pathname) + self.returned_obj = urlopen("file:%s" % urllib_parse.quote(self.pathname)) def tearDown(self): """Shut down the open object""" @@ -167,7 +167,7 @@ def test_info(self): self.assertIsInstance(self.returned_obj.info(), email_message.Message) def test_geturl(self): - self.assertEqual(self.returned_obj.geturl(), self.pathname) + self.assertEqual(self.returned_obj.geturl(), urllib_parse.quote(self.pathname)) def test_getcode(self): self.assertIsNone(self.returned_obj.getcode()) @@ -781,8 +781,9 @@ def test_unquoting(self): "%s" % result) self.assertRaises((TypeError, AttributeError), urllib_parse.unquote, None) self.assertRaises((TypeError, AttributeError), urllib_parse.unquote, ()) - with support.check_warnings(('', BytesWarning), quiet=True): - self.assertRaises((TypeError, AttributeError), urllib_parse.unquote, bytes(b'')) + if sys.version_info < (3, 9): + with support.check_warnings(('', BytesWarning), quiet=True): + self.assertRaises((TypeError, AttributeError), urllib_parse.unquote, bytes(b'')) def test_unquoting_badpercent(self): # Test unquoting on bad percent-escapes diff --git a/tox.ini b/tox.ini index 1ca3286b..48e17601 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py{26,27,33,34,35,36,37}, + py{26,27,33,34,35,36,37,38,39}, docs [testenv]