1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Refs #23919 -- Removed six.PY2/PY3 usage

Thanks Tim Graham for the review.
This commit is contained in:
Claude Paroz 2016-12-01 11:38:01 +01:00
parent e63d98b7be
commit c716fe8782
111 changed files with 305 additions and 1296 deletions

View File

@ -15,7 +15,6 @@ from django.db import models
from django.http import Http404 from django.http import Http404
from django.template.engine import Engine from django.template.engine import Engine
from django.urls import get_mod_func, get_resolver, get_urlconf, reverse 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.decorators import method_decorator
from django.utils.inspect import ( from django.utils.inspect import (
func_accepts_kwargs, func_accepts_var_args, func_has_no_args, func_accepts_kwargs, func_accepts_var_args, func_has_no_args,
@ -132,12 +131,7 @@ class ViewIndexView(BaseAdminDocsView):
@staticmethod @staticmethod
def _get_full_name(func): def _get_full_name(func):
mod_name = func.__module__ mod_name = func.__module__
if six.PY3: return '%s.%s' % (mod_name, func.__qualname__)
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)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
views = [] views = []

View File

@ -8,8 +8,6 @@ from django.apps import apps as global_apps
from django.contrib.auth import get_permission_codename from django.contrib.auth import get_permission_codename
from django.core import exceptions from django.core import exceptions
from django.db import DEFAULT_DB_ALIAS, router 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): def _get_all_permissions(opts):
@ -98,12 +96,6 @@ def get_system_username():
# if there is no corresponding entry in the /etc/passwd file # if there is no corresponding entry in the /etc/passwd file
# (a very restricted chroot environment, for example). # (a very restricted chroot environment, for example).
return '' return ''
if six.PY2:
try:
result = result.decode(DEFAULT_LOCALE_ENCODING)
except UnicodeDecodeError:
# UnicodeDecodeError - preventive treatment for non-latin Windows.
return ''
return result return result

View File

@ -1,7 +1,7 @@
import django.contrib.auth.models import django.contrib.auth.models
from django.contrib.auth import validators from django.contrib.auth import validators
from django.db import migrations, models from django.db import migrations, models
from django.utils import six, timezone from django.utils import timezone
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -63,9 +63,7 @@ class Migration(migrations.Migration):
('username', models.CharField( ('username', models.CharField(
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True,
max_length=30, verbose_name='username', max_length=30, verbose_name='username',
validators=[ validators=[validators.UnicodeUsernameValidator()],
validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()
],
)), )),
('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)), ('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)), ('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),

View File

@ -1,6 +1,5 @@
from django.contrib.auth import validators from django.contrib.auth import validators
from django.db import migrations, models from django.db import migrations, models
from django.utils import six
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -16,7 +15,7 @@ class Migration(migrations.Migration):
name='username', name='username',
field=models.CharField( field=models.CharField(
error_messages={'unique': 'A user with that username already exists.'}, max_length=30, 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.', help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
unique=True, verbose_name='username' unique=True, verbose_name='username'
), ),

View File

@ -1,6 +1,5 @@
from django.contrib.auth import validators from django.contrib.auth import validators
from django.db import migrations, models from django.db import migrations, models
from django.utils import six
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -18,7 +17,7 @@ class Migration(migrations.Migration):
help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
max_length=30, max_length=30,
unique=True, unique=True,
validators=[validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()], validators=[validators.UnicodeUsernameValidator()],
verbose_name='username', verbose_name='username',
), ),
), ),

View File

@ -1,6 +1,5 @@
from django.contrib.auth import validators from django.contrib.auth import validators
from django.db import migrations, models from django.db import migrations, models
from django.utils import six
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -18,7 +17,7 @@ class Migration(migrations.Migration):
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
max_length=150, max_length=150,
unique=True, unique=True,
validators=[validators.UnicodeUsernameValidator() if six.PY3 else validators.ASCIIUsernameValidator()], validators=[validators.UnicodeUsernameValidator()],
verbose_name='username', verbose_name='username',
), ),
), ),

View File

@ -9,7 +9,7 @@ from django.db.models.manager import EmptyManager
from django.utils import six, timezone from django.utils import six, timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .validators import ASCIIUsernameValidator, UnicodeUsernameValidator from .validators import UnicodeUsernameValidator
def update_last_login(sender, user, **kwargs): 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 and password are required. Other fields are optional.
""" """
username_validator = UnicodeUsernameValidator() if six.PY3 else ASCIIUsernameValidator() username_validator = UnicodeUsernameValidator()
username = models.CharField( username = models.CharField(
_('username'), _('username'),

View File

@ -1,7 +1,6 @@
import re import re
from django.core import validators from django.core import validators
from django.utils import six
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.translation import ugettext_lazy as _ 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, ' 'Enter a valid username. This value may contain only English letters, '
'numbers, and @/./+/-/_ characters.' 'numbers, and @/./+/-/_ characters.'
) )
flags = re.ASCII if six.PY3 else 0 flags = re.ASCII
@deconstructible @deconstructible
@ -23,4 +22,4 @@ class UnicodeUsernameValidator(validators.RegexValidator):
'Enter a valid username. This value may contain only letters, ' 'Enter a valid username. This value may contain only letters, '
'numbers, and @/./+/-/_ characters.' 'numbers, and @/./+/-/_ characters.'
) )
flags = re.UNICODE if six.PY2 else 0 flags = 0

View File

@ -235,5 +235,4 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
if name_field: if name_field:
yield '' yield ''
yield ' def __%s__(self): return self.%s' % ( yield ' def __str__(self): return self.%s' % name_field
'str' if six.PY3 else 'unicode', name_field)

View File

@ -1,18 +1,13 @@
from psycopg2 import ProgrammingError from psycopg2 import ProgrammingError
from psycopg2.extras import register_hstore from psycopg2.extras import register_hstore
from django.utils import six
def register_hstore_handler(connection, **kwargs): def register_hstore_handler(connection, **kwargs):
if connection.vendor != 'postgresql': if connection.vendor != 'postgresql':
return return
try: try:
if six.PY2: register_hstore(connection.connection, globally=True)
register_hstore(connection.connection, globally=True, unicode=True)
else:
register_hstore(connection.connection, globally=True)
except ProgrammingError: except ProgrammingError:
# Hstore is not available on the database. # Hstore is not available on the database.
# #

View File

@ -5,7 +5,7 @@ from datetime import datetime
from django.conf import settings from django.conf import settings
from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
from django.db import DatabaseError, connections, models, router, transaction 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 from django.utils.encoding import force_bytes
try: try:
@ -112,11 +112,9 @@ class DatabaseCache(BaseDatabaseCache):
if num > self._max_entries: if num > self._max_entries:
self._cull(db, cursor, now) self._cull(db, cursor, now)
pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) 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 # The DB column is expecting a string, so make sure the value is a
# string, not bytes. Refs #19274. # string, not bytes. Refs #19274.
if six.PY3: b64encoded = base64.b64encode(pickled).decode('latin1')
b64encoded = b64encoded.decode('latin1')
try: try:
# Note: typecasting for datetimes is needed by some 3rd party # Note: typecasting for datetimes is needed by some 3rd party
# database backends. All core backends work without typecasting, # database backends. All core backends work without typecasting,

View File

@ -1,7 +1,6 @@
""" """
Global Django exception and warning classes. Global Django exception and warning classes.
""" """
from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -115,10 +114,7 @@ class ValidationError(Exception):
if isinstance(message, ValidationError): if isinstance(message, ValidationError):
if hasattr(message, 'error_dict'): if hasattr(message, 'error_dict'):
message = message.error_dict message = message.error_dict
# PY2 has a `message` property which is always there so we can't elif not hasattr(message, 'message'):
# 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'):
message = message.error_list message = message.error_list
else: else:
message, code, params = message.message, message.code, message.params message, code, params = message.message, message.code, message.params

View File

@ -3,7 +3,7 @@ from io import BytesIO, StringIO, UnsupportedOperation
from django.core.files.utils import FileProxyMixin from django.core.files.utils import FileProxyMixin
from django.utils import six 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): class File(FileProxyMixin):
@ -140,11 +140,7 @@ class ContentFile(File):
A File-like object that takes just raw content, rather than an actual file. A File-like object that takes just raw content, rather than an actual file.
""" """
def __init__(self, content, name=None): def __init__(self, content, name=None):
if six.PY3: stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
stream_class = StringIO if isinstance(content, six.text_type) else BytesIO
else:
stream_class = BytesIO
content = force_bytes(content)
super(ContentFile, self).__init__(stream_class(content), name=name) super(ContentFile, self).__init__(stream_class(content), name=name)
self.size = len(content) self.size = len(content)

View File

@ -8,7 +8,6 @@ from django.conf import settings
from django.core import signals from django.core import signals
from django.core.handlers import base from django.core.handlers import base
from django.urls import set_script_prefix from django.urls import set_script_prefix
from django.utils import six
from django.utils.encoding import ( from django.utils.encoding import (
force_str, force_text, repercent_broken_unicode, 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. Get a value from the WSGI environ dictionary as bytes.
key and default should be str objects. Under Python 2 they may also be key and default should be str objects.
unicode objects provided they only contain ASCII characters.
""" """
value = environ.get(str(key), str(default)) value = environ.get(str(key), str(default))
# Under Python 3, non-ASCII values in the WSGI environ are arbitrarily # Non-ASCII values in the WSGI environ are arbitrarily decoded with
# decoded with ISO-8859-1. This is wrong for Django websites where UTF-8 # ISO-8859-1. This is wrong for Django websites where UTF-8 is the default.
# is the default. Re-encode to recover the original bytestring. # Re-encode to recover the original bytestring.
return value.encode(ISO_8859_1) if six.PY3 else value return value.encode(ISO_8859_1)
def get_str_from_wsgi(environ, key, default): def get_str_from_wsgi(environ, key, default):
""" """
Get a value from the WSGI environ dictionary as str. Get a value from the WSGI environ dictionary as str.
key and default should be str objects. Under Python 2 they may also be key and default should be str objects.
unicode objects provided they only contain ASCII characters.
""" """
value = get_bytes_from_wsgi(environ, key, default) 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')

View File

@ -5,7 +5,6 @@ import sys
import threading import threading
from django.core.mail.backends.base import BaseEmailBackend from django.core.mail.backends.base import BaseEmailBackend
from django.utils import six
class EmailBackend(BaseEmailBackend): class EmailBackend(BaseEmailBackend):
@ -17,9 +16,8 @@ class EmailBackend(BaseEmailBackend):
def write_message(self, message): def write_message(self, message):
msg = message.message() msg = message.message()
msg_data = msg.as_bytes() msg_data = msg.as_bytes()
if six.PY3: charset = msg.get_charset().get_output_charset() if msg.get_charset() else 'utf-8'
charset = msg.get_charset().get_output_charset() if msg.get_charset() else 'utf-8' msg_data = msg_data.decode(charset)
msg_data = msg_data.decode(charset)
self.stream.write('%s\n' % msg_data) self.stream.write('%s\n' % msg_data)
self.stream.write('-' * 79) self.stream.write('-' * 79)
self.stream.write('\n') self.stream.write('\n')

View File

@ -5,7 +5,9 @@ import time
from email import ( from email import (
charset as Charset, encoders as Encoders, generator, message_from_string, charset as Charset, encoders as Encoders, generator, message_from_string,
) )
from email.errors import InvalidHeaderDefect, NonASCIILocalPartDefect
from email.header import Header from email.header import Header
from email.headerregistry import Address
from email.message import Message from email.message import Message
from email.mime.base import MIMEBase from email.mime.base import MIMEBase
from email.mime.message import MIMEMessage 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 except UnicodeEncodeError: # IDN or non-ascii in the local part
localpart, domain = split_addr(addr, encoding) localpart, domain = split_addr(addr, encoding)
if six.PY2: # An `email.headerregistry.Address` object is used since
# 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
# email.utils.formataddr() naively encodes the name as ascii (see #25986). # 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: if localpart and domain:
address = Address(nm, username=localpart, domain=domain) address = Address(nm, username=localpart, domain=domain)
return str(address) return str(address)
@ -174,27 +166,21 @@ class MIMEMixin():
""" """
fp = six.StringIO() fp = six.StringIO()
g = generator.Generator(fp, mangle_from_=False) g = generator.Generator(fp, mangle_from_=False)
if six.PY2: g.flatten(self, unixfrom=unixfrom, linesep=linesep)
g.flatten(self, unixfrom=unixfrom)
else:
g.flatten(self, unixfrom=unixfrom, linesep=linesep)
return fp.getvalue() return fp.getvalue()
if six.PY2: def as_bytes(self, unixfrom=False, linesep='\n'):
as_bytes = as_string """Return the entire formatted message as bytes.
else: Optional `unixfrom' when True, means include the Unix From_ envelope
def as_bytes(self, unixfrom=False, linesep='\n'): header.
"""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 This overrides the default as_bytes() implementation to not mangle
lines that begin with 'From '. See bug #13433 for details. lines that begin with 'From '. See bug #13433 for details.
""" """
fp = BytesIO() fp = BytesIO()
g = generator.BytesGenerator(fp, mangle_from_=False) g = generator.BytesGenerator(fp, mangle_from_=False)
g.flatten(self, unixfrom=unixfrom, linesep=linesep) g.flatten(self, unixfrom=unixfrom, linesep=linesep)
return fp.getvalue() return fp.getvalue()
class SafeMIMEMessage(MIMEMixin, MIMEMessage): class SafeMIMEMessage(MIMEMixin, MIMEMessage):
@ -450,8 +436,6 @@ class EmailMessage(object):
try: try:
filename.encode('ascii') filename.encode('ascii')
except UnicodeEncodeError: except UnicodeEncodeError:
if six.PY2:
filename = filename.encode('utf-8')
filename = ('utf-8', '', filename) filename = ('utf-8', '', filename)
attachment.add_header('Content-Disposition', 'attachment', attachment.add_header('Content-Disposition', 'attachment',
filename=filename) filename=filename)

View File

@ -20,7 +20,6 @@ from django.utils import lru_cache
from django.utils._os import upath from django.utils._os import upath
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.glob import glob_escape
try: try:
import bz2 import bz2
@ -238,7 +237,7 @@ class Command(BaseCommand):
self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir)) self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir))
fixture_files_in_dir = [] fixture_files_in_dir = []
path = os.path.join(fixture_dir, fixture_name) 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: if os.path.basename(candidate) in targets:
# Save the fixture_dir and fixture_name for future error messages. # Save the fixture_dir and fixture_name for future error messages.
fixture_files_in_dir.append((candidate, fixture_dir, fixture_name)) fixture_files_in_dir.append((candidate, fixture_dir, fixture_name))

View File

@ -10,8 +10,8 @@ from django.core.management.base import BaseCommand, CommandError
from django.core.servers.basehttp import ( from django.core.servers.basehttp import (
WSGIServer, get_internal_wsgi_application, run, WSGIServer, get_internal_wsgi_application, run,
) )
from django.utils import autoreload, six from django.utils import autoreload
from django.utils.encoding import force_text, get_system_encoding from django.utils.encoding import force_text
naiveip_re = re.compile(r"""^(?: naiveip_re = re.compile(r"""^(?:
@ -125,8 +125,6 @@ class Command(BaseCommand):
# requires_migrations_check attribute. # requires_migrations_check attribute.
self.check_migrations() self.check_migrations()
now = datetime.now().strftime('%B %d, %Y - %X') now = datetime.now().strftime('%B %d, %Y - %X')
if six.PY2:
now = now.decode(get_system_encoding())
self.stdout.write(now) self.stdout.write(now)
self.stdout.write(( self.stdout.write((
"Django version %(version)s, using settings %(settings)r\n" "Django version %(version)s, using settings %(settings)r\n"

View File

@ -16,7 +16,7 @@ from django.conf import settings
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.core.management.utils import handle_extensions from django.core.management.utils import handle_extensions
from django.template import Context, Engine 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.six.moves.urllib.request import urlretrieve
from django.utils.version import get_docs_version from django.utils.version import get_docs_version
@ -218,21 +218,11 @@ class TemplateCommand(BaseCommand):
raise CommandError("you must provide %s %s name" % ( raise CommandError("you must provide %s %s name" % (
"an" if app_or_project == "app" else "a", app_or_project)) "an" if app_or_project == "app" else "a", app_or_project))
# If it's not a valid directory name. # If it's not a valid directory name.
if six.PY2: if not name.isidentifier():
if not re.search(r'^[_a-zA-Z]\w*$', name): raise CommandError(
# Provide a smart error message, depending on the error. "%r is not a valid %s name. Please make sure the name is "
if not re.search(r'^[_a-zA-Z]', name): "a valid identifier." % (name, app_or_project)
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)
)
def download(self, url): def download(self, url):
""" """

View File

@ -219,8 +219,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
'conv': django_conversions, 'conv': django_conversions,
'charset': 'utf8', 'charset': 'utf8',
} }
if six.PY2:
kwargs['use_unicode'] = True
settings_dict = self.settings_dict settings_dict = self.settings_dict
if settings_dict['USER']: if settings_dict['USER']:
kwargs['user'] = settings_dict['USER'] kwargs['user'] = settings_dict['USER']

View File

@ -252,8 +252,6 @@ WHEN (new.%(col_name)s IS NULL)
# https://cx-oracle.readthedocs.io/en/latest/cursor.html#Cursor.statement # https://cx-oracle.readthedocs.io/en/latest/cursor.html#Cursor.statement
# The DB API definition does not define this attribute. # The DB API definition does not define this attribute.
statement = cursor.statement 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 # Unlike Psycopg's `query` and MySQLdb`'s `_last_executed`, CxOracle's
# `statement` doesn't contain the query parameters. refs #20010. # `statement` doesn't contain the query parameters. refs #20010.
return super(DatabaseOperations, self).last_executed_query(cursor, statement, params) return super(DatabaseOperations, self).last_executed_query(cursor, statement, params)

View File

@ -12,7 +12,6 @@ from django.core.exceptions import ImproperlyConfigured
from django.db import DEFAULT_DB_ALIAS from django.db import DEFAULT_DB_ALIAS
from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.utils import DatabaseError as WrappedDatabaseError from django.db.utils import DatabaseError as WrappedDatabaseError
from django.utils import six
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.safestring import SafeBytes, SafeText 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 .utils import utc_tzinfo_factory # NOQA isort:skip
from .version import get_version # 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(SafeBytes, psycopg2.extensions.QuotedString)
psycopg2.extensions.register_adapter(SafeText, psycopg2.extensions.QuotedString) psycopg2.extensions.register_adapter(SafeText, psycopg2.extensions.QuotedString)
psycopg2.extras.register_uuid() psycopg2.extras.register_uuid()

View File

@ -19,7 +19,6 @@ from django.utils.dateparse import (
parse_date, parse_datetime, parse_duration, parse_time, parse_date, parse_datetime, parse_duration, parse_time,
) )
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.safestring import SafeBytes
try: try:
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_converter(str("decimal"), decoder(backend_utils.typecast_decimal))
Database.register_adapter(decimal.Decimal, backend_utils.rev_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): class DatabaseWrapper(BaseDatabaseWrapper):

View File

@ -1,6 +1,5 @@
from django.db import utils from django.db import utils
from django.db.backends.base.features import BaseDatabaseFeatures from django.db.backends.base.features import BaseDatabaseFeatures
from django.utils import six
from django.utils.functional import cached_property from django.utils.functional import cached_property
from .base import Database from .base import Database
@ -48,7 +47,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@cached_property @cached_property
def can_share_in_memory_db(self): def can_share_in_memory_db(self):
return ( return (
six.PY3 and
Database.__name__ == 'sqlite3.dbapi2' and Database.__name__ == 'sqlite3.dbapi2' and
Database.sqlite_version_info >= (3, 7, 13) Database.sqlite_version_info >= (3, 7, 13)
) )

View File

@ -4,7 +4,7 @@ import sys
from django.apps import apps from django.apps import apps
from django.db.models.fields import NOT_PROVIDED 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 django.utils.six.moves import input
from .loader import MigrationLoader from .loader import MigrationLoader
@ -125,13 +125,7 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
prompt = "[default: {}] >>> ".format(default) prompt = "[default: {}] >>> ".format(default)
else: else:
prompt = ">>> " prompt = ">>> "
if six.PY3: code = input(prompt)
# 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)
if not code and default: if not code and default:
code = default code = default
if not code: if not code:

View File

@ -53,11 +53,7 @@ class BaseSimpleSerializer(BaseSerializer):
class ByteTypeSerializer(BaseSerializer): class ByteTypeSerializer(BaseSerializer):
def serialize(self): def serialize(self):
value_repr = repr(self.value) return repr(self.value), set()
if six.PY2:
# Prepend the `b` prefix since we're importing unicode_literals
value_repr = 'b' + value_repr
return value_repr, set()
class DatetimeSerializer(BaseSerializer): class DatetimeSerializer(BaseSerializer):
@ -276,11 +272,7 @@ class SettingsReferenceSerializer(BaseSerializer):
class TextTypeSerializer(BaseSerializer): class TextTypeSerializer(BaseSerializer):
def serialize(self): def serialize(self):
value_repr = repr(self.value) return repr(self.value), set()
if six.PY2:
# Strip the `u` prefix since we're importing unicode_literals
value_repr = value_repr[1:]
return value_repr, set()
class TimedeltaSerializer(BaseSerializer): class TimedeltaSerializer(BaseSerializer):

View File

@ -510,9 +510,7 @@ class Model(six.with_metaclass(ModelBase)):
return force_str('<%s: %s>' % (self.__class__.__name__, u)) return force_str('<%s: %s>' % (self.__class__.__name__, u))
def __str__(self): def __str__(self):
if six.PY2 and hasattr(self, '__unicode__'): return '%s object' % self.__class__.__name__
return force_text(self).encode('utf-8')
return str('%s object' % self.__class__.__name__)
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, Model): if not isinstance(other, Model):

View File

@ -107,7 +107,6 @@ class RelatedField(Field):
return errors return errors
def _check_related_name_is_valid(self): def _check_related_name_is_valid(self):
import re
import keyword import keyword
related_name = self.remote_field.related_name related_name = self.remote_field.related_name
if related_name is None: if related_name is None:
@ -115,12 +114,8 @@ class RelatedField(Field):
is_valid_id = True is_valid_id = True
if keyword.iskeyword(related_name): if keyword.iskeyword(related_name):
is_valid_id = False is_valid_id = False
if six.PY3: if not related_name.isidentifier():
if not related_name.isidentifier(): is_valid_id = False
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 (is_valid_id or related_name.endswith('+')): if not (is_valid_id or related_name.endswith('+')):
return [ return [
checks.Error( checks.Error(

View File

@ -4,7 +4,6 @@ from importlib import import_module
from django.db import router from django.db import router
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.utils import six
class BaseManager(object): class BaseManager(object):
@ -86,9 +85,7 @@ class BaseManager(object):
return manager_method return manager_method
new_methods = {} new_methods = {}
# Refs http://bugs.python.org/issue1785. for name, method in inspect.getmembers(queryset_class, predicate=inspect.isfunction):
predicate = inspect.isfunction if six.PY3 else inspect.ismethod
for name, method in inspect.getmembers(queryset_class, predicate=predicate):
# Only copy missing methods. # Only copy missing methods.
if hasattr(cls, name): if hasattr(cls, name):
continue continue

View File

@ -14,7 +14,7 @@ DEFAULT_DB_ALIAS = 'default'
DJANGO_VERSION_PICKLE_KEY = '_django_version' DJANGO_VERSION_PICKLE_KEY = '_django_version'
class Error(Exception if six.PY3 else StandardError): # NOQA: StandardError undefined on PY3 class Error(Exception):
pass pass

View File

@ -2,15 +2,9 @@ import sys
import threading import threading
import weakref import weakref
from django.utils import six
from django.utils.inspect import func_accepts_kwargs from django.utils.inspect import func_accepts_kwargs
from django.utils.six.moves import range from django.utils.six.moves import range
if six.PY2:
from .weakref_backports import WeakMethod
else:
from weakref import WeakMethod
def _make_id(target): def _make_id(target):
if hasattr(target, '__func__'): if hasattr(target, '__func__'):
@ -107,13 +101,10 @@ class Signal(object):
receiver_object = receiver receiver_object = receiver
# Check for bound methods # Check for bound methods
if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'): if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'):
ref = WeakMethod ref = weakref.WeakMethod
receiver_object = receiver.__self__ receiver_object = receiver.__self__
if six.PY3: receiver = ref(receiver)
receiver = ref(receiver) weakref.finalize(receiver_object, self._remove_receiver)
weakref.finalize(receiver_object, self._remove_receiver)
else:
receiver = ref(receiver, self._remove_receiver)
with self.lock: with self.lock:
self._clear_dead_receivers() self._clear_dead_receivers()

View File

@ -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__

View File

@ -1,12 +1,7 @@
import sys import sys
from django.utils import six
from django.utils.encoding import force_str
from django.utils.six.moves import http_cookies 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+ # Cookie pickling bug is fixed in Python 2.7.9 and Python 3.4.3+
# http://bugs.python.org/issue22775 # http://bugs.python.org/issue22775
cookie_pickles_properly = ( cookie_pickles_properly = (
@ -14,7 +9,7 @@ cookie_pickles_properly = (
sys.version_info >= (3, 4, 3) sys.version_info >= (3, 4, 3)
) )
if _cookie_allows_colon_in_names and cookie_pickles_properly: if cookie_pickles_properly:
SimpleCookie = http_cookies.SimpleCookie SimpleCookie = http_cookies.SimpleCookie
else: else:
Morsel = http_cookies.Morsel Morsel = http_cookies.Morsel
@ -30,37 +25,12 @@ else:
else: else:
super(SimpleCookie, self).__setitem__(key, value) 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): def parse_cookie(cookie):
""" """
Return a dictionary parsed from a `Cookie:` header string. Return a dictionary parsed from a `Cookie:` header string.
""" """
cookiedict = {} cookiedict = {}
if six.PY2:
cookie = force_str(cookie)
for chunk in cookie.split(str(';')): for chunk in cookie.split(str(';')):
if str('=') in chunk: if str('=') in chunk:
key, val = chunk.split(str('='), 1) key, val = chunk.split(str('='), 1)

View File

@ -40,8 +40,6 @@ RAW = "raw"
FILE = "file" FILE = "file"
FIELD = "field" FIELD = "field"
_BASE64_DECODE_ERROR = TypeError if six.PY2 else binascii.Error
class MultiPartParser(object): class MultiPartParser(object):
""" """
@ -190,7 +188,7 @@ class MultiPartParser(object):
num_bytes_read += len(raw_data) num_bytes_read += len(raw_data)
try: try:
data = base64.b64decode(raw_data) data = base64.b64decode(raw_data)
except _BASE64_DECODE_ERROR: except binascii.Error:
data = raw_data data = raw_data
else: else:
data = field_stream.read(size=read_size) data = field_stream.read(size=read_size)
@ -684,10 +682,7 @@ def parse_header(line):
value = p[i + 1:].strip() value = p[i + 1:].strip()
if has_encoding: if has_encoding:
encoding, lang, value = value.split(b"'") encoding, lang, value = value.split(b"'")
if six.PY3: value = unquote(value.decode(), encoding=encoding.decode())
value = unquote(value.decode(), encoding=encoding.decode())
else:
value = unquote(value).decode(encoding)
if len(value) >= 2 and value[:1] == value[-1:] == b'"': if len(value) >= 2 and value[:1] == value[-1:] == b'"':
value = value[1:-1] value = value[1:-1]
value = value.replace(b'\\\\', b'\\').replace(b'\\"', b'"') value = value.replace(b'\\\\', b'\\').replace(b'\\"', b'"')

View File

@ -14,7 +14,7 @@ from django.http.multipartparser import MultiPartParser, MultiPartParserError
from django.utils import six from django.utils import six
from django.utils.datastructures import ImmutableList, MultiValueDict from django.utils.datastructures import ImmutableList, MultiValueDict
from django.utils.encoding import ( 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.http import is_same_domain, limited_parse_qsl
from django.utils.six.moves.urllib.parse import ( from django.utils.six.moves.urllib.parse import (
@ -381,24 +381,15 @@ class QueryDict(MultiValueDict):
'fields_limit': settings.DATA_UPLOAD_MAX_NUMBER_FIELDS, 'fields_limit': settings.DATA_UPLOAD_MAX_NUMBER_FIELDS,
'encoding': encoding, 'encoding': encoding,
} }
if six.PY3: if isinstance(query_string, bytes):
if isinstance(query_string, bytes): # query_string normally contains URL-encoded data, a subset of ASCII.
# query_string normally contains URL-encoded data, a subset of ASCII. try:
try: query_string = query_string.decode(encoding)
query_string = query_string.decode(encoding) except UnicodeDecodeError:
except UnicodeDecodeError: # ... but some user agents are misbehaving :-(
# ... but some user agents are misbehaving :-( query_string = query_string.decode('iso-8859-1')
query_string = query_string.decode('iso-8859-1') for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs):
for key, value in limited_parse_qsl(query_string, **parse_qsl_kwargs): self.appendlist(key, value)
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)
self._mutable = mutable self._mutable = mutable
@classmethod @classmethod

View File

@ -100,10 +100,7 @@ class HttpResponseBase(six.Iterator):
] ]
return b'\r\n'.join(headers) return b'\r\n'.join(headers)
if six.PY3: __bytes__ = serialize_headers
__bytes__ = serialize_headers
else:
__str__ = serialize_headers
@property @property
def _content_type_for_repr(self): 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)): isinstance(value, six.text_type) and ('\n' in value or '\r' in value)):
raise BadHeaderError("Header values can't contain newlines (got %r)" % value) raise BadHeaderError("Header values can't contain newlines (got %r)" % value)
try: try:
if six.PY3: if isinstance(value, str):
if isinstance(value, str): # Ensure string is valid in given charset
# Ensure string is valid in given charset value.encode(charset)
value.encode(charset)
else:
# Convert bytestring using given charset
value = value.decode(charset)
else: else:
if isinstance(value, str): # Convert bytestring using given charset
# Ensure string is valid in given charset value = value.decode(charset)
value.decode(charset)
else:
# Convert unicode string to given charset
value = value.encode(charset)
except UnicodeError as e: except UnicodeError as e:
if mime_encode: if mime_encode:
# Wrapping in str() is a workaround for #12422 under Python 2. # 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.""" """Full HTTP message, including headers, as a bytestring."""
return self.serialize_headers() + b'\r\n\r\n' + self.content return self.serialize_headers() + b'\r\n\r\n' + self.content
if six.PY3: __bytes__ = serialize
__bytes__ = serialize
else:
__str__ = serialize
@property @property
def content(self): def content(self):

View File

@ -322,10 +322,10 @@ class RequestFactory(object):
if parsed[3]: if parsed[3]:
path += str(";") + force_str(parsed[3]) path += str(";") + force_str(parsed[3])
path = uri_to_iri(path).encode(UTF_8) path = uri_to_iri(path).encode(UTF_8)
# Under Python 3, non-ASCII values in the WSGI environ are arbitrarily # Replace the behavior where non-ASCII values in the WSGI environ are
# decoded with ISO-8859-1. We replicate this behavior here. # arbitrarily decoded with ISO-8859-1.
# Refs comment in `get_bytes_from_wsgi()`. # 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): def get(self, path, data=None, secure=False, **extra):
"Construct a GET request." "Construct a GET request."
@ -406,10 +406,8 @@ class RequestFactory(object):
r.update(extra) r.update(extra)
# If QUERY_STRING is absent or empty, we want to extract it from the URL. # If QUERY_STRING is absent or empty, we want to extract it from the URL.
if not r.get('QUERY_STRING'): if not r.get('QUERY_STRING'):
query_string = force_bytes(parsed[4])
# WSGI requires latin-1 encoded strings. See get_path_info(). # WSGI requires latin-1 encoded strings. See get_path_info().
if six.PY3: query_string = force_bytes(parsed[4]).decode('iso-8859-1')
query_string = query_string.decode('iso-8859-1')
r['QUERY_STRING'] = query_string r['QUERY_STRING'] = query_string
return self.request(**r) return self.request(**r)

View File

@ -9,7 +9,7 @@ from django.core.signals import setting_changed
from django.db import connections, router from django.db import connections, router
from django.db.utils import ConnectionRouter from django.db.utils import ConnectionRouter
from django.dispatch import Signal, receiver 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.formats import FORMAT_SETTINGS, reset_format_cache
from django.utils.functional import empty from django.utils.functional import empty
@ -139,7 +139,7 @@ def complex_setting_changed(**kwargs):
# Considering the current implementation of the signals framework, # Considering the current implementation of the signals framework,
# this stacklevel shows the line containing the override_settings call. # this stacklevel shows the line containing the override_settings call.
warnings.warn("Overriding setting %s can lead to unexpected behavior." 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) @receiver(setting_changed)

View File

@ -775,12 +775,6 @@ class SimpleTestCase(unittest.TestCase):
standardMsg = '%s == %s' % (safe_repr(xml1, True), safe_repr(xml2, True)) standardMsg = '%s == %s' % (safe_repr(xml1, True), safe_repr(xml2, True))
self.fail(self._formatMessage(msg, standardMsg)) 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): class TransactionTestCase(SimpleTestCase):

View File

@ -6,6 +6,7 @@ import time
import warnings import warnings
from contextlib import contextmanager from contextlib import contextmanager
from functools import wraps from functools import wraps
from types import SimpleNamespace
from unittest import TestCase, skipIf, skipUnless from unittest import TestCase, skipIf, skipUnless
from xml.dom.minidom import Node, parseString 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.encoding import force_str
from django.utils.translation import deactivate from django.utils.translation import deactivate
if six.PY3:
from types import SimpleNamespace
else:
class SimpleNamespace(object):
pass
try: try:
import jinja2 import jinja2
except ImportError: except ImportError:
@ -615,7 +610,7 @@ def strip_quotes(want, got):
def str_prefix(s): def str_prefix(s):
return s % {'_': '' if six.PY3 else 'u'} return s % {'_': ''}
class CaptureQueriesContext(object): class CaptureQueriesContext(object):

View File

@ -209,11 +209,7 @@ class RegexURLPattern(LocaleRegexProvider):
callback = callback.func callback = callback.func
if not hasattr(callback, '__name__'): if not hasattr(callback, '__name__'):
return callback.__module__ + "." + callback.__class__.__name__ return callback.__module__ + "." + callback.__class__.__name__
elif six.PY3: return callback.__module__ + "." + callback.__qualname__
return callback.__module__ + "." + callback.__qualname__
else:
# PY2 does not support __qualname__
return callback.__module__ + "." + callback.__name__
class RegexURLResolver(LocaleRegexProvider): class RegexURLResolver(LocaleRegexProvider):

View File

@ -1,41 +1,18 @@
import os import os
import sys
import tempfile 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.core.exceptions import SuspiciousFileOperation
from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
if six.PY2:
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
abspathu = abspath
# 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)
def upath(path): def upath(path):
""" """
Always return a unicode path. Always return a unicode path.
""" """
if six.PY2 and not isinstance(path, six.text_type):
return path.decode(fs_encoding)
return path return path
@ -44,8 +21,6 @@ def npath(path):
Always return a native path, that is unicode on Python 3 and bytestring on Always return a native path, that is unicode on Python 3 and bytestring on
Python 2. Python 2.
""" """
if six.PY2 and not isinstance(path, bytes):
return path.encode(fs_encoding)
return path return path

View File

@ -9,7 +9,6 @@ import struct
import time import time
from django.conf import settings from django.conf import settings
from django.utils import six
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.six.moves import range from django.utils.six.moves import range
@ -94,7 +93,7 @@ else:
if len(val1) != len(val2): if len(val1) != len(val2):
return False return False
result = 0 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): for x, y in zip(val1, val2):
result |= x ^ y result |= x ^ y
else: else:

View File

@ -179,7 +179,7 @@ class MultiValueDict(dict):
"""Appends an item to the internal list associated with key.""" """Appends an item to the internal list associated with key."""
self.setlistdefault(key).append(value) self.setlistdefault(key).append(value)
def _iteritems(self): def items(self):
""" """
Yields (key, value) pairs, where value is the last item in the list Yields (key, value) pairs, where value is the last item in the list
associated with the key. associated with the key.
@ -187,33 +187,15 @@ class MultiValueDict(dict):
for key in self: for key in self:
yield key, self[key] yield key, self[key]
def _iterlists(self): def lists(self):
"""Yields (key, list) pairs.""" """Yields (key, list) pairs."""
return six.iteritems(super(MultiValueDict, self)) return six.iteritems(super(MultiValueDict, self))
def _itervalues(self): def values(self):
"""Yield the last value on every key list.""" """Yield the last value on every key list."""
for key in self: for key in self:
yield self[key] 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): def copy(self):
"""Returns a shallow copy of this object.""" """Returns a shallow copy of this object."""
return copy.copy(self) return copy.copy(self)

View File

@ -7,8 +7,6 @@ except ImportError:
from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wraps from functools import WRAPPER_ASSIGNMENTS, update_wrapper, wraps
from django.utils import six
class classonlymethod(classmethod): class classonlymethod(classmethod):
def __get__(self, instance, cls=None): def __get__(self, instance, cls=None):
@ -121,13 +119,10 @@ def decorator_from_middleware(middleware_class):
def available_attrs(fn): def available_attrs(fn):
""" """
Return the list of functools-wrappable attributes on a callable. 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. under Python 2.
""" """
if six.PY3: return WRAPPER_ASSIGNMENTS
return WRAPPER_ASSIGNMENTS
else:
return tuple(a for a in WRAPPER_ASSIGNMENTS if hasattr(fn, a))
def make_middleware_decorator(middleware_class): def make_middleware_decorator(middleware_class):

View File

@ -2,13 +2,11 @@ import codecs
import datetime import datetime
import locale import locale
from decimal import Decimal from decimal import Decimal
from urllib.parse import unquote_to_bytes
from django.utils import six from django.utils import six
from django.utils.functional import Promise from django.utils.functional import Promise
from django.utils.six.moves.urllib.parse import quote, unquote from django.utils.six.moves.urllib.parse import quote
if six.PY3:
from urllib.parse import unquote_to_bytes
class DjangoUnicodeDecodeError(UnicodeDecodeError): class DjangoUnicodeDecodeError(UnicodeDecodeError):
@ -66,15 +64,10 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
return s return s
try: try:
if not issubclass(type(s), six.string_types): if not issubclass(type(s), six.string_types):
if six.PY3: if isinstance(s, bytes):
if isinstance(s, bytes): s = six.text_type(s, encoding, errors)
s = six.text_type(s, encoding, errors)
else:
s = six.text_type(s)
elif hasattr(s, '__unicode__'):
s = six.text_type(s)
else: else:
s = six.text_type(bytes(s), encoding, errors) s = six.text_type(s)
else: else:
# Note: We use .decode() here, instead of six.text_type(s, encoding, # 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 # 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) return six.text_type(s).encode(encoding, errors)
if not isinstance(s, six.string_types): if not isinstance(s, six.string_types):
try: try:
if six.PY3: return six.text_type(s).encode(encoding)
return six.text_type(s).encode(encoding)
else:
return bytes(s)
except UnicodeEncodeError: except UnicodeEncodeError:
if isinstance(s, Exception): if isinstance(s, Exception):
# An Exception subclass containing non-ASCII data that doesn't # 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) return s.encode(encoding, errors)
if six.PY3: smart_str = smart_text
smart_str = smart_text force_str = force_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.__doc__ = """ smart_str.__doc__ = """
Apply smart_text in Python 3 and smart_bytes in Python 2. 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: if uri is None:
return uri return uri
uri = force_bytes(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') return repercent_broken_unicode(iri).decode('utf-8')

View File

@ -23,7 +23,7 @@ http://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/
""" """
import datetime 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.encoding import force_text, iri_to_uri
from django.utils.six import StringIO from django.utils.six import StringIO
from django.utils.six.moves.urllib.parse import urlparse from django.utils.six.moves.urllib.parse import urlparse
@ -42,8 +42,6 @@ def rfc2822_date(date):
dow = days[date.weekday()] dow = days[date.weekday()]
month = months[date.month - 1] month = months[date.month - 1]
time_str = date.strftime('%s, %%d %s %%Y %%H:%%M:%%S ' % (dow, month)) 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() offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC. # Historically, this function assumes that naive datetimes are in UTC.
if offset is None: if offset is None:
@ -58,8 +56,6 @@ def rfc3339_date(date):
# Support datetime objects older than 1900 # Support datetime objects older than 1900
date = datetime_safe.new_datetime(date) date = datetime_safe.new_datetime(date)
time_str = date.strftime('%Y-%m-%dT%H:%M:%S') 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() offset = date.utcoffset()
# Historically, this function assumes that naive datetimes are in UTC. # Historically, this function assumes that naive datetimes are in UTC.
if offset is None: if offset is None:

View File

@ -92,16 +92,9 @@ def lazy(func, *resultclasses):
assert not (cls._delegate_bytes and cls._delegate_text), ( assert not (cls._delegate_bytes and cls._delegate_text), (
"Cannot call lazy() with both bytes and text return types.") "Cannot call lazy() with both bytes and text return types.")
if cls._delegate_text: if cls._delegate_text:
if six.PY3: cls.__str__ = cls.__text_cast
cls.__str__ = cls.__text_cast
else:
cls.__unicode__ = cls.__text_cast
cls.__str__ = cls.__bytes_cast_encoded
elif cls._delegate_bytes: elif cls._delegate_bytes:
if six.PY3: cls.__bytes__ = cls.__bytes_cast
cls.__bytes__ = cls.__bytes_cast
else:
cls.__str__ = cls.__bytes_cast
@classmethod @classmethod
def __promise__(cls, method_name): def __promise__(cls, method_name):
@ -154,9 +147,7 @@ def lazy(func, *resultclasses):
return hash(self.__cast()) return hash(self.__cast())
def __mod__(self, rhs): def __mod__(self, rhs):
if self._delegate_bytes and six.PY2: if self._delegate_text:
return bytes(self) % rhs
elif self._delegate_text:
return six.text_type(self) % rhs return six.text_type(self) % rhs
return self.__cast() % rhs return self.__cast() % rhs
@ -316,14 +307,9 @@ class LazyObject(object):
return result return result
return copy.deepcopy(self._wrapped, memo) return copy.deepcopy(self._wrapped, memo)
if six.PY3: __bytes__ = new_method_proxy(bytes)
__bytes__ = new_method_proxy(bytes) __str__ = new_method_proxy(str)
__str__ = new_method_proxy(str) __bool__ = new_method_proxy(bool)
__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)
# Introspection support # Introspection support
__dir__ = new_method_proxy(dir) __dir__ = new_method_proxy(dir)

View File

@ -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

View File

@ -363,22 +363,12 @@ def html_safe(klass):
"can't apply @html_safe to %s because it defines " "can't apply @html_safe to %s because it defines "
"__html__()." % klass.__name__ "__html__()." % klass.__name__
) )
if six.PY2: if '__str__' not in klass.__dict__:
if '__unicode__' not in klass.__dict__: raise ValueError(
raise ValueError( "can't apply @html_safe to %s because it doesn't "
"can't apply @html_safe to %s because it doesn't " "define __str__()." % klass.__name__
"define __unicode__()." % klass.__name__ )
) klass_str = klass.__str__
klass_unicode = klass.__unicode__ klass.__str__ = lambda self: mark_safe(klass_str(self))
klass.__unicode__ = lambda self: mark_safe(klass_unicode(self)) klass.__html__ = lambda self: str(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)
return klass return klass

View File

@ -1,4 +1,3 @@
from django.utils import six
from django.utils.six.moves import html_parser as _html_parser from django.utils.six.moves import html_parser as _html_parser
try: try:
@ -8,15 +7,13 @@ except AttributeError:
class HTMLParseError(Exception): class HTMLParseError(Exception):
pass 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 class HTMLParser(_html_parser.HTMLParser):
it at call time because Python 2.7 does not have the keyword """Explicitly set convert_charrefs to be False.
argument.
""" This silences a deprecation warning on Python 3.4, but we can't do
def __init__(self, convert_charrefs=False, **kwargs): it at call time because Python 2.7 does not have the keyword
_html_parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs) argument.
else: """
HTMLParser = _html_parser.HTMLParser def __init__(self, convert_charrefs=False, **kwargs):
_html_parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs)

View File

@ -189,12 +189,7 @@ def base36_to_int(s):
# is sufficient to base36-encode any 64-bit integer) # is sufficient to base36-encode any 64-bit integer)
if len(s) > 13: if len(s) > 13:
raise ValueError("Base36 input too large") raise ValueError("Base36 input too large")
value = int(s, 36) return 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
def int_to_base36(i): def int_to_base36(i):
@ -204,11 +199,6 @@ def int_to_base36(i):
char_set = '0123456789abcdefghijklmnopqrstuvwxyz' char_set = '0123456789abcdefghijklmnopqrstuvwxyz'
if i < 0: if i < 0:
raise ValueError("Negative base36 conversion input.") 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: if i < 36:
return char_set[i] return char_set[i]
b36 = '' b36 = ''
@ -296,11 +286,6 @@ def is_safe_url(url, host=None, allowed_hosts=None, require_https=False):
url = url.strip() url = url.strip()
if not url: if not url:
return False return False
if six.PY2:
try:
url = force_text(url)
except UnicodeDecodeError:
return False
if allowed_hosts is None: if allowed_hosts is None:
allowed_hosts = set() allowed_hosts = set()
if host: if host:
@ -388,13 +373,9 @@ def limited_parse_qsl(qs, keep_blank_values=False, encoding='utf-8',
else: else:
continue continue
if len(nv[1]) or keep_blank_values: if len(nv[1]) or keep_blank_values:
if six.PY3: name = nv[0].replace('+', ' ')
name = nv[0].replace('+', ' ') name = unquote(name, encoding=encoding, errors=errors)
name = unquote(name, encoding=encoding, errors=errors) value = nv[1].replace('+', ' ')
value = nv[1].replace('+', ' ') value = unquote(value, encoding=encoding, errors=errors)
value = unquote(value, encoding=encoding, errors=errors)
else:
name = unquote(nv[0].replace(b'+', b' '))
value = unquote(nv[1].replace(b'+', b' '))
r.append((name, value)) r.append((name, value))
return r return r

View File

@ -1,12 +1,7 @@
import inspect import inspect
from django.utils import six
def getargspec(func): def getargspec(func):
if six.PY2:
return inspect.getargspec(func)
sig = inspect.signature(func) sig = inspect.signature(func)
args = [ args = [
p.name for p in sig.parameters.values() p.name for p in sig.parameters.values()
@ -30,10 +25,6 @@ def getargspec(func):
def get_func_args(func): def get_func_args(func):
if six.PY2:
argspec = inspect.getargspec(func)
return argspec.args[1:] # ignore 'self'
sig = inspect.signature(func) sig = inspect.signature(func)
return [ return [
arg_name for arg_name, param in sig.parameters.items() 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 does not have a default value, omit it in the tuple. Arguments such as
*args and **kwargs are also included. *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) sig = inspect.signature(func)
args = [] args = []
for arg_name, param in sig.parameters.items(): for arg_name, param in sig.parameters.items():
@ -80,20 +57,6 @@ def get_func_full_args(func):
def func_accepts_kwargs(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( return any(
p for p in inspect.signature(func).parameters.values() p for p in inspect.signature(func).parameters.values()
if p.kind == p.VAR_KEYWORD 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. Return True if function 'func' accepts positional arguments *args.
""" """
if six.PY2:
return inspect.getargspec(func)[1] is not None
return any( return any(
p for p in inspect.signature(func).parameters.values() p for p in inspect.signature(func).parameters.values()
if p.kind == p.VAR_POSITIONAL if p.kind == p.VAR_POSITIONAL
@ -114,7 +74,7 @@ def func_accepts_var_args(func):
def func_has_no_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() p for p in inspect.signature(func).parameters.values()
if p.kind == p.POSITIONAL_OR_KEYWORD if p.kind == p.POSITIONAL_OR_KEYWORD
] ]
@ -122,8 +82,4 @@ def func_has_no_args(func):
def func_supports_parameter(func, parameter): def func_supports_parameter(func, parameter):
if six.PY3: return parameter in inspect.signature(func).parameters
return parameter in inspect.signature(func).parameters
else:
args, varargs, varkw, defaults = inspect.getargspec(func)
return parameter in args

View File

@ -2,6 +2,7 @@ import copy
import os import os
import sys import sys
from importlib import import_module from importlib import import_module
from importlib.util import find_spec as importlib_find
from django.utils import six from django.utils import six
@ -63,88 +64,17 @@ def autodiscover_modules(*args, **kwargs):
raise raise
if six.PY3: def module_has_submodule(package, module_name):
from importlib.util import find_spec as importlib_find """See if 'module' is in 'package'."""
try:
package_name = package.__name__
package_path = package.__path__
except AttributeError:
# package isn't a package.
return False
def module_has_submodule(package, module_name): full_module_name = package_name + '.' + module_name
"""See if 'module' is in 'package'.""" return importlib_find(full_module_name, package_path) is not None
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_dir(module): def module_dir(module):

View File

@ -83,12 +83,7 @@ class SafeText(six.text_type, SafeData):
encode = curry(_proxy_method, method=six.text_type.encode) encode = curry(_proxy_method, method=six.text_type.encode)
if six.PY3: SafeString = SafeText
SafeString = SafeText
else:
SafeString = SafeBytes
# backwards compatibility for Python 2
SafeUnicode = SafeText
def _safety_decorator(safety_marker, func): def _safety_decorator(safety_marker, func):

View File

@ -12,11 +12,6 @@ from django.utils.safestring import SafeText, mark_safe
from django.utils.six.moves import html_entities from django.utils.six.moves import html_entities
from django.utils.translation import pgettext, ugettext as _, ugettext_lazy 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 @keep_lazy_text
def capfirst(x): def capfirst(x):

View File

@ -5,7 +5,6 @@ from django.template.base import (
TOKEN_BLOCK, TOKEN_COMMENT, TOKEN_TEXT, TOKEN_VAR, TRANSLATOR_COMMENT_MARK, TOKEN_BLOCK, TOKEN_COMMENT, TOKEN_TEXT, TOKEN_VAR, TRANSLATOR_COMMENT_MARK,
Lexer, Lexer,
) )
from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.six import StringIO from django.utils.six import StringIO
@ -57,7 +56,7 @@ def templatize(src, origin=None, charset='utf-8'):
comment_lineno_cache = None comment_lineno_cache = None
# Adding the u prefix allows gettext to recognize the Unicode string # Adding the u prefix allows gettext to recognize the Unicode string
# (#26093). # (#26093).
raw_prefix = 'u' if six.PY3 else '' raw_prefix = 'u'
def join_tokens(tokens, trim=False): def join_tokens(tokens, trim=False):
message = ''.join(tokens) message = ''.join(tokens)

View File

@ -13,7 +13,7 @@ from django.conf.locale import LANG_INFO
from django.core.exceptions import AppRegistryNotReady from django.core.exceptions import AppRegistryNotReady
from django.core.signals import setting_changed from django.core.signals import setting_changed
from django.dispatch import receiver 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._os import upath
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.safestring import SafeData, mark_safe from django.utils.safestring import SafeData, mark_safe
@ -336,11 +336,7 @@ def gettext(message):
return do_translate(message, 'gettext') return do_translate(message, 'gettext')
if six.PY3: ugettext = gettext
ugettext = gettext
else:
def ugettext(message):
return do_translate(message, 'ugettext')
def pgettext(context, message): def pgettext(context, message):
@ -384,15 +380,7 @@ def ngettext(singular, plural, number):
return do_ntranslate(singular, plural, number, 'ngettext') return do_ntranslate(singular, plural, number, 'ngettext')
if six.PY3: ungettext = ngettext
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')
def npgettext(context, singular, plural, number): def npgettext(context, singular, plural, number):

View File

@ -399,11 +399,9 @@ class ExceptionReporter(object):
if not exceptions: if not exceptions:
return frames return frames
# In case there's just one exception (always in Python 2, # In case there's just one exception, take the traceback from self.tb
# sometimes in Python 3), take the traceback from self.tb (Python 2
# doesn't have a __traceback__ attribute on Exception)
exc_value = exceptions.pop() 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: while tb is not None:
# Support for __traceback_hide__ which is used by a few libraries # 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 # If the traceback for current exception is consumed, try the
# other exception. # other exception.
if six.PY2: if not tb.tb_next and exceptions:
tb = tb.tb_next
elif not tb.tb_next and exceptions:
exc_value = exceptions.pop() exc_value = exceptions.pop()
tb = exc_value.__traceback__ tb = exc_value.__traceback__
else: else:

View File

@ -3,7 +3,7 @@ doc_files = docs extras AUTHORS INSTALL LICENSE README.rst
install-script = scripts/rpm-install.sh install-script = scripts/rpm-install.sh
[flake8] [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 ignore = W601
max-line-length = 119 max-line-length = 119

View File

@ -10,7 +10,6 @@ from django.db.models import fields
from django.test import SimpleTestCase, modify_settings, override_settings from django.test import SimpleTestCase, modify_settings, override_settings
from django.test.utils import captured_stderr from django.test.utils import captured_stderr
from django.urls import reverse from django.urls import reverse
from django.utils import six
from .models import Company, Person from .models import Company, Person
from .tests import AdminDocsTestCase, TestDataMixin from .tests import AdminDocsTestCase, TestDataMixin
@ -53,7 +52,6 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase):
self.assertContains(response, 'Views by namespace test') self.assertContains(response, 'Views by namespace test')
self.assertContains(response, 'Name: <code>test:func</code>.') 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): def test_view_index_with_method(self):
""" """
Views that are methods are listed correctly. 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']) url = reverse('django-admindocs-views-detail', args=['django.contrib.admin.sites.AdminSite.index'])
response = self.client.get(url) 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): def test_model_index(self):
response = self.client.get(reverse('django-admindocs-models-index')) response = self.client.get(reverse('django-admindocs-models-index'))

View File

@ -27,7 +27,7 @@ from django.test import (
) )
from django.utils._os import npath, upath from django.utils._os import npath, upath
from django.utils.encoding import force_text 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') 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(app_path))
self.assertTrue(os.path.exists(os.path.join(app_path, 'api.py'))) 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): def test_startapp_unicode_name(self):
"directory: startapp creates the correct directory with unicode characters" "directory: startapp creates the correct directory with unicode characters"
args = ['startapp', 'こんにちは'] args = ['startapp', 'こんにちは']
@ -1897,18 +1896,11 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
self.addCleanup(shutil.rmtree, testproject_dir, True) self.addCleanup(shutil.rmtree, testproject_dir, True)
out, err = self.run_django_admin(args) out, err = self.run_django_admin(args)
if PY2: self.assertOutput(
self.assertOutput( err,
err, "Error: '%s' is not a valid project name. Please make "
"Error: '%s' is not a valid project name. Please make " "sure the name is a valid identifier." % bad_name
"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.assertFalse(os.path.exists(testproject_dir)) self.assertFalse(os.path.exists(testproject_dir))
def test_simple_project_different_directory(self): def test_simple_project_different_directory(self):

View File

@ -8,7 +8,6 @@ from django.db.models import (
) )
from django.db.models.functions import Lower from django.db.models.functions import Lower
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
from django.utils import six
from .models import ( from .models import (
Author, Book, Company, DepartmentStore, Employee, Publisher, Store, Ticket, Author, Book, Company, DepartmentStore, Employee, Publisher, Store, Ticket,
@ -24,7 +23,7 @@ def cxOracle_py3_bug(func):
""" """
from unittest import expectedFailure from unittest import expectedFailure
from django.db import connection 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): class NonAggregateAnnotationTestCase(TestCase):

View File

@ -1,5 +1,4 @@
import os import os
from unittest import skipUnless
from django.apps import AppConfig, apps from django.apps import AppConfig, apps
from django.apps.registry import 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.db import models
from django.test import SimpleTestCase, override_settings from django.test import SimpleTestCase, override_settings
from django.test.utils import extend_sys_path, isolate_apps from django.test.utils import extend_sys_path, isolate_apps
from django.utils import six
from django.utils._os import upath from django.utils._os import upath
from .default_config_app.apps import CustomConfig from .default_config_app.apps import CustomConfig
@ -371,7 +369,6 @@ class AppConfigTests(SimpleTestCase):
self.assertEqual(ac.path, 'a') self.assertEqual(ac.path, 'a')
@skipUnless(six.PY3, "Namespace packages sans __init__.py were added in Python 3.3")
class NamespacePackageAppTests(SimpleTestCase): class NamespacePackageAppTests(SimpleTestCase):
# We need nsapp to be top-level so our multiple-paths tests can add another # 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 # location for it (if its inside a normal package with an __init__.py that

View File

@ -1,6 +1,5 @@
import datetime import datetime
import re import re
from unittest import skipIf
from django import forms from django import forms
from django.contrib.auth.forms import ( from django.contrib.auth.forms import (
@ -15,7 +14,7 @@ from django.core import mail
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
from django.forms.fields import CharField, Field, IntegerField from django.forms.fields import CharField, Field, IntegerField
from django.test import SimpleTestCase, TestCase, mock, override_settings 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.encoding import force_text
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -114,14 +113,10 @@ class UserCreationFormTest(TestDataMixin, TestCase):
'password2': 'test123', 'password2': 'test123',
} }
form = UserCreationForm(data) form = UserCreationForm(data)
if six.PY3: self.assertTrue(form.is_valid())
self.assertTrue(form.is_valid()) u = form.save()
u = form.save() self.assertEqual(u.username, '')
self.assertEqual(u.username, '')
else:
self.assertFalse(form.is_valid())
@skipIf(six.PY2, "Python 2 doesn't support unicode usernames by default.")
def test_normalize_username(self): def test_normalize_username(self):
# The normalization happens in AbstractBaseUser.clean() and ModelForm # The normalization happens in AbstractBaseUser.clean() and ModelForm
# validation calls Model.clean(). # validation calls Model.clean().
@ -137,7 +132,6 @@ class UserCreationFormTest(TestDataMixin, TestCase):
self.assertNotEqual(user.username, ohm_username) self.assertNotEqual(user.username, ohm_username)
self.assertEqual(user.username, 'testΩ') # U+03A9 GREEK CAPITAL LETTER OMEGA 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): def test_duplicate_normalized_unicode(self):
""" """
To prevent almost identical usernames, visually identical but differing To prevent almost identical usernames, visually identical but differing

View File

@ -32,9 +32,6 @@ def mock_inputs(inputs):
class mock_getpass: class mock_getpass:
@staticmethod @staticmethod
def getpass(prompt=b'Password: ', stream=None): 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']): if callable(inputs['password']):
return inputs['password']() return inputs['password']()
return inputs['password'] return inputs['password']

View File

@ -1,11 +1,9 @@
import unittest
from datetime import date, timedelta from datetime import date, timedelta
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.test import TestCase from django.test import TestCase
from django.utils.six import PY3
class TokenGeneratorTest(TestCase): class TokenGeneratorTest(TestCase):
@ -51,18 +49,6 @@ class TokenGeneratorTest(TestCase):
p2 = Mocked(date.today() + timedelta(settings.PASSWORD_RESET_TIMEOUT_DAYS + 1)) p2 = Mocked(date.today() + timedelta(settings.PASSWORD_RESET_TIMEOUT_DAYS + 1))
self.assertFalse(p2.check_token(user, tk1)) 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): def test_check_token_with_nonexistent_token_and_user(self):
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw') user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
p0 = PasswordResetTokenGenerator() p0 = PasswordResetTokenGenerator()

View File

@ -1,7 +1,6 @@
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db.utils import load_backend from django.db.utils import load_backend
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils import six
class TestLoadBackend(SimpleTestCase): class TestLoadBackend(SimpleTestCase):
@ -10,7 +9,7 @@ class TestLoadBackend(SimpleTestCase):
"'foo' isn't an available database backend.\n" "'foo' isn't an available database backend.\n"
"Try using 'django.db.backends.XXX', where XXX is one of:\n" "Try using 'django.db.backends.XXX', where XXX is one of:\n"
" 'mysql', 'oracle', 'postgresql', 'sqlite3'\n" " 'mysql', 'oracle', 'postgresql', 'sqlite3'\n"
"Error was: No module named %s" "Error was: No module named 'foo'"
) % "foo.base" if six.PY2 else "'foo'" )
with self.assertRaisesMessage(ImproperlyConfigured, msg): with self.assertRaisesMessage(ImproperlyConfigured, msg):
load_backend('foo') load_backend('foo')

View File

@ -13,12 +13,3 @@ class CustomBaseModel(models.base.ModelBase):
class MyModel(six.with_metaclass(CustomBaseModel, models.Model)): class MyModel(six.with_metaclass(CustomBaseModel, models.Model)):
"""Model subclass with a custom base using six.with_metaclass.""" """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

View File

@ -928,11 +928,7 @@ class BaseCacheTests(object):
self.assertEqual(cache.get_or_set('mykey', my_callable()), 'value') self.assertEqual(cache.get_or_set('mykey', my_callable()), 'value')
def test_get_or_set_version(self): def test_get_or_set_version(self):
msg = ( msg = "get_or_set() missing 1 required positional argument: 'default'"
"get_or_set() missing 1 required positional argument: 'default'"
if six.PY3
else 'get_or_set() takes at least 3 arguments'
)
cache.get_or_set('brian', 1979, version=2) cache.get_or_set('brian', 1979, version=2)
with self.assertRaisesMessage(TypeError, msg): with self.assertRaisesMessage(TypeError, msg):
cache.get_or_set('brian') cache.get_or_set('brian')

View File

@ -3,7 +3,6 @@ import os
from django.db.backends.postgresql.client import DatabaseClient from django.db.backends.postgresql.client import DatabaseClient
from django.test import SimpleTestCase, mock from django.test import SimpleTestCase, mock
from django.utils import six
from django.utils.encoding import force_bytes, force_str from django.utils.encoding import force_bytes, force_str
@ -91,16 +90,12 @@ class PostgreSqlDbshellCommandTestCase(SimpleTestCase):
encoding = locale.getpreferredencoding() encoding = locale.getpreferredencoding()
username = 'rôle' username = 'rôle'
password = 'sésame' password = 'sésame'
try: username_str = force_str(username, encoding)
username_str = force_str(username, encoding) password_str = force_str(password, encoding)
password_str = force_str(password, encoding) pgpass_bytes = force_bytes(
pgpass_bytes = force_bytes( 'somehost:444:dbname:%s:%s' % (username, password),
'somehost:444:dbname:%s:%s' % (username, password), encoding=encoding,
encoding=encoding, )
)
except UnicodeEncodeError:
if six.PY2:
self.skipTest("Your locale can't run this test.")
self.assertEqual( self.assertEqual(
self._run_it({ self._run_it({
'database': 'dbname', 'database': 'dbname',

View File

@ -15,7 +15,7 @@ from django.http.multipartparser import MultiPartParser, parse_header
from django.test import SimpleTestCase, TestCase, client, override_settings from django.test import SimpleTestCase, TestCase, client, override_settings
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.http import urlquote from django.utils.http import urlquote
from django.utils.six import PY2, StringIO from django.utils.six import StringIO
from . import uploadhandler from . import uploadhandler
from .models import FileModel from .models import FileModel
@ -102,9 +102,7 @@ class FileUploadTests(TestCase):
self._test_base64_upload("Big data" * 68000) # > 512Kb self._test_base64_upload("Big data" * 68000) # > 512Kb
def test_big_base64_newlines_upload(self): def test_big_base64_newlines_upload(self):
self._test_base64_upload( self._test_base64_upload("Big data" * 68000, encode=base64.encodebytes)
# encodestring is a deprecated alias on Python 3
"Big data" * 68000, encode=base64.encodestring if PY2 else base64.encodebytes)
def test_unicode_file_name(self): def test_unicode_file_name(self):
tdir = sys_tempfile.mkdtemp() tdir = sys_tempfile.mkdtemp()

View File

@ -181,10 +181,7 @@ class ContentFileTestCase(unittest.TestCase):
retrieved content is of the same type. retrieved content is of the same type.
""" """
self.assertIsInstance(ContentFile(b"content").read(), bytes) self.assertIsInstance(ContentFile(b"content").read(), bytes)
if six.PY3: self.assertIsInstance(ContentFile("español").read(), six.text_type)
self.assertIsInstance(ContentFile("español").read(), six.text_type)
else:
self.assertIsInstance(ContentFile("español").read(), bytes)
class DimensionClosingBug(unittest.TestCase): class DimensionClosingBug(unittest.TestCase):

View File

@ -2,10 +2,8 @@
import json import json
import os import os
import re import re
import unittest
import warnings import warnings
import django
from django.core import management, serializers from django.core import management, serializers
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.serializers.base import DeserializationError from django.core.serializers.base import DeserializationError
@ -15,9 +13,8 @@ from django.test import (
TestCase, TransactionTestCase, override_settings, skipIfDBFeature, TestCase, TransactionTestCase, override_settings, skipIfDBFeature,
skipUnlessDBFeature, skipUnlessDBFeature,
) )
from django.utils import six
from django.utils._os import upath from django.utils._os import upath
from django.utils.six import PY3, StringIO from django.utils.six import StringIO
from .models import ( from .models import (
Absolute, Animal, Article, Book, Child, Circle1, Circle2, Circle3, 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__))) _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): class TestFixtures(TestCase):
def animal_pre_save_check(self, signal, sender, instance, **kwargs): def animal_pre_save_check(self, signal, sender, instance, **kwargs):
@ -205,7 +192,6 @@ class TestFixtures(TestCase):
verbosity=0, verbosity=0,
) )
@skipIfNonASCIIPath
@override_settings(SERIALIZATION_MODULES={'unkn': 'unexistent.path'}) @override_settings(SERIALIZATION_MODULES={'unkn': 'unexistent.path'})
def test_unimportable_serializer(self): def test_unimportable_serializer(self):
""" """
@ -350,8 +336,8 @@ class TestFixtures(TestCase):
self.assertEqual( self.assertEqual(
self.pre_save_checks, self.pre_save_checks,
[ [
("Count = 42 (<%s 'int'>)" % ('class' if PY3 else 'type'), ("Count = 42 (<class 'int'>)",
"Weight = 1.2 (<%s 'float'>)" % ('class' if PY3 else 'type')) "Weight = 1.2 (<class 'float'>)")
] ]
) )
finally: finally:
@ -531,7 +517,6 @@ class TestFixtures(TestCase):
with self.assertRaisesMessage(ImproperlyConfigured, "settings.FIXTURE_DIRS contains duplicates."): with self.assertRaisesMessage(ImproperlyConfigured, "settings.FIXTURE_DIRS contains duplicates."):
management.call_command('loaddata', 'absolute.json', verbosity=0) management.call_command('loaddata', 'absolute.json', verbosity=0)
@skipIfNonASCIIPath
@override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures')]) @override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures')])
def test_fixture_dirs_with_default_fixture_path(self): def test_fixture_dirs_with_default_fixture_path(self):
""" """

View File

@ -34,7 +34,7 @@ class HandlerTests(SimpleTestCase):
produces a 404. produces a 404.
""" """
environ = RequestFactory().get('/').environ environ = RequestFactory().get('/').environ
environ['PATH_INFO'] = b'\xed' if six.PY2 else '\xed' environ['PATH_INFO'] = '\xed'
handler = WSGIHandler() handler = WSGIHandler()
response = handler(environ, lambda *a, **k: None) response = handler(environ, lambda *a, **k: None)
# The path of the request will be encoded to '/%ED'. # The path of the request will be encoded to '/%ED'.
@ -53,25 +53,17 @@ class HandlerTests(SimpleTestCase):
] ]
got = [] got = []
for raw_query_string in raw_query_strings: for raw_query_string in raw_query_strings:
if six.PY3: # Simulate http.server.BaseHTTPRequestHandler.parse_request handling of raw request
# Simulate http.server.BaseHTTPRequestHandler.parse_request handling of raw request environ['QUERY_STRING'] = str(raw_query_string, 'iso-8859-1')
environ['QUERY_STRING'] = str(raw_query_string, 'iso-8859-1')
else:
environ['QUERY_STRING'] = raw_query_string
request = WSGIRequest(environ) request = WSGIRequest(environ)
got.append(request.GET['want']) got.append(request.GET['want'])
if six.PY2: # %E9 is converted to the unicode replacement character by parse_qsl
self.assertListEqual(got, ['café', 'café', 'café', 'café']) self.assertListEqual(got, ['café', 'café', 'caf\ufffd', 'café'])
else:
# On Python 3, %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): def test_non_ascii_cookie(self):
"""Non-ASCII cookies set in JavaScript are properly decoded (#20557).""" """Non-ASCII cookies set in JavaScript are properly decoded (#20557)."""
environ = RequestFactory().get('/').environ environ = RequestFactory().get('/').environ
raw_cookie = 'want="café"' raw_cookie = 'want="café"'.encode('utf-8').decode('iso-8859-1')
if six.PY3:
raw_cookie = raw_cookie.encode('utf-8').decode('iso-8859-1')
environ['HTTP_COOKIE'] = raw_cookie environ['HTTP_COOKIE'] = raw_cookie
request = WSGIRequest(environ) request = WSGIRequest(environ)
# If would be nicer if request.COOKIES returned unicode values. # If would be nicer if request.COOKIES returned unicode values.

View File

@ -55,8 +55,6 @@ class QueryDictTests(SimpleTestCase):
def test_immutable_basic_operations(self): def test_immutable_basic_operations(self):
q = QueryDict() q = QueryDict()
self.assertEqual(q.getlist('foo'), []) self.assertEqual(q.getlist('foo'), [])
if six.PY2:
self.assertIs(q.has_key('foo'), False)
self.assertNotIn('foo', q) self.assertNotIn('foo', q)
self.assertEqual(list(six.iteritems(q)), []) self.assertEqual(list(six.iteritems(q)), [])
self.assertEqual(list(six.iterlists(q)), []) self.assertEqual(list(six.iterlists(q)), [])
@ -85,11 +83,7 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
q.appendlist('foo', ['bar']) q.appendlist('foo', ['bar'])
if six.PY2:
self.assertTrue(q.has_key('foo'))
self.assertIn('foo', q) self.assertIn('foo', q)
if six.PY2:
self.assertFalse(q.has_key('bar'))
self.assertNotIn('bar', q) self.assertNotIn('bar', q)
self.assertEqual(list(six.iteritems(q)), [('foo', 'bar')]) self.assertEqual(list(six.iteritems(q)), [('foo', 'bar')])
@ -150,8 +144,6 @@ class QueryDictTests(SimpleTestCase):
q.appendlist('foo', 'another') q.appendlist('foo', 'another')
self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another']) self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another'])
self.assertEqual(q['foo'], 'another') self.assertEqual(q['foo'], 'another')
if six.PY2:
self.assertTrue(q.has_key('foo'))
self.assertIn('foo', q) self.assertIn('foo', q)
self.assertListEqual(sorted(six.iteritems(q)), self.assertListEqual(sorted(six.iteritems(q)),
@ -199,11 +191,7 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
q.appendlist('foo', ['bar']) q.appendlist('foo', ['bar'])
if six.PY2:
self.assertIs(q.has_key('vote'), True)
self.assertIn('vote', q) self.assertIn('vote', q)
if six.PY2:
self.assertIs(q.has_key('foo'), False)
self.assertNotIn('foo', q) self.assertNotIn('foo', q)
self.assertEqual(list(six.iteritems(q)), [('vote', 'no')]) self.assertEqual(list(six.iteritems(q)), [('vote', 'no')])
self.assertEqual(list(six.iterlists(q)), [('vote', ['yes', 'no'])]) self.assertEqual(list(six.iterlists(q)), [('vote', ['yes', 'no'])])
@ -224,19 +212,6 @@ class QueryDictTests(SimpleTestCase):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
q.__delitem__('vote') 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): def test_pickle(self):
q = QueryDict() q = QueryDict()
q1 = pickle.loads(pickle.dumps(q, 2)) q1 = pickle.loads(pickle.dumps(q, 2))
@ -807,15 +782,6 @@ class CookieTests(unittest.TestCase):
c.load({'name': 'val'}) c.load({'name': 'val'})
self.assertEqual(c['name'].value, '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): def test_pickle(self):
rawdata = 'Customer="WILE_E_COYOTE"; Path=/acme; Version=1' rawdata = 'Customer="WILE_E_COYOTE"; Path=/acme; Version=1'
expected_output = 'Set-Cookie: %s' % rawdata expected_output = 'Set-Cookie: %s' % rawdata

View File

@ -12,7 +12,7 @@ from django.core.management.commands.makemessages import \
from django.core.management.utils import find_command from django.core.management.utils import find_command
from django.test import SimpleTestCase, mock, override_settings from django.test import SimpleTestCase, mock, override_settings
from django.test.utils import captured_stderr, captured_stdout 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.encoding import force_text
from django.utils.six import StringIO from django.utils.six import StringIO
from django.utils.translation import ugettext from django.utils.translation import ugettext
@ -144,18 +144,11 @@ class CompilationErrorHandling(MessageCompilationTests):
env = os.environ.copy() env = os.environ.copy()
env.update({str('LANG'): str('C')}) env.update({str('LANG'): str('C')})
with mock.patch('django.core.management.utils.Popen', lambda *args, **kwargs: Popen(*args, env=env, **kwargs)): with mock.patch('django.core.management.utils.Popen', lambda *args, **kwargs: Popen(*args, env=env, **kwargs)):
if six.PY2: cmd = MakeMessagesCommand()
# Various assertRaises on PY2 don't support unicode error messages. if cmd.gettext_version < (0, 18, 3):
try: self.skipTest("python-brace-format is a recent gettext addition.")
call_command('compilemessages', locale=['ko'], verbosity=0) with self.assertRaisesMessage(CommandError, "' cannot start a field name"):
except CommandError as err: call_command('compilemessages', locale=['ko'], verbosity=0)
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)
class ProjectAndAppTests(MessageCompilationTests): class ProjectAndAppTests(MessageCompilationTests):

View File

@ -6,7 +6,6 @@ import pickle
from contextlib import contextmanager from contextlib import contextmanager
from importlib import import_module from importlib import import_module
from threading import local from threading import local
from unittest import skipUnless
from django import forms from django import forms
from django.conf import settings 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.numberformat import format as nformat
from django.utils.safestring import SafeBytes, SafeText from django.utils.safestring import SafeBytes, SafeText
from django.utils.six import PY3
from django.utils.translation import ( from django.utils.translation import (
LANGUAGE_SESSION_KEY, activate, check_for_language, deactivate, LANGUAGE_SESSION_KEY, activate, check_for_language, deactivate,
get_language, get_language_from_request, get_language_info, gettext, get_language, get_language_from_request, get_language_info, gettext_lazy,
gettext_lazy, ngettext_lazy, npgettext, npgettext_lazy, pgettext, ngettext_lazy, npgettext, npgettext_lazy, pgettext, trans_real, ugettext,
pgettext_lazy, trans_real, ugettext, ugettext_lazy, ungettext, ugettext_lazy, ungettext, ungettext_lazy,
ungettext_lazy,
) )
from .forms import CompanyForm, I18nForm, SelectDateForm from .forms import CompanyForm, I18nForm, SelectDateForm
@ -141,33 +138,6 @@ class TranslationTests(SimpleTestCase):
s4 = ugettext_lazy('Some other string') s4 = ugettext_lazy('Some other string')
self.assertNotEqual(s, s4) 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): def test_lazy_pickle(self):
s1 = ugettext_lazy("test") s1 = ugettext_lazy("test")
self.assertEqual(six.text_type(s1), "test") self.assertEqual(six.text_type(s1), "test")
@ -223,20 +193,6 @@ class TranslationTests(SimpleTestCase):
with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'): with self.assertRaisesMessage(KeyError, 'Your dictionary lacks key'):
complex_context_deferred % {'name': 'Jim'} 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): def test_ungettext_lazy_bool(self):
self.assertTrue(ungettext_lazy('%d good result', '%d good results')) self.assertTrue(ungettext_lazy('%d good result', '%d good results'))
self.assertFalse(ungettext_lazy('', '')) self.assertFalse(ungettext_lazy('', ''))
@ -298,7 +254,7 @@ class FormattingTests(SimpleTestCase):
self.d = datetime.date(2009, 12, 31) self.d = datetime.date(2009, 12, 31)
self.dt = datetime.datetime(2009, 12, 31, 20, 50) self.dt = datetime.datetime(2009, 12, 31, 20, 50)
self.t = datetime.time(10, 15, 48) 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({ self.ctxt = Context({
'n': self.n, 'n': self.n,
't': self.t, 't': self.t,

View File

@ -5,7 +5,7 @@ from django.core.management import call_command
from django.db import connection from django.db import connection
from django.test import TestCase, mock, skipUnlessDBFeature from django.test import TestCase, mock, skipUnlessDBFeature
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.six import PY3, StringIO from django.utils.six import StringIO
from .models import ColumnTypes 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_0 = models.IntegerField(db_column='%s__')" % base_name, output)
self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", output) self.assertIn("field_field_1 = models.IntegerField(db_column='__field')", output)
self.assertIn("prc_x = models.IntegerField(db_column='prc(%) x')", output) self.assertIn("prc_x = models.IntegerField(db_column='prc(%) x')", output)
if PY3: self.assertIn("tamaño = models.IntegerField()", output)
# 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)
def test_table_name_introspection(self): def test_table_name_introspection(self):
""" """

View File

@ -3,7 +3,6 @@ from django.db import models
from django.db.models.fields.related import ForeignObject from django.db.models.fields.related import ForeignObject
from django.test.testcases import SimpleTestCase, skipIfDBFeature from django.test.testcases import SimpleTestCase, skipIfDBFeature
from django.test.utils import isolate_apps, override_settings from django.test.utils import isolate_apps, override_settings
from django.utils import six
@isolate_apps('invalid_models_tests') @isolate_apps('invalid_models_tests')
@ -655,10 +654,8 @@ class RelativeFieldTests(SimpleTestCase):
'with', # a Python keyword 'with', # a Python keyword
'related_name\n', 'related_name\n',
'', '',
'', # non-ASCII
] ]
# Python 2 crashes on non-ASCII strings.
if six.PY3:
invalid_related_names.append('')
class Parent(models.Model): class Parent(models.Model):
pass pass
@ -695,10 +692,9 @@ class RelativeFieldTests(SimpleTestCase):
'ends_with_plus+', 'ends_with_plus+',
'_+', '_+',
'+', '+',
'',
'試驗+',
] ]
# Python 2 crashes on non-ASCII strings.
if six.PY3:
related_names.extend(['', '試驗+'])
class Parent(models.Model): class Parent(models.Model):
pass pass

View File

@ -8,8 +8,10 @@ import socket
import sys import sys
import tempfile import tempfile
import threading import threading
from email import message_from_binary_file, message_from_bytes
from email.header import Header from email.header import Header
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email.utils import parseaddr
from smtplib import SMTP, SMTPAuthenticationError, SMTPException from smtplib import SMTP, SMTPAuthenticationError, SMTPException
from ssl import SSLError 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.test.utils import requires_tz_support
from django.utils._os import upath from django.utils._os import upath
from django.utils.encoding import force_bytes, force_text 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 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): class HeadersCheckMixin(object):
@ -656,16 +648,10 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
sanitize_address(('A name', 'to@example.com'), 'ascii'), sanitize_address(('A name', 'to@example.com'), 'ascii'),
'A name <to@example.com>' 'A name <to@example.com>'
) )
if PY3: self.assertEqual(
self.assertEqual( sanitize_address(('A name', 'to@example.com'), 'utf-8'),
sanitize_address(('A name', 'to@example.com'), 'utf-8'), '=?utf-8?q?A_name?= <to@example.com>'
'=?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>'
)
# Unicode characters are are supported in RFC-6532. # Unicode characters are are supported in RFC-6532.
self.assertEqual( self.assertEqual(
@ -1165,18 +1151,8 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
self.active_lock = threading.Lock() self.active_lock = threading.Lock()
self.sink_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): 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) m = message_from_bytes(data)
maddr = parseaddr(m.get('from'))[1] maddr = parseaddr(m.get('from'))[1]
@ -1448,8 +1424,7 @@ class SMTPBackendTests(BaseEmailBackendTests, SMTPBackendTestsBase):
self.assertTrue(msg) 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. # The message only contains CRLF and not combinations of CRLF, LF, and CR.
msg = msg.replace('\r\n', '') msg = msg.replace('\r\n', '')
self.assertNotIn('\r', msg) self.assertNotIn('\r', msg)

View File

@ -2,7 +2,6 @@ import gzip
import random import random
import re import re
from io import BytesIO from io import BytesIO
from unittest import skipIf
from django.conf import settings from django.conf import settings
from django.core import mail from django.core import mail
@ -401,24 +400,6 @@ class BrokenLinkEmailsMiddlewareTest(SimpleTestCase):
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp) BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
self.assertEqual(len(mail.outbox), 0) 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): def test_custom_request_checker(self):
class SubclassedMiddleware(BrokenLinkEmailsMiddleware): class SubclassedMiddleware(BrokenLinkEmailsMiddleware):
ignored_user_agent_patterns = (re.compile(r'Spider.*'), re.compile(r'Robot.*')) ignored_user_agent_patterns = (re.compile(r'Spider.*'), re.compile(r'Robot.*'))

View File

@ -661,18 +661,10 @@ class MakeMigrationsTests(MigrationTestBase):
self.assertIn('migrations.CreateModel', content) self.assertIn('migrations.CreateModel', content)
self.assertIn('initial = True', content) self.assertIn('initial = True', content)
if six.PY3: self.assertIn('úñí©óðé µóðéø', content) # Meta.verbose_name
self.assertIn('úñí©óðé µóðéø', content) # Meta.verbose_name self.assertIn('úñí©óðé µóðéøß', content) # Meta.verbose_name_plural
self.assertIn('úñí©óðé µóðéøß', content) # Meta.verbose_name_plural self.assertIn('ÚÑÍ¢ÓÐÉ', content) # title.verbose_name
self.assertIn('ÚÑÍ¢ÓÐÉ', content) # title.verbose_name self.assertIn('“Ðjáñgó”', content) # title.default
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
def test_makemigrations_order(self): def test_makemigrations_order(self):
""" """

View File

@ -1,5 +1,3 @@
from unittest import skipIf
from django.db import connection, connections from django.db import connection, connections
from django.db.migrations.exceptions import ( from django.db.migrations.exceptions import (
AmbiguityError, InconsistentMigrationHistory, NodeNotFoundError, AmbiguityError, InconsistentMigrationHistory, NodeNotFoundError,
@ -7,7 +5,6 @@ from django.db.migrations.exceptions import (
from django.db.migrations.loader import MigrationLoader from django.db.migrations.loader import MigrationLoader
from django.db.migrations.recorder import MigrationRecorder from django.db.migrations.recorder import MigrationRecorder
from django.test import TestCase, modify_settings, override_settings from django.test import TestCase, modify_settings, override_settings
from django.utils import six
class RecorderTests(TestCase): class RecorderTests(TestCase):
@ -170,7 +167,6 @@ class LoaderTests(TestCase):
"App with migrations module file not in unmigrated apps." "App with migrations module file not in unmigrated apps."
) )
@skipIf(six.PY2, "PY2 doesn't load empty dirs.")
def test_load_empty_dir(self): def test_load_empty_dir(self):
with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}): with override_settings(MIGRATION_MODULES={"migrations": "migrations.faulty_migrations.namespace"}):
loader = MigrationLoader(connection) loader = MigrationLoader(connection)

View File

@ -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): class OperationWriterTests(SimpleTestCase):
def test_empty_signature(self): def test_empty_signature(self):
@ -486,15 +480,6 @@ class WriterTests(SimpleTestCase):
self.assertEqual(string, 'range') self.assertEqual(string, 'range')
self.assertEqual(imports, set()) 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): def test_serialize_local_function_reference(self):
""" """
Neither py2 or py3 can serialize a reference in a local scope. Neither py2 or py3 can serialize a reference in a local scope.

View File

@ -1,13 +1,12 @@
import datetime import datetime
import unittest
from decimal import Decimal from decimal import Decimal
from django.db.models.fields import ( from django.db.models.fields import (
AutoField, BigIntegerField, BinaryField, BooleanField, CharField, AutoField, BinaryField, BooleanField, CharField, DateField, DateTimeField,
DateField, DateTimeField, DecimalField, EmailField, FilePathField, DecimalField, EmailField, FilePathField, FloatField, GenericIPAddressField,
FloatField, GenericIPAddressField, IntegerField, IPAddressField, IntegerField, IPAddressField, NullBooleanField, PositiveIntegerField,
NullBooleanField, PositiveIntegerField, PositiveSmallIntegerField, PositiveSmallIntegerField, SlugField, SmallIntegerField, TextField,
SlugField, SmallIntegerField, TextField, TimeField, URLField, TimeField, URLField,
) )
from django.db.models.fields.files import FileField, ImageField from django.db.models.fields.files import FileField, ImageField
from django.test import SimpleTestCase from django.test import SimpleTestCase
@ -21,11 +20,6 @@ class PromiseTest(SimpleTestCase):
lazy_func = lazy(lambda: 1, int) lazy_func = lazy(lambda: 1, int)
self.assertIsInstance(AutoField(primary_key=True).get_prep_value(lazy_func()), 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): def test_BinaryField(self):
lazy_func = lazy(lambda: b'', bytes) lazy_func = lazy(lambda: b'', bytes)
self.assertIsInstance(BinaryField().get_prep_value(lazy_func()), bytes) self.assertIsInstance(BinaryField().get_prep_value(lazy_func()), bytes)

View File

@ -1,18 +1,11 @@
import os import os
import shutil import shutil
import unittest
from django import conf from django import conf
from django.test import TestCase from django.test import TestCase
from django.utils import six
from django.utils._os import upath 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): class TestStartProjectSettings(TestCase):
def setUp(self): def setUp(self):
# Ensure settings.py exists # Ensure settings.py exists

View File

@ -11,7 +11,6 @@ from django.db.models.sql.constants import LOUTER
from django.db.models.sql.where import NothingNode, WhereNode from django.db.models.sql.where import NothingNode, WhereNode
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import CaptureQueriesContext from django.test.utils import CaptureQueriesContext
from django.utils import six
from django.utils.six.moves import range from django.utils.six.moves import range
from .models import ( from .models import (
@ -406,7 +405,7 @@ class Queries1Tests(TestCase):
local_recursion_limit = 127 local_recursion_limit = 127
msg = 'Maximum recursion depth exceeded: too many subqueries.' msg = 'Maximum recursion depth exceeded: too many subqueries.'
with self.assertRaisesMessage(RuntimeError, msg): 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) x = Tag.objects.filter(pk__in=x)
def test_reasonable_number_of_subq_aliases(self): 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): def test_slicing_without_step_is_lazy(self):
with self.assertNumQueries(0): with self.assertNumQueries(0):
self.get_ordered_articles()[0:5] self.get_ordered_articles()[0:5]
@ -2965,8 +2945,6 @@ class QuerySetExceptionTests(TestCase):
def test_invalid_order_by(self): def test_invalid_order_by(self):
msg = "Invalid order_by arguments: ['*']" msg = "Invalid order_by arguments: ['*']"
if six.PY2:
msg = msg.replace("[", "[u")
with self.assertRaisesMessage(FieldError, msg): with self.assertRaisesMessage(FieldError, msg):
list(Article.objects.order_by('*')) list(Article.objects.order_by('*'))

View File

@ -1,7 +1,6 @@
import datetime import datetime
from django.db import DJANGO_VERSION_PICKLE_KEY, models from django.db import DJANGO_VERSION_PICKLE_KEY, models
from django.utils import six
from django.utils.translation import ugettext_lazy as _ 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) when = models.DateTimeField(blank=True, default=datetime.datetime.now)
name = models.CharField(blank=True, max_length=100, default="test") name = models.CharField(blank=True, max_length=100, default="test")
number1 = models.IntegerField(blank=True, default=standalone_number) number1 = models.IntegerField(blank=True, default=standalone_number)
if six.PY3: number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
# default serializable on Python 3 only
number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
class Container(object): class Container(object):

View File

@ -1,10 +1,8 @@
import datetime import datetime
import pickle import pickle
import unittest
from django.db import models from django.db import models
from django.test import TestCase from django.test import TestCase
from django.utils import six
from django.utils.version import get_version from django.utils.version import get_version
from .models import Container, Event, Group, Happening, M2MModel from .models import Container, Event, Group, Happening, M2MModel
@ -33,7 +31,6 @@ class PickleabilityTestCase(TestCase):
def test_standalone_method_as_default(self): def test_standalone_method_as_default(self):
self.assert_pickles(Happening.objects.filter(number1=1)) 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): def test_staticmethod_as_default(self):
self.assert_pickles(Happening.objects.filter(number2=1)) self.assert_pickles(Happening.objects.filter(number2=1))

View File

@ -12,7 +12,6 @@ from django.http.request import split_domain_port
from django.test import RequestFactory, SimpleTestCase, override_settings from django.test import RequestFactory, SimpleTestCase, override_settings
from django.test.client import FakePayload from django.test.client import FakePayload
from django.test.utils import freeze_time, str_prefix from django.test.utils import freeze_time, str_prefix
from django.utils import six
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.http import cookie_date, urlencode from django.utils.http import cookie_date, urlencode
from django.utils.six.moves import http_cookies from django.utils.six.moves import http_cookies
@ -168,9 +167,8 @@ class RequestsTests(SimpleTestCase):
def test_wsgirequest_path_info(self): def test_wsgirequest_path_info(self):
def wsgi_str(path_info, encoding='utf-8'): def wsgi_str(path_info, encoding='utf-8'):
path_info = path_info.encode(encoding) # Actual URL sent by the browser (bytestring) 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.decode('iso-8859-1') # Value in the WSGI environ dict (native string)
return path_info return path_info
# Regression for #19468 # Regression for #19468
request = WSGIRequest({'PATH_INFO': wsgi_str("/سلام/"), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')}) request = WSGIRequest({'PATH_INFO': wsgi_str("/سلام/"), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
@ -583,7 +581,7 @@ class RequestsTests(SimpleTestCase):
request = WSGIRequest({ request = WSGIRequest({
'REQUEST_METHOD': 'GET', 'REQUEST_METHOD': 'GET',
'wsgi.input': '', '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']}) self.assertEqual(request.GET, {'name': ['Hello Günter']})
request.encoding = 'iso-8859-16' request.encoding = 'iso-8859-16'

View File

@ -3,7 +3,6 @@ import datetime
from django.core import signing from django.core import signing
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.test.utils import freeze_time from django.test.utils import freeze_time
from django.utils import six
from django.utils.encoding import force_str from django.utils.encoding import force_str
@ -45,8 +44,6 @@ class TestSigner(SimpleTestCase):
'jkw osanteuh ,rcuh nthu aou oauh ,ud du', 'jkw osanteuh ,rcuh nthu aou oauh ,ud du',
'\u2019', '\u2019',
] ]
if six.PY2:
examples.append(b'a byte string')
for example in examples: for example in examples:
signed = signer.sign(example) signed = signer.sign(example)
self.assertIsInstance(signed, str) self.assertIsInstance(signed, str)
@ -76,8 +73,6 @@ class TestSigner(SimpleTestCase):
'a unicode string \u2019', 'a unicode string \u2019',
{'a': 'dictionary'}, {'a': 'dictionary'},
] ]
if six.PY2:
objects.append(b'a byte string')
for o in objects: for o in objects:
self.assertNotEqual(o, signing.dumps(o)) self.assertNotEqual(o, signing.dumps(o))
self.assertEqual(o, signing.loads(signing.dumps(o))) self.assertEqual(o, signing.loads(signing.dumps(o)))

View File

@ -183,8 +183,7 @@ class TestInteractiveMessages(CollectionTestCase):
@staticmethod @staticmethod
def mock_input(stdout): def mock_input(stdout):
def _input(msg): def _input(msg):
# Python 2 reads bytes from the console output, use bytes for the StringIO stdout.write(msg)
stdout.write(msg.encode('utf-8') if six.PY2 else msg)
return 'yes' return 'yes'
return _input return _input

View File

@ -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 Although it's not a strict requirement, each model should have a ``_str__()``
``_str__()`` or ``__unicode__()`` method to return a "human-readable" method to return a "human-readable" representation of the object. Do this not
representation of the object. Do this not only for your own sanity when dealing only for your own sanity when dealing with the interactive prompt, but also
with the interactive prompt, but also because objects' representations are used because objects' representations are used throughout Django's
throughout Django's automatically-generated admin. 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.
""" """
from django.db import models 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): class InternationalArticle(models.Model):
headline = models.CharField(max_length=100) headline = models.CharField(max_length=100)
pub_date = models.DateTimeField() pub_date = models.DateTimeField()

View File

@ -1,25 +1,14 @@
import datetime import datetime
from unittest import skipIf
from django.db import models from django.db import models
from django.test import TestCase from django.test import TestCase
from django.test.utils import isolate_apps from django.test.utils import isolate_apps
from django.utils import six
from .models import Article, InternationalArticle from .models import InternationalArticle
class SimpleTests(TestCase): 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): def test_international(self):
a = InternationalArticle.objects.create( a = InternationalArticle.objects.create(
headline='Girl wins €12.500 in lottery', headline='Girl wins €12.500 in lottery',

View File

@ -1,6 +1,5 @@
from django.template import TemplateSyntaxError from django.template import TemplateSyntaxError
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils import six
from ..utils import setup from ..utils import setup
@ -36,11 +35,10 @@ class WidthRatioTagTests(SimpleTestCase):
@setup({'widthratio06': '{% widthratio a b 100 %}'}) @setup({'widthratio06': '{% widthratio a b 100 %}'})
def test_widthratio06(self): def test_widthratio06(self):
""" """
62.5 should round to 63 on Python 2 and 62 on Python 3 62.5 should round to 62
See http://docs.python.org/py3k/whatsnew/3.0.html
""" """
output = self.engine.render_to_string('widthratio06', {'a': 50, 'b': 80}) 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 %}'}) @setup({'widthratio07': '{% widthratio a b 100 %}'})
def test_widthratio07(self): def test_widthratio07(self):

View File

@ -1,12 +1,10 @@
import os import os
from unittest import skipUnless
from django.template import Context, Engine, TemplateSyntaxError from django.template import Context, Engine, TemplateSyntaxError
from django.template.base import Node from django.template.base import Node
from django.template.library import InvalidTemplateLibrary from django.template.library import InvalidTemplateLibrary
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.test.utils import extend_sys_path from django.test.utils import extend_sys_path
from django.utils import six
from .templatetags import custom, inclusion from .templatetags import custom, inclusion
from .utils import ROOT from .utils import ROOT
@ -344,7 +342,6 @@ class TemplateTagLoadingTests(SimpleTestCase):
}) })
engine.from_string(ttext) engine.from_string(ttext)
@skipUnless(six.PY3, "Python 3 only -- Python 2 doesn't have annotations.")
def test_load_annotated_function(self): def test_load_annotated_function(self):
Engine(libraries={ Engine(libraries={
'annotated_tag_function': 'template_tests.annotated_tag_function', 'annotated_tag_function': 'template_tests.annotated_tag_function',

View File

@ -7,7 +7,6 @@ from contextlib import contextmanager
from django.template import TemplateDoesNotExist from django.template import TemplateDoesNotExist
from django.template.engine import Engine from django.template.engine import Engine
from django.test import SimpleTestCase, override_settings from django.test import SimpleTestCase, override_settings
from django.utils import six
from django.utils.functional import lazystr from django.utils.functional import lazystr
from .utils import TEMPLATE_DIR from .utils import TEMPLATE_DIR
@ -64,7 +63,6 @@ class CachedLoaderTests(SimpleTestCase):
self.assertIsInstance(e, TemplateDoesNotExist) self.assertIsInstance(e, TemplateDoesNotExist)
self.assertEqual(e.args[0], 'debug-template-missing.html') 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): def test_cached_exception_no_traceback(self):
""" """
When a TemplateDoesNotExist instance is cached, the cached instance When a TemplateDoesNotExist instance is cached, the cached instance

View File

@ -2,7 +2,6 @@ from unittest import TestCase
from django.template import Context, Engine from django.template import Context, Engine
from django.template.base import TextNode, VariableNode from django.template.base import TextNode, VariableNode
from django.utils import six
class NodelistTest(TestCase): class NodelistTest(TestCase):
@ -38,13 +37,11 @@ class TextNodeTest(TestCase):
def test_textnode_repr(self): def test_textnode_repr(self):
engine = Engine() engine = Engine()
for temptext, reprtext in [ for temptext, reprtext in [
("Hello, world!", "<TextNode: u'Hello, world!'>"), ("Hello, world!", "<TextNode: 'Hello, world!'>"),
("One\ntwo.", "<TextNode: u'One\\ntwo.'>"), ("One\ntwo.", "<TextNode: 'One\\ntwo.'>"),
]: ]:
template = engine.from_string(temptext) template = engine.from_string(temptext)
texts = template.nodelist.get_nodes_by_type(TextNode) texts = template.nodelist.get_nodes_by_type(TextNode)
if six.PY3:
reprtext = reprtext.replace("u'", "'")
self.assertEqual(repr(texts[0]), reprtext) self.assertEqual(repr(texts[0]), reprtext)

View File

@ -5,7 +5,6 @@ from django.db import connection
from django.test import TestCase from django.test import TestCase
from django.test.runner import DiscoverRunner from django.test.runner import DiscoverRunner
from django.utils import six from django.utils import six
from django.utils.encoding import force_text
from .models import Person from .models import Person
@ -43,8 +42,6 @@ class TestDebugSQL(unittest.TestCase):
).run(suite) ).run(suite)
runner.teardown_databases(old_config) runner.teardown_databases(old_config)
if six.PY2:
stream.buflist = [force_text(x) for x in stream.buflist]
return stream.getvalue() return stream.getvalue()
def test_output_normal(self): def test_output_normal(self):

Some files were not shown because too many files have changed in this diff Show More