Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ticket 19038 - Add support for Python 3.3 #435

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion django/test/testcases.py
Expand Up @@ -867,7 +867,9 @@ def log_message(*args):
pass pass




if sys.version_info >= (2, 7, 0): if sys.version_info >= (3, 3, 0):
_ImprovedEvent = threading.Event
elif sys.version_info >= (2, 7, 0):
_ImprovedEvent = threading._Event _ImprovedEvent = threading._Event
else: else:
class _ImprovedEvent(threading._Event): class _ImprovedEvent(threading._Event):
Expand Down
10 changes: 10 additions & 0 deletions django/utils/functional.py
Expand Up @@ -293,6 +293,16 @@ def __getstate__(self):
self._setup() self._setup()
return self._wrapped.__dict__ return self._wrapped.__dict__


# Python 3.3 will call __reduce__ when pickling; these methods are needed
# to serialize and deserialize correctly. They are not called in earlier
# versions of Python.
@classmethod
def __newobj__(cls, *args):
return cls.__new__(cls, *args)

def __reduce__(self):
return (self.__newobj__, (self.__class__,), self.__getstate__())

# Need to pretend to be the wrapped class, for the sake of objects that care # Need to pretend to be the wrapped class, for the sake of objects that care
# about this (especially in equality tests) # about this (especially in equality tests)
__class__ = property(new_method_proxy(operator.attrgetter("__class__"))) __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
Expand Down
22 changes: 13 additions & 9 deletions django/views/debug.py
Expand Up @@ -354,15 +354,19 @@ def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, mod
if source is None: if source is None:
return None, [], None, [] return None, [], None, []


encoding = 'ascii' # If we just read the source from a file, or if the loader did not
for line in source[:2]: # apply tokenize.detect_encoding to decode the source into a Unicode
# File coding may be specified. Match pattern from PEP-263 # string, then we should do that ourselves.
# (http://www.python.org/dev/peps/pep-0263/) if isinstance(source[0], six.binary_type):
match = re.search(br'coding[:=]\s*([-\w.]+)', line) encoding = 'ascii'
if match: for line in source[:2]:
encoding = match.group(1).decode('ascii') # File coding may be specified. Match pattern from PEP-263
break # (http://www.python.org/dev/peps/pep-0263/)
source = [six.text_type(sline, encoding, 'replace') for sline in source] match = re.search(br'coding[:=]\s*([-\w.]+)', line)
if match:
encoding = match.group(1).decode('ascii')
break
source = [six.text_type(sline, encoding, 'replace') for sline in source]


lower_bound = max(0, lineno - context_lines) lower_bound = max(0, lineno - context_lines)
upper_bound = lineno + context_lines upper_bound = lineno + context_lines
Expand Down
3 changes: 1 addition & 2 deletions tests/modeltests/basic/tests.py
Expand Up @@ -259,9 +259,8 @@ def test_object_creation(self):
"datetime.datetime(2005, 7, 28, 0, 0)"]) "datetime.datetime(2005, 7, 28, 0, 0)"])


# dates() requires valid arguments. # dates() requires valid arguments.
six.assertRaisesRegex(self, self.assertRaises(
TypeError, TypeError,
"dates\(\) takes at least 3 arguments \(1 given\)",
Article.objects.dates, Article.objects.dates,
) )


Expand Down
6 changes: 4 additions & 2 deletions tests/regressiontests/admin_scripts/tests.py
Expand Up @@ -1010,7 +1010,8 @@ def test_builtin_command(self):
args = ['sqlall', 'admin_scripts'] args = ['sqlall', 'admin_scripts']
out, err = self.run_manage(args) out, err = self.run_manage(args)
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, "No module named foo42bar") self.assertOutput(err, "No module named")
self.assertOutput(err, "foo42bar")


def test_builtin_command_with_attribute_error(self): def test_builtin_command_with_attribute_error(self):
""" """
Expand All @@ -1033,7 +1034,8 @@ def test_nonexistent_app(self):
args = ['validate'] args = ['validate']
out, err = self.run_manage(args) out, err = self.run_manage(args)
self.assertNoOutput(out) self.assertNoOutput(out)
self.assertOutput(err, 'No module named admin_scriptz') self.assertOutput(err, 'No module named')
self.assertOutput(err, 'admin_scriptz')


def test_broken_app(self): def test_broken_app(self):
"manage.py validate reports an ImportError if an app's models.py raises one on import" "manage.py validate reports an ImportError if an app's models.py raises one on import"
Expand Down
2 changes: 1 addition & 1 deletion tests/regressiontests/file_storage/tests.py
Expand Up @@ -78,7 +78,7 @@ def test_get_nonexisting_storage_module(self):
six.assertRaisesRegex(self, six.assertRaisesRegex(self,
ImproperlyConfigured, ImproperlyConfigured,
('Error importing storage module django.core.files.non_existing_' ('Error importing storage module django.core.files.non_existing_'
'storage: "No module named .*non_existing_storage"'), 'storage: "No module named .*non_existing_storage'),
get_storage_class, get_storage_class,
'django.core.files.non_existing_storage.NonExistingStorage' 'django.core.files.non_existing_storage.NonExistingStorage'
) )
Expand Down
2 changes: 1 addition & 1 deletion tests/regressiontests/fixtures_regress/tests.py
Expand Up @@ -159,7 +159,7 @@ def test_unimportable_serializer(self):
Test that failing serializer import raises the proper error Test that failing serializer import raises the proper error
""" """
with six.assertRaisesRegex(self, ImportError, with six.assertRaisesRegex(self, ImportError,
"No module named unexistent.path"): r"No module named.*unexistent"):
management.call_command( management.call_command(
'loaddata', 'loaddata',
'bad_fixture1.unkn', 'bad_fixture1.unkn',
Expand Down
2 changes: 1 addition & 1 deletion tests/regressiontests/requests/tests.py
Expand Up @@ -56,7 +56,7 @@ def test_wsgirequest_repr(self):
str_prefix("<WSGIRequest\npath:/otherpath/,\nGET:{%(_)s'a': %(_)s'b'},\nPOST:{%(_)s'c': %(_)s'd'},\nCOOKIES:{%(_)s'e': %(_)s'f'},\nMETA:{%(_)s'g': %(_)s'h'}>")) str_prefix("<WSGIRequest\npath:/otherpath/,\nGET:{%(_)s'a': %(_)s'b'},\nPOST:{%(_)s'c': %(_)s'd'},\nCOOKIES:{%(_)s'e': %(_)s'f'},\nMETA:{%(_)s'g': %(_)s'h'}>"))


def test_parse_cookie(self): def test_parse_cookie(self):
self.assertEqual(parse_cookie('invalid:key=true'), {}) self.assertEqual(parse_cookie('invalid@key=true'), {})


def test_httprequest_location(self): def test_httprequest_location(self):
request = HttpRequest() request = HttpRequest()
Expand Down