summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-12-01 11:38:01 +0100
committerClaude Paroz <claude@2xlibre.net>2017-01-18 16:21:28 +0100
commitc716fe87821df00f9f03ecc761c914d1682591a2 (patch)
tree0436706cdb190acbc76fb5fcf6d66f16e09fafa3
parente63d98b7beb16d1410168a2315cbe04c43c9c80d (diff)
downloaddjango-c716fe87821df00f9f03ecc761c914d1682591a2.tar.gz
Refs #23919 -- Removed six.PY2/PY3 usage
Thanks Tim Graham for the review.
-rw-r--r--django/contrib/admindocs/views.py8
-rw-r--r--django/contrib/auth/management/__init__.py8
-rw-r--r--django/contrib/auth/migrations/0001_initial.py6
-rw-r--r--django/contrib/auth/migrations/0004_alter_user_username_opts.py3
-rw-r--r--django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py3
-rw-r--r--django/contrib/auth/migrations/0008_alter_user_username_max_length.py3
-rw-r--r--django/contrib/auth/models.py4
-rw-r--r--django/contrib/auth/validators.py5
-rw-r--r--django/contrib/gis/utils/ogrinspect.py3
-rw-r--r--django/contrib/postgres/signals.py7
-rw-r--r--django/core/cache/backends/db.py6
-rw-r--r--django/core/exceptions.py6
-rw-r--r--django/core/files/base.py8
-rw-r--r--django/core/handlers/wsgi.py17
-rw-r--r--django/core/mail/backends/console.py6
-rw-r--r--django/core/mail/message.py46
-rw-r--r--django/core/management/commands/loaddata.py3
-rw-r--r--django/core/management/commands/runserver.py6
-rw-r--r--django/core/management/templates.py22
-rw-r--r--django/db/backends/mysql/base.py2
-rw-r--r--django/db/backends/oracle/operations.py2
-rw-r--r--django/db/backends/postgresql/base.py4
-rw-r--r--django/db/backends/sqlite3/base.py4
-rw-r--r--django/db/backends/sqlite3/features.py2
-rw-r--r--django/db/migrations/questioner.py10
-rw-r--r--django/db/migrations/serializer.py12
-rw-r--r--django/db/models/base.py4
-rw-r--r--django/db/models/fields/related.py9
-rw-r--r--django/db/models/manager.py5
-rw-r--r--django/db/utils.py2
-rw-r--r--django/dispatch/dispatcher.py15
-rw-r--r--django/dispatch/weakref_backports.py67
-rw-r--r--django/http/cookie.py32
-rw-r--r--django/http/multipartparser.py9
-rw-r--r--django/http/request.py29
-rw-r--r--django/http/response.py28
-rw-r--r--django/test/client.py10
-rw-r--r--django/test/signals.py4
-rw-r--r--django/test/testcases.py6
-rw-r--r--django/test/utils.py9
-rw-r--r--django/urls/resolvers.py6
-rw-r--r--django/utils/_os.py29
-rw-r--r--django/utils/crypto.py3
-rw-r--r--django/utils/datastructures.py24
-rw-r--r--django/utils/decorators.py9
-rw-r--r--django/utils/encoding.py35
-rw-r--r--django/utils/feedgenerator.py6
-rw-r--r--django/utils/functional.py26
-rw-r--r--django/utils/glob.py19
-rw-r--r--django/utils/html.py26
-rw-r--r--django/utils/html_parser.py21
-rw-r--r--django/utils/http.py29
-rw-r--r--django/utils/inspect.py48
-rw-r--r--django/utils/module_loading.py94
-rw-r--r--django/utils/safestring.py7
-rw-r--r--django/utils/text.py5
-rw-r--r--django/utils/translation/template.py3
-rw-r--r--django/utils/translation/trans_real.py18
-rw-r--r--django/views/debug.py10
-rw-r--r--setup.cfg2
-rw-r--r--tests/admin_docs/test_views.py4
-rw-r--r--tests/admin_scripts/tests.py20
-rw-r--r--tests/annotations/tests.py3
-rw-r--r--tests/apps/tests.py3
-rw-r--r--tests/auth_tests/test_forms.py14
-rw-r--r--tests/auth_tests/test_management.py3
-rw-r--r--tests/auth_tests/test_tokens.py14
-rw-r--r--tests/backends/test_utils.py5
-rw-r--r--tests/base/models.py9
-rw-r--r--tests/cache/tests.py6
-rw-r--r--tests/dbshell/test_postgresql_psycopg2.py17
-rw-r--r--tests/file_uploads/tests.py6
-rw-r--r--tests/files/tests.py5
-rw-r--r--tests/fixtures_regress/tests.py21
-rw-r--r--tests/handlers/tests.py20
-rw-r--r--tests/httpwrappers/tests.py34
-rw-r--r--tests/i18n/test_compilation.py19
-rw-r--r--tests/i18n/tests.py52
-rw-r--r--tests/inspectdb/tests.py8
-rw-r--r--tests/invalid_models_tests/test_relative_fields.py10
-rw-r--r--tests/mail/tests.py43
-rw-r--r--tests/middleware/tests.py19
-rw-r--r--tests/migrations/test_commands.py16
-rw-r--r--tests/migrations/test_loader.py4
-rw-r--r--tests/migrations/test_writer.py15
-rw-r--r--tests/model_fields/test_promises.py16
-rw-r--r--tests/project_template/test_settings.py7
-rw-r--r--tests/queries/tests.py24
-rw-r--r--tests/queryset_pickle/models.py5
-rw-r--r--tests/queryset_pickle/tests.py3
-rw-r--r--tests/requests/tests.py8
-rw-r--r--tests/signing/tests.py5
-rw-r--r--tests/staticfiles_tests/test_management.py3
-rw-r--r--tests/str/models.py27
-rw-r--r--tests/str/tests.py13
-rw-r--r--tests/template_tests/syntax_tests/test_width_ratio.py6
-rw-r--r--tests/template_tests/test_custom.py3
-rw-r--r--tests/template_tests/test_loaders.py2
-rw-r--r--tests/template_tests/test_nodelist.py7
-rw-r--r--tests/test_runner/test_debug_sql.py3
-rw-r--r--tests/test_runner/test_parallel.py6
-rw-r--r--tests/urlpatterns_reverse/tests.py9
-rw-r--r--tests/utils_tests/test_encoding.py31
-rw-r--r--tests/utils_tests/test_functional.py17
-rw-r--r--tests/utils_tests/test_glob.py13
-rw-r--r--tests/utils_tests/test_html.py50
-rw-r--r--tests/utils_tests/test_http.py18
-rw-r--r--tests/utils_tests/test_simplelazyobject.py7
-rw-r--r--tests/view_tests/tests/py3_test_debug.py45
-rw-r--r--tests/view_tests/tests/test_debug.py48
-rw-r--r--tests/view_tests/tests/test_i18n.py6
111 files changed, 308 insertions, 1299 deletions
diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py
index 3488e9fb3a..4a8e1eb599 100644
--- a/django/contrib/admindocs/views.py
+++ b/django/contrib/admindocs/views.py
@@ -15,7 +15,6 @@ from django.db import models
from django.http import Http404
from django.template.engine import Engine
from django.urls import get_mod_func, get_resolver, get_urlconf, reverse
-from django.utils import six
from django.utils.decorators import method_decorator
from django.utils.inspect import (
func_accepts_kwargs, func_accepts_var_args, func_has_no_args,
@@ -132,12 +131,7 @@ class ViewIndexView(BaseAdminDocsView):
@staticmethod
def _get_full_name(func):
mod_name = func.__module__
- if six.PY3:
- return '%s.%s' % (mod_name, func.__qualname__)
- else:
- # PY2 does not support __qualname__
- func_name = getattr(func, '__name__', func.__class__.__name__)
- return '%s.%s' % (mod_name, func_name)
+ return '%s.%s' % (mod_name, func.__qualname__)
def get_context_data(self, **kwargs):
views = []
diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py
index 17fd8dd11a..0d3fca03eb 100644
--- a/django/contrib/auth/management/__init__.py
+++ b/django/contrib/auth/management/__init__.py
@@ -8,8 +8,6 @@ from django.apps import apps as global_apps
from django.contrib.auth import get_permission_codename
from django.core import exceptions
from django.db import DEFAULT_DB_ALIAS, router
-from django.utils import six
-from django.utils.encoding import DEFAULT_LOCALE_ENCODING
def _get_all_permissions(opts):
@@ -98,12 +96,6 @@ def get_system_username():
# if there is no corresponding entry in the /etc/passwd file
# (a very restricted chroot environment, for example).
return ''
- if six.PY2:
- try:
- result = result.decode(DEFAULT_LOCALE_ENCODING)
- except UnicodeDecodeError:
- # UnicodeDecodeError - preventive treatment for non-latin Windows.
- return ''
return result
diff --git a/django/contrib/auth/migrations/0001_initial.py b/django/contrib/auth/migrations/0001_initial.py
index f97caae1e4..5ab80b64e0 100644
--- a/django/contrib/auth/migrations/0001_initial.py
+++ b/django/contrib/auth/migrations/0001_initial.py
@@ -1,7 +1,7 @@
import django.contrib.auth.models
from django.contrib.auth import validators
from django.db import migrations, models
-from django.utils import six, timezone
+from django.utils import timezone
class Migration(migrations.Migration):
@@ -63,9 +63,7 @@ class Migration(migrations.Migration):
('username', models.CharField(
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True,
max_length=30, verbose_name='username',
- validators=[
- validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()
- ],
+ validators=[validators.UnicodeUsernameValidator()],
)),
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
diff --git a/django/contrib/auth/migrations/0004_alter_user_username_opts.py b/django/contrib/auth/migrations/0004_alter_user_username_opts.py
index f4afcf7bd8..a16083ee37 100644
--- a/django/contrib/auth/migrations/0004_alter_user_username_opts.py
+++ b/django/contrib/auth/migrations/0004_alter_user_username_opts.py
@@ -1,6 +1,5 @@
from django.contrib.auth import validators
from django.db import migrations, models
-from django.utils import six
class Migration(migrations.Migration):
@@ -16,7 +15,7 @@ class Migration(migrations.Migration):
name='username',
field=models.CharField(
error_messages={'unique': 'A user with that username already exists.'}, max_length=30,
- validators=[validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()],
+ validators=[validators.UnicodeUsernameValidator()],
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
unique=True, verbose_name='username'
),
diff --git a/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py b/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py
index 6d44280856..42f5087730 100644
--- a/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py
+++ b/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py
@@ -1,6 +1,5 @@
from django.contrib.auth import validators
from django.db import migrations, models
-from django.utils import six
class Migration(migrations.Migration):
@@ -18,7 +17,7 @@ class Migration(migrations.Migration):
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
max_length=30,
unique=True,
- validators=[validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()],
+ validators=[validators.UnicodeUsernameValidator()],
verbose_name='username',
),
),
diff --git a/django/contrib/auth/migrations/0008_alter_user_username_max_length.py b/django/contrib/auth/migrations/0008_alter_user_username_max_length.py
index 15b9cf8c94..7c9dae0950 100644
--- a/django/contrib/auth/migrations/0008_alter_user_username_max_length.py
+++ b/django/contrib/auth/migrations/0008_alter_user_username_max_length.py
@@ -1,6 +1,5 @@
from django.contrib.auth import validators
from django.db import migrations, models
-from django.utils import six
class Migration(migrations.Migration):
@@ -18,7 +17,7 @@ class Migration(migrations.Migration):
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
max_length=150,
unique=True,
- validators=[validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()],
+ validators=[validators.UnicodeUsernameValidator()],
verbose_name='username',
),
),
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index 51b0d8fa63..7155bd1199 100644
--- a/django/contrib/auth/models.py
+++ b/django/contrib/auth/models.py
@@ -9,7 +9,7 @@ from django.db.models.manager import EmptyManager
from django.utils import six, timezone
from django.utils.translation import ugettext_lazy as _
-from .validators import ASCIIUsernameValidator, UnicodeUsernameValidator
+from .validators import UnicodeUsernameValidator
def update_last_login(sender, user, **kwargs):
@@ -297,7 +297,7 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
Username and password are required. Other fields are optional.
"""
- username_validator = UnicodeUsernameValidator() if six.PY3 else ASCIIUsernameValidator()
+ username_validator = UnicodeUsernameValidator()
username = models.CharField(
_('username'),
diff --git a/django/contrib/auth/validators.py b/django/contrib/auth/validators.py
index 0691d22a88..d8083de809 100644
--- a/django/contrib/auth/validators.py
+++ b/django/contrib/auth/validators.py
@@ -1,7 +1,6 @@
import re
from django.core import validators
-from django.utils import six
from django.utils.deconstruct import deconstructible
from django.utils.translation import ugettext_lazy as _
@@ -13,7 +12,7 @@ class ASCIIUsernameValidator(validators.RegexValidator):
'Enter a valid username. This value may contain only English letters, '
'numbers, and @/./+/-/_ characters.'
)
- flags = re.ASCII if six.PY3 else 0
+ flags = re.ASCII
@deconstructible
@@ -23,4 +22,4 @@ class UnicodeUsernameValidator(validators.RegexValidator):
'Enter a valid username. This value may contain only letters, '
'numbers, and @/./+/-/_ characters.'
)
- flags = re.UNICODE if six.PY2 else 0
+ flags = 0
diff --git a/django/contrib/gis/utils/ogrinspect.py b/django/contrib/gis/utils/ogrinspect.py
index 3cf9b10fd5..71e4c64878 100644
--- a/django/contrib/gis/utils/ogrinspect.py
+++ b/django/contrib/gis/utils/ogrinspect.py
@@ -235,5 +235,4 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
if name_field:
yield ''
- yield ' def __%s__(self): return self.%s' % (
- 'str' if six.PY3 else 'unicode', name_field)
+ yield ' def __str__(self): return self.%s' % name_field
diff --git a/django/contrib/postgres/signals.py b/django/contrib/postgres/signals.py
index 183ba1d983..682627de1d 100644
--- a/django/contrib/postgres/signals.py
+++ b/django/contrib/postgres/signals.py
@@ -1,18 +1,13 @@
from psycopg2 import ProgrammingError
from psycopg2.extras import register_hstore
-from django.utils import six
-
def register_hstore_handler(connection, **kwargs):
if connection.vendor != 'postgresql':
return
try:
- if six.PY2:
- register_hstore(connection.connection, globally=True, unicode=True)
- else:
- register_hstore(connection.connection, globally=True)
+ register_hstore(connection.connection, globally=True)
except ProgrammingError:
# Hstore is not available on the database.
#
diff --git a/django/core/cache/backends/db.py b/django/core/cache/backends/db.py
index ce48018d91..ad805324bd 100644
--- a/django/core/cache/backends/db.py
+++ b/django/core/cache/backends/db.py
@@ -5,7 +5,7 @@ from datetime import datetime
from django.conf import settings
from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
from django.db import DatabaseError, connections, models, router, transaction
-from django.utils import six, timezone
+from django.utils import timezone
from django.utils.encoding import force_bytes
try:
@@ -112,11 +112,9 @@ class DatabaseCache(BaseDatabaseCache):
if num > self._max_entries:
self._cull(db, cursor, now)
pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
- b64encoded = base64.b64encode(pickled)
# The DB column is expecting a string, so make sure the value is a
# string, not bytes. Refs #19274.
- if six.PY3:
- b64encoded = b64encoded.decode('latin1')
+ b64encoded = base64.b64encode(pickled).decode('latin1')
try:
# Note: typecasting for datetimes is needed by some 3rd party
# database backends. All core backends work without typecasting,
diff --git a/django/core/exceptions.py b/django/core/exceptions.py
index 47c5359c75..3bf52fab00 100644
--- a/django/core/exceptions.py
+++ b/django/core/exceptions.py
@@ -1,7 +1,6 @@
"""
Global Django exception and warning classes.
"""
-from django.utils import six
from django.utils.encoding import force_text
@@ -115,10 +114,7 @@ class ValidationError(Exception):
if isinstance(message, ValidationError):
if hasattr(message, 'error_dict'):
message = message.error_dict
- # PY2 has a `message` property which is always there so we can't
- # duck-type on it. It was introduced in Python 2.5 and already
- # deprecated in Python 2.6.
- elif not hasattr(message, 'message' if six.PY3 else 'code'):
+ elif not hasattr(message, 'message'):
message = message.error_list
else:
message, code, params = message.message, message.code, message.params
diff --git a/django/core/files/base.py b/django/core/files/base.py
index f797158881..dd07bc959a 100644
--- a/django/core/files/base.py
+++ b/django/core/files/base.py
@@ -3,7 +3,7 @@ from io import BytesIO, StringIO, UnsupportedOperation
from django.core.files.utils import FileProxyMixin
from django.utils import six
-from django.utils.encoding import force_bytes, force_str, force_text
+from django.utils.encoding import force_str, force_text
class File(FileProxyMixin):
@@ -140,11 +140,7 @@ class ContentFile(File):
A File-like object that takes just raw content, rather than an actual file.
"""
def __init__(self, content, name=None):
- if six.PY3:
- stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
- else:
- stream_class = BytesIO
- content = force_bytes(content)
+ stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
super(ContentFile, self).__init__(stream_class(content), name=name)
self.size = len(content)
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 538373cd8d..f4d3e6553a 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -8,7 +8,6 @@ from django.conf import settings
from django.core import signals
from django.core.handlers import base
from django.urls import set_script_prefix
-from django.utils import six
from django.utils.encoding import (
force_str, force_text, repercent_broken_unicode,
)
@@ -212,22 +211,20 @@ def get_bytes_from_wsgi(environ, key, default):
"""
Get a value from the WSGI environ dictionary as bytes.
- key and default should be str objects. Under Python 2 they may also be
- unicode objects provided they only contain ASCII characters.
+ key and default should be str objects.
"""
value = environ.get(str(key), str(default))
- # Under Python 3, non-ASCII values in the WSGI environ are arbitrarily
- # decoded with ISO-8859-1. This is wrong for Django websites where UTF-8
- # is the default. Re-encode to recover the original bytestring.
- return value.encode(ISO_8859_1) if six.PY3 else value
+ # Non-ASCII values in the WSGI environ are arbitrarily decoded with
+ # ISO-8859-1. This is wrong for Django websites where UTF-8 is the default.
+ # Re-encode to recover the original bytestring.
+ return value.encode(ISO_8859_1)
def get_str_from_wsgi(environ, key, default):
"""
Get a value from the WSGI environ dictionary as str.
- key and default should be str objects. Under Python 2 they may also be
- unicode objects provided they only contain ASCII characters.
+ key and default should be str objects.
"""
value = get_bytes_from_wsgi(environ, key, default)
- return value.decode(UTF_8, errors='replace') if six.PY3 else value
+ return value.decode(UTF_8, errors='replace')
diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py
index 0ce88534ea..49ddade984 100644
--- a/django/core/mail/backends/console.py
+++ b/django/core/mail/backends/console.py
@@ -5,7 +5,6 @@ import sys
import threading
from django.core.mail.backends.base import BaseEmailBackend
-from django.utils import six
class EmailBackend(BaseEmailBackend):
@@ -17,9 +16,8 @@ class EmailBackend(BaseEmailBackend):
def write_message(self, message):
msg = message.message()
msg_data = msg.as_bytes()
- if six.PY3:
- charset = msg.get_charset().get_output_charset() if msg.get_charset() else 'utf-8'
- msg_data = msg_data.decode(charset)
+ charset = msg.get_charset().get_output_charset() if msg.get_charset() else 'utf-8'
+ msg_data = msg_data.decode(charset)
self.stream.write('%s\n' % msg_data)
self.stream.write('-' * 79)
self.stream.write('\n')
diff --git a/django/core/mail/message.py b/django/core/mail/message.py
index 2c68e82809..c4df44fa9d 100644
--- a/django/core/mail/message.py
+++ b/django/core/mail/message.py
@@ -5,7 +5,9 @@ import time
from email import (
charset as Charset, encoders as Encoders, generator, message_from_string,
)
+from email.errors import InvalidHeaderDefect, NonASCIILocalPartDefect
from email.header import Header
+from email.headerregistry import Address
from email.message import Message
from email.mime.base import MIMEBase
from email.mime.message import MIMEMessage
@@ -139,18 +141,8 @@ def sanitize_address(addr, encoding):
except UnicodeEncodeError: # IDN or non-ascii in the local part
localpart, domain = split_addr(addr, encoding)
- if six.PY2:
- # On Python 2, use the stdlib since `email.headerregistry` doesn't exist.
- from email.utils import formataddr
- if localpart and domain:
- addr = '@'.join([localpart, domain])
- return formataddr((nm, addr))
-
- # On Python 3, an `email.headerregistry.Address` object is used since
+ # An `email.headerregistry.Address` object is used since
# email.utils.formataddr() naively encodes the name as ascii (see #25986).
- from email.headerregistry import Address
- from email.errors import InvalidHeaderDefect, NonASCIILocalPartDefect
-
if localpart and domain:
address = Address(nm, username=localpart, domain=domain)
return str(address)
@@ -174,27 +166,21 @@ class MIMEMixin():
"""
fp = six.StringIO()
g = generator.Generator(fp, mangle_from_=False)
- if six.PY2:
- g.flatten(self, unixfrom=unixfrom)
- else:
- g.flatten(self, unixfrom=unixfrom, linesep=linesep)
+ g.flatten(self, unixfrom=unixfrom, linesep=linesep)
return fp.getvalue()
- if six.PY2:
- as_bytes = as_string
- else:
- def as_bytes(self, unixfrom=False, linesep='\n'):
- """Return the entire formatted message as bytes.
- Optional `unixfrom' when True, means include the Unix From_ envelope
- header.
+ def as_bytes(self, unixfrom=False, linesep='\n'):
+ """Return the entire formatted message as bytes.
+ Optional `unixfrom' when True, means include the Unix From_ envelope
+ header.
- This overrides the default as_bytes() implementation to not mangle
- lines that begin with 'From '. See bug #13433 for details.
- """
- fp = BytesIO()
- g = generator.BytesGenerator(fp, mangle_from_=False)
- g.flatten(self, unixfrom=unixfrom, linesep=linesep)
- return fp.getvalue()
+ This overrides the default as_bytes() implementation to not mangle
+ lines that begin with 'From '. See bug #13433 for details.
+ """
+ fp = BytesIO()
+ g = generator.BytesGenerator(fp, mangle_from_=False)
+ g.flatten(self, unixfrom=unixfrom, linesep=linesep)
+ return fp.getvalue()
class SafeMIMEMessage(MIMEMixin, MIMEMessage):
@@ -450,8 +436,6 @@ class EmailMessage(object):
try:
filename.encode('ascii')
except UnicodeEncodeError:
- if six.PY2:
- filename = filename.encode('utf-8')
filename = ('utf-8', '', filename)
attachment.add_header('Content-Disposition', 'attachment',
filename=filename)
diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py
index 4b621205e6..9f71400862 100644
--- a/django/core/management/commands/loaddata.py
+++ b/django/core/management/commands/loaddata.py
@@ -20,7 +20,6 @@ from django.utils import lru_cache
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.functional import cached_property
-from django.utils.glob import glob_escape
try:
import bz2
@@ -238,7 +237,7 @@ class Command(BaseCommand):
self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir))
fixture_files_in_dir = []
path = os.path.join(fixture_dir, fixture_name)
- for candidate in glob.iglob(glob_escape(path) + '*'):
+ for candidate in glob.iglob(glob.escape(path) + '*'):
if os.path.basename(candidate) in targets:
# Save the fixture_dir and fixture_name for future error messages.
fixture_files_in_dir.append((candidate, fixture_dir, fixture_name))
diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py
index 62370072c5..e5dcaa1771 100644
--- a/django/core/management/commands/runserver.py
+++ b/django/core/management/commands/runserver.py
@@ -10,8 +10,8 @@ from django.core.management.base import BaseCommand, CommandError
from django.core.servers.basehttp import (
WSGIServer, get_internal_wsgi_application, run,
)
-from django.utils import autoreload, six
-from django.utils.encoding import force_text, get_system_encoding
+from django.utils import autoreload
+from django.utils.encoding import force_text
naiveip_re = re.compile(r"""^(?:
@@ -125,8 +125,6 @@ class Command(BaseCommand):
# requires_migrations_check attribute.
self.check_migrations()
now = datetime.now().strftime('%B %d, %Y - %X')
- if six.PY2:
- now = now.decode(get_system_encoding())
self.stdout.write(now)
self.stdout.write((
"Django version %(version)s, using settings %(settings)r\n"
diff --git a/django/core/management/templates.py b/django/core/management/templates.py
index 805da99148..775e75201b 100644
--- a/django/core/management/templates.py
+++ b/django/core/management/templates.py
@@ -16,7 +16,7 @@ from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.core.management.utils import handle_extensions
from django.template import Context, Engine
-from django.utils import archive, six
+from django.utils import archive
from django.utils.six.moves.urllib.request import urlretrieve
from django.utils.version import get_docs_version
@@ -218,21 +218,11 @@ class TemplateCommand(BaseCommand):
raise CommandError("you must provide %s %s name" % (
"an" if app_or_project == "app" else "a", app_or_project))
# If it's not a valid directory name.
- if six.PY2:
- if not re.search(r'^[_a-zA-Z]\w*$', name):
- # Provide a smart error message, depending on the error.
- if not re.search(r'^[_a-zA-Z]', name):
- message = 'make sure the name begins with a letter or underscore'
- else:
- message = 'use only numbers, letters and underscores'
- raise CommandError("%r is not a valid %s name. Please %s." %
- (name, app_or_project, message))
- else:
- if not name.isidentifier():
- raise CommandError(
- "%r is not a valid %s name. Please make sure the name is "
- "a valid identifier." % (name, app_or_project)
- )
+ if not name.isidentifier():
+ raise CommandError(
+ "%r is not a valid %s name. Please make sure the name is "
+ "a valid identifier." % (name, app_or_project)
+ )
def download(self, url):
"""
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 3d6cb71915..495ca33221 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -219,8 +219,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
'conv': django_conversions,
'charset': 'utf8',
}
- if six.PY2:
- kwargs['use_unicode'] = True
settings_dict = self.settings_dict
if settings_dict['USER']:
kwargs['user'] = settings_dict['USER']
diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py
index fd9d2d1179..9878fbd9bb 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -252,8 +252,6 @@ WHEN (new.%(col_name)s IS NULL)
# https://cx-oracle.readthedocs.io/en/latest/cursor.html#Cursor.statement
# The DB API definition does not define this attribute.
statement = cursor.statement
- if statement and six.PY2 and not isinstance(statement, unicode): # NOQA: unicode undefined on PY3
- statement = statement.decode('utf-8')
# Unlike Psycopg's `query` and MySQLdb`'s `_last_executed`, CxOracle's
# `statement` doesn't contain the query parameters. refs #20010.
return super(DatabaseOperations, self).last_executed_query(cursor, statement, params)
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index 85a21a8905..10b54faa20 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -12,7 +12,6 @@ from django.core.exceptions import ImproperlyConfigured
from django.db import DEFAULT_DB_ALIAS
from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.utils import DatabaseError as WrappedDatabaseError
-from django.utils import six
from django.utils.encoding import force_str
from django.utils.functional import cached_property
from django.utils.safestring import SafeBytes, SafeText
@@ -46,9 +45,6 @@ from .schema import DatabaseSchemaEditor # NOQA isort:skip
from .utils import utc_tzinfo_factory # NOQA isort:skip
from .version import get_version # NOQA isort:skip
-if six.PY2:
- psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
- psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
psycopg2.extensions.register_adapter(SafeBytes, psycopg2.extensions.QuotedString)
psycopg2.extensions.register_adapter(SafeText, psycopg2.extensions.QuotedString)
psycopg2.extras.register_uuid()
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index 0cd0516a0a..de3aa40000 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -19,7 +19,6 @@ from django.utils.dateparse import (
parse_date, parse_datetime, parse_duration, parse_time,
)
from django.utils.encoding import force_text
-from django.utils.safestring import SafeBytes
try:
try:
@@ -55,9 +54,6 @@ Database.register_converter(str("TIMESTAMP"), decoder(parse_datetime))
Database.register_converter(str("decimal"), decoder(backend_utils.typecast_decimal))
Database.register_adapter(decimal.Decimal, backend_utils.rev_typecast_decimal)
-if six.PY2:
- Database.register_adapter(str, lambda s: s.decode('utf-8'))
- Database.register_adapter(SafeBytes, lambda s: s.decode('utf-8'))
class DatabaseWrapper(BaseDatabaseWrapper):
diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py
index 43a29b78f5..5bf1997b4c 100644
--- a/django/db/backends/sqlite3/features.py
+++ b/django/db/backends/sqlite3/features.py
@@ -1,6 +1,5 @@
from django.db import utils
from django.db.backends.base.features import BaseDatabaseFeatures
-from django.utils import six
from django.utils.functional import cached_property
from .base import Database
@@ -48,7 +47,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@cached_property
def can_share_in_memory_db(self):
return (
- six.PY3 and
Database.__name__ == 'sqlite3.dbapi2' and
Database.sqlite_version_info >= (3, 7, 13)
)
diff --git a/django/db/migrations/questioner.py b/django/db/migrations/questioner.py
index d508ee9b78..17b9da8eaf 100644
--- a/django/db/migrations/questioner.py
+++ b/django/db/migrations/questioner.py
@@ -4,7 +4,7 @@ import sys
from django.apps import apps
from django.db.models.fields import NOT_PROVIDED
-from django.utils import datetime_safe, six, timezone
+from django.utils import datetime_safe, timezone
from django.utils.six.moves import input
from .loader import MigrationLoader
@@ -125,13 +125,7 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
prompt = "[default: {}] >>> ".format(default)
else:
prompt = ">>> "
- if six.PY3:
- # Six does not correctly abstract over the fact that
- # py3 input returns a unicode string, while py2 raw_input
- # returns a bytestring.
- code = input(prompt)
- else:
- code = input(prompt).decode(sys.stdin.encoding)
+ code = input(prompt)
if not code and default:
code = default
if not code:
diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py
index b273097da4..261fcabd73 100644
--- a/django/db/migrations/serializer.py
+++ b/django/db/migrations/serializer.py
@@ -53,11 +53,7 @@ class BaseSimpleSerializer(BaseSerializer):
class ByteTypeSerializer(BaseSerializer):
def serialize(self):
- value_repr = repr(self.value)
- if six.PY2:
- # Prepend the `b` prefix since we're importing unicode_literals
- value_repr = 'b' + value_repr
- return value_repr, set()
+ return repr(self.value), set()
class DatetimeSerializer(BaseSerializer):
@@ -276,11 +272,7 @@ class SettingsReferenceSerializer(BaseSerializer):
class TextTypeSerializer(BaseSerializer):
def serialize(self):
- value_repr = repr(self.value)
- if six.PY2:
- # Strip the `u` prefix since we're importing unicode_literals
- value_repr = value_repr[1:]
- return value_repr, set()
+ return repr(self.value), set()
class TimedeltaSerializer(BaseSerializer):
diff --git a/django/db/models/base.py b/django/db/models/base.py
index e18615d76d..38d0b96217 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -510,9 +510,7 @@ class Model(six.with_metaclass(ModelBase)):
return force_str('<%s: %s>' % (self.__class__.__name__, u))
def __str__(self):
- if six.PY2 and hasattr(self, '__unicode__'):
- return force_text(self).encode('utf-8')
- return str('%s object' % self.__class__.__name__)
+ return '%s object' % self.__class__.__name__
def __eq__(self, other):
if not isinstance(other, Model):
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index aec362e84a..7f7a6d3ea8 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -107,7 +107,6 @@ class RelatedField(Field):
return errors
def _check_related_name_is_valid(self):
- import re
import keyword
related_name = self.remote_field.related_name
if related_name is None:
@@ -115,12 +114,8 @@ class RelatedField(Field):
is_valid_id = True
if keyword.iskeyword(related_name):
is_valid_id = False
- if six.PY3:
- if not related_name.isidentifier():
- is_valid_id = False
- else:
- if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*\Z', related_name):
- is_valid_id = False
+ if not related_name.isidentifier():
+ is_valid_id = False
if not (is_valid_id or related_name.endswith('+')):
return [
checks.Error(
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
index 5b498d631b..96c82e54eb 100644
--- a/django/db/models/manager.py
+++ b/django/db/models/manager.py
@@ -4,7 +4,6 @@ from importlib import import_module
from django.db import router
from django.db.models.query import QuerySet
-from django.utils import six
class BaseManager(object):
@@ -86,9 +85,7 @@ class BaseManager(object):
return manager_method
new_methods = {}
- # Refs http://bugs.python.org/issue1785.
- predicate = inspect.isfunction if six.PY3 else inspect.ismethod
- for name, method in inspect.getmembers(queryset_class, predicate=predicate):
+ for name, method in inspect.getmembers(queryset_class, predicate=inspect.isfunction):
# Only copy missing methods.
if hasattr(cls, name):
continue
diff --git a/django/db/utils.py b/django/db/utils.py
index 92354b7bad..4451f5a60e 100644
--- a/django/db/utils.py
+++ b/django/db/utils.py
@@ -14,7 +14,7 @@ DEFAULT_DB_ALIAS = 'default'
DJANGO_VERSION_PICKLE_KEY = '_django_version'
-class Error(Exception if six.PY3 else StandardError): # NOQA: StandardError undefined on PY3
+class Error(Exception):
pass
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py
index db2f6839f8..8cf1680b6e 100644
--- a/django/dispatch/dispatcher.py
+++ b/django/dispatch/dispatcher.py
@@ -2,15 +2,9 @@ import sys
import threading
import weakref
-from django.utils import six
from django.utils.inspect import func_accepts_kwargs
from django.utils.six.moves import range
-if six.PY2:
- from .weakref_backports import WeakMethod
-else:
- from weakref import WeakMethod
-
def _make_id(target):
if hasattr(target, '__func__'):
@@ -107,13 +101,10 @@ class Signal(object):
receiver_object = receiver
# Check for bound methods
if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'):
- ref = WeakMethod
+ ref = weakref.WeakMethod
receiver_object = receiver.__self__
- if six.PY3:
- receiver = ref(receiver)
- weakref.finalize(receiver_object, self._remove_receiver)
- else:
- receiver = ref(receiver, self._remove_receiver)
+ receiver = ref(receiver)
+ weakref.finalize(receiver_object, self._remove_receiver)
with self.lock:
self._clear_dead_receivers()
diff --git a/django/dispatch/weakref_backports.py b/django/dispatch/weakref_backports.py
deleted file mode 100644
index 736f7e1ab8..0000000000
--- a/django/dispatch/weakref_backports.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""
-weakref_backports is a partial backport of the weakref module for python
-versions below 3.4.
-
-Copyright (C) 2013 Python Software Foundation, see LICENSE.python for details.
-
-The following changes were made to the original sources during backporting:
-
- * Added `self` to `super` calls.
- * Removed `from None` when raising exceptions.
-
-"""
-from weakref import ref
-
-
-class WeakMethod(ref):
- """
- A custom `weakref.ref` subclass which simulates a weak reference to
- a bound method, working around the lifetime problem of bound methods.
- """
-
- __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
-
- def __new__(cls, meth, callback=None):
- try:
- obj = meth.__self__
- func = meth.__func__
- except AttributeError:
- raise TypeError("argument should be a bound method, not {}"
- .format(type(meth)))
- def _cb(arg):
- # The self-weakref trick is needed to avoid creating a reference
- # cycle.
- self = self_wr()
- if self._alive:
- self._alive = False
- if callback is not None:
- callback(self)
- self = ref.__new__(cls, obj, _cb)
- self._func_ref = ref(func, _cb)
- self._meth_type = type(meth)
- self._alive = True
- self_wr = ref(self)
- return self
-
- def __call__(self):
- obj = super(WeakMethod, self).__call__()
- func = self._func_ref()
- if obj is None or func is None:
- return None
- return self._meth_type(func, obj)
-
- def __eq__(self, other):
- if isinstance(other, WeakMethod):
- if not self._alive or not other._alive:
- return self is other
- return ref.__eq__(self, other) and self._func_ref == other._func_ref
- return False
-
- def __ne__(self, other):
- if isinstance(other, WeakMethod):
- if not self._alive or not other._alive:
- return self is not other
- return ref.__ne__(self, other) or self._func_ref != other._func_ref
- return True
-
- __hash__ = ref.__hash__
diff --git a/django/http/cookie.py b/django/http/cookie.py
index 49048787eb..7251d04c40 100644
--- a/django/http/cookie.py
+++ b/django/http/cookie.py
@@ -1,12 +1,7 @@
import sys
-from django.utils import six
-from django.utils.encoding import force_str
from django.utils.six.moves import http_cookies
-# http://bugs.python.org/issue2193 is fixed in Python 3.3+.
-_cookie_allows_colon_in_names = six.PY3
-
# Cookie pickling bug is fixed in Python 2.7.9 and Python 3.4.3+
# http://bugs.python.org/issue22775
cookie_pickles_properly = (
@@ -14,7 +9,7 @@ cookie_pickles_properly = (
sys.version_info >= (3, 4, 3)
)
-if _cookie_allows_colon_in_names and cookie_pickles_properly:
+if cookie_pickles_properly:
SimpleCookie = http_cookies.SimpleCookie
else:
Morsel = http_cookies.Morsel
@@ -30,37 +25,12 @@ else:
else:
super(SimpleCookie, self).__setitem__(key, value)
- if not _cookie_allows_colon_in_names:
- def load(self, rawdata):
- self.bad_cookies = set()
- if isinstance(rawdata, six.text_type):
- rawdata = force_str(rawdata)
- super(SimpleCookie, self).load(rawdata)
- for key in self.bad_cookies:
- del self[key]
-
- # override private __set() method:
- # (needed for using our Morsel, and for laxness with CookieError
- def _BaseCookie__set(self, key, real_value, coded_value):
- key = force_str(key)
- try:
- M = self.get(key, Morsel())
- M.set(key, real_value, coded_value)
- dict.__setitem__(self, key, M)
- except http_cookies.CookieError:
- if not hasattr(self, 'bad_cookies'):
- self.bad_cookies = set()
- self.bad_cookies.add(key)
- dict.__setitem__(self, key, http_cookies.Morsel())
-
def parse_cookie(cookie):
"""
Return a dictionary parsed from a `Cookie:` header string.
"""
cookiedict = {}
- if six.PY2:
- cookie = force_str(cookie)
for chunk in cookie.split(str(';')):
if str('=') in chunk:
key, val = chunk.split(str('='), 1)
diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py
index ecfbdf7252..812e83eff0 100644
--- a/django/http/multipartparser.py
+++ b/django/http/multipartparser.py
@@ -40,8 +40,6 @@ RAW = "raw"
FILE = "file"
FIELD = "field"
-_BASE64_DECODE_ERROR = TypeError if six.PY2 else binascii.Error
-
class MultiPartParser(object):
"""
@@ -190,7 +188,7 @@ class MultiPartParser(object):
num_bytes_read += len(raw_data)
try:
data = base64.b64decode(raw_data)
- except _BASE64_DECODE_ERROR:
+ except binascii.Error:
data = raw_data
else:
data = field_stream.read(size=read_size)
@@ -684,10 +682,7 @@ def parse_header(line):
value = p[i + 1:].strip()
if has_encoding:
encoding, lang, value = value.split(b"'")
- if six.PY3:
- value = unquote(value.decode(), encoding=encoding.decode())
- else:
- value = unquote(value).decode(encoding)
+ value = unquote(value.decode(), encoding=encoding.decode())
if len(value) >= 2 and value[:1] == value[-1:] == b'"':
value = value[1:-1]
value = value.replace(b'\\\\', b'\\').replace(b'\\"', b'"')
diff --git a/django/http/request.py b/django/http/request.py
index 559081b50c..b4053142ac 100644
--- a/django/http/request.py
+++ b/django/http/request.py
@@ -14,7 +14,7 @@ from django.http.multipartparser import MultiPartParser, MultiPartParserError
from django.utils import six
from django.utils.datastructures import ImmutableList, MultiValueDict
from django.utils.encoding import (
- escape_uri_path, force_bytes, force_str, force_text, iri_to_uri,
+ escape_uri_path, force_bytes, force_str, iri_to_uri,
)
from django.utils.http import is_same_domain, limited_parse_qsl
from django.utils.six.moves.urllib.parse import (
@@ -381,24 +381,15 @@ class QueryDict(MultiValueDict):
'fields_limit': settings.DATA_UPLOAD_MAX_NUMBER_FIELDS,
'encoding': encoding,
}
- if six.PY3:
- if isinstance(query_string, bytes):
- # query_string normally contains URL-encoded data, a subset of ASCII.
- try:
- query_string = query_string.decode(encoding)
- except UnicodeDecodeError:
- # ... but some user agents are misbehaving :-(
- query_string = query_string.decode('iso-8859-1')
- for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs):
- self.appendlist(key, value)
- else:
- for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs):
- try:
- value = value.decode(encoding)
- except UnicodeDecodeError:
- value = value.decode('iso-8859-1')
- self.appendlist(force_text(key, encoding, errors='replace'),
- value)
+ if isinstance(query_string, bytes):
+ # query_string normally contains URL-encoded data, a subset of ASCII.
+ try:
+ query_string = query_string.decode(encoding)
+ except UnicodeDecodeError:
+ # ... but some user agents are misbehaving :-(
+ query_string = query_string.decode('iso-8859-1')
+ for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs):
+ self.appendlist(key, value)
self._mutable = mutable
@classmethod
diff --git a/django/http/response.py b/django/http/response.py
index 597d688602..e4cce4fdbe 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -100,10 +100,7 @@ class HttpResponseBase(six.Iterator):
]
return b'\r\n'.join(headers)
- if six.PY3:
- __bytes__ = serialize_headers
- else:
- __str__ = serialize_headers
+ __bytes__ = serialize_headers
@property
def _content_type_for_repr(self):
@@ -122,20 +119,12 @@ class HttpResponseBase(six.Iterator):
isinstance(value, six.text_type) and ('\n' in value or '\r' in value)):
raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try:
- if six.PY3:
- if isinstance(value, str):
- # Ensure string is valid in given charset
- value.encode(charset)
- else:
- # Convert bytestring using given charset
- value = value.decode(charset)
+ if isinstance(value, str):
+ # Ensure string is valid in given charset
+ value.encode(charset)
else:
- if isinstance(value, str):
- # Ensure string is valid in given charset
- value.decode(charset)
- else:
- # Convert unicode string to given charset
- value = value.encode(charset)
+ # Convert bytestring using given charset
+ value = value.decode(charset)
except UnicodeError as e:
if mime_encode:
# Wrapping in str() is a workaround for #12422 under Python 2.
@@ -311,10 +300,7 @@ class HttpResponse(HttpResponseBase):
"""Full HTTP message, including headers, as a bytestring."""
return self.serialize_headers() + b'\r\n\r\n' + self.content
- if six.PY3:
- __bytes__ = serialize
- else:
- __str__ = serialize
+ __bytes__ = serialize
@property
def content(self):
diff --git a/django/test/client.py b/django/test/client.py
index 7365b1d2aa..8134c17253 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -322,10 +322,10 @@ class RequestFactory(object):
if parsed[3]:
path += str(";") + force_str(parsed[3])
path = uri_to_iri(path).encode(UTF_8)
- # Under Python 3, non-ASCII values in the WSGI environ are arbitrarily
- # decoded with ISO-8859-1. We replicate this behavior here.
+ # Replace the behavior where non-ASCII values in the WSGI environ are
+ # arbitrarily decoded with ISO-8859-1.
# Refs comment in `get_bytes_from_wsgi()`.
- return path.decode(ISO_8859_1) if six.PY3 else path
+ return path.decode(ISO_8859_1)
def get(self, path, data=None, secure=False, **extra):
"Construct a GET request."
@@ -406,10 +406,8 @@ class RequestFactory(object):
r.update(extra)
# If QUERY_STRING is absent or empty, we want to extract it from the URL.
if not r.get('QUERY_STRING'):
- query_string = force_bytes(parsed[4])
# WSGI requires latin-1 encoded strings. See get_path_info().
- if six.PY3:
- query_string = query_string.decode('iso-8859-1')
+ query_string = force_bytes(parsed[4]).decode('iso-8859-1')
r['QUERY_STRING'] = query_string
return self.request(**r)
diff --git a/django/test/signals.py b/django/test/signals.py
index 7b105eda35..a623e756ce 100644
--- a/django/test/signals.py
+++ b/django/test/signals.py
@@ -9,7 +9,7 @@ from django.core.signals import setting_changed
from django.db import connections, router
from django.db.utils import ConnectionRouter
from django.dispatch import Signal, receiver
-from django.utils import six, timezone
+from django.utils import timezone
from django.utils.formats import FORMAT_SETTINGS, reset_format_cache
from django.utils.functional import empty
@@ -139,7 +139,7 @@ def complex_setting_changed(**kwargs):
# Considering the current implementation of the signals framework,
# this stacklevel shows the line containing the override_settings call.
warnings.warn("Overriding setting %s can lead to unexpected behavior."
- % kwargs['setting'], stacklevel=5 if six.PY2 else 6)
+ % kwargs['setting'], stacklevel=6)
@receiver(setting_changed)
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 88d355311d..7e8cee5c0d 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -775,12 +775,6 @@ class SimpleTestCase(unittest.TestCase):
standardMsg = '%s == %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
self.fail(self._formatMessage(msg, standardMsg))
- if six.PY2:
- assertCountEqual = unittest.TestCase.assertItemsEqual
- assertNotRegex = unittest.TestCase.assertNotRegexpMatches
- assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
- assertRegex = unittest.TestCase.assertRegexpMatches
-
class TransactionTestCase(SimpleTestCase):
diff --git a/django/test/utils.py b/django/test/utils.py
index b24f2e8c80..5ed32dbab5 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -6,6 +6,7 @@ import time
import warnings
from contextlib import contextmanager
from functools import wraps
+from types import SimpleNamespace
from unittest import TestCase, skipIf, skipUnless
from xml.dom.minidom import Node, parseString
@@ -25,12 +26,6 @@ from django.utils.decorators import available_attrs
from django.utils.encoding import force_str
from django.utils.translation import deactivate
-if six.PY3:
- from types import SimpleNamespace
-else:
- class SimpleNamespace(object):
- pass
-
try:
import jinja2
except ImportError:
@@ -615,7 +610,7 @@ def strip_quotes(want, got):
def str_prefix(s):
- return s % {'_': '' if six.PY3 else 'u'}
+ return s % {'_': ''}
class CaptureQueriesContext(object):
diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py
index 4a66895de5..4e8bded3db 100644
--- a/django/urls/resolvers.py
+++ b/django/urls/resolvers.py
@@ -209,11 +209,7 @@ class RegexURLPattern(LocaleRegexProvider):
callback = callback.func
if not hasattr(callback, '__name__'):
return callback.__module__ + "." + callback.__class__.__name__
- elif six.PY3:
- return callback.__module__ + "." + callback.__qualname__
- else:
- # PY2 does not support __qualname__
- return callback.__module__ + "." + callback.__name__
+ return callback.__module__ + "." + callback.__qualname__
class RegexURLResolver(LocaleRegexProvider):
diff --git a/django/utils/_os.py b/django/utils/_os.py
index 994f766d49..ddf2132f5f 100644
--- a/django/utils/_os.py
+++ b/django/utils/_os.py
@@ -1,41 +1,18 @@
import os
-import sys
import tempfile
-from os.path import abspath, dirname, isabs, join, normcase, normpath, sep
+from os.path import abspath, dirname, join, normcase, sep
from django.core.exceptions import SuspiciousFileOperation
-from django.utils import six
from django.utils.encoding import force_text
-if six.PY2:
- fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-
-# Under Python 2, define our own abspath function that can handle joining
-# unicode paths to a current working directory that has non-ASCII characters
-# in it. This isn't necessary on Windows since the Windows version of abspath
-# handles this correctly. It also handles drive letters differently than the
-# pure Python implementation, so it's best not to replace it.
-if six.PY3 or os.name == 'nt':
- abspathu = abspath
-else:
- def abspathu(path):
- """
- Version of os.path.abspath that uses the unicode representation
- of the current working directory, thus avoiding a UnicodeDecodeError
- in join when the cwd has non-ASCII characters.
- """
- if not isabs(path):
- path = join(os.getcwdu(), path)
- return normpath(path)
+abspathu = abspath
def upath(path):
"""
Always return a unicode path.
"""
- if six.PY2 and not isinstance(path, six.text_type):
- return path.decode(fs_encoding)
return path
@@ -44,8 +21,6 @@ def npath(path):
Always return a native path, that is unicode on Python 3 and bytestring on
Python 2.
"""
- if six.PY2 and not isinstance(path, bytes):
- return path.encode(fs_encoding)
return path
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
index a7257a1b3a..554958b6ee 100644
--- a/django/utils/crypto.py
+++ b/django/utils/crypto.py
@@ -9,7 +9,6 @@ import struct
import time
from django.conf import settings
-from django.utils import six
from django.utils.encoding import force_bytes
from django.utils.six.moves import range
@@ -94,7 +93,7 @@ else:
if len(val1) != len(val2):
return False
result = 0
- if six.PY3 and isinstance(val1, bytes) and isinstance(val2, bytes):
+ if isinstance(val1, bytes) and isinstance(val2, bytes):
for x, y in zip(val1, val2):
result |= x ^ y
else:
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index a95f8c351a..7367924600 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -179,7 +179,7 @@ class MultiValueDict(dict):
"""Appends an item to the internal list associated with key."""
self.setlistdefault(key).append(value)
- def _iteritems(self):
+ def items(self):
"""
Yields (key, value) pairs, where value is the last item in the list
associated with the key.
@@ -187,33 +187,15 @@ class MultiValueDict(dict):
for key in self:
yield key, self[key]
- def _iterlists(self):
+ def lists(self):
"""Yields (key, list) pairs."""
return six.iteritems(super(MultiValueDict, self))
- def _itervalues(self):
+ def values(self):
"""Yield the last value on every key list."""
for key in self:
yield self[key]
- if six.PY3:
- items = _iteritems
- lists = _iterlists
- values = _itervalues
- else:
- iteritems = _iteritems
- iterlists = _iterlists
- itervalues = _itervalues
-
- def items(self):
- return list(self.iteritems())
-
- def lists(self):
- return list(self.iterlists())
-
- def values(self):
- return list(self.itervalues())
-
def copy(self):
"""Returns a shallow copy of this object."""
return copy.copy(self)
diff --git a/django/utils/decorators.py b/django/utils/decorators.py
index 7ba31a32e3..071028930f 100644
--- a/django/utils/decorators.py
+++ b/django/utils/decorators.py
@@ -7,8 +7,6 @@ except ImportError:
from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wraps
-from django.utils import six
-
class classonlymethod(classmethod):
def __get__(self, instance, cls=None):
@@ -121,13 +119,10 @@ def decorator_from_middleware(middleware_class):
def available_attrs(fn):
"""
Return the list of functools-wrappable attributes on a callable.
- This is required as a workaround for http://bugs.python.org/issue3445
+ This was required as a workaround for http://bugs.python.org/issue3445
under Python 2.
"""
- if six.PY3:
- return WRAPPER_ASSIGNMENTS
- else:
- return tuple(a for a in WRAPPER_ASSIGNMENTS if hasattr(fn, a))
+ return WRAPPER_ASSIGNMENTS
def make_middleware_decorator(middleware_class):
diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index a3b07dcec6..f0627f5d39 100644
--- a/django/utils/encoding.py
+++ b/django/utils/encoding.py
@@ -2,13 +2,11 @@ import codecs
import datetime
import locale
from decimal import Decimal
+from urllib.parse import unquote_to_bytes
from django.utils import six
from django.utils.functional import Promise
-from django.utils.six.moves.urllib.parse import quote, unquote
-
-if six.PY3:
- from urllib.parse import unquote_to_bytes
+from django.utils.six.moves.urllib.parse import quote
class DjangoUnicodeDecodeError(UnicodeDecodeError):
@@ -66,15 +64,10 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
return s
try:
if not issubclass(type(s), six.string_types):
- if six.PY3:
- if isinstance(s, bytes):
- s = six.text_type(s, encoding, errors)
- else:
- s = six.text_type(s)
- elif hasattr(s, '__unicode__'):
- s = six.text_type(s)
+ if isinstance(s, bytes):
+ s = six.text_type(s, encoding, errors)
else:
- s = six.text_type(bytes(s), encoding, errors)
+ s = six.text_type(s)
else:
# Note: We use .decode() here, instead of six.text_type(s, encoding,
# errors), so that if s is a SafeBytes, it ends up being a
@@ -127,10 +120,7 @@ def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
return six.text_type(s).encode(encoding, errors)
if not isinstance(s, six.string_types):
try:
- if six.PY3:
- return six.text_type(s).encode(encoding)
- else:
- return bytes(s)
+ return six.text_type(s).encode(encoding)
except UnicodeEncodeError:
if isinstance(s, Exception):
# An Exception subclass containing non-ASCII data that doesn't
@@ -143,15 +133,8 @@ def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
return s.encode(encoding, errors)
-if six.PY3:
- smart_str = smart_text
- force_str = force_text
-else:
- smart_str = smart_bytes
- force_str = force_bytes
- # backwards compatibility for Python 2
- smart_unicode = smart_text
- force_unicode = force_text
+smart_str = smart_text
+force_str = force_text
smart_str.__doc__ = """
Apply smart_text in Python 3 and smart_bytes in Python 2.
@@ -207,7 +190,7 @@ def uri_to_iri(uri):
if uri is None:
return uri
uri = force_bytes(uri)
- iri = unquote_to_bytes(uri) if six.PY3 else unquote(uri)
+ iri = unquote_to_bytes(uri)
return repercent_broken_unicode(iri).decode('utf-8')
diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py
index 64aa970e93..fbab58b905 100644
--- a/django/utils/feedgenerator.py
+++ b/django/utils/feedgenerator.py
@@ -23,7 +23,7 @@ http://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/
"""
import datetime
-from django.utils import datetime_safe, six
+from django.utils import datetime_safe
from django.utils.encoding import force_text, iri_to_uri
from django.utils.six import StringIO
from django.utils.six.moves.urllib.parse import urlparse
@@ -42,8 +42,6 @@ def rfc2822_date(date):
dow = days[date.weekday()]
month = months[date.month - 1]
time_str = date.strftime('%s, %%d %s %%Y %%H:%%M:%%S ' % (dow, month))
- if six.PY2: # strftime returns a byte string in Python 2
- time_str = time_str.decode('utf-8')
offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC.
if offset is None:
@@ -58,8 +56,6 @@ def rfc3339_date(date):
# Support datetime objects older than 1900
date = datetime_safe.new_datetime(date)
time_str = date.strftime('%Y-%m-%dT%H:%M:%S')
- if six.PY2: # strftime returns a byte string in Python 2
- time_str = time_str.decode('utf-8')
offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC.
if offset is None:
diff --git a/django/utils/functional.py b/django/utils/functional.py
index 794f31047c..933085391d 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -92,16 +92,9 @@ def lazy(func, *resultclasses):
assert not (cls._delegate_bytes and cls._delegate_text), (
"Cannot call lazy() with both bytes and text return types.")
if cls._delegate_text:
- if six.PY3:
- cls.__str__ = cls.__text_cast
- else:
- cls.__unicode__ = cls.__text_cast
- cls.__str__ = cls.__bytes_cast_encoded
+ cls.__str__ = cls.__text_cast
elif cls._delegate_bytes:
- if six.PY3:
- cls.__bytes__ = cls.__bytes_cast
- else:
- cls.__str__ = cls.__bytes_cast
+ cls.__bytes__ = cls.__bytes_cast
@classmethod
def __promise__(cls, method_name):
@@ -154,9 +147,7 @@ def lazy(func, *resultclasses):
return hash(self.__cast())
def __mod__(self, rhs):
- if self._delegate_bytes and six.PY2:
- return bytes(self) % rhs
- elif self._delegate_text:
+ if self._delegate_text:
return six.text_type(self) % rhs
return self.__cast() % rhs
@@ -316,14 +307,9 @@ class LazyObject(object):
return result
return copy.deepcopy(self._wrapped, memo)
- if six.PY3:
- __bytes__ = new_method_proxy(bytes)
- __str__ = new_method_proxy(str)
- __bool__ = new_method_proxy(bool)
- else:
- __str__ = new_method_proxy(str)
- __unicode__ = new_method_proxy(unicode) # NOQA: unicode undefined on PY3
- __nonzero__ = new_method_proxy(bool)
+ __bytes__ = new_method_proxy(bytes)
+ __str__ = new_method_proxy(str)
+ __bool__ = new_method_proxy(bool)
# Introspection support
__dir__ = new_method_proxy(dir)
diff --git a/django/utils/glob.py b/django/utils/glob.py
deleted file mode 100644
index 92194d21eb..0000000000
--- a/django/utils/glob.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import os.path
-import re
-
-from django.utils import six
-
-# backport of Python 3.4's glob.escape
-
-if six.PY3:
- from glob import escape as glob_escape
-else:
- _magic_check = re.compile('([*?[])')
-
- def glob_escape(pathname):
- """
- Escape all special characters.
- """
- drive, pathname = os.path.splitdrive(pathname)
- pathname = _magic_check.sub(r'[\1]', pathname)
- return drive + pathname
diff --git a/django/utils/html.py b/django/utils/html.py
index 384093a02f..36b5d53283 100644
--- a/django/utils/html.py
+++ b/django/utils/html.py
@@ -363,22 +363,12 @@ def html_safe(klass):
"can't apply @html_safe to %s because it defines "
"__html__()." % klass.__name__
)
- if six.PY2:
- if '__unicode__' not in klass.__dict__:
- raise ValueError(
- "can't apply @html_safe to %s because it doesn't "
- "define __unicode__()." % klass.__name__
- )
- klass_unicode = klass.__unicode__
- klass.__unicode__ = lambda self: mark_safe(klass_unicode(self))
- klass.__html__ = lambda self: unicode(self) # NOQA: unicode undefined on PY3
- else:
- if '__str__' not in klass.__dict__:
- raise ValueError(
- "can't apply @html_safe to %s because it doesn't "
- "define __str__()." % klass.__name__
- )
- klass_str = klass.__str__
- klass.__str__ = lambda self: mark_safe(klass_str(self))
- klass.__html__ = lambda self: str(self)
+ if '__str__' not in klass.__dict__:
+ raise ValueError(
+ "can't apply @html_safe to %s because it doesn't "
+ "define __str__()." % klass.__name__
+ )
+ klass_str = klass.__str__
+ klass.__str__ = lambda self: mark_safe(klass_str(self))
+ klass.__html__ = lambda self: str(self)
return klass
diff --git a/django/utils/html_parser.py b/django/utils/html_parser.py
index 89646079db..d272004f77 100644
--- a/django/utils/html_parser.py
+++ b/django/utils/html_parser.py
@@ -1,4 +1,3 @@
-from django.utils import six
from django.utils.six.moves import html_parser as _html_parser
try:
@@ -8,15 +7,13 @@ except AttributeError:
class HTMLParseError(Exception):
pass
-if six.PY3:
- class HTMLParser(_html_parser.HTMLParser):
- """Explicitly set convert_charrefs to be False.
- This silences a deprecation warning on Python 3.4, but we can't do
- it at call time because Python 2.7 does not have the keyword
- argument.
- """
- def __init__(self, convert_charrefs=False, **kwargs):
- _html_parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs)
-else:
- HTMLParser = _html_parser.HTMLParser
+class HTMLParser(_html_parser.HTMLParser):
+ """Explicitly set convert_charrefs to be False.
+
+ This silences a deprecation warning on Python 3.4, but we can't do
+ it at call time because Python 2.7 does not have the keyword
+ argument.
+ """
+ def __init__(self, convert_charrefs=False, **kwargs):
+ _html_parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs)
diff --git a/django/utils/http.py b/django/utils/http.py
index f4e77b86f9..0308e14676 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -189,12 +189,7 @@ def base36_to_int(s):
# is sufficient to base36-encode any 64-bit integer)
if len(s) > 13:
raise ValueError("Base36 input too large")
- value = int(s, 36)
- # ... then do a final check that the value will fit into an int to avoid
- # returning a long (#15067). The long type was removed in Python 3.
- if six.PY2 and value > sys.maxint:
- raise ValueError("Base36 input too large")
- return value
+ return int(s, 36)
def int_to_base36(i):
@@ -204,11 +199,6 @@ def int_to_base36(i):
char_set = '0123456789abcdefghijklmnopqrstuvwxyz'
if i < 0:
raise ValueError("Negative base36 conversion input.")
- if six.PY2:
- if not isinstance(i, six.integer_types):
- raise TypeError("Non-integer base36 conversion input.")
- if i > sys.maxint:
- raise ValueError("Base36 conversion input too large.")
if i < 36:
return char_set[i]
b36 = ''
@@ -296,11 +286,6 @@ def is_safe_url(url, host=None, allowed_hosts=None, require_https=False):
url = url.strip()
if not url:
return False
- if six.PY2:
- try:
- url = force_text(url)
- except UnicodeDecodeError:
- return False
if allowed_hosts is None:
allowed_hosts = set()
if host:
@@ -388,13 +373,9 @@ def limited_parse_qsl(qs, keep_blank_values=False, encoding='utf-8',
else:
continue
if len(nv[1]) or keep_blank_values:
- if six.PY3:
- name = nv[0].replace('+', ' ')
- name = unquote(name, encoding=encoding, errors=errors)
- value = nv[1].replace('+', ' ')
- value = unquote(value, encoding=encoding, errors=errors)
- else:
- name = unquote(nv[0].replace(b'+', b' '))
- value = unquote(nv[1].replace(b'+', b' '))
+ name = nv[0].replace('+', ' ')
+ name = unquote(name, encoding=encoding, errors=errors)
+ value = nv[1].replace('+', ' ')
+ value = unquote(value, encoding=encoding, errors=errors)
r.append((name, value))
return r
diff --git a/django/utils/inspect.py b/django/utils/inspect.py
index ffcbf30407..9ef28bbf00 100644
--- a/django/utils/inspect.py
+++ b/django/utils/inspect.py
@@ -1,12 +1,7 @@
import inspect
-from django.utils import six
-
def getargspec(func):
- if six.PY2:
- return inspect.getargspec(func)
-
sig = inspect.signature(func)
args = [
p.name for p in sig.parameters.values()
@@ -30,10 +25,6 @@ def getargspec(func):
def get_func_args(func):
- if six.PY2:
- argspec = inspect.getargspec(func)
- return argspec.args[1:] # ignore 'self'
-
sig = inspect.signature(func)
return [
arg_name for arg_name, param in sig.parameters.items()
@@ -47,20 +38,6 @@ def get_func_full_args(func):
does not have a default value, omit it in the tuple. Arguments such as
*args and **kwargs are also included.
"""
- if six.PY2:
- argspec = inspect.getargspec(func)
- args = argspec.args[1:] # ignore 'self'
- defaults = argspec.defaults or []
- # Split args into two lists depending on whether they have default value
- no_default = args[:len(args) - len(defaults)]
- with_default = args[len(args) - len(defaults):]
- # Join the two lists and combine it with default values
- args = [(arg,) for arg in no_default] + zip(with_default, defaults)
- # Add possible *args and **kwargs and prepend them with '*' or '**'
- varargs = [('*' + argspec.varargs,)] if argspec.varargs else []
- kwargs = [('**' + argspec.keywords,)] if argspec.keywords else []
- return args + varargs + kwargs
-
sig = inspect.signature(func)
args = []
for arg_name, param in sig.parameters.items():
@@ -80,20 +57,6 @@ def get_func_full_args(func):
def func_accepts_kwargs(func):
- if six.PY2:
- # Not all callables are inspectable with getargspec, so we'll
- # try a couple different ways but in the end fall back on assuming
- # it is -- we don't want to prevent registration of valid but weird
- # callables.
- try:
- argspec = inspect.getargspec(func)
- except TypeError:
- try:
- argspec = inspect.getargspec(func.__call__)
- except (TypeError, AttributeError):
- argspec = None
- return not argspec or argspec[2] is not None
-
return any(
p for p in inspect.signature(func).parameters.values()
if p.kind == p.VAR_KEYWORD
@@ -104,9 +67,6 @@ def func_accepts_var_args(func):
"""
Return True if function 'func' accepts positional arguments *args.
"""
- if six.PY2:
- return inspect.getargspec(func)[1] is not None
-
return any(
p for p in inspect.signature(func).parameters.values()
if p.kind == p.VAR_POSITIONAL
@@ -114,7 +74,7 @@ def func_accepts_var_args(func):
def func_has_no_args(func):
- args = inspect.getargspec(func)[0] if six.PY2 else [
+ args = [
p for p in inspect.signature(func).parameters.values()
if p.kind == p.POSITIONAL_OR_KEYWORD
]
@@ -122,8 +82,4 @@ def func_has_no_args(func):
def func_supports_parameter(func, parameter):
- if six.PY3:
- return parameter in inspect.signature(func).parameters
- else:
- args, varargs, varkw, defaults = inspect.getargspec(func)
- return parameter in args
+ return parameter in inspect.signature(func).parameters
diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py
index 9dcbc926b9..ed2b8da635 100644
--- a/django/utils/module_loading.py
+++ b/django/utils/module_loading.py
@@ -2,6 +2,7 @@ import copy
import os
import sys
from importlib import import_module
+from importlib.util import find_spec as importlib_find
from django.utils import six
@@ -63,88 +64,17 @@ def autodiscover_modules(*args, **kwargs):
raise
-if six.PY3:
- from importlib.util import find_spec as importlib_find
-
- def module_has_submodule(package, module_name):
- """See if 'module' is in 'package'."""
- try:
- package_name = package.__name__
- package_path = package.__path__
- except AttributeError:
- # package isn't a package.
- return False
-
- full_module_name = package_name + '.' + module_name
- return importlib_find(full_module_name, package_path) is not None
-
-else:
- import imp
-
- def module_has_submodule(package, module_name):
- """See if 'module' is in 'package'."""
- name = ".".join([package.__name__, module_name])
- try:
- # None indicates a cached miss; see mark_miss() in Python/import.c.
- return sys.modules[name] is not None
- except KeyError:
- pass
- try:
- package_path = package.__path__ # No __path__, then not a package.
- except AttributeError:
- # Since the remainder of this function assumes that we're dealing with
- # a package (module with a __path__), so if it's not, then bail here.
- return False
- for finder in sys.meta_path:
- if finder.find_module(name, package_path):
- return True
- for entry in package_path:
- try:
- # Try the cached finder.
- finder = sys.path_importer_cache[entry]
- if finder is None:
- # Implicit import machinery should be used.
- try:
- file_, _, _ = imp.find_module(module_name, [entry])
- if file_:
- file_.close()
- return True
- except ImportError:
- continue
- # Else see if the finder knows of a loader.
- elif finder.find_module(name):
- return True
- else:
- continue
- except KeyError:
- # No cached finder, so try and make one.
- for hook in sys.path_hooks:
- try:
- finder = hook(entry)
- # XXX Could cache in sys.path_importer_cache
- if finder.find_module(name):
- return True
- else:
- # Once a finder is found, stop the search.
- break
- except ImportError:
- # Continue the search for a finder.
- continue
- else:
- # No finder found.
- # Try the implicit import machinery if searching a directory.
- if os.path.isdir(entry):
- try:
- file_, _, _ = imp.find_module(module_name, [entry])
- if file_:
- file_.close()
- return True
- except ImportError:
- pass
- # XXX Could insert None or NullImporter
- else:
- # Exhausted the search, so the module cannot be found.
- return False
+def module_has_submodule(package, module_name):
+ """See if 'module' is in 'package'."""
+ try:
+ package_name = package.__name__
+ package_path = package.__path__
+ except AttributeError:
+ # package isn't a package.
+ return False
+
+ full_module_name = package_name + '.' + module_name
+ return importlib_find(full_module_name, package_path) is not None
def module_dir(module):
diff --git a/django/utils/safestring.py b/django/utils/safestring.py
index 4355a050a0..3f4b3d48fd 100644
--- a/django/utils/safestring.py
+++ b/django/utils/safestring.py
@@ -83,12 +83,7 @@ class SafeText(six.text_type, SafeData):
encode = curry(_proxy_method, method=six.text_type.encode)
-if six.PY3:
- SafeString = SafeText
-else:
- SafeString = SafeBytes
- # backwards compatibility for Python 2
- SafeUnicode = SafeText
+SafeString = SafeText
def _safety_decorator(safety_marker, func):
diff --git a/django/utils/text.py b/django/utils/text.py
index dcedc524b0..fc8677cf4e 100644
--- a/django/utils/text.py
+++ b/django/utils/text.py
@@ -12,11 +12,6 @@ from django.utils.safestring import SafeText, mark_safe
from django.utils.six.moves import html_entities
from django.utils.translation import pgettext, ugettext as _, ugettext_lazy
-if six.PY2:
- # Import force_unicode even though this module doesn't use it, because some
- # people rely on it being here.
- from django.utils.encoding import force_unicode # NOQA
-
@keep_lazy_text
def capfirst(x):
diff --git a/django/utils/translation/template.py b/django/utils/translation/template.py
index 04dac65e90..b6d8832f9c 100644
--- a/django/utils/translation/template.py
+++ b/django/utils/translation/template.py
@@ -5,7 +5,6 @@ from django.template.base import (
TOKEN_BLOCK, TOKEN_COMMENT, TOKEN_TEXT, TOKEN_VAR, TRANSLATOR_COMMENT_MARK,
Lexer,
)
-from django.utils import six
from django.utils.encoding import force_text
from django.utils.six import StringIO
@@ -57,7 +56,7 @@ def templatize(src, origin=None, charset='utf-8'):
comment_lineno_cache = None
# Adding the u prefix allows gettext to recognize the Unicode string
# (#26093).
- raw_prefix = 'u' if six.PY3 else ''
+ raw_prefix = 'u'
def join_tokens(tokens, trim=False):
message = ''.join(tokens)
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 9f016e8524..aca57ded0e 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -13,7 +13,7 @@ from django.conf.locale import LANG_INFO
from django.core.exceptions import AppRegistryNotReady
from django.core.signals import setting_changed
from django.dispatch import receiver
-from django.utils import lru_cache, six
+from django.utils import lru_cache
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.safestring import SafeData, mark_safe
@@ -336,11 +336,7 @@ def gettext(message):
return do_translate(message, 'gettext')
-if six.PY3:
- ugettext = gettext
-else:
- def ugettext(message):
- return do_translate(message, 'ugettext')
+ugettext = gettext
def pgettext(context, message):
@@ -384,15 +380,7 @@ def ngettext(singular, plural, number):
return do_ntranslate(singular, plural, number, 'ngettext')
-if six.PY3:
- ungettext = ngettext
-else:
- def ungettext(singular, plural, number):
- """
- Returns a unicode strings of the translation of either the singular or
- plural, based on the number.
- """
- return do_ntranslate(singular, plural, number, 'ungettext')
+ungettext = ngettext
def npgettext(context, singular, plural, number):
diff --git a/django/views/debug.py b/django/views/debug.py
index 7c33aa8eca..2390995b56 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -399,11 +399,9 @@ class ExceptionReporter(object):
if not exceptions:
return frames
- # In case there's just one exception (always in Python 2,
- # sometimes in Python 3), take the traceback from self.tb (Python 2
- # doesn't have a __traceback__ attribute on Exception)
+ # In case there's just one exception, take the traceback from self.tb
exc_value = exceptions.pop()
- tb = self.tb if six.PY2 or not exceptions else exc_value.__traceback__
+ tb = self.tb if not exceptions else exc_value.__traceback__
while tb is not None:
# Support for __traceback_hide__ which is used by a few libraries
@@ -438,9 +436,7 @@ class ExceptionReporter(object):
# If the traceback for current exception is consumed, try the
# other exception.
- if six.PY2:
- tb = tb.tb_next
- elif not tb.tb_next and exceptions:
+ if not tb.tb_next and exceptions:
exc_value = exceptions.pop()
tb = exc_value.__traceback__
else:
diff --git a/setup.cfg b/setup.cfg
index 9d336981dd..c1ff45c56a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -3,7 +3,7 @@ doc_files = docs extras AUTHORS INSTALL LICENSE README.rst
install-script = scripts/rpm-install.sh
[flake8]
-exclude = build,.git,.tox,./django/utils/lru_cache.py,./django/utils/six.py,./django/conf/app_template/*,./django/dispatch/weakref_backports.py,./tests/.env,./xmlrunner,tests/view_tests/tests/py3_test_debug.py,tests/template_tests/annotated_tag_function.py
+exclude = build,.git,.tox,./django/utils/lru_cache.py,./django/utils/six.py,./django/conf/app_template/*,./tests/.env,./xmlrunner
ignore = W601
max-line-length = 119
diff --git a/tests/admin_docs/test_views.py b/tests/admin_docs/test_views.py
index 9f7f0ee268..34f6af6cdc 100644
--- a/tests/admin_docs/test_views.py
+++ b/tests/admin_docs/test_views.py
@@ -10,7 +10,6 @@ from django.db.models import fields
from django.test import SimpleTestCase, modify_settings, override_settings
from django.test.utils import captured_stderr
from django.urls import reverse
-from django.utils import six
from .models import Company, Person
from .tests import AdminDocsTestCase, TestDataMixin
@@ -53,7 +52,6 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase):
self.assertContains(response, 'Views by namespace test')
self.assertContains(response, 'Name: <code>test:func</code>.')
- @unittest.skipIf(six.PY2, "Python 2 doesn't support __qualname__.")
def test_view_index_with_method(self):
"""
Views that are methods are listed correctly.
@@ -89,7 +87,7 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase):
"""
url = reverse('django-admindocs-views-detail', args=['django.contrib.admin.sites.AdminSite.index'])
response = self.client.get(url)
- self.assertEqual(response.status_code, 200 if six.PY3 else 404)
+ self.assertEqual(response.status_code, 200)
def test_model_index(self):
response = self.client.get(reverse('django-admindocs-models-index'))
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py
index 08fe645535..e37e8a4256 100644
--- a/tests/admin_scripts/tests.py
+++ b/tests/admin_scripts/tests.py
@@ -27,7 +27,7 @@ from django.test import (
)
from django.utils._os import npath, upath
from django.utils.encoding import force_text
-from django.utils.six import PY2, StringIO
+from django.utils.six import StringIO
custom_templates_dir = os.path.join(os.path.dirname(upath(__file__)), 'custom_templates')
@@ -626,7 +626,6 @@ class DjangoAdminSettingsDirectory(AdminScriptTestCase):
self.assertTrue(os.path.exists(app_path))
self.assertTrue(os.path.exists(os.path.join(app_path, 'api.py')))
- @unittest.skipIf(PY2, "Python 2 doesn't support Unicode package names.")
def test_startapp_unicode_name(self):
"directory: startapp creates the correct directory with unicode characters"
args = ['startapp', 'こんにちは']
@@ -1897,18 +1896,11 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
self.addCleanup(shutil.rmtree, testproject_dir, True)
out, err = self.run_django_admin(args)
- if PY2:
- self.assertOutput(
- err,
- "Error: '%s' is not a valid project name. Please make "
- "sure the name begins with a letter or underscore." % bad_name
- )
- else:
- self.assertOutput(
- err,
- "Error: '%s' is not a valid project name. Please make "
- "sure the name is a valid identifier." % bad_name
- )
+ self.assertOutput(
+ err,
+ "Error: '%s' is not a valid project name. Please make "
+ "sure the name is a valid identifier." % bad_name
+ )
self.assertFalse(os.path.exists(testproject_dir))
def test_simple_project_different_directory(self):
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index bffac69e21..65886b2063 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -8,7 +8,6 @@ from django.db.models import (
)
from django.db.models.functions import Lower
from django.test import TestCase, skipUnlessDBFeature
-from django.utils import six
from .models import (
Author, Book, Company, DepartmentStore, Employee, Publisher, Store, Ticket,
@@ -24,7 +23,7 @@ def cxOracle_py3_bug(func):
"""
from unittest import expectedFailure
from django.db import connection
- return expectedFailure(func) if connection.vendor == 'oracle' and six.PY3 else func
+ return expectedFailure(func) if connection.vendor == 'oracle' else func
class NonAggregateAnnotationTestCase(TestCase):
diff --git a/tests/apps/tests.py b/tests/apps/tests.py
index d2adc681f2..9576420b54 100644
--- a/tests/apps/tests.py
+++ b/tests/apps/tests.py
@@ -1,5 +1,4 @@
import os
-from unittest import skipUnless
from django.apps import AppConfig, apps
from django.apps.registry import Apps
@@ -8,7 +7,6 @@ from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
from django.db import models
from django.test import SimpleTestCase, override_settings
from django.test.utils import extend_sys_path, isolate_apps
-from django.utils import six
from django.utils._os import upath
from .default_config_app.apps import CustomConfig
@@ -371,7 +369,6 @@ class AppConfigTests(SimpleTestCase):
self.assertEqual(ac.path, 'a')
-@skipUnless(six.PY3, "Namespace packages sans __init__.py were added in Python 3.3")
class NamespacePackageAppTests(SimpleTestCase):
# We need nsapp to be top-level so our multiple-paths tests can add another
# location for it (if its inside a normal package with an __init__.py that
diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py
index 36b4e8f4e7..c055b58042 100644
--- a/tests/auth_tests/test_forms.py
+++ b/tests/auth_tests/test_forms.py
@@ -1,6 +1,5 @@
import datetime
import re
-from unittest import skipIf
from django import forms
from django.contrib.auth.forms import (
@@ -15,7 +14,7 @@ from django.core import mail
from django.core.mail import EmailMultiAlternatives
from django.forms.fields import CharField, Field, IntegerField
from django.test import SimpleTestCase, TestCase, mock, override_settings
-from django.utils import six, translation
+from django.utils import translation
from django.utils.encoding import force_text
from django.utils.text import capfirst
from django.utils.translation import ugettext as _
@@ -114,14 +113,10 @@ class UserCreationFormTest(TestDataMixin, TestCase):
'password2': 'test123',
}
form = UserCreationForm(data)
- if six.PY3:
- self.assertTrue(form.is_valid())
- u = form.save()
- self.assertEqual(u.username, '宝')
- else:
- self.assertFalse(form.is_valid())
+ self.assertTrue(form.is_valid())
+ u = form.save()
+ self.assertEqual(u.username, '宝')
- @skipIf(six.PY2, "Python 2 doesn't support unicode usernames by default.")
def test_normalize_username(self):
# The normalization happens in AbstractBaseUser.clean() and ModelForm
# validation calls Model.clean().
@@ -137,7 +132,6 @@ class UserCreationFormTest(TestDataMixin, TestCase):
self.assertNotEqual(user.username, ohm_username)
self.assertEqual(user.username, 'testΩ') # U+03A9 GREEK CAPITAL LETTER OMEGA
- @skipIf(six.PY2, "Python 2 doesn't support unicode usernames by default.")
def test_duplicate_normalized_unicode(self):
"""
To prevent almost identical usernames, visually identical but differing
diff --git a/tests/auth_tests/test_management.py b/tests/auth_tests/test_management.py
index eaceafb444..ac57bbd511 100644
--- a/tests/auth_tests/test_management.py
+++ b/tests/auth_tests/test_management.py
@@ -32,9 +32,6 @@ def mock_inputs(inputs):
class mock_getpass:
@staticmethod
def getpass(prompt=b'Password: ', stream=None):
- if six.PY2:
- # getpass on Windows only supports prompt as bytestring (#19807)
- assert isinstance(prompt, six.binary_type)
if callable(inputs['password']):
return inputs['password']()
return inputs['password']
diff --git a/tests/auth_tests/test_tokens.py b/tests/auth_tests/test_tokens.py
index 7ff3f15f3d..0662ec513e 100644
--- a/tests/auth_tests/test_tokens.py
+++ b/tests/auth_tests/test_tokens.py
@@ -1,11 +1,9 @@
-import unittest
from datetime import date, timedelta
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.test import TestCase
-from django.utils.six import PY3
class TokenGeneratorTest(TestCase):
@@ -51,18 +49,6 @@ class TokenGeneratorTest(TestCase):
p2 = Mocked(date.today() + timedelta(settings.PASSWORD_RESET_TIMEOUT_DAYS + 1))
self.assertFalse(p2.check_token(user, tk1))
- @unittest.skipIf(PY3, "Unnecessary test with Python 3")
- def test_date_length(self):
- """
- Overly long dates, which are a potential DoS vector, aren't allowed.
- """
- user = User.objects.create_user('ima1337h4x0r', 'test4@example.com', 'p4ssw0rd')
- p0 = PasswordResetTokenGenerator()
-
- # This will put a 14-digit base36 timestamp into the token, which is too large.
- with self.assertRaises(ValueError):
- p0._make_token_with_timestamp(user, 175455491841851871349)
-
def test_check_token_with_nonexistent_token_and_user(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
p0 = PasswordResetTokenGenerator()
diff --git a/tests/backends/test_utils.py b/tests/backends/test_utils.py
index 6f59d1b23b..d158e2a5a2 100644
--- a/tests/backends/test_utils.py
+++ b/tests/backends/test_utils.py
@@ -1,7 +1,6 @@
from django.core.exceptions import ImproperlyConfigured
from django.db.utils import load_backend
from django.test import SimpleTestCase
-from django.utils import six
class TestLoadBackend(SimpleTestCase):
@@ -10,7 +9,7 @@ class TestLoadBackend(SimpleTestCase):
"'foo' isn't an available database backend.\n"
"Try using 'django.db.backends.XXX', where XXX is one of:\n"
" 'mysql', 'oracle', 'postgresql', 'sqlite3'\n"
- "Error was: No module named %s"
- ) % "foo.base" if six.PY2 else "'foo'"
+ "Error was: No module named 'foo'"
+ )
with self.assertRaisesMessage(ImproperlyConfigured, msg):
load_backend('foo')
diff --git a/tests/base/models.py b/tests/base/models.py
index 077b93fbb8..fb91522717 100644
--- a/tests/base/models.py
+++ b/tests/base/models.py
@@ -13,12 +13,3 @@ class CustomBaseModel(models.base.ModelBase):
class MyModel(six.with_metaclass(CustomBaseModel, models.Model)):
"""Model subclass with a custom base using six.with_metaclass."""
-
-
-# This is done to ensure that for Python2 only, defining metaclasses
-# still does not fail to create the model.
-
-if six.PY2:
- class MyPython2Model(models.Model):
- """Model subclass with a custom base using __metaclass__."""
- __metaclass__ = CustomBaseModel
diff --git a/tests/cache/tests.py b/tests/cache/tests.py
index 5be3db0ef4..caeb8a47df 100644
--- a/tests/cache/tests.py
+++ b/tests/cache/tests.py
@@ -928,11 +928,7 @@ class BaseCacheTests(object):
self.assertEqual(cache.get_or_set('mykey', my_callable()), 'value')
def test_get_or_set_version(self):
- msg = (
- "get_or_set() missing 1 required positional argument: 'default'"
- if six.PY3
- else 'get_or_set() takes at least 3 arguments'
- )
+ msg = "get_or_set() missing 1 required positional argument: 'default'"
cache.get_or_set('brian', 1979, version=2)
with self.assertRaisesMessage(TypeError, msg):
cache.get_or_set('brian')
diff --git a/tests/dbshell/test_postgresql_psycopg2.py b/tests/dbshell/test_postgresql_psycopg2.py
index 4c4a1ae25e..755464b3bb 100644
--- a/tests/dbshell/test_postgresql_psycopg2.py
+++ b/tests/dbshell/test_postgresql_psycopg2.py
@@ -3,7 +3,6 @@ import os
from django.db.backends.postgresql.client import DatabaseClient
from django.test import SimpleTestCase, mock
-from django.utils import six
from django.utils.encoding import force_bytes, force_str
@@ -91,16 +90,12 @@ class PostgreSqlDbshellCommandTestCase(SimpleTestCase):
encoding = locale.getpreferredencoding()
username = 'rôle'
password = 'sésame'
- try:
- username_str = force_str(username, encoding)
- password_str = force_str(password, encoding)
- pgpass_bytes = force_bytes(
- 'somehost:444:dbname:%s:%s' % (username, password),
- encoding=encoding,
- )
- except UnicodeEncodeError:
- if six.PY2:
- self.skipTest("Your locale can't run this test.")
+ username_str = force_str(username, encoding)
+ password_str = force_str(password, encoding)
+ pgpass_bytes = force_bytes(
+ 'somehost:444:dbname:%s:%s' % (username, password),
+ encoding=encoding,
+ )
self.assertEqual(
self._run_it({
'database': 'dbname',
diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py
index 769c06c904..f9cecf96a2 100644
--- a/tests/file_uploads/tests.py
+++ b/tests/file_uploads/tests.py
@@ -15,7 +15,7 @@ from django.http.multipartparser import MultiPartParser, parse_header
from django.test import SimpleTestCase, TestCase, client, override_settings
from django.utils.encoding import force_bytes
from django.utils.http import urlquote
-from django.utils.six import PY2, StringIO
+from django.utils.six import StringIO
from . import uploadhandler
from .models import FileModel
@@ -102,9 +102,7 @@ class FileUploadTests(TestCase):
self._test_base64_upload("Big data" * 68000) # > 512Kb
def test_big_base64_newlines_upload(self):
- self._test_base64_upload(
- # encodestring is a deprecated alias on Python 3
- "Big data" * 68000, encode=base64.encodestring if PY2 else base64.encodebytes)
+ self._test_base64_upload("Big data" * 68000, encode=base64.encodebytes)
def test_unicode_file_name(self):
tdir = sys_tempfile.mkdtemp()
diff --git a/tests/files/tests.py b/tests/files/tests.py
index 276cbed544..a0ff3d4782 100644
--- a/tests/files/tests.py
+++ b/tests/files/tests.py
@@ -181,10 +181,7 @@ class ContentFileTestCase(unittest.TestCase):
retrieved content is of the same type.
"""
self.assertIsInstance(ContentFile(b"content").read(), bytes)
- if six.PY3:
- self.assertIsInstance(ContentFile("español").read(), six.text_type)
- else:
- self.assertIsInstance(ContentFile("español").read(), bytes)
+ self.assertIsInstance(ContentFile("español").read(), six.text_type)
class DimensionClosingBug(unittest.TestCase):
diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py
index 3667fcbd4c..7ea9e6cc3e 100644
--- a/tests/fixtures_regress/tests.py
+++ b/tests/fixtures_regress/tests.py
@@ -2,10 +2,8 @@
import json
import os
import re
-import unittest
import warnings
-import django
from django.core import management, serializers
from django.core.exceptions import ImproperlyConfigured
from django.core.serializers.base import DeserializationError
@@ -15,9 +13,8 @@ from django.test import (
TestCase, TransactionTestCase, override_settings, skipIfDBFeature,
skipUnlessDBFeature,
)
-from django.utils import six
from django.utils._os import upath
-from django.utils.six import PY3, StringIO
+from django.utils.six import StringIO
from .models import (
Absolute, Animal, Article, Book, Child, Circle1, Circle2, Circle3,
@@ -32,16 +29,6 @@ from .models import (
_cur_dir = os.path.dirname(os.path.abspath(upath(__file__)))
-def is_ascii(s):
- return all(ord(c) < 128 for c in s)
-
-
-skipIfNonASCIIPath = unittest.skipIf(
- not is_ascii(django.__file__) and six.PY2,
- 'Python 2 crashes when checking non-ASCII exception messages.'
-)
-
-
class TestFixtures(TestCase):
def animal_pre_save_check(self, signal, sender, instance, **kwargs):
@@ -205,7 +192,6 @@ class TestFixtures(TestCase):
verbosity=0,
)
- @skipIfNonASCIIPath
@override_settings(SERIALIZATION_MODULES={'unkn': 'unexistent.path'})
def test_unimportable_serializer(self):
"""
@@ -350,8 +336,8 @@ class TestFixtures(TestCase):
self.assertEqual(
self.pre_save_checks,
[
- ("Count = 42 (<%s 'int'>)" % ('class' if PY3 else 'type'),
- "Weight = 1.2 (<%s 'float'>)" % ('class' if PY3 else 'type'))
+ ("Count = 42 (<class 'int'>)",
+ "Weight = 1.2 (<class 'float'>)")
]
)
finally:
@@ -531,7 +517,6 @@ class TestFixtures(TestCase):
with self.assertRaisesMessage(ImproperlyConfigured, "settings.FIXTURE_DIRS contains duplicates."):
management.call_command('loaddata', 'absolute.json', verbosity=0)
- @skipIfNonASCIIPath
@override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures')])
def test_fixture_dirs_with_default_fixture_path(self):
"""
diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py
index bae2043918..72ba98b1d3 100644
--- a/tests/handlers/tests.py
+++ b/tests/handlers/tests.py
@@ -34,7 +34,7 @@ class HandlerTests(SimpleTestCase):
produces a 404.
"""
environ = RequestFactory().get('/').environ
- environ['PATH_INFO'] = b'\xed' if six.PY2 else '\xed'
+ environ['PATH_INFO'] = '\xed'
handler = WSGIHandler()
response = handler(environ, lambda *a, **k: None)
# The path of the request will be encoded to '/%ED'.
@@ -53,25 +53,17 @@ class HandlerTests(SimpleTestCase):
]
got = []
for raw_query_string in raw_query_strings:
- if six.PY3:
- # Simulate http.server.BaseHTTPRequestHandler.parse_request handling of raw request
- environ['QUERY_STRING'] = str(raw_query_string, 'iso-8859-1')
- else:
- environ['QUERY_STRING'] = raw_query_string
+ # Simulate http.server.BaseHTTPRequestHandler.parse_request handling of raw request
+ environ['QUERY_STRING'] = str(raw_query_string, 'iso-8859-1')
request = WSGIRequest(environ)
got.append(request.GET['want'])
- if six.PY2:
- self.assertListEqual(got, ['café', 'café', 'café', 'café'])
- else:
- # On Python 3, %E9 is converted to the unicode replacement character by parse_qsl
- self.assertListEqual(got, ['café', 'café', 'caf\ufffd', 'café'])
+ # %E9 is converted to the unicode replacement character by parse_qsl
+ self.assertListEqual(got, ['café', 'café', 'caf\ufffd', 'café'])
def test_non_ascii_cookie(self):
"""Non-ASCII cookies set in JavaScript are properly decoded (#20557)."""
environ = RequestFactory().get('/').environ
- raw_cookie = 'want="café"'
- if six.PY3:
- raw_cookie = raw_cookie.encode('utf-8').decode('iso-8859-1')
+ raw_cookie = 'want="café"'.encode('utf-8').decode('iso-8859-1')
environ['HTTP_COOKIE'] = raw_cookie
request = WSGIRequest(environ)
# If would be nicer if request.COOKIES returned unicode values.
diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py
index d9885ea40c..9042f8ed6e 100644
--- a/tests/httpwrappers/tests.py
+++ b/tests/httpwrappers/tests.py
@@ -55,8 +55,6 @@ class QueryDictTests(SimpleTestCase):
def test_immutable_basic_operations(self):
q = QueryDict()
self.assertEqual(q.getlist('foo'), [])
- if six.PY2:
- self.assertIs(q.has_key('foo'), False)
self.assertNotIn('foo', q)
self.assertEqual(list(six.iteritems(q)), [])
self.assertEqual(list(six.iterlists(q)), [])
@@ -85,11 +83,7 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError):
q.appendlist('foo', ['bar'])
- if six.PY2:
- self.assertTrue(q.has_key('foo'))
self.assertIn('foo', q)
- if six.PY2:
- self.assertFalse(q.has_key('bar'))
self.assertNotIn('bar', q)
self.assertEqual(list(six.iteritems(q)), [('foo', 'bar')])
@@ -150,8 +144,6 @@ class QueryDictTests(SimpleTestCase):
q.appendlist('foo', 'another')
self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another'])
self.assertEqual(q['foo'], 'another')
- if six.PY2:
- self.assertTrue(q.has_key('foo'))
self.assertIn('foo', q)
self.assertListEqual(sorted(six.iteritems(q)),
@@ -199,11 +191,7 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError):
q.appendlist('foo', ['bar'])
- if six.PY2:
- self.assertIs(q.has_key('vote'), True)
self.assertIn('vote', q)
- if six.PY2:
- self.assertIs(q.has_key('foo'), False)
self.assertNotIn('foo', q)
self.assertEqual(list(six.iteritems(q)), [('vote', 'no')])
self.assertEqual(list(six.iterlists(q)), [('vote', ['yes', 'no'])])
@@ -224,19 +212,6 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError):
q.__delitem__('vote')
- if six.PY2:
- def test_invalid_input_encoding(self):
- """
- QueryDicts must be able to handle invalid input encoding (in this
- case, bad UTF-8 encoding), falling back to ISO-8859-1 decoding.
-
- This test doesn't apply under Python 3 because the URL is a string
- and not a bytestring.
- """
- q = QueryDict(str(b'foo=bar&foo=\xff'))
- self.assertEqual(q['foo'], '\xff')
- self.assertEqual(q.getlist('foo'), ['bar', '\xff'])
-
def test_pickle(self):
q = QueryDict()
q1 = pickle.loads(pickle.dumps(q, 2))
@@ -807,15 +782,6 @@ class CookieTests(unittest.TestCase):
c.load({'name': 'val'})
self.assertEqual(c['name'].value, 'val')
- @unittest.skipUnless(six.PY2, "PY3 throws an exception on invalid cookie keys.")
- def test_bad_cookie(self):
- """
- Regression test for #18403
- """
- r = HttpResponse()
- r.set_cookie("a:.b/", 1)
- self.assertEqual(len(r.cookies.bad_cookies), 1)
-
def test_pickle(self):
rawdata = 'Customer="WILE_E_COYOTE"; Path=/acme; Version=1'
expected_output = 'Set-Cookie: %s' % rawdata
diff --git a/tests/i18n/test_compilation.py b/tests/i18n/test_compilation.py
index d17078e290..3f3bf773bf 100644
--- a/tests/i18n/test_compilation.py
+++ b/tests/i18n/test_compilation.py
@@ -12,7 +12,7 @@ from django.core.management.commands.makemessages import \
from django.core.management.utils import find_command
from django.test import SimpleTestCase, mock, override_settings
from django.test.utils import captured_stderr, captured_stdout
-from django.utils import six, translation
+from django.utils import translation
from django.utils.encoding import force_text
from django.utils.six import StringIO
from django.utils.translation import ugettext
@@ -144,18 +144,11 @@ class CompilationErrorHandling(MessageCompilationTests):
env = os.environ.copy()
env.update({str('LANG'): str('C')})
with mock.patch('django.core.management.utils.Popen', lambda *args, **kwargs: Popen(*args, env=env, **kwargs)):
- if six.PY2:
- # Various assertRaises on PY2 don't support unicode error messages.
- try:
- call_command('compilemessages', locale=['ko'], verbosity=0)
- except CommandError as err:
- self.assertIn("' cannot start a field name", six.text_type(err))
- else:
- cmd = MakeMessagesCommand()
- if cmd.gettext_version < (0, 18, 3):
- self.skipTest("python-brace-format is a recent gettext addition.")
- with self.assertRaisesMessage(CommandError, "' cannot start a field name"):
- call_command('compilemessages', locale=['ko'], verbosity=0)
+ cmd = MakeMessagesCommand()
+ if cmd.gettext_version < (0, 18, 3):
+ self.skipTest("python-brace-format is a recent gettext addition.")
+ with self.assertRaisesMessage(CommandError, "' cannot start a field name"):
+ call_command('compilemessages', locale=['ko'], verbosity=0)
class ProjectAndAppTests(MessageCompilationTests):
diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py
index 2b9793109b..d039d016ce 100644
--- a/tests/i18n/tests.py
+++ b/tests/i18n/tests.py
@@ -6,7 +6,6 @@ import pickle
from contextlib import contextmanager
from importlib import import_module
from threading import local
-from unittest import skipUnless
from django import forms
from django.conf import settings
@@ -23,13 +22,11 @@ from django.utils.formats import (
)
from django.utils.numberformat import format as nformat
from django.utils.safestring import SafeBytes, SafeText
-from django.utils.six import PY3
from django.utils.translation import (
LANGUAGE_SESSION_KEY, activate, check_for_language, deactivate,
- get_language, get_language_from_request, get_language_info, gettext,
- gettext_lazy, ngettext_lazy, npgettext, npgettext_lazy, pgettext,
- pgettext_lazy, trans_real, ugettext, ugettext_lazy, ungettext,
- ungettext_lazy,
+ get_language, get_language_from_request, get_language_info, gettext_lazy,
+ ngettext_lazy, npgettext, npgettext_lazy, pgettext, trans_real, ugettext,
+ ugettext_lazy, ungettext, ungettext_lazy,
)
from .forms import CompanyForm, I18nForm, SelectDateForm
@@ -141,33 +138,6 @@ class TranslationTests(SimpleTestCase):
s4 = ugettext_lazy('Some other string')
self.assertNotEqual(s, s4)
- @skipUnless(six.PY2, "No more bytestring translations on PY3")
- def test_bytestrings(self):
- """gettext() returns a bytestring if input is bytestring."""
-
- # Using repr() to check translated text and type
- self.assertEqual(repr(gettext(b"Time")), repr(b"Time"))
- self.assertEqual(repr(gettext("Time")), repr("Time"))
-
- with translation.override('de', deactivate=True):
- self.assertEqual(repr(gettext(b"Time")), repr(b"Zeit"))
- self.assertEqual(repr(gettext("Time")), repr(b"Zeit"))
-
- @skipUnless(six.PY2, "No more bytestring translations on PY3")
- def test_lazy_and_bytestrings(self):
- # On Python 2, (n)gettext_lazy should not transform a bytestring to unicode
- self.assertEqual(gettext_lazy(b"test").upper(), b"TEST")
- self.assertEqual((ngettext_lazy(b"%d test", b"%d tests") % 1).upper(), b"1 TEST")
-
- # Other versions of lazy functions always return unicode
- self.assertEqual(ugettext_lazy(b"test").upper(), "TEST")
- self.assertEqual((ungettext_lazy(b"%d test", b"%d tests") % 1).upper(), "1 TEST")
- self.assertEqual(pgettext_lazy(b"context", b"test").upper(), "TEST")
- self.assertEqual(
- (npgettext_lazy(b"context", b"%d test", b"%d tests") % 1).upper(),
- "1 TEST"
- )
-
def test_lazy_pickle(self):
s1 = ugettext_lazy("test")
self.assertEqual(six.text_type(s1), "test")
@@ -223,20 +193,6 @@ class TranslationTests(SimpleTestCase):
with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'):
complex_context_deferred % {'name': 'Jim'}
- @skipUnless(six.PY2, "PY3 doesn't have distinct int and long types")
- def test_ungettext_lazy_long(self):
- """
- Regression test for #22820: int and long should be treated alike in ungettext_lazy.
- """
- result = ungettext_lazy('%(name)s has %(num)d good result', '%(name)s has %(num)d good results', 4)
- self.assertEqual(result % {'name': 'Joe', 'num': 4}, "Joe has 4 good results")
- # Now with a long
- result = ungettext_lazy(
- '%(name)s has %(num)d good result', '%(name)s has %(num)d good results',
- long(4) # NOQA: long undefined on PY3
- )
- self.assertEqual(result % {'name': 'Joe', 'num': 4}, "Joe has 4 good results")
-
def test_ungettext_lazy_bool(self):
self.assertTrue(ungettext_lazy('%d good result', '%d good results'))
self.assertFalse(ungettext_lazy('', ''))
@@ -298,7 +254,7 @@ class FormattingTests(SimpleTestCase):
self.d = datetime.date(2009, 12, 31)
self.dt = datetime.datetime(2009, 12, 31, 20, 50)
self.t = datetime.time(10, 15, 48)
- self.long = 10000 if PY3 else long(10000) # NOQA: long undefined on PY3
+ self.long = 10000
self.ctxt = Context({
'n': self.n,
't': self.t,
diff --git a/tests/inspectdb/tests.py b/tests/inspectdb/tests.py
index 1293ff68ac..8f17735929 100644
--- a/tests/inspectdb/tests.py
+++ b/tests/inspectdb/tests.py
@@ -5,7 +5,7 @@ from django.core.management import call_command
from django.db import connection
from django.test import TestCase, mock, skipUnlessDBFeature
from django.utils.encoding import force_text
-from django.utils.six import PY3, StringIO
+from django.utils.six import StringIO
from .models import ColumnTypes
@@ -196,11 +196,7 @@ class InspectDBTestCase(TestCase):
self.assertIn("field_field_0 = models.IntegerField(db_column='%s__')" % base_name, output)
self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", output)
self.assertIn("prc_x = models.IntegerField(db_column='prc(%) x')", output)
- if PY3:
- # Python 3 allows non-ASCII identifiers
- self.assertIn("tamaño = models.IntegerField()", output)
- else:
- self.assertIn("tama_o = models.IntegerField(db_column='tama\\xf1o')", output)
+ self.assertIn("tamaño = models.IntegerField()", output)
def test_table_name_introspection(self):
"""
diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py
index 5fd76229e9..384d1fa03e 100644
--- a/tests/invalid_models_tests/test_relative_fields.py
+++ b/tests/invalid_models_tests/test_relative_fields.py
@@ -3,7 +3,6 @@ from django.db import models
from django.db.models.fields.related import ForeignObject
from django.test.testcases import SimpleTestCase, skipIfDBFeature
from django.test.utils import isolate_apps, override_settings
-from django.utils import six
@isolate_apps('invalid_models_tests')
@@ -655,10 +654,8 @@ class RelativeFieldTests(SimpleTestCase):
'with', # a Python keyword
'related_name\n',
'',
+ ',', # non-ASCII
]
- # Python 2 crashes on non-ASCII strings.
- if six.PY3:
- invalid_related_names.append(',')
class Parent(models.Model):
pass
@@ -695,10 +692,9 @@ class RelativeFieldTests(SimpleTestCase):
'ends_with_plus+',
'_+',
'+',
+ '試',
+ '試驗+',
]
- # Python 2 crashes on non-ASCII strings.
- if six.PY3:
- related_names.extend(['試', '試驗+'])
class Parent(models.Model):
pass
diff --git a/tests/mail/tests.py b/tests/mail/tests.py
index ba7ff44714..cfe2889aa6 100644
--- a/tests/mail/tests.py
+++ b/tests/mail/tests.py
@@ -8,8 +8,10 @@ import socket
import sys
import tempfile
import threading
+from email import message_from_binary_file, message_from_bytes
from email.header import Header
from email.mime.text import MIMEText
+from email.utils import parseaddr
from smtplib import SMTP, SMTPAuthenticationError, SMTPException
from ssl import SSLError
@@ -24,19 +26,9 @@ from django.test import SimpleTestCase, override_settings
from django.test.utils import requires_tz_support
from django.utils._os import upath
from django.utils.encoding import force_bytes, force_text
-from django.utils.six import PY3, StringIO, binary_type
+from django.utils.six import StringIO, binary_type
from django.utils.translation import ugettext_lazy
-if PY3:
- from email.utils import parseaddr
- from email import message_from_bytes, message_from_binary_file
-else:
- from email.Utils import parseaddr
- from email import (
- message_from_string as message_from_bytes,
- message_from_file as message_from_binary_file,
- )
-
class HeadersCheckMixin(object):
@@ -656,16 +648,10 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
sanitize_address(('A name', 'to@example.com'), 'ascii'),
'A name <to@example.com>'
)
- if PY3:
- self.assertEqual(
- sanitize_address(('A name', 'to@example.com'), 'utf-8'),
- '=?utf-8?q?A_name?= <to@example.com>'
- )
- else:
- self.assertEqual(
- sanitize_address(('A name', 'to@example.com'), 'utf-8'),
- 'A name <to@example.com>'
- )
+ self.assertEqual(
+ sanitize_address(('A name', 'to@example.com'), 'utf-8'),
+ '=?utf-8?q?A_name?= <to@example.com>'
+ )
# Unicode characters are are supported in RFC-6532.
self.assertEqual(
@@ -1165,18 +1151,8 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
self.active_lock = threading.Lock()
self.sink_lock = threading.Lock()
- if not PY3:
- def handle_accept(self):
- # copy of Python 2.7 smtpd.SMTPServer.handle_accept with hardcoded
- # SMTPChannel replaced by self.channel_class
- pair = self.accept()
- if pair is not None:
- conn, addr = pair
- self.channel_class(self, conn, addr)
-
def process_message(self, peer, mailfrom, rcpttos, data):
- if PY3:
- data = data.encode('utf-8')
+ data = data.encode('utf-8')
m = message_from_bytes(data)
maddr = parseaddr(m.get('from'))[1]
@@ -1448,8 +1424,7 @@ class SMTPBackendTests(BaseEmailBackendTests, SMTPBackendTestsBase):
self.assertTrue(msg)
- if PY3:
- msg = msg.decode('utf-8')
+ msg = msg.decode('utf-8')
# The message only contains CRLF and not combinations of CRLF, LF, and CR.
msg = msg.replace('\r\n', '')
self.assertNotIn('\r', msg)
diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py
index 43ea0748a0..3c0d3d81ea 100644
--- a/tests/middleware/tests.py
+++ b/tests/middleware/tests.py
@@ -2,7 +2,6 @@ import gzip
import random
import re
from io import BytesIO
-from unittest import skipIf
from django.conf import settings
from django.core import mail
@@ -401,24 +400,6 @@ class BrokenLinkEmailsMiddlewareTest(SimpleTestCase):
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
self.assertEqual(len(mail.outbox), 0)
- @skipIf(six.PY3, "HTTP_REFERER is str type on Python 3")
- def test_404_error_nonascii_referrer(self):
- # Such referer strings should not happen, but anyway, if it happens,
- # let's not crash
- self.req.META['HTTP_REFERER'] = b'http://testserver/c/\xd0\xbb\xd0\xb8/'
- BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
- self.assertEqual(len(mail.outbox), 1)
-
- @skipIf(six.PY3, "HTTP_USER_AGENT is str type on Python 3")
- def test_404_error_nonascii_user_agent(self):
- # Such user agent strings should not happen, but anyway, if it happens,
- # let's not crash
- self.req.META['HTTP_REFERER'] = '/another/url/'
- self.req.META['HTTP_USER_AGENT'] = b'\xd0\xbb\xd0\xb8\xff\xff'
- BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
- self.assertEqual(len(mail.outbox), 1)
- self.assertIn('User agent: \u043b\u0438\ufffd\ufffd\n', mail.outbox[0].body)
-
def test_custom_request_checker(self):
class SubclassedMiddleware(BrokenLinkEmailsMiddleware):
ignored_user_agent_patterns = (re.compile(r'Spider.*'), re.compile(r'Robot.*'))
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index ab2e47fabd..ca6b42044f 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -661,18 +661,10 @@ class MakeMigrationsTests(MigrationTestBase):
self.assertIn('migrations.CreateModel', content)
self.assertIn('initial = True', content)
- if six.PY3:
- self.assertIn('úñí©óðé µóðéø', content) # Meta.verbose_name
- self.assertIn('úñí©óðé µóðéøß', content) # Meta.verbose_name_plural
- self.assertIn('ÚÑÍ¢ÓÐÉ', content) # title.verbose_name
- self.assertIn('“Ðjáñgó”', content) # title.default
- else:
- # Meta.verbose_name
- self.assertIn('\\xfa\\xf1\\xed\\xa9\\xf3\\xf0\\xe9 \\xb5\\xf3\\xf0\\xe9\\xf8', content)
- # Meta.verbose_name_plural
- self.assertIn('\\xfa\\xf1\\xed\\xa9\\xf3\\xf0\\xe9 \\xb5\\xf3\\xf0\\xe9\\xf8\\xdf', content)
- self.assertIn('\\xda\\xd1\\xcd\\xa2\\xd3\\xd0\\xc9', content) # title.verbose_name
- self.assertIn('\\u201c\\xd0j\\xe1\\xf1g\\xf3\\u201d', content) # title.default
+ self.assertIn('úñí©óðé µóðéø', content) # Meta.verbose_name
+ self.assertIn('úñí©óðé µóðéøß', content) # Meta.verbose_name_plural
+ self.assertIn('ÚÑÍ¢ÓÐÉ', content) # title.verbose_name
+ self.assertIn('“Ðjáñgó”', content) # title.default
def test_makemigrations_order(self):
"""
diff --git a/tests/migrations/test_loader.py b/tests/migrations/test_loader.py
index 6c91a50430..b06ff8f89c 100644
--- a/tests/migrations/test_loader.py
+++ b/tests/migrations/test_loader.py
@@ -1,5 +1,3 @@
-from unittest import skipIf
-
from django.db import connection, connections
from django.db.migrations.exceptions import (
AmbiguityError, InconsistentMigrationHistory, NodeNotFoundError,
@@ -7,7 +5,6 @@ from django.db.migrations.exceptions import (
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.recorder import MigrationRecorder
from django.test import TestCase, modify_settings, override_settings
-from django.utils import six
class RecorderTests(TestCase):
@@ -170,7 +167,6 @@ class LoaderTests(TestCase):
"App with migrations module file not in unmigrated apps."
)
- @skipIf(six.PY2, "PY2 doesn't load empty dirs.")
def test_load_empty_dir(self):
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
loader = MigrationLoader(connection)
diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py
index c03d8cfd38..b926757920 100644
--- a/tests/migrations/test_writer.py
+++ b/tests/migrations/test_writer.py
@@ -47,12 +47,6 @@ 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):
@@ -486,15 +480,6 @@ class WriterTests(SimpleTestCase):
self.assertEqual(string, 'range')
self.assertEqual(imports, set())
- @unittest.skipUnless(six.PY2, "Only applies on Python 2")
- def test_serialize_direct_function_reference(self):
- """
- Ticket #22436: You cannot use a function straight from its body
- (e.g. define the method and use it in the same body)
- """
- with self.assertRaises(ValueError):
- self.serialize_round_trip(TestModel1.thing)
-
def test_serialize_local_function_reference(self):
"""
Neither py2 or py3 can serialize a reference in a local scope.
diff --git a/tests/model_fields/test_promises.py b/tests/model_fields/test_promises.py
index bf5258cddf..0dcb1abf3b 100644
--- a/tests/model_fields/test_promises.py
+++ b/tests/model_fields/test_promises.py
@@ -1,13 +1,12 @@
import datetime
-import unittest
from decimal import Decimal
from django.db.models.fields import (
- AutoField, BigIntegerField, BinaryField, BooleanField, CharField,
- DateField, DateTimeField, DecimalField, EmailField, FilePathField,
- FloatField, GenericIPAddressField, IntegerField, IPAddressField,
- NullBooleanField, PositiveIntegerField, PositiveSmallIntegerField,
- SlugField, SmallIntegerField, TextField, TimeField, URLField,
+ AutoField, BinaryField, BooleanField, CharField, DateField, DateTimeField,
+ DecimalField, EmailField, FilePathField, FloatField, GenericIPAddressField,
+ IntegerField, IPAddressField, NullBooleanField, PositiveIntegerField,
+ PositiveSmallIntegerField, SlugField, SmallIntegerField, TextField,
+ TimeField, URLField,
)
from django.db.models.fields.files import FileField, ImageField
from django.test import SimpleTestCase
@@ -21,11 +20,6 @@ class PromiseTest(SimpleTestCase):
lazy_func = lazy(lambda: 1, int)
self.assertIsInstance(AutoField(primary_key=True).get_prep_value(lazy_func()), int)
- @unittest.skipIf(six.PY3, 'Python 3 has no `long` type.')
- def test_BigIntegerField(self):
- lazy_func = lazy(lambda: long(9999999999999999999), long) # NOQA: long undefined on PY3
- self.assertIsInstance(BigIntegerField().get_prep_value(lazy_func()), long) # NOQA
-
def test_BinaryField(self):
lazy_func = lazy(lambda: b'', bytes)
self.assertIsInstance(BinaryField().get_prep_value(lazy_func()), bytes)
diff --git a/tests/project_template/test_settings.py b/tests/project_template/test_settings.py
index a0047dd836..5623df320b 100644
--- a/tests/project_template/test_settings.py
+++ b/tests/project_template/test_settings.py
@@ -1,18 +1,11 @@
import os
import shutil
-import unittest
from django import conf
from django.test import TestCase
-from django.utils import six
from django.utils._os import upath
-@unittest.skipIf(
- six.PY2,
- 'Python 2 cannot import the project template because '
- 'django/conf/project_template doesn\'t have an __init__.py file.'
-)
class TestStartProjectSettings(TestCase):
def setUp(self):
# Ensure settings.py exists
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index e2dd86bac1..ed323be154 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -11,7 +11,6 @@ from django.db.models.sql.constants import LOUTER
from django.db.models.sql.where import NothingNode, WhereNode
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import CaptureQueriesContext
-from django.utils import six
from django.utils.six.moves import range
from .models import (
@@ -406,7 +405,7 @@ class Queries1Tests(TestCase):
local_recursion_limit = 127
msg = 'Maximum recursion depth exceeded: too many subqueries.'
with self.assertRaisesMessage(RuntimeError, msg):
- for i in six.moves.range(local_recursion_limit * 2):
+ for i in range(local_recursion_limit * 2):
x = Tag.objects.filter(pk__in=x)
def test_reasonable_number_of_subq_aliases(self):
@@ -2249,25 +2248,6 @@ class QuerySetSupportsPythonIdioms(TestCase):
]
)
- @unittest.skipUnless(six.PY2, "Python 2 only -- Python 3 doesn't have longs.")
- def test_slicing_works_with_longs(self):
- # NOQA: long undefined on PY3
- self.assertEqual(self.get_ordered_articles()[long(0)].name, 'Article 1') # NOQA
- self.assertQuerysetEqual(self.get_ordered_articles()[long(1):long(3)], # NOQA
- ["<Article: Article 2>", "<Article: Article 3>"])
- self.assertQuerysetEqual(
- self.get_ordered_articles()[::long(2)], [ # NOQA
- "<Article: Article 1>",
- "<Article: Article 3>",
- "<Article: Article 5>",
- "<Article: Article 7>"
- ]
- )
-
- # And can be mixed with ints.
- self.assertQuerysetEqual(self.get_ordered_articles()[1:long(3)], # NOQA
- ["<Article: Article 2>", "<Article: Article 3>"])
-
def test_slicing_without_step_is_lazy(self):
with self.assertNumQueries(0):
self.get_ordered_articles()[0:5]
@@ -2965,8 +2945,6 @@ class QuerySetExceptionTests(TestCase):
def test_invalid_order_by(self):
msg = "Invalid order_by arguments: ['*']"
- if six.PY2:
- msg = msg.replace("[", "[u")
with self.assertRaisesMessage(FieldError, msg):
list(Article.objects.order_by('*'))
diff --git a/tests/queryset_pickle/models.py b/tests/queryset_pickle/models.py
index 5e60963272..4faad0175b 100644
--- a/tests/queryset_pickle/models.py
+++ b/tests/queryset_pickle/models.py
@@ -1,7 +1,6 @@
import datetime
from django.db import DJANGO_VERSION_PICKLE_KEY, models
-from django.utils import six
from django.utils.translation import ugettext_lazy as _
@@ -45,9 +44,7 @@ class Happening(models.Model):
when = models.DateTimeField(blank=True, default=datetime.datetime.now)
name = models.CharField(blank=True, max_length=100, default="test")
number1 = models.IntegerField(blank=True, default=standalone_number)
- if six.PY3:
- # default serializable on Python 3 only
- number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
+ number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
class Container(object):
diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py
index 9333e96fc3..ac5174051f 100644
--- a/tests/queryset_pickle/tests.py
+++ b/tests/queryset_pickle/tests.py
@@ -1,10 +1,8 @@
import datetime
import pickle
-import unittest
from django.db import models
from django.test import TestCase
-from django.utils import six
from django.utils.version import get_version
from .models import Container, Event, Group, Happening, M2MModel
@@ -33,7 +31,6 @@ class PickleabilityTestCase(TestCase):
def test_standalone_method_as_default(self):
self.assert_pickles(Happening.objects.filter(number1=1))
- @unittest.skipIf(six.PY2, "Field doesn't exist on Python 2.")
def test_staticmethod_as_default(self):
self.assert_pickles(Happening.objects.filter(number2=1))
diff --git a/tests/requests/tests.py b/tests/requests/tests.py
index c5a148ffbb..09b08540f4 100644
--- a/tests/requests/tests.py
+++ b/tests/requests/tests.py
@@ -12,7 +12,6 @@ from django.http.request import split_domain_port
from django.test import RequestFactory, SimpleTestCase, override_settings
from django.test.client import FakePayload
from django.test.utils import freeze_time, str_prefix
-from django.utils import six
from django.utils.encoding import force_str
from django.utils.http import cookie_date, urlencode
from django.utils.six.moves import http_cookies
@@ -168,9 +167,8 @@ class RequestsTests(SimpleTestCase):
def test_wsgirequest_path_info(self):
def wsgi_str(path_info, encoding='utf-8'):
- path_info = path_info.encode(encoding) # Actual URL sent by the browser (bytestring)
- if six.PY3:
- path_info = path_info.decode('iso-8859-1') # Value in the WSGI environ dict (native string)
+ path_info = path_info.encode(encoding) # Actual URL sent by the browser (bytestring)
+ path_info = path_info.decode('iso-8859-1') # Value in the WSGI environ dict (native string)
return path_info
# Regression for #19468
request = WSGIRequest({'PATH_INFO': wsgi_str("/سلام/"), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
@@ -583,7 +581,7 @@ class RequestsTests(SimpleTestCase):
request = WSGIRequest({
'REQUEST_METHOD': 'GET',
'wsgi.input': '',
- 'QUERY_STRING': b'name=Hello%20G%C3%BCnter' if six.PY2 else 'name=Hello%20G%C3%BCnter'
+ 'QUERY_STRING': 'name=Hello%20G%C3%BCnter',
})
self.assertEqual(request.GET, {'name': ['Hello Günter']})
request.encoding = 'iso-8859-16'
diff --git a/tests/signing/tests.py b/tests/signing/tests.py
index c6145d09cb..bc838d015f 100644
--- a/tests/signing/tests.py
+++ b/tests/signing/tests.py
@@ -3,7 +3,6 @@ import datetime
from django.core import signing
from django.test import SimpleTestCase
from django.test.utils import freeze_time
-from django.utils import six
from django.utils.encoding import force_str
@@ -45,8 +44,6 @@ class TestSigner(SimpleTestCase):
'jkw osanteuh ,rcuh nthu aou oauh ,ud du',
'\u2019',
]
- if six.PY2:
- examples.append(b'a byte string')
for example in examples:
signed = signer.sign(example)
self.assertIsInstance(signed, str)
@@ -76,8 +73,6 @@ class TestSigner(SimpleTestCase):
'a unicode string \u2019',
{'a': 'dictionary'},
]
- if six.PY2:
- objects.append(b'a byte string')
for o in objects:
self.assertNotEqual(o, signing.dumps(o))
self.assertEqual(o, signing.loads(signing.dumps(o)))
diff --git a/tests/staticfiles_tests/test_management.py b/tests/staticfiles_tests/test_management.py
index ad608ea24b..e8c00eb3f5 100644
--- a/tests/staticfiles_tests/test_management.py
+++ b/tests/staticfiles_tests/test_management.py
@@ -183,8 +183,7 @@ class TestInteractiveMessages(CollectionTestCase):
@staticmethod
def mock_input(stdout):
def _input(msg):
- # Python 2 reads bytes from the console output, use bytes for the StringIO
- stdout.write(msg.encode('utf-8') if six.PY2 else msg)
+ stdout.write(msg)
return 'yes'
return _input
diff --git a/tests/str/models.py b/tests/str/models.py
index 12f0247570..d2f7a45c20 100644
--- a/tests/str/models.py
+++ b/tests/str/models.py
@@ -1,31 +1,16 @@
"""
-Adding __str__() or __unicode__() to models
+Adding __str__() to models
-Although it's not a strict requirement, each model should have a
-``_str__()`` or ``__unicode__()`` method to return a "human-readable"
-representation of the object. Do this not only for your own sanity when dealing
-with the interactive prompt, but also because objects' representations are used
-throughout Django's automatically-generated admin.
-
-Normally, you should write ``__unicode__()`` method, since this will work for
-all field types (and Django will automatically provide an appropriate
-``__str__()`` method). However, you can write a ``__str__()`` method directly,
-if you prefer. You must be careful to encode the results correctly, though.
+Although it's not a strict requirement, each model should have a ``_str__()``
+method to return a "human-readable" representation of the object. Do this not
+only for your own sanity when dealing with the interactive prompt, but also
+because objects' representations are used throughout Django's
+automatically-generated admin.
"""
from django.db import models
-class Article(models.Model):
- headline = models.CharField(max_length=100)
- pub_date = models.DateTimeField()
-
- def __str__(self):
- # Caution: this is only safe if you are certain that headline will be
- # in ASCII.
- return self.headline
-
-
class InternationalArticle(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateTimeField()
diff --git a/tests/str/tests.py b/tests/str/tests.py
index c4dd1d6b26..2d82c03ebf 100644
--- a/tests/str/tests.py
+++ b/tests/str/tests.py
@@ -1,25 +1,14 @@
import datetime
-from unittest import skipIf
from django.db import models
from django.test import TestCase
from django.test.utils import isolate_apps
-from django.utils import six
-from .models import Article, InternationalArticle
+from .models import InternationalArticle
class SimpleTests(TestCase):
- @skipIf(six.PY3, "tests a __str__ method returning unicode under Python 2")
- def test_basic(self):
- a = Article.objects.create(
- headline=b'Parrot programs in Python',
- pub_date=datetime.datetime(2005, 7, 28)
- )
- self.assertEqual(str(a), str('Parrot programs in Python'))
- self.assertEqual(repr(a), str('<Article: Parrot programs in Python>'))
-
def test_international(self):
a = InternationalArticle.objects.create(
headline='Girl wins €12.500 in lottery',
diff --git a/tests/template_tests/syntax_tests/test_width_ratio.py b/tests/template_tests/syntax_tests/test_width_ratio.py
index 8206b83c58..bec7d93a4c 100644
--- a/tests/template_tests/syntax_tests/test_width_ratio.py
+++ b/tests/template_tests/syntax_tests/test_width_ratio.py
@@ -1,6 +1,5 @@
from django.template import TemplateSyntaxError
from django.test import SimpleTestCase
-from django.utils import six
from ..utils import setup
@@ -36,11 +35,10 @@ class WidthRatioTagTests(SimpleTestCase):
@setup({'widthratio06': '{% widthratio a b 100 %}'})
def test_widthratio06(self):
"""
- 62.5 should round to 63 on Python 2 and 62 on Python 3
- See http://docs.python.org/py3k/whatsnew/3.0.html
+ 62.5 should round to 62
"""
output = self.engine.render_to_string('widthratio06', {'a': 50, 'b': 80})
- self.assertEqual(output, '62' if six.PY3 else '63')
+ self.assertEqual(output, '62')
@setup({'widthratio07': '{% widthratio a b 100 %}'})
def test_widthratio07(self):
diff --git a/tests/template_tests/test_custom.py b/tests/template_tests/test_custom.py
index df8ea17fb0..03d4308937 100644
--- a/tests/template_tests/test_custom.py
+++ b/tests/template_tests/test_custom.py
@@ -1,12 +1,10 @@
import os
-from unittest import skipUnless
from django.template import Context, Engine, TemplateSyntaxError
from django.template.base import Node
from django.template.library import InvalidTemplateLibrary
from django.test import SimpleTestCase
from django.test.utils import extend_sys_path
-from django.utils import six
from .templatetags import custom, inclusion
from .utils import ROOT
@@ -344,7 +342,6 @@ class TemplateTagLoadingTests(SimpleTestCase):
})
engine.from_string(ttext)
- @skipUnless(six.PY3, "Python 3 only -- Python 2 doesn't have annotations.")
def test_load_annotated_function(self):
Engine(libraries={
'annotated_tag_function': 'template_tests.annotated_tag_function',
diff --git a/tests/template_tests/test_loaders.py b/tests/template_tests/test_loaders.py
index 6e9b6eb453..c36e1ba6be 100644
--- a/tests/template_tests/test_loaders.py
+++ b/tests/template_tests/test_loaders.py
@@ -7,7 +7,6 @@ from contextlib import contextmanager
from django.template import TemplateDoesNotExist
from django.template.engine import Engine
from django.test import SimpleTestCase, override_settings
-from django.utils import six
from django.utils.functional import lazystr
from .utils import TEMPLATE_DIR
@@ -64,7 +63,6 @@ class CachedLoaderTests(SimpleTestCase):
self.assertIsInstance(e, TemplateDoesNotExist)
self.assertEqual(e.args[0], 'debug-template-missing.html')
- @unittest.skipIf(six.PY2, "Python 2 doesn't set extra exception attributes")
def test_cached_exception_no_traceback(self):
"""
When a TemplateDoesNotExist instance is cached, the cached instance
diff --git a/tests/template_tests/test_nodelist.py b/tests/template_tests/test_nodelist.py
index 042702e3c0..b69e7c063b 100644
--- a/tests/template_tests/test_nodelist.py
+++ b/tests/template_tests/test_nodelist.py
@@ -2,7 +2,6 @@ from unittest import TestCase
from django.template import Context, Engine
from django.template.base import TextNode, VariableNode
-from django.utils import six
class NodelistTest(TestCase):
@@ -38,13 +37,11 @@ class TextNodeTest(TestCase):
def test_textnode_repr(self):
engine = Engine()
for temptext, reprtext in [
- ("Hello, world!", "<TextNode: u'Hello, world!'>"),
- ("One\ntwo.", "<TextNode: u'One\\ntwo.'>"),
+ ("Hello, world!", "<TextNode: 'Hello, world!'>"),
+ ("One\ntwo.", "<TextNode: 'One\\ntwo.'>"),
]:
template = engine.from_string(temptext)
texts = template.nodelist.get_nodes_by_type(TextNode)
- if six.PY3:
- reprtext = reprtext.replace("u'", "'")
self.assertEqual(repr(texts[0]), reprtext)
diff --git a/tests/test_runner/test_debug_sql.py b/tests/test_runner/test_debug_sql.py
index e230066100..c6b9b01dbc 100644
--- a/tests/test_runner/test_debug_sql.py
+++ b/tests/test_runner/test_debug_sql.py
@@ -5,7 +5,6 @@ from django.db import connection
from django.test import TestCase
from django.test.runner import DiscoverRunner
from django.utils import six
-from django.utils.encoding import force_text
from .models import Person
@@ -43,8 +42,6 @@ class TestDebugSQL(unittest.TestCase):
).run(suite)
runner.teardown_databases(old_config)
- if six.PY2:
- stream.buflist = [force_text(x) for x in stream.buflist]
return stream.getvalue()
def test_output_normal(self):
diff --git a/tests/test_runner/test_parallel.py b/tests/test_runner/test_parallel.py
index b888dc62af..08731f68eb 100644
--- a/tests/test_runner/test_parallel.py
+++ b/tests/test_runner/test_parallel.py
@@ -2,7 +2,6 @@ import unittest
from django.test import SimpleTestCase
from django.test.runner import RemoteTestResult
-from django.utils import six
try:
import tblib
@@ -28,7 +27,6 @@ class ParallelTestRunnerTest(SimpleTestCase):
parallel.
"""
- @unittest.skipUnless(six.PY3, 'subtests were added in Python 3.4')
def test_subtest(self):
"""
Passing subtests work.
@@ -61,12 +59,10 @@ class RemoteTestResultTest(SimpleTestCase):
result._confirm_picklable(picklable_error)
msg = '__init__() missing 1 required positional argument'
- if six.PY2:
- msg = '__init__() takes exactly 2 arguments (1 given)'
with self.assertRaisesMessage(TypeError, msg):
result._confirm_picklable(not_unpicklable_error)
- @unittest.skipUnless(six.PY3 and tblib is not None, 'requires tblib to be installed')
+ @unittest.skipUnless(tblib is not None, 'requires tblib to be installed')
def test_add_failing_subtests(self):
"""
Failing subtests are added correctly using addSubTest().
diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py
index a84e5bfb24..157479a579 100644
--- a/tests/urlpatterns_reverse/tests.py
+++ b/tests/urlpatterns_reverse/tests.py
@@ -3,7 +3,6 @@ Unit tests for reverse URL lookups.
"""
import sys
import threading
-import unittest
from admin_scripts.tests import AdminScriptTestCase
@@ -430,7 +429,7 @@ class ResolverTests(SimpleTestCase):
[{'type': RegexURLResolver}, {'type': RegexURLPattern, 'name': None}],
[{'type': RegexURLResolver}, {'type': RegexURLResolver}],
]
- with self.assertRaisesMessage(Resolver404, b'tried' if six.PY2 else 'tried') as cm:
+ with self.assertRaisesMessage(Resolver404, 'tried') as cm:
resolve('/included/non-existent-url', urlconf=urls)
e = cm.exception
# make sure we at least matched the root ('/') url resolver:
@@ -463,7 +462,6 @@ class ResolverTests(SimpleTestCase):
self.assertTrue(resolver._is_callback('urlpatterns_reverse.nested_urls.View3'))
self.assertFalse(resolver._is_callback('urlpatterns_reverse.nested_urls.blub'))
- @unittest.skipIf(six.PY2, "Python 2 doesn't support __qualname__.")
def test_view_detail_as_method(self):
# Views which have a class name as part of their path.
resolver = get_resolver('urlpatterns_reverse.method_view_urls')
@@ -503,11 +501,6 @@ class ReverseLazyTest(TestCase):
'Some URL: %s' % reverse_lazy('some-login-page'),
'Some URL: /login/'
)
- if six.PY2:
- self.assertEqual(
- b'Some URL: %s' % reverse_lazy('some-login-page'),
- 'Some URL: /login/'
- )
class ReverseLazySettingsTest(AdminScriptTestCase):
diff --git a/tests/utils_tests/test_encoding.py b/tests/utils_tests/test_encoding.py
index 1d6976fc77..b4e7b9c0ac 100644
--- a/tests/utils_tests/test_encoding.py
+++ b/tests/utils_tests/test_encoding.py
@@ -21,10 +21,8 @@ class TestEncodingUtils(unittest.TestCase):
__unicode__ = __str__
- # str(s) raises a TypeError on python 3 if the result is not a text type.
- # python 2 fails when it tries converting from str to unicode (via ASCII).
- exception = TypeError if six.PY3 else UnicodeError
- with self.assertRaises(exception):
+ # str(s) raises a TypeError if the result is not a text type.
+ with self.assertRaises(TypeError):
force_text(MyString())
def test_force_text_lazy(self):
@@ -47,26 +45,15 @@ class TestEncodingUtils(unittest.TestCase):
def test_smart_text(self):
class Test:
- if six.PY3:
- def __str__(self):
- return 'ŠĐĆŽćžšđ'
- else:
- def __str__(self):
- return 'ŠĐĆŽćžšđ'.encode('utf-8')
+ def __str__(self):
+ return 'ŠĐĆŽćžšđ'
class TestU:
- if six.PY3:
- def __str__(self):
- return 'ŠĐĆŽćžšđ'
-
- def __bytes__(self):
- return b'Foo'
- else:
- def __str__(self):
- return b'Foo'
-
- def __unicode__(self):
- return '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
+ def __str__(self):
+ return 'ŠĐĆŽćžšđ'
+
+ def __bytes__(self):
+ return b'Foo'
self.assertEqual(smart_text(Test()), '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
self.assertEqual(smart_text(TestU()), '\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
diff --git a/tests/utils_tests/test_functional.py b/tests/utils_tests/test_functional.py
index f7b12724af..0ca534445f 100644
--- a/tests/utils_tests/test_functional.py
+++ b/tests/utils_tests/test_functional.py
@@ -38,18 +38,11 @@ class FunctionalTestCase(unittest.TestCase):
def test_lazy_object_to_string(self):
class Klazz(object):
- if six.PY3:
- def __str__(self):
- return "Î am ā Ǩlâzz."
-
- def __bytes__(self):
- return b"\xc3\x8e am \xc4\x81 binary \xc7\xa8l\xc3\xa2zz."
- else:
- def __unicode__(self):
- return "Î am ā Ǩlâzz."
-
- def __str__(self):
- return b"\xc3\x8e am \xc4\x81 binary \xc7\xa8l\xc3\xa2zz."
+ def __str__(self):
+ return "Î am ā Ǩlâzz."
+
+ def __bytes__(self):
+ return b"\xc3\x8e am \xc4\x81 binary \xc7\xa8l\xc3\xa2zz."
t = lazy(lambda: Klazz(), Klazz)()
self.assertEqual(six.text_type(t), "Î am ā Ǩlâzz.")
diff --git a/tests/utils_tests/test_glob.py b/tests/utils_tests/test_glob.py
deleted file mode 100644
index 5cd7fbbe28..0000000000
--- a/tests/utils_tests/test_glob.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from django.test import SimpleTestCase
-from django.utils.glob import glob_escape
-
-
-class TestUtilsGlob(SimpleTestCase):
- def test_glob_escape(self):
- filename = '/my/file?/name[with special chars*'
- expected = '/my/file[?]/name[[]with special chars[*]'
- filename_b = b'/my/file?/name[with special chars*'
- expected_b = b'/my/file[?]/name[[]with special chars[*]'
-
- self.assertEqual(glob_escape(filename), expected)
- self.assertEqual(glob_escape(filename_b), expected_b)
diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py
index ec818318b4..8f887fd011 100644
--- a/tests/utils_tests/test_html.py
+++ b/tests/utils_tests/test_html.py
@@ -2,7 +2,7 @@ import os
from datetime import datetime
from django.test import SimpleTestCase
-from django.utils import html, safestring, six
+from django.utils import html, safestring
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.functional import lazystr
@@ -168,12 +168,8 @@ class TestUtilsHtml(SimpleTestCase):
def test_html_safe(self):
@html.html_safe
class HtmlClass(object):
- if six.PY2:
- def __unicode__(self):
- return "<h1>I'm a html class!</h1>"
- else:
- def __str__(self):
- return "<h1>I'm a html class!</h1>"
+ def __str__(self):
+ return "<h1>I'm a html class!</h1>"
html_obj = HtmlClass()
self.assertTrue(hasattr(HtmlClass, '__html__'))
@@ -181,34 +177,19 @@ class TestUtilsHtml(SimpleTestCase):
self.assertEqual(force_text(html_obj), html_obj.__html__())
def test_html_safe_subclass(self):
- if six.PY2:
- class BaseClass(object):
- def __html__(self):
- # defines __html__ on its own
- return 'some html content'
+ class BaseClass(object):
+ def __html__(self):
+ # defines __html__ on its own
+ return 'some html content'
- def __unicode__(self):
- return 'some non html content'
+ def __str__(self):
+ return 'some non html content'
- @html.html_safe
- class Subclass(BaseClass):
- def __unicode__(self):
- # overrides __unicode__ and is marked as html_safe
- return 'some html safe content'
- else:
- class BaseClass(object):
- def __html__(self):
- # defines __html__ on its own
- return 'some html content'
-
- def __str__(self):
- return 'some non html content'
-
- @html.html_safe
- class Subclass(BaseClass):
- def __str__(self):
- # overrides __str__ and is marked as html_safe
- return 'some html safe content'
+ @html.html_safe
+ class Subclass(BaseClass):
+ def __str__(self):
+ # overrides __str__ and is marked as html_safe
+ return 'some html safe content'
subclass_obj = Subclass()
self.assertEqual(force_text(subclass_obj), subclass_obj.__html__())
@@ -222,8 +203,7 @@ class TestUtilsHtml(SimpleTestCase):
return "<h1>I'm a html class!</h1>"
def test_html_safe_doesnt_define_str(self):
- method_name = '__unicode__()' if six.PY2 else '__str__()'
- msg = "can't apply @html_safe to HtmlClass because it doesn't define %s." % method_name
+ msg = "can't apply @html_safe to HtmlClass because it doesn't define __str__()."
with self.assertRaisesMessage(ValueError, msg):
@html.html_safe
class HtmlClass(object):
diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py
index 30a8846021..281fb77fbb 100644
--- a/tests/utils_tests/test_http.py
+++ b/tests/utils_tests/test_http.py
@@ -1,9 +1,8 @@
-import sys
import unittest
from datetime import datetime
from django.test import ignore_warnings
-from django.utils import http, six
+from django.utils import http
from django.utils.datastructures import MultiValueDict
from django.utils.deprecation import RemovedInDjango21Warning
@@ -51,15 +50,10 @@ class TestUtilsHttp(unittest.TestCase):
# reciprocity works
for n in [0, 1, 1000, 1000000]:
self.assertEqual(n, http.base36_to_int(http.int_to_base36(n)))
- if six.PY2:
- self.assertEqual(sys.maxint, http.base36_to_int(http.int_to_base36(sys.maxint)))
# bad input
with self.assertRaises(ValueError):
http.int_to_base36(-1)
- if six.PY2:
- with self.assertRaises(ValueError):
- http.int_to_base36(sys.maxint + 1)
for n in ['1', 'foo', {1: 2}, (1, 2, 3), 3.141]:
with self.assertRaises(TypeError):
http.int_to_base36(n)
@@ -132,16 +126,6 @@ class TestUtilsHttp(unittest.TestCase):
"%s should be allowed" % good_url,
)
- if six.PY2:
- # Check binary URLs, regression tests for #26308
- self.assertTrue(
- http.is_safe_url(b'https://testserver/', allowed_hosts={'testserver'}),
- "binary URLs should be allowed on Python 2"
- )
- self.assertFalse(http.is_safe_url(b'\x08//example.com', allowed_hosts={'testserver'}))
- self.assertTrue(http.is_safe_url('àview/'.encode('utf-8'), allowed_hosts={'testserver'}))
- self.assertFalse(http.is_safe_url('àview'.encode('latin-1'), allowed_hosts={'testserver'}))
-
# Valid basic auth credentials are allowed.
self.assertTrue(http.is_safe_url(r'http://user:pass@testserver/', allowed_hosts={'user:pass@testserver'}))
# A path without host is allowed.
diff --git a/tests/utils_tests/test_simplelazyobject.py b/tests/utils_tests/test_simplelazyobject.py
index 8501b89e92..a83c78bf4c 100644
--- a/tests/utils_tests/test_simplelazyobject.py
+++ b/tests/utils_tests/test_simplelazyobject.py
@@ -2,7 +2,6 @@ import pickle
from django.contrib.auth.models import User
from django.test import TestCase
-from django.utils import six
from django.utils.functional import SimpleLazyObject
@@ -21,9 +20,3 @@ class TestUtilsSimpleLazyObjectDjangoTestCase(TestCase):
pickle.dumps(x, 0)
pickle.dumps(x, 1)
pickle.dumps(x, 2)
-
- if six.PY2:
- import cPickle
-
- # This would fail with "TypeError: expected string or Unicode object, NoneType found".
- cPickle.dumps(x)
diff --git a/tests/view_tests/tests/py3_test_debug.py b/tests/view_tests/tests/py3_test_debug.py
deleted file mode 100644
index 30201bae53..0000000000
--- a/tests/view_tests/tests/py3_test_debug.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-Since this file contains Python 3 specific syntax, it's named without a test_
-prefix so the test runner won't try to import it. Instead, the test class is
-imported in test_debug.py, but only on Python 3.
-
-This filename is also in setup.cfg flake8 exclude since the Python 2 syntax
-error (raise ... from ...) can't be silenced using NOQA.
-"""
-import sys
-
-from django.test import RequestFactory, TestCase
-from django.views.debug import ExceptionReporter
-
-
-class Py3ExceptionReporterTests(TestCase):
-
- rf = RequestFactory()
-
- def test_reporting_of_nested_exceptions(self):
- request = self.rf.get('/test_view/')
- try:
- try:
- raise AttributeError('Top level')
- except AttributeError as explicit:
- try:
- raise ValueError('Second exception') from explicit
- except ValueError:
- raise IndexError('Final exception')
- except Exception:
- # Custom exception handler, just pass it into ExceptionReporter
- exc_type, exc_value, tb = sys.exc_info()
-
- explicit_exc = 'The above exception ({0}) was the direct cause of the following exception:'
- implicit_exc = 'During handling of the above exception ({0}), another exception occurred:'
-
- reporter = ExceptionReporter(request, exc_type, exc_value, tb)
- html = reporter.get_traceback_html()
- # Both messages are twice on page -- one rendered as html,
- # one as plain text (for pastebin)
- self.assertEqual(2, html.count(explicit_exc.format("Top level")))
- self.assertEqual(2, html.count(implicit_exc.format("Second exception")))
-
- text = reporter.get_traceback_text()
- self.assertIn(explicit_exc.format("Top level"), text)
- self.assertIn(implicit_exc.format("Second exception"), text)
diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py
index 19ab456ba5..1d8397c5ef 100644
--- a/tests/view_tests/tests/test_debug.py
+++ b/tests/view_tests/tests/test_debug.py
@@ -4,7 +4,6 @@ import os
import re
import sys
import tempfile
-from unittest import skipIf
from django.conf.urls import url
from django.core import mail
@@ -30,9 +29,6 @@ from ..views import (
sensitive_method_view, sensitive_view,
)
-if six.PY3:
- from .py3_test_debug import Py3ExceptionReporterTests # NOQA
-
PY36 = sys.version_info >= (3, 6)
@@ -352,6 +348,34 @@ class ExceptionReporterTests(SimpleTestCase):
self.assertIn('<h2>Request information</h2>', html)
self.assertNotIn('<p>Request data not supplied</p>', html)
+ def test_reporting_of_nested_exceptions(self):
+ request = self.rf.get('/test_view/')
+ try:
+ try:
+ raise AttributeError('Top level')
+ except AttributeError as explicit:
+ try:
+ raise ValueError('Second exception') from explicit
+ except ValueError:
+ raise IndexError('Final exception')
+ except Exception:
+ # Custom exception handler, just pass it into ExceptionReporter
+ exc_type, exc_value, tb = sys.exc_info()
+
+ explicit_exc = 'The above exception ({0}) was the direct cause of the following exception:'
+ implicit_exc = 'During handling of the above exception ({0}), another exception occurred:'
+
+ reporter = ExceptionReporter(request, exc_type, exc_value, tb)
+ html = reporter.get_traceback_html()
+ # Both messages are twice on page -- one rendered as html,
+ # one as plain text (for pastebin)
+ self.assertEqual(2, html.count(explicit_exc.format("Top level")))
+ self.assertEqual(2, html.count(implicit_exc.format("Second exception")))
+
+ text = reporter.get_traceback_text()
+ self.assertIn(explicit_exc.format("Top level"), text)
+ self.assertIn(implicit_exc.format("Second exception"), text)
+
def test_request_and_message(self):
"A message can be provided in addition to a request"
request = self.rf.get('/test_view/')
@@ -426,11 +450,10 @@ class ExceptionReporterTests(SimpleTestCase):
self.assertEqual(len(html) // 1024 // 128, 0) # still fit in 128Kb
self.assertIn('&lt;trimmed %d bytes string&gt;' % (large + repr_of_str_adds,), html)
- @skipIf(six.PY2, 'Bug manifests on PY3 only')
def test_unfrozen_importlib(self):
"""
importlib is not a frozen app, but its loader thinks it's frozen which
- results in an ImportError on Python 3. Refs #21443.
+ results in an ImportError. Refs #21443.
"""
try:
request = self.rf.get('/test_view/')
@@ -478,10 +501,7 @@ class ExceptionReporterTests(SimpleTestCase):
An exception report can be generated for requests with 'items' in
request GET, POST, FILES, or COOKIES QueryDicts.
"""
- if six.PY3:
- value = '<td>items</td><td class="code"><pre>&#39;Oops&#39;</pre></td>'
- else:
- value = '<td>items</td><td class="code"><pre>u&#39;Oops&#39;</pre></td>'
+ value = '<td>items</td><td class="code"><pre>&#39;Oops&#39;</pre></td>'
# GET
request = self.rf.get('/test_view/?items=Oops')
reporter = ExceptionReporter(request, None, None, None)
@@ -597,20 +617,16 @@ class PlainTextReportTests(SimpleTestCase):
An exception report can be generated for requests with 'items' in
request GET, POST, FILES, or COOKIES QueryDicts.
"""
- if six.PY3:
- value = "items = 'Oops'"
- else:
- value = "items = u'Oops'"
# GET
request = self.rf.get('/test_view/?items=Oops')
reporter = ExceptionReporter(request, None, None, None)
text = reporter.get_traceback_text()
- self.assertIn(value, text)
+ self.assertIn("items = 'Oops'", text)
# POST
request = self.rf.post('/test_view/', data={'items': 'Oops'})
reporter = ExceptionReporter(request, None, None, None)
text = reporter.get_traceback_text()
- self.assertIn(value, text)
+ self.assertIn("items = 'Oops'", text)
# FILES
fp = six.StringIO('filecontent')
request = self.rf.post('/test_view/', data={'name': 'filename', 'items': fp})
diff --git a/tests/view_tests/tests/test_i18n.py b/tests/view_tests/tests/test_i18n.py
index fc7be41594..d330b60ff7 100644
--- a/tests/view_tests/tests/test_i18n.py
+++ b/tests/view_tests/tests/test_i18n.py
@@ -8,7 +8,6 @@ from django.test import (
)
from django.test.selenium import SeleniumTestCase
from django.urls import reverse
-from django.utils import six
from django.utils._os import upath
from django.utils.translation import (
LANGUAGE_SESSION_KEY, get_language, override,
@@ -193,10 +192,7 @@ class JsI18NTests(SimpleTestCase):
for lang_code in ['es', 'fr', 'ru']:
with override(lang_code):
catalog = gettext.translation('djangojs', locale_dir, [lang_code])
- if six.PY3:
- trans_txt = catalog.gettext('this is to be translated')
- else:
- trans_txt = catalog.ugettext('this is to be translated')
+ trans_txt = catalog.gettext('this is to be translated')
response = self.client.get('/jsi18n/')
# response content must include a line like:
# "this is to be translated": <value of trans_txt Python variable>