Refs #23919 -- Removed misc references to Python 2.

This commit is contained in:
Tim Graham 2017-01-21 20:02:00 -05:00 committed by GitHub
parent c22212220a
commit d170c63351
34 changed files with 40 additions and 167 deletions

View File

@ -1,17 +1,10 @@
Thanks for downloading Django. Thanks for downloading Django.
To install it, make sure you have Python 2.7 or greater installed. Then run To install it, make sure you have Python 3.4 or greater installed. Then run
this command from the command prompt: this command from the command prompt:
python setup.py install python setup.py install
If you're upgrading from a previous version, you need to remove it first. If you're upgrading from a previous version, you need to remove it first.
AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
site-packages directory, which is located wherever your Python installation
lives. Some places you might check are:
/usr/lib/python2.7/site-packages (Unix, Python 2.7)
C:\\PYTHON\site-packages (Windows)
For more detailed instructions, see docs/intro/install.txt. For more detailed instructions, see docs/intro/install.txt.

View File

@ -17,7 +17,7 @@ class AppConfig:
self.name = app_name self.name = app_name
# Root module for the application eg. <module 'django.contrib.admin' # Root module for the application eg. <module 'django.contrib.admin'
# from 'django/contrib/admin/__init__.pyc'>. # from 'django/contrib/admin/__init__.py'>.
self.module = app_module self.module = app_module
# Reference to the Apps registry that holds this AppConfig. Set by the # Reference to the Apps registry that holds this AppConfig. Set by the
@ -37,13 +37,12 @@ class AppConfig:
self.verbose_name = self.label.title() self.verbose_name = self.label.title()
# Filesystem path to the application directory eg. # Filesystem path to the application directory eg.
# u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. Unicode on # '/path/to/django/contrib/admin'.
# Python 2 and a str on Python 3.
if not hasattr(self, 'path'): if not hasattr(self, 'path'):
self.path = self._path_from_module(app_module) self.path = self._path_from_module(app_module)
# Module containing models eg. <module 'django.contrib.admin.models' # Module containing models eg. <module 'django.contrib.admin.models'
# from 'django/contrib/admin/models.pyc'>. Set by import_models(). # from 'django/contrib/admin/models.py'>. Set by import_models().
# None if the application doesn't have a models module. # None if the application doesn't have a models module.
self.models_module = None self.models_module = None

View File

@ -6,17 +6,10 @@ if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
try: try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError: except ImportError as exc:
# The above import may fail for some other reason. Ensure that the raise ImportError(
# issue is really that Django is missing to avoid masking other "Couldn't import Django. Are you sure it's installed and "
# exceptions on Python 2. "available on your PYTHONPATH environment variable? Did you "
try: "forget to activate a virtual environment?"
import django ) from exc
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)

View File

@ -159,9 +159,6 @@ class MeasureBase:
else: else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)})
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __itruediv__(self, other): def __itruediv__(self, other):
if isinstance(other, NUMERIC_TYPES): if isinstance(other, NUMERIC_TYPES):
self.standard /= float(other) self.standard /= float(other)
@ -169,9 +166,6 @@ class MeasureBase:
else: else:
raise TypeError('%(class)s must be divided with number' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be divided with number' % {"class": pretty_name(self)})
def __idiv__(self, other): # Python 2 compatibility
return type(self).__itruediv__(self, other)
def __bool__(self): def __bool__(self):
return bool(self.standard) return bool(self.standard)
@ -333,9 +327,6 @@ class Area(MeasureBase):
else: else:
raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)}) raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)})
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
# Shortcuts # Shortcuts
D = Distance D = Distance

View File

@ -64,7 +64,7 @@ def _check_lazy_references(apps, ignore=None):
operation, args, keywords = obj, [], {} operation, args, keywords = obj, [], {}
while hasattr(operation, 'func'): while hasattr(operation, 'func'):
# The or clauses are redundant but work around a bug (#25945) in # The or clauses are redundant but work around a bug (#25945) in
# functools.partial in Python 3 <= 3.5.1 and Python 2 <= 2.7.11. # functools.partial in Python <= 3.5.1.
args.extend(getattr(operation, 'args', []) or []) args.extend(getattr(operation, 'args', []) or [])
keywords.update(getattr(operation, 'keywords', {}) or {}) keywords.update(getattr(operation, 'keywords', {}) or {})
operation = operation.func operation = operation.func

View File

@ -9,8 +9,8 @@ if the same flag is not provided [1][2]. Note that this does not address the
more general issue of opening a file for writing and reading in multiple more general issue of opening a file for writing and reading in multiple
processes in a manner that works across platforms. processes in a manner that works across platforms.
Also note that the custom version of NamedTemporaryFile does not support the The custom version of NamedTemporaryFile doesn't support the same keyword
full range of keyword arguments available in Python 2.6+ and 3.0+. arguments available in tempfile.NamedTemporaryFile.
1: https://mail.python.org/pipermail/python-list/2005-December/336957.html 1: https://mail.python.org/pipermail/python-list/2005-December/336957.html
2: http://bugs.python.org/issue14243 2: http://bugs.python.org/issue14243
@ -30,10 +30,9 @@ if os.name == 'nt':
Temporary file object constructor that supports reopening of the Temporary file object constructor that supports reopening of the
temporary file in Windows. temporary file in Windows.
Note that unlike tempfile.NamedTemporaryFile from the standard library, Unlike tempfile.NamedTemporaryFile from the standard library,
__init__() does not support the 'delete' keyword argument in __init__() doesn't support the 'delete', 'buffering', 'encoding', or
Python 2.6+, or the 'delete', 'buffering', 'encoding', or 'newline' 'newline' keyword arguments.
keyword arguments in Python 3.0+.
""" """
def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='', dir=None): def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='', dir=None):
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)

View File

@ -83,7 +83,6 @@ class WSGIServer(simple_server.WSGIServer):
super(WSGIServer, self).handle_error(request, client_address) super(WSGIServer, self).handle_error(request, client_address)
# Inheriting from object required on Python 2.
class ServerHandler(simple_server.ServerHandler): class ServerHandler(simple_server.ServerHandler):
def handle_error(self): def handle_error(self):
# Ignore broken pipe errors, otherwise pass on # Ignore broken pipe errors, otherwise pass on

View File

@ -2,7 +2,6 @@
MySQL database backend for Django. MySQL database backend for Django.
Requires mysqlclient: https://pypi.python.org/pypi/mysqlclient/ Requires mysqlclient: https://pypi.python.org/pypi/mysqlclient/
MySQLdb is supported for Python 2 only: http://sourceforge.net/projects/mysql-python
""" """
import re import re
import sys import sys

View File

@ -81,7 +81,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
self.cache_bust_counter)) self.cache_bust_counter))
description = [] description = []
for desc in cursor.description: for desc in cursor.description:
name = force_text(desc[0]) # cx_Oracle always returns a 'str' on both Python 2 and 3 name = force_text(desc[0]) # cx_Oracle always returns a 'str'
internal_size, default = field_map[name] internal_size, default = field_map[name]
name = name % {} # cx_Oracle, for some reason, doubles percent signs. name = name % {} # cx_Oracle, for some reason, doubles percent signs.
description.append(FieldInfo(*(name.lower(),) + desc[1:3] + (internal_size,) + desc[4:] + (default,))) description.append(FieldInfo(*(name.lower(),) + desc[1:3] + (internal_size,) + desc[4:] + (default,)))

View File

@ -160,24 +160,14 @@ class FunctionTypeSerializer(BaseSerializer):
if "<" not in self.value.__qualname__: # Qualname can include <locals> if "<" not in self.value.__qualname__: # Qualname can include <locals>
return "%s.%s" % \ return "%s.%s" % \
(self.value.__module__, self.value.__qualname__), {"import %s" % self.value.__module__} (self.value.__module__, self.value.__qualname__), {"import %s" % self.value.__module__}
# Python 2/fallback version # Fallback version
module_name = self.value.__module__ module_name = self.value.__module__
# Make sure it's actually there and not an unbound method # Make sure it's actually there
module = import_module(module_name) module = import_module(module_name)
if not hasattr(module, self.value.__name__): if not hasattr(module, self.value.__name__):
raise ValueError( raise ValueError(
"Could not find function %s in %s.\n" "Could not find function %s in %s.\n" % (self.value.__name__, module_name)
"Please note that due to Python 2 limitations, you cannot "
"serialize unbound method functions (e.g. a method "
"declared and used in the same class body). Please move "
"the function into the main module body to use migrations.\n"
"For more information, see "
"https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
% (self.value.__name__, module_name, get_docs_version())
) )
# Needed on Python 2 only
if module_name == '__builtin__':
return self.value.__name__, set()
return "%s.%s" % (module_name, self.value.__name__), {"import %s" % module_name} return "%s.%s" % (module_name, self.value.__name__), {"import %s" % module_name}

View File

@ -60,9 +60,6 @@ class Combinable:
def __truediv__(self, other): def __truediv__(self, other):
return self._combine(other, self.DIV, False) return self._combine(other, self.DIV, False)
def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)
def __mod__(self, other): def __mod__(self, other):
return self._combine(other, self.MOD, False) return self._combine(other, self.MOD, False)
@ -103,9 +100,6 @@ class Combinable:
def __rtruediv__(self, other): def __rtruediv__(self, other):
return self._combine(other, self.DIV, True) return self._combine(other, self.DIV, True)
def __rdiv__(self, other): # Python 2 compatibility
return type(self).__rtruediv__(self, other)
def __rmod__(self, other): def __rmod__(self, other):
return self._combine(other, self.MOD, True) return self._combine(other, self.MOD, True)

View File

@ -27,11 +27,8 @@ class InvalidQuery(Exception):
def subclasses(cls): def subclasses(cls):
yield cls yield cls
# Python 2 lacks 'yield from', which could replace the inner loop
for subclass in cls.__subclasses__(): for subclass in cls.__subclasses__():
# yield from subclasses(subclass) yield from subclasses(subclass)
for item in subclasses(subclass):
yield item
class QueryWrapper: class QueryWrapper:

View File

@ -875,14 +875,8 @@ class SQLCompiler:
try: try:
cursor.execute(sql, params) cursor.execute(sql, params)
except Exception: except Exception:
try: # Might fail for server-side cursors (e.g. connection closed)
# Might fail for server-side cursors (e.g. connection closed) cursor.close()
cursor.close()
except Exception:
# Ignore clean up errors and raise the original error instead.
# Python 2 doesn't chain exceptions. Remove this error
# silencing when dropping Python 2 compatibility.
pass
raise raise
if result_type == CURSOR: if result_type == CURSOR:

View File

@ -1,5 +1,6 @@
import json import json
import sys import sys
from collections import UserList
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError # backwards compatibility from django.core.exceptions import ValidationError # backwards compatibility
@ -8,11 +9,6 @@ from django.utils.encoding import force_text
from django.utils.html import escape, format_html, format_html_join, html_safe from django.utils.html import escape, format_html, format_html_join, html_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
try:
from collections import UserList
except ImportError: # Python 2
from UserList import UserList
def pretty_name(name): def pretty_name(name):
"""Converts 'first_name' to 'First name'""" """Converts 'first_name' to 'First name'"""

View File

@ -310,7 +310,7 @@ def get_runner(settings, test_runner_class=None):
test_runner_class = settings.TEST_RUNNER test_runner_class = settings.TEST_RUNNER
test_path = test_runner_class.split('.') test_path = test_runner_class.split('.')
# Allow for Python 2.5 relative paths # Allow for relative paths
if len(test_path) > 1: if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1]) test_module_name = '.'.join(test_path[:-1])
else: else:

View File

@ -24,7 +24,7 @@ def deconstructible(*args, **kwargs):
Returns a 3-tuple of class import path, positional arguments, Returns a 3-tuple of class import path, positional arguments,
and keyword arguments. and keyword arguments.
""" """
# Python 2/fallback version # Fallback version
if path: if path:
module_name, _, name = path.rpartition('.') module_name, _, name = path.rpartition('.')
else: else:

View File

@ -172,9 +172,7 @@ def strip_tags(value):
while '<' in value and '>' in value: while '<' in value and '>' in value:
new_value = _strip_once(value) new_value = _strip_once(value)
if len(new_value) >= len(value): if len(new_value) >= len(value):
# _strip_once was not able to detect more tags or length increased # _strip_once was not able to detect more tags
# due to http://bugs.python.org/issue20288
# (affects Python 2 < 2.7.7 and Python 3 < 3.3.5)
break break
value = new_value value = new_value
return value return value

View File

@ -11,9 +11,7 @@ except AttributeError:
class HTMLParser(html.parser.HTMLParser): class HTMLParser(html.parser.HTMLParser):
"""Explicitly set convert_charrefs to be False. """Explicitly set convert_charrefs to be False.
This silences a deprecation warning on Python 3.4, but we can't do This silences a deprecation warning on Python 3.4.
it at call time because Python 2.7 does not have the keyword
argument.
""" """
def __init__(self, convert_charrefs=False, **kwargs): def __init__(self, convert_charrefs=False, **kwargs):
html.parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs) html.parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs)

View File

@ -101,7 +101,6 @@ class DjangoTranslation(gettext_module.GNUTranslations):
gettext_module.GNUTranslations.__init__(self) gettext_module.GNUTranslations.__init__(self)
if domain is not None: if domain is not None:
self.domain = domain self.domain = domain
self.set_output_charset('utf-8') # For Python 2 gettext() (#25720)
self.__language = language self.__language = language
self.__to_language = to_language(language) self.__to_language = to_language(language)
@ -326,11 +325,7 @@ def do_translate(message, translation_function):
def gettext(message): def gettext(message):
""" """Return a string of the translation of the message."""
Returns a string of the translation of the message.
Returns a string on Python 3 and an UTF-8-encoded bytestring on Python 2.
"""
return do_translate(message, 'gettext') return do_translate(message, 'gettext')
@ -372,8 +367,6 @@ def ngettext(singular, plural, number):
""" """
Returns a string of the translation of either the singular or plural, Returns a string of the translation of either the singular or plural,
based on the number. based on the number.
Returns a string on Python 3 and an UTF-8-encoded bytestring on Python 2.
""" """
return do_ntranslate(singular, plural, number, 'ngettext') return do_ntranslate(singular, plural, number, 'ngettext')

View File

@ -206,12 +206,12 @@ Read-only attributes
.. attribute:: AppConfig.module .. attribute:: AppConfig.module
Root module for the application, e.g. ``<module 'django.contrib.admin' from Root module for the application, e.g. ``<module 'django.contrib.admin' from
'django/contrib/admin/__init__.pyc'>``. 'django/contrib/admin/__init__.py'>``.
.. attribute:: AppConfig.models_module .. attribute:: AppConfig.models_module
Module containing the models, e.g. ``<module 'django.contrib.admin.models' Module containing the models, e.g. ``<module 'django.contrib.admin.models'
from 'django/contrib/admin/models.pyc'>``. from 'django/contrib/admin/models.py'>``.
It may be ``None`` if the application doesn't contain a ``models`` module. It may be ``None`` if the application doesn't contain a ``models`` module.
Note that the database related signals such as Note that the database related signals such as

View File

@ -568,10 +568,6 @@ class ChangeListTests(TestCase):
self.assertNotContains(response, '<a href="%s">' % link) self.assertNotContains(response, '<a href="%s">' % link)
def test_tuple_list_display(self): def test_tuple_list_display(self):
"""
Regression test for #17128
(ChangeList failing under Python 2.5 after r16319)
"""
swallow = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2') swallow = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
swallow2 = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2') swallow2 = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
swallow_o2o = SwallowOneToOne.objects.create(swallow=swallow2) swallow_o2o = SwallowOneToOne.objects.create(swallow=swallow2)

View File

@ -101,9 +101,6 @@ class AdminScriptTestCase(unittest.TestCase):
if sys.platform.startswith('java'): if sys.platform.startswith('java'):
# Jython produces module$py.class files # Jython produces module$py.class files
os.remove(re.sub(r'\.py$', '$py.class', full_name)) os.remove(re.sub(r'\.py$', '$py.class', full_name))
else:
# CPython produces module.pyc files
os.remove(full_name + 'c')
except OSError: except OSError:
pass pass
# Also remove a __pycache__ directory, if it exists # Also remove a __pycache__ directory, if it exists

View File

@ -971,8 +971,7 @@ site.register(RelatedWithUUIDPKModel)
# related ForeignKey object not registered in admin # related ForeignKey object not registered in admin
# related OneToOne object registered in admin # related OneToOne object registered in admin
# related OneToOne object not registered in admin # related OneToOne object not registered in admin
# when deleting Book so as exercise all four troublesome (w.r.t escaping # when deleting Book so as exercise all four paths through
# and calling force_text to avoid problems on Python 2.3) paths through
# contrib.admin.utils's get_deleted_objects function. # contrib.admin.utils's get_deleted_objects function.
site.register(Book, inlines=[ChapterInline]) site.register(Book, inlines=[ChapterInline])
site.register(Promo) site.register(Promo)

View File

@ -130,21 +130,7 @@ class AuthContextProcessorTests(TestCase):
# bug #12037 is tested by the {% url %} in the template: # bug #12037 is tested by the {% url %} in the template:
self.assertContains(response, "url: /userpage/super/") self.assertContains(response, "url: /userpage/super/")
# See if this object can be used for queries where a Q() comparing # A Q() comparing a user and with another Q() (in an AND or OR fashion).
# a user can be used with another Q() (in an AND or OR fashion).
# This simulates what a template tag might do with the user from the
# context. Note that we don't need to execute a query, just build it.
#
# The failure case (bug #12049) on Python 2.4 with a LazyObject-wrapped
# User is a fatal TypeError: "function() takes at least 2 arguments
# (0 given)" deep inside deepcopy().
#
# Python 2.5 and 2.6 succeeded, but logged internally caught exception
# spew:
#
# Exception RuntimeError: 'maximum recursion depth exceeded while
# calling a Python object' in <type 'exceptions.AttributeError'>
# ignored"
Q(user=response.context['user']) & Q(someflag=True) Q(user=response.context['user']) & Q(someflag=True)
# Tests for user equality. This is hard because User defines # Tests for user equality. This is hard because User defines

View File

@ -62,11 +62,6 @@ class Unpicklable:
raise pickle.PickleError() raise pickle.PickleError()
class UnpicklableType:
# Unpicklable using the default pickling protocol on Python 2.
__slots__ = 'a',
@override_settings(CACHES={ @override_settings(CACHES={
'default': { 'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
@ -1360,10 +1355,6 @@ class FileBasedCacheTests(BaseCacheTests, TestCase):
cache.set('foo', 'bar') cache.set('foo', 'bar')
os.path.exists(self.dirname) os.path.exists(self.dirname)
def test_cache_write_unpicklable_type(self):
# This fails if not using the highest pickling protocol on Python 2.
cache.set('unpicklable', UnpicklableType())
def test_get_ignores_enoent(self): def test_get_ignores_enoent(self):
cache.set('foo', 'bar') cache.set('foo', 'bar')
os.unlink(cache._key_to_file('foo')) os.unlink(cache._key_to_file('foo'))

View File

@ -256,8 +256,8 @@ class MethodDecoratorTests(SimpleTestCase):
def test_bad_iterable(self): def test_bad_iterable(self):
decorators = {myattr_dec_m, myattr2_dec_m} decorators = {myattr_dec_m, myattr2_dec_m}
# The rest of the exception message differs between Python 2 and 3. msg = "'set' object is not subscriptable"
with self.assertRaisesMessage(TypeError, "'set' object"): with self.assertRaisesMessage(TypeError, msg):
@method_decorator(decorators, "method") @method_decorator(decorators, "method")
class TestIterable: class TestIterable:
def method(self): def method(self):

View File

@ -637,8 +637,6 @@ class CaseExpressionTests(TestCase):
def test_update_binary(self): def test_update_binary(self):
CaseTestModel.objects.update( CaseTestModel.objects.update(
binary=Case( binary=Case(
# fails on postgresql on Python 2.7 if output_field is not
# set explicitly
When(integer=1, then=Value(b'one', output_field=models.BinaryField())), When(integer=1, then=Value(b'one', output_field=models.BinaryField())),
When(integer=2, then=Value(b'two', output_field=models.BinaryField())), When(integer=2, then=Value(b'two', output_field=models.BinaryField())),
default=Value(b'', output_field=models.BinaryField()), default=Value(b'', output_field=models.BinaryField()),

View File

@ -139,9 +139,6 @@ class FileTests(unittest.TestCase):
test_file.seek(0) test_file.seek(0)
wrapper = TextIOWrapper(test_file, 'utf-8', newline='\n') wrapper = TextIOWrapper(test_file, 'utf-8', newline='\n')
self.assertEqual(wrapper.read(), content) self.assertEqual(wrapper.read(), content)
# The following seek() call is required on Windows Python 2 when
# switching from reading to writing.
wrapper.seek(0, 2)
wrapper.write(content) wrapper.write(content)
wrapper.seek(0) wrapper.seek(0)
self.assertEqual(wrapper.read(), content * 2) self.assertEqual(wrapper.read(), content * 2)

View File

@ -21,8 +21,7 @@ from django.template import Context, Template
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.html import format_html from django.utils.safestring import mark_safe
from django.utils.safestring import SafeData, mark_safe
class Person(Form): class Person(Form):
@ -2028,22 +2027,6 @@ Password: <input type="password" name="password" required /></li>
form = PersonForm({}) form = PersonForm({})
self.assertEqual(form['name'].value(), 'John Doe') self.assertEqual(form['name'].value(), 'John Doe')
def test_boundfield_rendering(self):
"""
Python 2 issue: Rendering a BoundField with bytestring content
doesn't lose it's safe string status (#22950).
"""
class CustomWidget(TextInput):
def render(self, name, value, attrs=None, choices=None,
renderer=None, extra_context=None):
return format_html(str('<input{} />'), ' id=custom')
class SampleForm(Form):
name = CharField(widget=CustomWidget)
f = SampleForm(data={'name': 'bar'})
self.assertIsInstance(force_text(f['name']), SafeData)
def test_custom_boundfield(self): def test_custom_boundfield(self):
class CustomField(CharField): class CustomField(CharField):
def get_bound_field(self, form, name): def get_bound_field(self, form, name):

View File

@ -7,7 +7,7 @@ source_code_dir = os.path.dirname(__file__)
def copytree(src, dst): def copytree(src, dst):
shutil.copytree(src, dst, ignore=shutil.ignore_patterns('*.pyc', '__pycache__')) shutil.copytree(src, dst, ignore=shutil.ignore_patterns('__pycache__'))
class POFileAssertionMixin: class POFileAssertionMixin:

View File

@ -1,7 +1,6 @@
from django.db.models import F, IntegerField, Value from django.db.models import F, IntegerField, Value
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
from django.utils.six.moves import range
from .models import Number, ReservedName from .models import Number, ReservedName

View File

@ -305,8 +305,7 @@ class TestComplexSettingOverride(SimpleTestCase):
self.assertEqual(settings.TEST_WARN, 'override') self.assertEqual(settings.TEST_WARN, 'override')
self.assertEqual(len(w), 1) self.assertEqual(len(w), 1)
# File extension may by .py, .pyc, etc. Compare only basename. self.assertEqual(w[0].filename, __file__)
self.assertEqual(os.path.splitext(w[0].filename)[0], os.path.splitext(__file__)[0])
self.assertEqual(str(w[0].message), 'Overriding setting TEST_WARN can lead to unexpected behavior.') self.assertEqual(str(w[0].message), 'Overriding setting TEST_WARN can lead to unexpected behavior.')

View File

@ -164,7 +164,7 @@ class SilentAttrClass:
class UTF8Class: class UTF8Class:
"Class whose __str__ returns non-ASCII data on Python 2" "Class whose __str__ returns non-ASCII data"
def __str__(self): def __str__(self):
return 'ŠĐĆŽćžšđ' return 'ŠĐĆŽćžšđ'

View File

@ -7,15 +7,10 @@ from django.utils.functional import SimpleLazyObject
class TestUtilsSimpleLazyObjectDjangoTestCase(TestCase): class TestUtilsSimpleLazyObjectDjangoTestCase(TestCase):
def test_pickle_py2_regression(self): def test_pickle(self):
# See ticket #20212
user = User.objects.create_user('johndoe', 'john@example.com', 'pass') user = User.objects.create_user('johndoe', 'john@example.com', 'pass')
x = SimpleLazyObject(lambda: user) x = SimpleLazyObject(lambda: user)
# This would fail with "TypeError: can't pickle instancemethod objects",
# only on Python 2.X.
pickle.dumps(x) pickle.dumps(x)
# Try the variant protocol levels. # Try the variant protocol levels.
pickle.dumps(x, 0) pickle.dumps(x, 0)
pickle.dumps(x, 1) pickle.dumps(x, 1)