Browse Source

Refs #23919 -- Removed misc Python 2/3 references.

Tim Graham 8 years ago
parent
commit
1c466994d9

+ 2 - 2
django/apps/config.py

@@ -57,8 +57,8 @@ class AppConfig:
         """Attempt to determine app's filesystem path from its module."""
         # See #21874 for extended discussion of the behavior of this method in
         # various cases.
-        # Convert paths to list because Python 3's _NamespacePath does not
-        # support indexing.
+        # Convert paths to list because Python's _NamespacePath doesn't support
+        # indexing.
         paths = list(getattr(module, '__path__', []))
         if len(paths) != 1:
             filename = getattr(module, '__file__', None)

+ 1 - 2
django/contrib/auth/hashers.py

@@ -419,8 +419,7 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
         # Hash the password prior to using bcrypt to prevent password
         # truncation as described in #20138.
         if self.digest is not None:
-            # Use binascii.hexlify() because a hex encoded bytestring is
-            # Unicode on Python 3.
+            # Use binascii.hexlify() because a hex encoded bytestring is str.
             password = binascii.hexlify(self.digest(force_bytes(password)).digest())
         else:
             password = force_bytes(password)

+ 2 - 2
django/contrib/auth/views.py

@@ -298,7 +298,7 @@ def password_reset_confirm(request, uidb64=None, token=None,
     else:
         post_reset_redirect = resolve_url(post_reset_redirect)
     try:
-        # urlsafe_base64_decode() decodes to bytestring on Python 3
+        # urlsafe_base64_decode() decodes to bytestring
         uid = force_text(urlsafe_base64_decode(uidb64))
         user = UserModel._default_manager.get(pk=uid)
     except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
@@ -442,7 +442,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
 
     def get_user(self, uidb64):
         try:
-            # urlsafe_base64_decode() decodes to bytestring on Python 3
+            # urlsafe_base64_decode() decodes to bytestring
             uid = force_text(urlsafe_base64_decode(uidb64))
             user = UserModel._default_manager.get(pk=uid)
         except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):

+ 2 - 2
django/core/mail/message.py

@@ -324,8 +324,8 @@ class EmailMessage:
                     try:
                         content = content.decode('utf-8')
                     except UnicodeDecodeError:
-                        # If mimetype suggests the file is text but it's actually
-                        # binary, read() will raise a UnicodeDecodeError on Python 3.
+                        # If mimetype suggests the file is text but it's
+                        # actually binary, read() raises a UnicodeDecodeError.
                         mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
 
             self.attachments.append((filename, content, mimetype))

+ 1 - 1
django/core/management/commands/shell.py

@@ -53,7 +53,7 @@ class Command(BaseCommand):
             import rlcompleter
             readline.set_completer(rlcompleter.Completer(imported_objects).complete)
             # Enable tab completion on systems using libedit (e.g. Mac OSX).
-            # These lines are copied from Lib/site.py on Python 3.4.
+            # These lines are copied from Python's Lib/site.py.
             readline_doc = getattr(readline, '__doc__', '')
             if readline_doc is not None and 'libedit' in readline_doc:
                 readline.parse_and_bind("bind ^I rl_complete")

+ 1 - 2
django/db/backends/oracle/base.py

@@ -322,8 +322,7 @@ class OracleParam:
             param = Oracle_datetime.from_datetime(param)
 
         string_size = 0
-        # Oracle doesn't recognize True and False correctly in Python 3.
-        # The conversion done below works both in 2 and 3.
+        # Oracle doesn't recognize True and False correctly.
         if param is True:
             param = 1
         elif param is False:

+ 8 - 14
django/db/migrations/serializer.py

@@ -8,7 +8,6 @@ import math
 import re
 import types
 import uuid
-from importlib import import_module
 
 from django.db import models
 from django.db.migrations.operations.base import Operation
@@ -155,20 +154,15 @@ class FunctionTypeSerializer(BaseSerializer):
             raise ValueError("Cannot serialize function: lambda")
         if self.value.__module__ is None:
             raise ValueError("Cannot serialize function %r: No module" % self.value)
-        # Python 3 is a lot easier, and only uses this branch if it's not local.
-        if getattr(self.value, "__qualname__", None) and getattr(self.value, "__module__", None):
-            if "<" not in self.value.__qualname__:  # Qualname can include <locals>
-                return "%s.%s" % \
-                    (self.value.__module__, self.value.__qualname__), {"import %s" % self.value.__module__}
-        # Fallback version
+
         module_name = self.value.__module__
-        # Make sure it's actually there
-        module = import_module(module_name)
-        if not hasattr(module, self.value.__name__):
-            raise ValueError(
-                "Could not find function %s in %s.\n" % (self.value.__name__, module_name)
-            )
-        return "%s.%s" % (module_name, self.value.__name__), {"import %s" % module_name}
+
+        if '<' not in self.value.__qualname__:  # Qualname can include <locals>
+            return '%s.%s' % (module_name, self.value.__qualname__), {'import %s' % self.value.__module__}
+
+        raise ValueError(
+            'Could not find function %s in %s.\n' % (self.value.__name__, module_name)
+        )
 
 
 class FunctoolsPartialSerializer(BaseSerializer):

+ 1 - 2
django/test/runner.py

@@ -258,8 +258,7 @@ def default_test_processes():
     """
     # The current implementation of the parallel test runner requires
     # multiprocessing to start subprocesses with fork().
-    # On Python 3.4+: if multiprocessing.get_start_method() != 'fork':
-    if not hasattr(os, 'fork'):
+    if multiprocessing.get_start_method() != 'fork':
         return 1
     try:
         return int(os.environ['DJANGO_TEST_PROCESSES'])

+ 1 - 1
docs/internals/howto-release-django.txt

@@ -303,7 +303,7 @@ Now you're ready to actually put the release out there. To do this:
         $ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION.tar.gz
         $ deactivate
         $ mktmpenv
-        $ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION-py2.py3-none-any.whl
+        $ pip install https://www.djangoproject.com/m/releases/$MAJOR_VERSION/Django-$RELEASE_VERSION-py3-none-any.whl
         $ deactivate
 
    This just tests that the tarballs are available (i.e. redirects are up) and

+ 0 - 8
docs/ref/contrib/gis/install/geodjango_setup.bat

@@ -1,8 +0,0 @@
-set OSGEO4W_ROOT=C:\OSGeo4W
-set PYTHON_ROOT=C:\Python27
-set GDAL_DATA=%OSGEO4W_ROOT%\share\gdal
-set PROJ_LIB=%OSGEO4W_ROOT%\share\proj
-set PATH=%PATH%;%PYTHON_ROOT%;%OSGEO4W_ROOT%\bin
-reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /t REG_EXPAND_SZ /f /d "%PATH%"
-reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v GDAL_DATA /t REG_EXPAND_SZ /f /d "%GDAL_DATA%"
-reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PROJ_LIB /t REG_EXPAND_SZ /f /d "%PROJ_LIB%"

+ 4 - 7
docs/ref/contrib/gis/install/index.txt

@@ -463,7 +463,7 @@ executable with ``cmd.exe``, will set this up:
 .. code-block:: bat
 
     set OSGEO4W_ROOT=C:\OSGeo4W
-    set PYTHON_ROOT=C:\Python27
+    set PYTHON_ROOT=C:\Python3X
     set GDAL_DATA=%OSGEO4W_ROOT%\share\gdal
     set PROJ_LIB=%OSGEO4W_ROOT%\share\proj
     set PATH=%PATH%;%PYTHON_ROOT%;%OSGEO4W_ROOT%\bin
@@ -471,15 +471,12 @@ executable with ``cmd.exe``, will set this up:
     reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v GDAL_DATA /t REG_EXPAND_SZ /f /d "%GDAL_DATA%"
     reg ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v PROJ_LIB /t REG_EXPAND_SZ /f /d "%PROJ_LIB%"
 
-For your convenience, these commands are available in the executable batch
-script, :download:`geodjango_setup.bat`.
-
 .. note::
 
     Administrator privileges are required to execute these commands.
-    To do this, right-click on :download:`geodjango_setup.bat` and select
-    :menuselection:`Run as administrator`. You need to log out and log back in again
-    for the settings to take effect.
+    To do this, create a ``bat`` script with the commands, right-click it, and
+    select :menuselection:`Run as administrator`. You need to log out and log
+    back in again for the settings to take effect.
 
 .. note::
 

+ 0 - 3
setup.cfg

@@ -18,6 +18,3 @@ not_skip = __init__.py
 
 [metadata]
 license-file = LICENSE
-
-[wheel]
-universal = 1

+ 0 - 2
setup.py

@@ -61,8 +61,6 @@ setup(
         'License :: OSI Approved :: BSD License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',

+ 1 - 1
tests/README.rst

@@ -3,7 +3,7 @@ install some requirements and run the tests::
 
     $ cd tests
     $ pip install -e ..
-    $ pip install -r requirements/py3.txt  # or py2.txt
+    $ pip install -r requirements/py3.txt
     $ ./runtests.py
 
 For more information about the test suite, see

+ 0 - 1
tests/auth_tests/test_hashers.py

@@ -434,7 +434,6 @@ class TestUtilsHashPass(SimpleTestCase):
 
     def test_load_library_importerror(self):
         PlainHasher = type('PlainHasher', (BasePasswordHasher,), {'algorithm': 'plain', 'library': 'plain'})
-        # Python 3 adds quotes around module name
         msg = "Couldn't load 'PlainHasher' algorithm library: No module named 'plain'"
         with self.assertRaisesMessage(ValueError, msg):
             PlainHasher()._load_library()

+ 0 - 4
tests/cache/tests.py

@@ -1912,10 +1912,6 @@ class CacheI18nTest(TestCase):
         get_cache_data = FetchFromCacheMiddleware().process_request(request)
         self.assertIsNone(get_cache_data)
 
-        # This test passes on Python < 3.3 even without the corresponding code
-        # in UpdateCacheMiddleware, because pickling a StreamingHttpResponse
-        # fails (http://bugs.python.org/issue14288). LocMemCache silently
-        # swallows the exception and doesn't store the response in cache.
         content = ['Check for cache with streaming content.']
         response = StreamingHttpResponse(content)
         UpdateCacheMiddleware().process_response(request, response)

+ 18 - 23
tests/i18n/test_extraction.py

@@ -16,6 +16,7 @@ from django.core.management.commands.makemessages import \
 from django.core.management.utils import find_command
 from django.test import SimpleTestCase, override_settings
 from django.test.utils import captured_stderr, captured_stdout
+from django.utils._os import symlinks_supported
 from django.utils.translation import TranslatorCommentWarning
 
 from .utils import POFileAssertionMixin, RunInTmpDirMixin, copytree
@@ -382,7 +383,10 @@ class BasicExtractorTests(ExtractorTests):
             cmd.gettext_version
 
     def test_po_file_encoding_when_updating(self):
-        """Update of PO file doesn't corrupt it with non-UTF-8 encoding on Python3+Windows (#23271)"""
+        """
+        Update of PO file doesn't corrupt it with non-UTF-8 encoding on Windows
+        (#23271).
+        """
         BR_PO_BASE = 'locale/pt_BR/LC_MESSAGES/django'
         shutil.copyfile(BR_PO_BASE + '.pristine', BR_PO_BASE + '.po')
         management.call_command('makemessages', locale=['pt_BR'], verbosity=0)
@@ -472,29 +476,20 @@ class SymlinkExtractorTests(ExtractorTests):
         self.symlinked_dir = os.path.join(self.test_dir, 'templates_symlinked')
 
     def test_symlink(self):
-        # On Python < 3.2 os.symlink() exists only on Unix
-        if hasattr(os, 'symlink'):
-            if os.path.exists(self.symlinked_dir):
-                self.assertTrue(os.path.islink(self.symlinked_dir))
-            else:
-                # On Python >= 3.2) os.symlink() exists always but then can
-                # fail at runtime when user hasn't the needed permissions on
-                # Windows versions that support symbolink links (>= 6/Vista).
-                # See Python issue 9333 (http://bugs.python.org/issue9333).
-                # Skip the test in that case
-                try:
-                    os.symlink(os.path.join(self.test_dir, 'templates'), self.symlinked_dir)
-                except (OSError, NotImplementedError):
-                    self.skipTest("os.symlink() is available on this OS but can't be used by this user.")
-            os.chdir(self.test_dir)
-            management.call_command('makemessages', locale=[LOCALE], verbosity=0, symlinks=True)
-            self.assertTrue(os.path.exists(self.PO_FILE))
-            with open(self.PO_FILE, 'r') as fp:
-                po_contents = fp.read()
-                self.assertMsgId('This literal should be included.', po_contents)
-            self.assertLocationCommentPresent(self.PO_FILE, None, 'templates_symlinked', 'test.html')
+        if os.path.exists(self.symlinked_dir):
+            self.assertTrue(os.path.islink(self.symlinked_dir))
         else:
-            self.skipTest("os.symlink() not available on this OS + Python version combination.")
+            if symlinks_supported():
+                os.symlink(os.path.join(self.test_dir, 'templates'), self.symlinked_dir)
+            else:
+                self.skipTest("os.symlink() not available on this OS + Python version combination.")
+        os.chdir(self.test_dir)
+        management.call_command('makemessages', locale=[LOCALE], verbosity=0, symlinks=True)
+        self.assertTrue(os.path.exists(self.PO_FILE))
+        with open(self.PO_FILE, 'r') as fp:
+            po_contents = fp.read()
+            self.assertMsgId('This literal should be included.', po_contents)
+        self.assertLocationCommentPresent(self.PO_FILE, None, 'templates_symlinked', 'test.html')
 
 
 class CopyPluralFormsExtractorTests(ExtractorTests):

+ 2 - 3
tests/mail/tests.py

@@ -192,7 +192,6 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
             'Content', 'from@example.com', ['to@example.com']
         )
         message = email.message()
-        # Note that in Python 3, maximum line length has increased from 76 to 78
         self.assertEqual(
             message['Subject'].encode(),
             b'Long subject lines that get wrapped should contain a space continuation\n'
@@ -1157,8 +1156,8 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
 
         if mailfrom != maddr:
             # According to the spec, mailfrom does not necessarily match the
-            # From header - on Python 3 this is the case where the local part
-            # isn't encoded, so try to correct that.
+            # From header - this is the case where the local part isn't
+            # encoded, so try to correct that.
             lp, domain = mailfrom.split('@', 1)
             lp = Header(lp, 'utf-8').encode()
             mailfrom = '@'.join([lp, domain])

+ 4 - 4
tests/migrations/test_commands.py

@@ -672,8 +672,8 @@ class MakeMigrationsTests(MigrationTestBase):
         module = 'migrations.test_migrations_order'
         with self.temporary_migration_module(module=module) as migration_dir:
             if hasattr(importlib, 'invalidate_caches'):
-                # Python 3 importlib caches os.listdir() on some platforms like
-                # Mac OS X (#23850).
+                # importlib caches os.listdir() on some platforms like Mac OS X
+                # (#23850).
                 importlib.invalidate_caches()
             call_command('makemigrations', 'migrations', '--empty', '-n', 'a', '-v', '0')
             self.assertTrue(os.path.exists(os.path.join(migration_dir, '0002_a.py')))
@@ -1202,8 +1202,8 @@ class MakeMigrationsTests(MigrationTestBase):
             content = cmd("0001", migration_name_0001)
             self.assertIn("dependencies=[\n]", content)
 
-            # Python 3 importlib caches os.listdir() on some platforms like
-            # Mac OS X (#23850).
+            # importlib caches os.listdir() on some platforms like Mac OS X
+            # (#23850).
             if hasattr(importlib, 'invalidate_caches'):
                 importlib.invalidate_caches()
 

+ 11 - 14
tests/migrations/test_writer.py

@@ -40,6 +40,12 @@ class Money(decimal.Decimal):
         )
 
 
+class TestModel1(object):
+    def upload_to(self):
+        return '/somewhere/dynamic/'
+    thing = models.FileField(upload_to=upload_to)
+
+
 class OperationWriterTests(SimpleTestCase):
 
     def test_empty_signature(self):
@@ -472,21 +478,12 @@ class WriterTests(SimpleTestCase):
         self.assertEqual(string, 'range')
         self.assertEqual(imports, set())
 
-    def test_serialize_local_function_reference(self):
-        """
-        Neither py2 or py3 can serialize a reference in a local scope.
-        """
-        class TestModel2:
-            def upload_to(self):
-                return "somewhere dynamic"
-            thing = models.FileField(upload_to=upload_to)
-        with self.assertRaises(ValueError):
-            self.serialize_round_trip(TestModel2.thing)
+    def test_serialize_unbound_method_reference(self):
+        """An unbound method used within a class body can be serialized."""
+        self.serialize_round_trip(TestModel1.thing)
 
-    def test_serialize_local_function_reference_message(self):
-        """
-        Make sure user is seeing which module/function is the issue
-        """
+    def test_serialize_local_function_reference(self):
+        """A reference in a local scope can't be serialized."""
         class TestModel2:
             def upload_to(self):
                 return "somewhere dynamic"

+ 1 - 10
tests/test_client/test_conditional_content_removal.py

@@ -1,19 +1,10 @@
 import gzip
-import io
 
 from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
 from django.test import SimpleTestCase
 from django.test.client import conditional_content_removal
 
 
-# based on Python 3.3's gzip.compress
-def gzip_compress(data):
-    buf = io.BytesIO()
-    with gzip.GzipFile(fileobj=buf, mode='wb', compresslevel=0) as f:
-        f.write(data)
-    return buf.getvalue()
-
-
 class ConditionalContentTests(SimpleTestCase):
 
     def test_conditional_content_removal(self):
@@ -43,7 +34,7 @@ class ConditionalContentTests(SimpleTestCase):
             self.assertEqual(b''.join(res), b'')
 
         # Issue #20472
-        abc = gzip_compress(b'abc')
+        abc = gzip.compress(b'abc')
         res = HttpResponse(abc, status=304)
         res['Content-Encoding'] = 'gzip'
         conditional_content_removal(req, res)

+ 2 - 7
tox.ini

@@ -11,10 +11,7 @@ envlist =
     docs
     isort
 
-# Add environments to use default python2 and python3 installations
-[testenv:py2]
-basepython = python2
-
+# Add environment to use the default python3 installation
 [testenv:py3]
 basepython = python3
 
@@ -24,7 +21,6 @@ passenv = DJANGO_SETTINGS_MODULE PYTHONPATH HOME DISPLAY
 setenv =
     PYTHONDONTWRITEBYTECODE=1
 deps =
-    py{2,27}: -rtests/requirements/py2.txt
     py{3,34,35,36}: -rtests/requirements/py3.txt
     postgres: -rtests/requirements/postgres.txt
     mysql: -rtests/requirements/mysql.txt
@@ -41,8 +37,7 @@ changedir = {toxinidir}
 commands = flake8 .
 
 [testenv:docs]
-# On OS X, as of pyenchant 1.6.6, the docs build only works under Python 2.
-basepython = python2
+basepython = python3
 usedevelop = false
 whitelist_externals =
     make