-
commit 4f8cadfe507ff58f3326abf0d7e1abe9835910f5
Author: Jonas Haag <jonas@lophus.org>
Date: Sun Mar 27 05:44:35 2011 -0700
Drop some 2.4 compatibility boilerplate code
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 43c5503..fbda8b7 100644
a
|
b
|
|
| 1 | from functools import update_wrapper, partial |
1 | 2 | from django import forms, template |
2 | 3 | from django.forms.formsets import all_valid |
3 | 4 | from django.forms.models import (modelform_factory, modelformset_factory, |
… |
… |
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
17 | 18 | from django.shortcuts import get_object_or_404, render_to_response |
18 | 19 | from django.utils.decorators import method_decorator |
19 | 20 | from django.utils.datastructures import SortedDict |
20 | | from django.utils.functional import update_wrapper |
21 | 21 | from django.utils.html import escape, escapejs |
22 | 22 | from django.utils.safestring import mark_safe |
23 | | from django.utils.functional import curry |
24 | 23 | from django.utils.text import capfirst, get_text_list |
25 | 24 | from django.utils.translation import ugettext as _ |
26 | 25 | from django.utils.translation import ungettext |
… |
… |
class ModelAdmin(BaseModelAdmin):
|
426 | 425 | "form": self.form, |
427 | 426 | "fields": fields, |
428 | 427 | "exclude": exclude, |
429 | | "formfield_callback": curry(self.formfield_for_dbfield, request=request), |
| 428 | "formfield_callback": partial(self.formfield_for_dbfield, request=request), |
430 | 429 | } |
431 | 430 | defaults.update(kwargs) |
432 | 431 | return modelform_factory(self.model, **defaults) |
… |
… |
class ModelAdmin(BaseModelAdmin):
|
457 | 456 | Returns a Form class for use in the Formset on the changelist page. |
458 | 457 | """ |
459 | 458 | defaults = { |
460 | | "formfield_callback": curry(self.formfield_for_dbfield, request=request), |
| 459 | "formfield_callback": partial(self.formfield_for_dbfield, request=request), |
461 | 460 | } |
462 | 461 | defaults.update(kwargs) |
463 | 462 | return modelform_factory(self.model, **defaults) |
… |
… |
class ModelAdmin(BaseModelAdmin):
|
468 | 467 | is used. |
469 | 468 | """ |
470 | 469 | defaults = { |
471 | | "formfield_callback": curry(self.formfield_for_dbfield, request=request), |
| 470 | "formfield_callback": partial(self.formfield_for_dbfield, request=request), |
472 | 471 | } |
473 | 472 | defaults.update(kwargs) |
474 | 473 | return modelformset_factory(self.model, |
… |
… |
class InlineModelAdmin(BaseModelAdmin):
|
1327 | 1326 | "fk_name": self.fk_name, |
1328 | 1327 | "fields": fields, |
1329 | 1328 | "exclude": exclude, |
1330 | | "formfield_callback": curry(self.formfield_for_dbfield, request=request), |
| 1329 | "formfield_callback": partial(self.formfield_for_dbfield, request=request), |
1331 | 1330 | "extra": self.extra, |
1332 | 1331 | "max_num": self.max_num, |
1333 | 1332 | "can_delete": self.can_delete, |
-
diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
index b03bce4..1f98db8 100644
a
|
b
|
|
1 | 1 | import re |
| 2 | from functools import update_wrapper |
2 | 3 | from django import http, template |
3 | 4 | from django.contrib.admin import ModelAdmin, actions |
4 | 5 | from django.contrib.admin.forms import AdminAuthenticationForm |
… |
… |
from django.db.models.base import ModelBase
|
9 | 10 | from django.core.exceptions import ImproperlyConfigured |
10 | 11 | from django.core.urlresolvers import reverse |
11 | 12 | from django.shortcuts import render_to_response |
12 | | from django.utils.functional import update_wrapper |
13 | 13 | from django.utils.safestring import mark_safe |
14 | 14 | from django.utils.text import capfirst |
15 | 15 | from django.utils.translation import ugettext as _ |
-
diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py
index 9088eb0..34b54e0 100644
a
|
b
|
|
1 | | try: |
2 | | from functools import wraps |
3 | | except ImportError: |
4 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 1 | from functools import wraps |
5 | 2 | |
6 | 3 | from django.utils.translation import ugettext as _ |
7 | 4 | from django.contrib.admin.forms import AdminAuthenticationForm |
-
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 1978b3e..5d3ef23 100644
a
|
b
|
|
2 | 2 | Form Widget classes specific to the Django admin site. |
3 | 3 | """ |
4 | 4 | |
5 | | import django.utils.copycompat as copy |
| 5 | import copy |
6 | 6 | |
7 | 7 | from django import forms |
8 | 8 | from django.forms.widgets import RadioFieldRenderer |
-
diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index 64b77a5..2e16c99 100644
a
|
b
|
|
1 | 1 | import urlparse |
2 | | try: |
3 | | from functools import wraps |
4 | | except ImportError: |
5 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 2 | from functools import wraps |
6 | 3 | |
7 | 4 | from django.conf import settings |
8 | 5 | from django.contrib.auth import REDIRECT_FIELD_NAME |
-
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index 8fcbdef..c17291f 100644
a
|
b
|
|
1 | 1 | import datetime |
2 | 2 | import urllib |
| 3 | from hashlib import sha1, md5 |
3 | 4 | |
4 | 5 | from django.contrib import auth |
5 | 6 | from django.contrib.auth.signals import user_logged_in |
… |
… |
from django.db import models
|
8 | 9 | from django.db.models.manager import EmptyManager |
9 | 10 | from django.contrib.contenttypes.models import ContentType |
10 | 11 | from django.utils.encoding import smart_str |
11 | | from django.utils.hashcompat import md5_constructor, sha_constructor |
12 | 12 | from django.utils.translation import ugettext_lazy as _ |
13 | 13 | from django.utils.crypto import constant_time_compare |
14 | 14 | |
… |
… |
def get_hexdigest(algorithm, salt, raw_password):
|
29 | 29 | return crypt.crypt(raw_password, salt) |
30 | 30 | |
31 | 31 | if algorithm == 'md5': |
32 | | return md5_constructor(salt + raw_password).hexdigest() |
| 32 | return md5(salt + raw_password).hexdigest() |
33 | 33 | elif algorithm == 'sha1': |
34 | | return sha_constructor(salt + raw_password).hexdigest() |
| 34 | return sha1(salt + raw_password).hexdigest() |
35 | 35 | raise ValueError("Got unknown password algorithm type in password.") |
36 | 36 | |
37 | 37 | def check_password(raw_password, enc_password): |
-
diff --git a/django/contrib/auth/tests/tokens.py b/django/contrib/auth/tests/tokens.py
index 20b2ecb..e96ce59 100644
a
|
b
|
class TokenGeneratorTest(TestCase):
|
58 | 58 | # Hard code in the Django 1.2 algorithm (not the result, as it is time |
59 | 59 | # dependent) |
60 | 60 | def _make_token(user): |
61 | | from django.utils.hashcompat import sha_constructor |
| 61 | from hashlib import sha1 |
62 | 62 | from django.utils.http import int_to_base36 |
63 | 63 | |
64 | 64 | timestamp = (date.today() - date(2001,1,1)).days |
65 | 65 | ts_b36 = int_to_base36(timestamp) |
66 | | hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + |
67 | | user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + |
68 | | unicode(timestamp)).hexdigest()[::2] |
| 66 | hash = sha1(settings.SECRET_KEY + unicode(user.id) + |
| 67 | user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + |
| 68 | unicode(timestamp)).hexdigest()[::2] |
69 | 69 | return "%s-%s" % (ts_b36, hash) |
70 | 70 | |
71 | 71 | user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw') |
-
diff --git a/django/contrib/auth/tokens.py b/django/contrib/auth/tokens.py
index f03ed0c..0150afc 100644
a
|
b
|
|
1 | 1 | from datetime import date |
| 2 | from hashlib import sha1 |
2 | 3 | |
3 | 4 | from django.conf import settings |
4 | | from django.utils.hashcompat import sha_constructor |
5 | 5 | from django.utils.http import int_to_base36, base36_to_int |
6 | 6 | from django.utils.crypto import constant_time_compare, salted_hmac |
7 | 7 | |
… |
… |
class PasswordResetTokenGenerator(object):
|
67 | 67 | def _make_token_with_timestamp_old(self, user, timestamp): |
68 | 68 | # The Django 1.2 method |
69 | 69 | ts_b36 = int_to_base36(timestamp) |
70 | | hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + |
71 | | user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + |
72 | | unicode(timestamp)).hexdigest()[::2] |
| 70 | hash = sha1(settings.SECRET_KEY + unicode(user.id) + |
| 71 | user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + |
| 72 | unicode(timestamp)).hexdigest()[::2] |
73 | 73 | return "%s-%s" % (ts_b36, hash) |
74 | 74 | |
75 | 75 | def _num_days(self, dt): |
-
diff --git a/django/contrib/comments/forms.py b/django/contrib/comments/forms.py
index 4ecc4c4..6d2be4f 100644
a
|
b
|
|
1 | 1 | import time |
2 | 2 | import datetime |
| 3 | from hashlib import sha1 |
3 | 4 | |
4 | 5 | from django import forms |
5 | 6 | from django.forms.util import ErrorDict |
… |
… |
from django.contrib.contenttypes.models import ContentType
|
8 | 9 | from models import Comment |
9 | 10 | from django.utils.crypto import salted_hmac, constant_time_compare |
10 | 11 | from django.utils.encoding import force_unicode |
11 | | from django.utils.hashcompat import sha_constructor |
12 | 12 | from django.utils.text import get_text_list |
13 | 13 | from django.utils.translation import ungettext, ugettext_lazy as _ |
14 | 14 | |
… |
… |
class CommentSecurityForm(forms.Form):
|
100 | 100 | """Generate a (SHA1) security hash from the provided info.""" |
101 | 101 | # Django 1.2 compatibility |
102 | 102 | info = (content_type, object_pk, timestamp, settings.SECRET_KEY) |
103 | | return sha_constructor("".join(info)).hexdigest() |
| 103 | return sha1("".join(info)).hexdigest() |
104 | 104 | |
105 | 105 | class CommentDetailsForm(CommentSecurityForm): |
106 | 106 | """ |
-
diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py
index 76f8eaf..62cf016 100644
a
|
b
|
|
2 | 2 | Classes allowing "generic" relations through ContentType and object-id fields. |
3 | 3 | """ |
4 | 4 | |
| 5 | from functools import partial |
| 6 | |
5 | 7 | from django.core.exceptions import ObjectDoesNotExist |
6 | 8 | from django.db import connection |
7 | 9 | from django.db.models import signals |
… |
… |
from django.forms import ModelForm
|
12 | 14 | from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance |
13 | 15 | from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets |
14 | 16 | from django.utils.encoding import smart_unicode |
15 | | from django.utils.functional import curry |
16 | 17 | |
17 | 18 | from django.contrib.contenttypes.models import ContentType |
18 | 19 | |
… |
… |
class GenericInlineModelAdmin(InlineModelAdmin):
|
414 | 415 | "ct_field": self.ct_field, |
415 | 416 | "fk_field": self.ct_fk_field, |
416 | 417 | "form": self.form, |
417 | | "formfield_callback": curry(self.formfield_for_dbfield, request=request), |
| 418 | "formfield_callback": partial(self.formfield_for_dbfield, request=request), |
418 | 419 | "formset": self.formset, |
419 | 420 | "extra": self.extra, |
420 | 421 | "can_delete": self.can_delete, |
-
diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py
index 3fa61ba..3f0674c 100644
a
|
b
|
|
1 | 1 | """ |
2 | 2 | Formtools Preview application. |
3 | 3 | """ |
4 | | |
5 | | import cPickle as pickle |
| 4 | try: |
| 5 | import cPickle as pickle |
| 6 | except ImportError: |
| 7 | import pickle |
6 | 8 | |
7 | 9 | from django.conf import settings |
8 | 10 | from django.http import Http404 |
9 | 11 | from django.shortcuts import render_to_response |
10 | 12 | from django.template.context import RequestContext |
11 | | from django.utils.hashcompat import md5_constructor |
12 | 13 | from django.utils.crypto import constant_time_compare |
13 | 14 | from django.contrib.formtools.utils import security_hash |
14 | 15 | |
-
diff --git a/django/contrib/formtools/utils.py b/django/contrib/formtools/utils.py
index 894178a..6374f39 100644
a
|
b
|
|
| 1 | from hashlib import md5 |
1 | 2 | try: |
2 | 3 | import cPickle as pickle |
3 | 4 | except ImportError: |
… |
… |
except ImportError:
|
6 | 7 | from django.conf import settings |
7 | 8 | from django.forms import BooleanField |
8 | 9 | from django.utils.crypto import salted_hmac |
9 | | from django.utils.hashcompat import md5_constructor |
10 | 10 | |
11 | 11 | |
12 | 12 | def security_hash(request, form, *args): |
… |
… |
def security_hash(request, form, *args):
|
39 | 39 | # Python 2.3, but Django requires 2.4 anyway, so that's OK. |
40 | 40 | pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) |
41 | 41 | |
42 | | return md5_constructor(pickled).hexdigest() |
| 42 | return md5(pickled).hexdigest() |
43 | 43 | |
44 | 44 | |
45 | 45 | def form_hmac(form): |
-
diff --git a/django/contrib/formtools/wizard.py b/django/contrib/formtools/wizard.py
index 6f3660d..9096250 100644
a
|
b
|
FormWizard class -- implements a multi-page form, validating between each
|
3 | 3 | step and storing the form's state as HTML hidden fields so that no state is |
4 | 4 | stored on the server side. |
5 | 5 | """ |
6 | | |
7 | | import cPickle as pickle |
| 6 | try: |
| 7 | import cPickle as pickle |
| 8 | except ImportError: |
| 9 | import pickle |
8 | 10 | |
9 | 11 | from django import forms |
10 | 12 | from django.conf import settings |
… |
… |
from django.http import Http404
|
13 | 15 | from django.shortcuts import render_to_response |
14 | 16 | from django.template.context import RequestContext |
15 | 17 | from django.utils.crypto import constant_time_compare |
16 | | from django.utils.hashcompat import md5_constructor |
17 | 18 | from django.utils.translation import ugettext_lazy as _ |
18 | 19 | from django.utils.decorators import method_decorator |
19 | 20 | from django.views.decorators.csrf import csrf_protect |
-
diff --git a/django/contrib/gis/geos/tests/test_geos.py b/django/contrib/gis/geos/tests/test_geos.py
index 8342b58..4620a9f 100644
a
|
b
|
class GEOSTest(unittest.TestCase, TestDataMixin):
|
820 | 820 | |
821 | 821 | def test22_copy(self): |
822 | 822 | "Testing use with the Python `copy` module." |
823 | | import django.utils.copycompat as copy |
| 823 | import copy |
824 | 824 | poly = GEOSGeometry('POLYGON((0 0, 0 23, 23 23, 23 0, 0 0), (5 5, 5 10, 10 10, 10 5, 5 5))') |
825 | 825 | cpy1 = copy.copy(poly) |
826 | 826 | cpy2 = copy.deepcopy(poly) |
-
diff --git a/django/contrib/gis/geos/tests/test_geos_mutation.py b/django/contrib/gis/geos/tests/test_geos_mutation.py
index 266a12d..cf0c6bf 100644
a
|
b
|
|
2 | 2 | # Modified from original contribution by Aryeh Leib Taurog, which was |
3 | 3 | # released under the New BSD license. |
4 | 4 | |
5 | | import django.utils.copycompat as copy |
| 5 | import copy |
6 | 6 | |
7 | 7 | from django.contrib.gis.geos import * |
8 | 8 | from django.contrib.gis.geos.error import GEOSIndexError |
-
diff --git a/django/contrib/gis/tests/layermap/tests.py b/django/contrib/gis/tests/layermap/tests.py
index ad7a504..dd9ff5c 100644
a
|
b
|
|
1 | 1 | import os |
| 2 | import copy |
2 | 3 | from decimal import Decimal |
3 | 4 | |
4 | | from django.utils.copycompat import copy |
5 | 5 | from django.utils.unittest import TestCase |
6 | 6 | |
7 | 7 | from django.contrib.gis.gdal import DataSource, OGRException |
-
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index bb09cb6..6983a16 100644
a
|
b
|
import os
|
3 | 3 | import random |
4 | 4 | import sys |
5 | 5 | import time |
| 6 | from hashlib import md5 |
6 | 7 | from datetime import datetime, timedelta |
7 | 8 | try: |
8 | 9 | import cPickle as pickle |
… |
… |
except ImportError:
|
11 | 12 | |
12 | 13 | from django.conf import settings |
13 | 14 | from django.core.exceptions import SuspiciousOperation |
14 | | from django.utils.hashcompat import md5_constructor |
15 | 15 | from django.utils.crypto import constant_time_compare, salted_hmac |
16 | 16 | |
17 | 17 | # Use the system (hardware-based) random number generator if it exists. |
… |
… |
class SessionBase(object):
|
119 | 119 | def _decode_old(self, session_data): |
120 | 120 | encoded_data = base64.decodestring(session_data) |
121 | 121 | pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] |
122 | | if not constant_time_compare(md5_constructor(pickled + settings.SECRET_KEY).hexdigest(), |
| 122 | if not constant_time_compare(md5(pickled + settings.SECRET_KEY).hexdigest(), |
123 | 123 | tamper_check): |
124 | 124 | raise SuspiciousOperation("User tampered with session cookie.") |
125 | 125 | return pickle.loads(pickled) |
… |
… |
class SessionBase(object):
|
161 | 161 | # No getpid() in Jython, for example |
162 | 162 | pid = 1 |
163 | 163 | while 1: |
164 | | session_key = md5_constructor("%s%s%s%s" |
| 164 | session_key = md5("%s%s%s%s" |
165 | 165 | % (randrange(0, MAX_SESSION_KEY), pid, time.time(), |
166 | 166 | settings.SECRET_KEY)).hexdigest() |
167 | 167 | if not self.exists(session_key): |
-
diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py
index afdb761..5e5fa27 100644
a
|
b
|
|
1 | 1 | import base64 |
2 | | from datetime import datetime, timedelta |
3 | 2 | import pickle |
4 | 3 | import shutil |
5 | 4 | import tempfile |
| 5 | from hashlib import md5 |
| 6 | from datetime import datetime, timedelta |
6 | 7 | |
7 | 8 | from django.conf import settings |
8 | 9 | from django.contrib.sessions.backends.db import SessionStore as DatabaseSession |
… |
… |
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
|
15 | 16 | from django.http import HttpResponse |
16 | 17 | from django.test import TestCase, RequestFactory |
17 | 18 | from django.utils import unittest |
18 | | from django.utils.hashcompat import md5_constructor |
19 | 19 | |
20 | 20 | |
21 | 21 | class SessionTestsMixin(object): |
… |
… |
class SessionTestsMixin(object):
|
257 | 257 | # Hard code the Django 1.2 method here: |
258 | 258 | def encode(session_dict): |
259 | 259 | pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) |
260 | | pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() |
| 260 | pickled_md5 = md5(pickled + settings.SECRET_KEY).hexdigest() |
261 | 261 | return base64.encodestring(pickled + pickled_md5) |
262 | 262 | |
263 | 263 | data = {'a test key': 'a test value'} |
-
diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py
index b75d636..3a0cde3 100644
a
|
b
|
|
3 | 3 | import os |
4 | 4 | import time |
5 | 5 | import shutil |
| 6 | from hashlib import md5 |
6 | 7 | try: |
7 | 8 | import cPickle as pickle |
8 | 9 | except ImportError: |
9 | 10 | import pickle |
10 | 11 | |
11 | 12 | from django.core.cache.backends.base import BaseCache |
12 | | from django.utils.hashcompat import md5_constructor |
13 | 13 | |
14 | 14 | class FileBasedCache(BaseCache): |
15 | 15 | def __init__(self, dir, params): |
… |
… |
class FileBasedCache(BaseCache):
|
145 | 145 | Thus, a cache key of "foo" gets turnned into a file named |
146 | 146 | ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``. |
147 | 147 | """ |
148 | | path = md5_constructor(key).hexdigest() |
| 148 | path = md5(key).hexdigest() |
149 | 149 | path = os.path.join(path[:2], path[2:4], path[4:]) |
150 | 150 | return os.path.join(self._dir, path) |
151 | 151 | |
-
diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py
index ecec875..fa3b4b7 100644
a
|
b
|
class LocMemCache(BaseCache):
|
77 | 77 | key = self.make_key(key, version=version) |
78 | 78 | self.validate_key(key) |
79 | 79 | self._lock.writer_enters() |
80 | | # Python 2.4 doesn't allow combined try-except-finally blocks. |
81 | 80 | try: |
82 | | try: |
83 | | self._set(key, pickle.dumps(value), timeout) |
84 | | except pickle.PickleError: |
85 | | pass |
| 81 | self._set(key, pickle.dumps(value), timeout) |
| 82 | except pickle.PickleError: |
| 83 | pass |
86 | 84 | finally: |
87 | 85 | self._lock.writer_leaves() |
88 | 86 | |
-
diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py
index fa71f38..7054975 100644
a
|
b
|
class EmailBackend(BaseEmailBackend):
|
18 | 18 | return |
19 | 19 | self._lock.acquire() |
20 | 20 | try: |
21 | | # The try-except is nested to allow for |
22 | | # Python 2.4 support (Refs #12147) |
23 | | try: |
24 | | stream_created = self.open() |
25 | | for message in email_messages: |
26 | | self.stream.write('%s\n' % message.message().as_string()) |
27 | | self.stream.write('-'*79) |
28 | | self.stream.write('\n') |
29 | | self.stream.flush() # flush after each message |
30 | | if stream_created: |
31 | | self.close() |
32 | | except: |
33 | | if not self.fail_silently: |
34 | | raise |
| 21 | stream_created = self.open() |
| 22 | for message in email_messages: |
| 23 | self.stream.write('%s\n' % message.message().as_string()) |
| 24 | self.stream.write('-'*79) |
| 25 | self.stream.write('\n') |
| 26 | self.stream.flush() # flush after each message |
| 27 | if stream_created: |
| 28 | self.close() |
| 29 | except: |
| 30 | if not self.fail_silently: |
| 31 | raise |
35 | 32 | finally: |
36 | 33 | self._lock.release() |
37 | 34 | return len(email_messages) |
-
diff --git a/django/core/mail/message.py b/django/core/mail/message.py
index 01bb1d6..bed4966 100644
a
|
b
|
import os
|
3 | 3 | import random |
4 | 4 | import time |
5 | 5 | from email import Charset, Encoders |
6 | | try: |
7 | | from email.generator import Generator |
8 | | except ImportError: |
9 | | from email.Generator import Generator # TODO: Remove when remove Python 2.4 support |
| 6 | from email.generator import Generator |
10 | 7 | from email.MIMEText import MIMEText |
11 | 8 | from email.MIMEMultipart import MIMEMultipart |
12 | 9 | from email.MIMEBase import MIMEBase |
-
diff --git a/django/core/management/validation.py b/django/core/management/validation.py
index 2eb6340..bb4fa55 100644
a
|
b
|
from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelati
|
4 | 4 | from django.core.management.color import color_style |
5 | 5 | from django.utils.itercompat import is_iterable |
6 | 6 | |
7 | | try: |
8 | | any |
9 | | except NameError: |
10 | | from django.utils.itercompat import any |
11 | | |
12 | 7 | class ModelErrorCollection: |
13 | 8 | def __init__(self, outfile=sys.stdout): |
14 | 9 | self.errors = [] |
-
diff --git a/django/db/__init__.py b/django/db/__init__.py
index 3f9645a..d39e7db 100644
a
|
b
|
|
| 1 | from functools import partial |
| 2 | |
1 | 3 | from django.conf import settings |
2 | 4 | from django.core import signals |
3 | 5 | from django.core.exceptions import ImproperlyConfigured |
4 | 6 | from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS, \ |
5 | 7 | DatabaseError, IntegrityError |
6 | | from django.utils.functional import curry |
7 | 8 | |
8 | 9 | __all__ = ('backend', 'connection', 'connections', 'router', 'DatabaseError', |
9 | 10 | 'IntegrityError', 'DEFAULT_DB_ALIAS') |
-
diff --git a/django/db/backends/util.py b/django/db/backends/util.py
index 2f92a30..bf62236 100644
a
|
b
|
|
1 | 1 | import datetime |
2 | 2 | import decimal |
3 | 3 | from time import time |
| 4 | from hashlib import md5 |
4 | 5 | |
5 | | from django.utils.hashcompat import md5_constructor |
6 | 6 | from django.utils.log import getLogger |
7 | 7 | |
8 | 8 | |
… |
… |
def truncate_name(name, length=None, hash_len=4):
|
130 | 130 | if length is None or len(name) <= length: |
131 | 131 | return name |
132 | 132 | |
133 | | hash = md5_constructor(name).hexdigest()[:hash_len] |
| 133 | hash = md5(name).hexdigest()[:hash_len] |
134 | 134 | |
135 | 135 | return '%s%s' % (name[:length-hash_len], hash) |
136 | 136 | |
-
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 286f9b0..8267031 100644
a
|
b
|
|
1 | 1 | import types |
2 | 2 | import sys |
| 3 | import copy |
3 | 4 | from itertools import izip |
| 5 | from functools import update_wrapper |
4 | 6 | |
5 | 7 | import django.db.models.manager # Imported to register signal handler. |
6 | 8 | from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS |
… |
… |
from django.db import (connections, router, transaction, DatabaseError,
|
17 | 19 | from django.db.models import signals |
18 | 20 | from django.db.models.loading import register_models, get_model |
19 | 21 | from django.utils.translation import ugettext_lazy as _ |
20 | | import django.utils.copycompat as copy |
21 | | from django.utils.functional import curry, update_wrapper |
| 22 | from django.utils.functional import curry |
22 | 23 | from django.utils.encoding import smart_str, force_unicode |
23 | 24 | from django.utils.text import get_text_list, capfirst |
24 | 25 | from django.conf import settings |
-
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 73960f5..a52fa24 100644
a
|
b
|
|
| 1 | from functools import wraps |
1 | 2 | from operator import attrgetter |
2 | 3 | |
3 | 4 | from django.db import connections, transaction, IntegrityError |
4 | 5 | from django.db.models import signals, sql |
5 | 6 | from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE |
6 | 7 | from django.utils.datastructures import SortedDict |
7 | | from django.utils.functional import wraps |
8 | 8 | |
9 | 9 | |
10 | 10 | class ProtectedError(IntegrityError): |
11 | 11 | def __init__(self, msg, protected_objects): |
12 | 12 | self.protected_objects = protected_objects |
13 | | # TODO change this to use super() when we drop Python 2.4 |
14 | | IntegrityError.__init__(self, msg, protected_objects) |
| 13 | super(ProtectedError, self).__init__(msg, protected_objects) |
15 | 14 | |
16 | 15 | |
17 | 16 | def CASCADE(collector, field, sub_objs, using): |
-
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 8b9c934..400b7c7 100644
a
|
b
|
|
1 | 1 | import datetime |
| 2 | from copy import deepcopy |
2 | 3 | |
3 | 4 | from django.utils import tree |
4 | | from django.utils.copycompat import deepcopy |
5 | 5 | |
6 | 6 | class ExpressionNode(tree.Node): |
7 | 7 | """ |
-
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 8081cf3..da52911 100644
a
|
b
|
import decimal
|
3 | 3 | import re |
4 | 4 | import time |
5 | 5 | import math |
| 6 | import copy |
6 | 7 | from itertools import tee |
7 | 8 | |
8 | | import django.utils.copycompat as copy |
9 | | |
10 | 9 | from django.db import connection |
11 | 10 | from django.db.models.fields.subclassing import LegacyConnection |
12 | 11 | from django.db.models.query_utils import QueryWrapper |
-
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index aaf1fbb..50dc236 100644
a
|
b
|
|
1 | 1 | import datetime |
2 | 2 | import os |
3 | 3 | |
4 | | import django.utils.copycompat as copy |
5 | | |
6 | 4 | from django.conf import settings |
7 | 5 | from django.db.models.fields import Field |
8 | 6 | from django.core.files.base import File, ContentFile |
-
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 1318706..6b609e4 100644
a
|
b
|
|
| 1 | from django.utils import datetime_safe |
1 | 2 | from django.conf import settings |
2 | 3 | from django.db import connection, router, transaction |
3 | 4 | from django.db.backends import util |
-
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
index 6a62c25..9528d66 100644
a
|
b
|
|
1 | | from django.utils import copycompat as copy |
| 1 | import copy |
2 | 2 | from django.conf import settings |
3 | 3 | from django.db import router |
4 | 4 | from django.db.models.query import QuerySet, EmptyQuerySet, insert_query, RawQuerySet |
-
diff --git a/django/db/models/options.py b/django/db/models/options.py
index 10617dc..6d8ab6f 100644
a
|
b
|
from django.utils.translation import activate, deactivate_all, get_language, str
|
11 | 11 | from django.utils.encoding import force_unicode, smart_str |
12 | 12 | from django.utils.datastructures import SortedDict |
13 | 13 | |
14 | | try: |
15 | | all |
16 | | except NameError: |
17 | | from django.utils.itercompat import all |
18 | | |
19 | 14 | # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces". |
20 | 15 | get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip() |
21 | 16 | |
-
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 0fc48f8..c11c442 100644
a
|
b
|
The main QuerySet implementation. This provides the public API for the ORM.
|
3 | 3 | """ |
4 | 4 | |
5 | 5 | from itertools import izip |
| 6 | from copy import deepcopy |
6 | 7 | |
7 | 8 | from django.db import connections, router, transaction, IntegrityError |
8 | 9 | from django.db.models.aggregates import Aggregate |
… |
… |
from django.db.models.query_utils import (Q, select_related_descend,
|
11 | 12 | deferred_class_factory, InvalidQuery) |
12 | 13 | from django.db.models.deletion import Collector |
13 | 14 | from django.db.models import signals, sql |
14 | | from django.utils.copycompat import deepcopy |
15 | 15 | |
16 | 16 | # Used to control how many objects are worked with at once in some cases (e.g. |
17 | 17 | # when deleting objects). |
-
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 80485e0..e3cf4ba 100644
a
|
b
|
circular import difficulties.
|
7 | 7 | """ |
8 | 8 | |
9 | 9 | import weakref |
10 | | from django.utils.copycompat import deepcopy |
| 10 | from copy import deepcopy |
11 | 11 | |
12 | 12 | from django.db.backends import util |
13 | 13 | from django.utils import tree |
-
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index ea89771..889324e 100644
a
|
b
|
databases). The abstraction barrier only works one way: this module has to know
|
7 | 7 | all about the internals of models in order to get the information it needs. |
8 | 8 | """ |
9 | 9 | |
10 | | from django.utils.copycompat import deepcopy |
| 10 | from copy import deepcopy |
11 | 11 | from django.utils.tree import Node |
12 | 12 | from django.utils.datastructures import SortedDict |
13 | 13 | from django.utils.encoding import force_unicode |
-
diff --git a/django/db/transaction.py b/django/db/transaction.py
index b5584dd..df903b0 100644
a
|
b
|
Managed transactions don't do those commits, but will need some kind of manual
|
12 | 12 | or implicit commits or rollbacks. |
13 | 13 | """ |
14 | 14 | import sys |
15 | | |
16 | | try: |
17 | | from functools import wraps |
18 | | except ImportError: |
19 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 15 | from functools import wraps |
20 | 16 | |
21 | 17 | from django.conf import settings |
22 | 18 | from django.db import connections, DEFAULT_DB_ALIAS |
… |
… |
class Transaction(object):
|
210 | 206 | @wraps(func) |
211 | 207 | def inner(*args, **kwargs): |
212 | 208 | # Once we drop support for Python 2.4 this block should become: |
213 | | # with self: |
214 | | # func(*args, **kwargs) |
215 | | self.__enter__() |
216 | | try: |
217 | | res = func(*args, **kwargs) |
218 | | except: |
219 | | self.__exit__(*sys.exc_info()) |
220 | | raise |
221 | | else: |
222 | | self.__exit__(None, None, None) |
223 | | return res |
| 209 | with self: |
| 210 | return func(*args, **kwargs) |
224 | 211 | return inner |
225 | 212 | |
226 | 213 | def _transaction_func(entering, exiting, using): |
-
diff --git a/django/dispatch/saferef.py b/django/dispatch/saferef.py
index 8bcfd8a..f446447 100644
a
|
b
|
class BoundNonDescriptorMethodWeakref(BoundMethodWeakref):
|
230 | 230 | if target is not None: |
231 | 231 | function = self.weakFunc() |
232 | 232 | if function is not None: |
233 | | # Using curry() would be another option, but it erases the |
| 233 | # Using partial() would be another option, but it erases the |
234 | 234 | # "signature" of the function. That is, after a function is |
235 | 235 | # curried, the inspect module can't be used to determine how |
236 | 236 | # many arguments the function expects, nor what keyword |
-
diff --git a/django/forms/extras/widgets.py b/django/forms/extras/widgets.py
index e8bacf2..d75e903 100644
a
|
b
|
class SelectDateWidget(Widget):
|
68 | 68 | if settings.USE_L10N: |
69 | 69 | try: |
70 | 70 | input_format = get_format('DATE_INPUT_FORMATS')[0] |
71 | | # Python 2.4 compatibility: |
72 | | # v = datetime.datetime.strptime(value, input_format) |
73 | | # would be clearer, but datetime.strptime was added in |
74 | | # Python 2.5 |
75 | | v = datetime.datetime(*(time.strptime(value, input_format)[0:6])) |
| 71 | v = datetime.datetime.strptime(value, input_format) |
76 | 72 | year_val, month_val, day_val = v.year, v.month, v.day |
77 | 73 | except ValueError: |
78 | 74 | pass |
-
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 4d7728f..0235d28 100644
a
|
b
|
Field classes.
|
5 | 5 | import datetime |
6 | 6 | import os |
7 | 7 | import re |
| 8 | import copy |
8 | 9 | import time |
9 | 10 | import urlparse |
10 | 11 | import warnings |
… |
… |
except ImportError:
|
16 | 17 | |
17 | 18 | from django.core.exceptions import ValidationError |
18 | 19 | from django.core import validators |
19 | | import django.utils.copycompat as copy |
20 | 20 | from django.utils import formats |
21 | 21 | from django.utils.translation import ugettext_lazy as _ |
22 | 22 | from django.utils.encoding import smart_unicode, smart_str |
-
diff --git a/django/forms/forms.py b/django/forms/forms.py
index f776861..31b1bc2 100644
a
|
b
|
|
2 | 2 | Form classes |
3 | 3 | """ |
4 | 4 | |
| 5 | from copy import deepcopy |
5 | 6 | from django.core.exceptions import ValidationError |
6 | | from django.utils.copycompat import deepcopy |
7 | 7 | from django.utils.datastructures import SortedDict |
8 | 8 | from django.utils.html import conditional_escape |
9 | 9 | from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode |
-
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index dd5868f..5122d4c 100644
a
|
b
|
|
2 | 2 | HTML Widget classes |
3 | 3 | """ |
4 | 4 | import datetime |
5 | | from itertools import chain |
6 | 5 | import time |
| 6 | import copy |
| 7 | from itertools import chain |
7 | 8 | from urlparse import urljoin |
8 | 9 | from util import flatatt |
9 | 10 | |
10 | | import django.utils.copycompat as copy |
11 | 11 | from django.conf import settings |
12 | 12 | from django.utils.datastructures import MultiValueDict, MergeDict |
13 | 13 | from django.utils.html import escape, conditional_escape |
-
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 714d552..62e327d 100644
a
|
b
|
class QueryDict(MultiValueDict):
|
364 | 364 | return result |
365 | 365 | |
366 | 366 | def __deepcopy__(self, memo): |
367 | | import django.utils.copycompat as copy |
| 367 | import copy |
368 | 368 | result = self.__class__('', mutable=True, encoding=self.encoding) |
369 | 369 | memo[id(self)] = result |
370 | 370 | for key, value in dict.items(self): |
-
diff --git a/django/middleware/common.py b/django/middleware/common.py
index 2252c8f..68bf891 100644
a
|
b
|
|
1 | 1 | import re |
| 2 | from hashlib import md5 |
2 | 3 | |
3 | 4 | from django.conf import settings |
4 | 5 | from django import http |
5 | 6 | from django.core.mail import mail_managers |
6 | 7 | from django.utils.http import urlquote |
7 | 8 | from django.core import urlresolvers |
8 | | from django.utils.hashcompat import md5_constructor |
9 | 9 | from django.utils.log import getLogger |
10 | 10 | |
11 | 11 | logger = getLogger('django.request') |
… |
… |
class CommonMiddleware(object):
|
113 | 113 | if response.has_header('ETag'): |
114 | 114 | etag = response['ETag'] |
115 | 115 | else: |
116 | | etag = '"%s"' % md5_constructor(response.content).hexdigest() |
| 116 | etag = '"%s"' % md5(response.content).hexdigest() |
117 | 117 | if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag: |
118 | 118 | cookies = response.cookies |
119 | 119 | response = http.HttpResponseNotModified() |
-
diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py
index b5a8579..a79e1e0 100644
a
|
b
|
against request forgeries from other sites.
|
8 | 8 | import itertools |
9 | 9 | import re |
10 | 10 | import random |
| 11 | from hashlib import md5 |
11 | 12 | |
12 | 13 | from django.conf import settings |
13 | 14 | from django.core.urlresolvers import get_callable |
14 | 15 | from django.utils.cache import patch_vary_headers |
15 | | from django.utils.hashcompat import md5_constructor |
16 | 16 | from django.utils.http import same_origin |
17 | 17 | from django.utils.log import getLogger |
18 | 18 | from django.utils.safestring import mark_safe |
… |
… |
def _get_failure_view():
|
47 | 47 | |
48 | 48 | |
49 | 49 | def _get_new_csrf_key(): |
50 | | return md5_constructor("%s%s" |
51 | | % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest() |
| 50 | return md5("%s%s" % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest() |
52 | 51 | |
53 | 52 | |
54 | 53 | def _make_legacy_session_token(session_id): |
55 | | return md5_constructor(settings.SECRET_KEY + session_id).hexdigest() |
| 54 | return md5(settings.SECRET_KEY + session_id).hexdigest() |
56 | 55 | |
57 | 56 | |
58 | 57 | def get_token(request): |
-
diff --git a/django/template/base.py b/django/template/base.py
index 49ef0b8..01f9752 100644
a
|
b
|
|
1 | 1 | import imp |
2 | 2 | import re |
3 | 3 | from inspect import getargspec |
| 4 | from functools import partial |
4 | 5 | |
5 | 6 | from django.conf import settings |
6 | 7 | from django.template.context import Context, RequestContext, ContextPopException |
7 | 8 | from django.utils.importlib import import_module |
8 | 9 | from django.utils.itercompat import is_iterable |
9 | | from django.utils.functional import curry, Promise |
| 10 | from django.utils.functional import Promise |
10 | 11 | from django.utils.text import smart_split, unescape_string_literal, get_text_list |
11 | 12 | from django.utils.encoding import smart_unicode, force_unicode, smart_str |
12 | 13 | from django.utils.translation import ugettext_lazy |
… |
… |
class Library(object):
|
884 | 885 | func_args = resolved_vars |
885 | 886 | return func(*func_args) |
886 | 887 | |
887 | | compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) |
| 888 | compile_func = partial(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) |
888 | 889 | compile_func.__doc__ = func.__doc__ |
889 | 890 | self.tag(getattr(func, "_decorated_function", func).__name__, compile_func) |
890 | 891 | return func |
… |
… |
class Library(object):
|
936 | 937 | new_context['csrf_token'] = csrf_token |
937 | 938 | return self.nodelist.render(new_context) |
938 | 939 | |
939 | | compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode) |
| 940 | compile_func = partial(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode) |
940 | 941 | compile_func.__doc__ = func.__doc__ |
941 | 942 | self.tag(getattr(func, "_decorated_function", func).__name__, compile_func) |
942 | 943 | return func |
-
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index d923d8a..dec69fd 100644
a
|
b
|
|
3 | 3 | import re |
4 | 4 | from decimal import Decimal, InvalidOperation, ROUND_HALF_UP |
5 | 5 | import random as random_module |
6 | | try: |
7 | | from functools import wraps |
8 | | except ImportError: |
9 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 6 | from functools import wraps |
10 | 7 | |
11 | 8 | from django.template.base import Variable, Library |
12 | 9 | from django.conf import settings |
-
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index 715542a..c40a337 100644
a
|
b
|
|
2 | 2 | Wrapper class that takes a list of template loaders as an argument and attempts |
3 | 3 | to load templates from them in order, caching the result. |
4 | 4 | """ |
| 5 | from hashlib import sha1 |
5 | 6 | |
6 | 7 | from django.core.exceptions import ImproperlyConfigured |
7 | 8 | from django.template.base import TemplateDoesNotExist |
8 | 9 | from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin |
9 | | from django.utils.hashcompat import sha_constructor |
10 | 10 | from django.utils.importlib import import_module |
11 | 11 | |
12 | 12 | class Loader(BaseLoader): |
… |
… |
class Loader(BaseLoader):
|
38 | 38 | key = template_name |
39 | 39 | if template_dirs: |
40 | 40 | # If template directories were specified, use a hash to differentiate |
41 | | key = '-'.join([template_name, sha_constructor('|'.join(template_dirs)).hexdigest()]) |
| 41 | key = '-'.join([template_name, sha1('|'.join(template_dirs)).hexdigest()]) |
42 | 42 | |
43 | 43 | if key not in self.template_cache: |
44 | 44 | template, origin = self.find_template(template_name, template_dirs) |
-
diff --git a/django/templatetags/cache.py b/django/templatetags/cache.py
index 4fe3c3b..44f8f77 100644
a
|
b
|
|
| 1 | from hashlib import md5 |
1 | 2 | from django.template import Library, Node, TemplateSyntaxError, Variable, VariableDoesNotExist |
2 | 3 | from django.template import resolve_variable |
3 | 4 | from django.core.cache import cache |
4 | 5 | from django.utils.encoding import force_unicode |
5 | 6 | from django.utils.http import urlquote |
6 | | from django.utils.hashcompat import md5_constructor |
7 | 7 | |
8 | 8 | register = Library() |
9 | 9 | |
… |
… |
class CacheNode(Node):
|
24 | 24 | except (ValueError, TypeError): |
25 | 25 | raise TemplateSyntaxError('"cache" tag got a non-integer timeout value: %r' % expire_time) |
26 | 26 | # Build a unicode key for this fragment and all vary-on's. |
27 | | args = md5_constructor(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on])) |
| 27 | args = md5(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on])) |
28 | 28 | cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest()) |
29 | 29 | value = cache.get(cache_key) |
30 | 30 | if value is None: |
-
diff --git a/django/test/client.py b/django/test/client.py
index dd0d811..b5256fb 100644
a
|
b
|
import re
|
6 | 6 | import mimetypes |
7 | 7 | import warnings |
8 | 8 | from copy import copy |
| 9 | from functools import partial |
9 | 10 | try: |
10 | 11 | from cStringIO import StringIO |
11 | 12 | except ImportError: |
-
diff --git a/django/test/simple.py b/django/test/simple.py
index d0b9a70..41b2a42 100644
a
|
b
|
from django.test.utils import setup_test_environment, teardown_test_environment
|
7 | 7 | from django.test.testcases import OutputChecker, DocTestRunner, TestCase |
8 | 8 | from django.utils import unittest |
9 | 9 | |
10 | | try: |
11 | | all |
12 | | except NameError: |
13 | | from django.utils.itercompat import all |
14 | | |
15 | | |
16 | 10 | __all__ = ('DjangoTestRunner', 'DjangoTestSuiteRunner', 'run_tests') |
17 | 11 | |
18 | 12 | # The module name for tests outside models.py |
-
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 02cd00c..e5c8ad9 100644
a
|
b
|
|
1 | 1 | import re |
2 | 2 | import sys |
| 3 | from functools import wraps |
3 | 4 | from urlparse import urlsplit, urlunsplit |
4 | 5 | from xml.dom.minidom import parseString, Node |
5 | 6 | |
… |
… |
from django.test.client import Client
|
16 | 17 | from django.test.utils import get_warnings_state, restore_warnings_state |
17 | 18 | from django.utils import simplejson, unittest as ut2 |
18 | 19 | from django.utils.encoding import smart_str |
19 | | from django.utils.functional import wraps |
20 | 20 | |
21 | 21 | __all__ = ('DocTestRunner', 'OutputChecker', 'TestCase', 'TransactionTestCase', |
22 | 22 | 'skipIfDBFeature', 'skipUnlessDBFeature') |
23 | 23 | |
24 | 24 | |
25 | | try: |
26 | | all |
27 | | except NameError: |
28 | | from django.utils.itercompat import all |
29 | | |
30 | 25 | normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) |
31 | 26 | normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)", lambda m: "Decimal(\"%s\")" % m.groups()[0], s) |
32 | 27 | |
… |
… |
class TransactionTestCase(ut2.TestCase):
|
550 | 545 | |
551 | 546 | def connections_support_transactions(): |
552 | 547 | """ |
553 | | Returns True if all connections support transactions. This is messy |
554 | | because 2.4 doesn't support any or all. |
| 548 | Returns True if all connections support transactions. |
555 | 549 | """ |
556 | 550 | return all(conn.features.supports_transactions |
557 | 551 | for conn in connections.all()) |
-
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 63c4af3..55a1344 100644
a
|
b
|
An example: i18n middleware would need to distinguish caches by the
|
19 | 19 | |
20 | 20 | import re |
21 | 21 | import time |
| 22 | from hashlib import md5 |
22 | 23 | |
23 | 24 | from django.conf import settings |
24 | 25 | from django.core.cache import get_cache |
25 | 26 | from django.utils.encoding import smart_str, iri_to_uri |
26 | 27 | from django.utils.http import http_date |
27 | | from django.utils.hashcompat import md5_constructor |
28 | 28 | from django.utils.translation import get_language |
29 | 29 | from django.http import HttpRequest |
30 | 30 | |
… |
… |
def patch_response_headers(response, cache_timeout=None):
|
102 | 102 | if cache_timeout < 0: |
103 | 103 | cache_timeout = 0 # Can't have max-age negative |
104 | 104 | if settings.USE_ETAGS and not response.has_header('ETag'): |
105 | | response['ETag'] = '"%s"' % md5_constructor(response.content).hexdigest() |
| 105 | response['ETag'] = '"%s"' % md5(response.content).hexdigest() |
106 | 106 | if not response.has_header('Last-Modified'): |
107 | 107 | response['Last-Modified'] = http_date() |
108 | 108 | if not response.has_header('Expires'): |
… |
… |
def _i18n_cache_key_suffix(request, cache_key):
|
155 | 155 | |
156 | 156 | def _generate_cache_key(request, method, headerlist, key_prefix): |
157 | 157 | """Returns a cache key from the headers given in the header list.""" |
158 | | ctx = md5_constructor() |
| 158 | ctx = md5() |
159 | 159 | for header in headerlist: |
160 | 160 | value = request.META.get(header, None) |
161 | 161 | if value is not None: |
162 | 162 | ctx.update(value) |
163 | | path = md5_constructor(iri_to_uri(request.get_full_path())) |
| 163 | path = md5(iri_to_uri(request.get_full_path())) |
164 | 164 | cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % ( |
165 | 165 | key_prefix, request.method, path.hexdigest(), ctx.hexdigest()) |
166 | 166 | return _i18n_cache_key_suffix(request, cache_key) |
167 | 167 | |
168 | 168 | def _generate_cache_header_key(key_prefix, request): |
169 | 169 | """Returns a cache key for the header cache.""" |
170 | | path = md5_constructor(iri_to_uri(request.get_full_path())) |
| 170 | path = md5(iri_to_uri(request.get_full_path())) |
171 | 171 | cache_key = 'views.decorators.cache.cache_header.%s.%s' % ( |
172 | 172 | key_prefix, path.hexdigest()) |
173 | 173 | return _i18n_cache_key_suffix(request, cache_key) |
-
diff --git a/django/utils/copycompat.py b/django/utils/copycompat.py
deleted file mode 100644
index 22b3cfb..0000000
+
|
-
|
|
1 | | """ |
2 | | Fixes Python 2.4's failure to deepcopy unbound functions. |
3 | | """ |
4 | | |
5 | | import copy |
6 | | import types |
7 | | |
8 | | # Monkeypatch copy's deepcopy registry to handle functions correctly. |
9 | | if (hasattr(copy, '_deepcopy_dispatch') and types.FunctionType not in copy._deepcopy_dispatch): |
10 | | copy._deepcopy_dispatch[types.FunctionType] = copy._deepcopy_atomic |
11 | | |
12 | | # Pose as the copy module now. |
13 | | del copy, types |
14 | | from copy import * |
-
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
index 87cd0b9..1650976 100644
a
|
b
|
|
2 | 2 | Django's standard crypto functions and utilities. |
3 | 3 | """ |
4 | 4 | import hmac |
| 5 | from hashlib import sha1 |
5 | 6 | |
6 | 7 | from django.conf import settings |
7 | | from django.utils.hashcompat import sha_constructor, sha_hmac |
8 | 8 | |
9 | 9 | |
10 | 10 | def salted_hmac(key_salt, value, secret=None): |
… |
… |
def salted_hmac(key_salt, value, secret=None):
|
21 | 21 | # passing the key_salt and our base key through a pseudo-random function and |
22 | 22 | # SHA1 works nicely. |
23 | 23 | |
24 | | key = sha_constructor(key_salt + secret).digest() |
| 24 | key = sha1(key_salt + secret).digest() |
25 | 25 | |
26 | 26 | # If len(key_salt + secret) > sha_constructor().block_size, the above |
27 | 27 | # line is redundant and could be replaced by key = key_salt + secret, since |
28 | 28 | # the hmac module does the same thing for keys longer than the block size. |
29 | 29 | # However, we need to ensure that we *always* do this. |
30 | 30 | |
31 | | return hmac.new(key, msg=value, digestmod=sha_hmac) |
| 31 | return hmac.new(key, msg=value, digestmod=sha1) |
32 | 32 | |
33 | 33 | |
34 | 34 | def constant_time_compare(val1, val2): |
-
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 7425ea2..a401ddd 100644
a
|
b
|
|
1 | 1 | from types import GeneratorType |
2 | | |
3 | | from django.utils.copycompat import copy, deepcopy |
| 2 | from copy import copy, deepcopy |
4 | 3 | |
5 | 4 | |
6 | 5 | class MergeDict(object): |
… |
… |
class MultiValueDict(dict):
|
269 | 268 | ]) |
270 | 269 | |
271 | 270 | def __deepcopy__(self, memo=None): |
272 | | import django.utils.copycompat as copy |
273 | 271 | if memo is None: |
274 | 272 | memo = {} |
275 | 273 | result = self.__class__() |
276 | 274 | memo[id(self)] = result |
277 | 275 | for key, value in dict.items(self): |
278 | | dict.__setitem__(result, copy.deepcopy(key, memo), |
279 | | copy.deepcopy(value, memo)) |
| 276 | dict.__setitem__(result, deepcopy(key, memo), |
| 277 | deepcopy(value, memo)) |
280 | 278 | return result |
281 | 279 | |
282 | 280 | def __getstate__(self): |
-
diff --git a/django/utils/decorators.py b/django/utils/decorators.py
index 17f2ea3..6099f88 100644
a
|
b
|
|
1 | 1 | "Functions that help with dynamically creating decorators for views." |
2 | 2 | |
3 | | try: |
4 | | from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS |
5 | | except ImportError: |
6 | | from django.utils.functional import wraps, update_wrapper, WRAPPER_ASSIGNMENTS # Python 2.4 fallback. |
| 3 | from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS |
7 | 4 | |
8 | 5 | class classonlymethod(classmethod): |
9 | 6 | def __get__(self, instance, owner): |
-
diff --git a/django/utils/functional.py b/django/utils/functional.py
index ccfbcb0..45382e3 100644
a
|
b
|
|
49 | 49 | # agrees to be bound by the terms and conditions of this License |
50 | 50 | # Agreement. |
51 | 51 | |
| 52 | from functools import wraps |
52 | 53 | |
53 | 54 | def curry(_curried_func, *args, **kwargs): |
54 | 55 | def _curried(*moreargs, **morekwargs): |
55 | 56 | return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) |
56 | 57 | return _curried |
57 | 58 | |
58 | | ### Begin from Python 2.5 functools.py ######################################## |
59 | | |
60 | | # Summary of changes made to the Python 2.5 code below: |
61 | | # * swapped ``partial`` for ``curry`` to maintain backwards-compatibility |
62 | | # in Django. |
63 | | |
64 | | # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. |
65 | | # All Rights Reserved. |
66 | | |
67 | | ############################################################################### |
68 | | |
69 | | # update_wrapper() and wraps() are tools to help write |
70 | | # wrapper functions that can handle naive introspection |
71 | | |
72 | | WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') |
73 | | WRAPPER_UPDATES = ('__dict__',) |
74 | | def update_wrapper(wrapper, |
75 | | wrapped, |
76 | | assigned = WRAPPER_ASSIGNMENTS, |
77 | | updated = WRAPPER_UPDATES): |
78 | | """Update a wrapper function to look like the wrapped function |
79 | | |
80 | | wrapper is the function to be updated |
81 | | wrapped is the original function |
82 | | assigned is a tuple naming the attributes assigned directly |
83 | | from the wrapped function to the wrapper function (defaults to |
84 | | functools.WRAPPER_ASSIGNMENTS) |
85 | | updated is a tuple naming the attributes off the wrapper that |
86 | | are updated with the corresponding attribute from the wrapped |
87 | | function (defaults to functools.WRAPPER_UPDATES) |
88 | | """ |
89 | | for attr in assigned: |
90 | | setattr(wrapper, attr, getattr(wrapped, attr)) |
91 | | for attr in updated: |
92 | | getattr(wrapper, attr).update(getattr(wrapped, attr)) |
93 | | # Return the wrapper so this can be used as a decorator via curry() |
94 | | return wrapper |
95 | | |
96 | | def wraps(wrapped, |
97 | | assigned = WRAPPER_ASSIGNMENTS, |
98 | | updated = WRAPPER_UPDATES): |
99 | | """Decorator factory to apply update_wrapper() to a wrapper function |
100 | | |
101 | | Returns a decorator that invokes update_wrapper() with the decorated |
102 | | function as the wrapper argument and the arguments to wraps() as the |
103 | | remaining arguments. Default arguments are as for update_wrapper(). |
104 | | This is a convenience function to simplify applying curry() to |
105 | | update_wrapper(). |
106 | | """ |
107 | | return curry(update_wrapper, wrapped=wrapped, |
108 | | assigned=assigned, updated=updated) |
109 | | |
110 | | ### End from Python 2.5 functools.py ########################################## |
111 | | |
112 | 59 | def memoize(func, cache, num_args): |
113 | 60 | """ |
114 | 61 | Wrap a function so that results for any argument tuple are stored in |
… |
… |
class SimpleLazyObject(LazyObject):
|
343 | 290 | memo[id(self)] = result |
344 | 291 | return result |
345 | 292 | else: |
346 | | # Changed to use deepcopy from copycompat, instead of copy |
347 | | # For Python 2.4. |
348 | | from django.utils.copycompat import deepcopy |
| 293 | from copy import deepcopy |
349 | 294 | return deepcopy(self._wrapped, memo) |
350 | 295 | |
351 | 296 | # Need to pretend to be the wrapped class, for the sake of objects that care |
-
diff --git a/django/utils/hashcompat.py b/django/utils/hashcompat.py
deleted file mode 100644
index 4d9b76f..0000000
+
|
-
|
|
1 | | """ |
2 | | The md5 and sha modules are deprecated since Python 2.5, replaced by the |
3 | | hashlib module containing both hash algorithms. Here, we provide a common |
4 | | interface to the md5 and sha constructors, depending on system version. |
5 | | """ |
6 | | |
7 | | import sys |
8 | | if sys.version_info >= (2, 5): |
9 | | import hashlib |
10 | | md5_constructor = hashlib.md5 |
11 | | md5_hmac = md5_constructor |
12 | | sha_constructor = hashlib.sha1 |
13 | | sha_hmac = sha_constructor |
14 | | else: |
15 | | import md5 |
16 | | md5_constructor = md5.new |
17 | | md5_hmac = md5 |
18 | | import sha |
19 | | sha_constructor = sha.new |
20 | | sha_hmac = sha |
-
diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py
index d4ff250..b302e22 100644
a
|
b
|
def is_iterable(x):
|
31 | 31 | return False |
32 | 32 | else: |
33 | 33 | return True |
34 | | |
35 | | def all(iterable): |
36 | | for item in iterable: |
37 | | if not item: |
38 | | return False |
39 | | return True |
40 | | |
41 | | def any(iterable): |
42 | | for item in iterable: |
43 | | if item: |
44 | | return True |
45 | | return False |
-
diff --git a/django/utils/log.py b/django/utils/log.py
index 4fb75b1..493f2ea 100644
a
|
b
|
try:
|
18 | 18 | except ImportError: |
19 | 19 | from django.utils.dictconfig import dictConfig |
20 | 20 | |
21 | | if sys.version_info < (2, 5): |
22 | | class LoggerCompat(object): |
23 | | def __init__(self, logger): |
24 | | self._logger = logger |
25 | | |
26 | | def __getattr__(self, name): |
27 | | val = getattr(self._logger, name) |
28 | | if callable(val): |
29 | | def _wrapper(*args, **kwargs): |
30 | | # Python 2.4 logging module doesn't support 'extra' parameter to |
31 | | # methods of Logger |
32 | | kwargs.pop('extra', None) |
33 | | return val(*args, **kwargs) |
34 | | return _wrapper |
35 | | else: |
36 | | return val |
37 | | |
38 | | def getLogger(name=None): |
39 | | return LoggerCompat(logging.getLogger(name=name)) |
40 | | else: |
41 | | getLogger = logging.getLogger |
| 21 | getLogger = logging.getLogger |
42 | 22 | |
43 | 23 | # Ensure the creation of the Django logger |
44 | 24 | # with a null handler. This ensures we don't get any |
… |
… |
if not logger.handlers:
|
49 | 29 | |
50 | 30 | class AdminEmailHandler(logging.Handler): |
51 | 31 | def __init__(self, include_html=False): |
52 | | logging.Handler.__init__(self) |
| 32 | logging.Handler.__init__(self) |
53 | 33 | self.include_html = include_html |
54 | 34 | |
55 | 35 | """An exception log handler that e-mails log entries to site admins. |
… |
… |
class AdminEmailHandler(logging.Handler):
|
63 | 43 | from django.views.debug import ExceptionReporter |
64 | 44 | |
65 | 45 | try: |
66 | | if sys.version_info < (2,5): |
67 | | # A nasty workaround required because Python 2.4's logging |
68 | | # module doesn't support passing in extra context. |
69 | | # For this handler, the only extra data we need is the |
70 | | # request, and that's in the top stack frame. |
71 | | request = record.exc_info[2].tb_frame.f_locals['request'] |
72 | | else: |
73 | | request = record.request |
74 | | |
| 46 | request = record.request |
75 | 47 | subject = '%s (%s IP): %s' % ( |
76 | 48 | record.levelname, |
77 | 49 | (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), |
-
diff --git a/django/utils/tree.py b/django/utils/tree.py
index a6cfec2..a9028b8 100644
a
|
b
|
A class for storing a tree graph. Primarily used for filter constructs in the
|
3 | 3 | ORM. |
4 | 4 | """ |
5 | 5 | |
6 | | from django.utils.copycompat import deepcopy |
| 6 | from copy import deepcopy |
7 | 7 | |
8 | 8 | class Node(object): |
9 | 9 | """ |
-
diff --git a/django/utils/unittest/case.py b/django/utils/unittest/case.py
index 78507c1..e8823fa 100644
a
|
b
|
class _ExpectedFailure(Exception):
|
36 | 36 | """ |
37 | 37 | |
38 | 38 | def __init__(self, exc_info): |
39 | | # can't use super because Python 2.4 exceptions are old style |
40 | | Exception.__init__(self) |
| 39 | super(_ExpectedFailure, self).__init__() |
41 | 40 | self.exc_info = exc_info |
42 | 41 | |
43 | 42 | class _UnexpectedSuccess(Exception): |
-
diff --git a/django/utils/unittest/compatibility.py b/django/utils/unittest/compatibility.py
index a0dc499..11c6161 100644
a
|
b
|
|
1 | 1 | import os |
2 | 2 | import sys |
3 | | |
4 | | try: |
5 | | from functools import wraps |
6 | | except ImportError: |
7 | | # only needed for Python 2.4 |
8 | | def wraps(_): |
9 | | def _wraps(func): |
10 | | return func |
11 | | return _wraps |
| 3 | from functools import wraps |
12 | 4 | |
13 | 5 | __unittest = True |
14 | 6 | |
-
diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py
index a836ac5..4db9a12 100644
a
|
b
|
|
1 | | try: |
2 | | from functools import wraps |
3 | | except ImportError: |
4 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 1 | from functools import wraps |
5 | 2 | |
6 | 3 | from django.utils.decorators import decorator_from_middleware_with_args, available_attrs |
7 | 4 | from django.utils.cache import patch_cache_control, add_never_cache_headers |
-
diff --git a/django/views/decorators/csrf.py b/django/views/decorators/csrf.py
index 578854a..330d1d3 100644
a
|
b
|
|
| 1 | from functools import wraps |
| 2 | |
1 | 3 | from django.middleware.csrf import CsrfViewMiddleware |
2 | 4 | from django.utils.decorators import decorator_from_middleware, available_attrs |
3 | 5 | |
4 | | try: |
5 | | from functools import wraps |
6 | | except ImportError: |
7 | | from django.utils.functional import wraps # Python 2.4 fallback. |
8 | | |
9 | 6 | csrf_protect = decorator_from_middleware(CsrfViewMiddleware) |
10 | 7 | csrf_protect.__name__ = "csrf_protect" |
11 | 8 | csrf_protect.__doc__ = """ |
-
diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py
index fb3181e..aaf3503 100644
a
|
b
|
|
1 | 1 | """ |
2 | 2 | Decorators for views based on HTTP headers. |
3 | 3 | """ |
4 | | |
5 | | try: |
6 | | from functools import wraps |
7 | | except ImportError: |
8 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 4 | from functools import wraps |
9 | 5 | |
10 | 6 | from calendar import timegm |
11 | 7 | from datetime import timedelta |
-
diff --git a/django/views/decorators/vary.py b/django/views/decorators/vary.py
index a10896c..f95534e 100644
a
|
b
|
|
1 | | try: |
2 | | from functools import wraps |
3 | | except ImportError: |
4 | | from django.utils.functional import wraps # Python 2.4 fallback. |
| 1 | from functools import wraps |
5 | 2 | |
6 | 3 | from django.utils.cache import patch_vary_headers |
7 | 4 | from django.utils.decorators import available_attrs |
-
diff --git a/django/views/generic/base.py b/django/views/generic/base.py
index d732af5..f2c6d3f 100644
a
|
b
|
|
| 1 | from functools import update_wrapper |
1 | 2 | from django import http |
2 | 3 | from django.core.exceptions import ImproperlyConfigured |
3 | 4 | from django.template import RequestContext, loader |
4 | 5 | from django.template.response import TemplateResponse |
5 | | from django.utils.functional import update_wrapper |
6 | 6 | from django.utils.log import getLogger |
7 | 7 | from django.utils.decorators import classonlymethod |
8 | 8 | |
-
diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py
index 2ad5b0c..bfb3b3d 100644
a
|
b
|
|
1 | 1 | import gc |
2 | 2 | import sys |
| 3 | import copy |
3 | 4 | |
4 | 5 | from django.dispatch import Signal |
5 | 6 | from django.utils import unittest |
6 | | import django.utils.copycompat as copy |
7 | 7 | |
8 | 8 | if sys.platform.startswith('java'): |
9 | 9 | def garbage_collect(): |
-
diff --git a/tests/regressiontests/extra_regress/models.py b/tests/regressiontests/extra_regress/models.py
index 073157a..4445a0f 100644
a
|
b
|
|
1 | 1 | import datetime |
2 | | |
3 | | import django.utils.copycompat as copy |
| 2 | import copy |
4 | 3 | |
5 | 4 | from django.contrib.auth.models import User |
6 | 5 | from django.db import models |
-
diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
index 4c5aeb0..894b0a6 100644
a
|
b
|
|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | import datetime |
3 | | from decimal import Decimal |
4 | 3 | import re |
5 | 4 | import time |
| 5 | import copy |
| 6 | from decimal import Decimal |
| 7 | |
6 | 8 | from django.conf import settings |
7 | 9 | from django.core.files.uploadedfile import SimpleUploadedFile |
8 | 10 | from django.forms import * |
9 | 11 | from django.forms.widgets import RadioFieldRenderer |
10 | | from django.utils import copycompat as copy |
11 | 12 | from django.utils import formats |
12 | 13 | from django.utils.safestring import mark_safe |
13 | 14 | from django.utils.translation import activate, deactivate |
-
diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py
index 90dea92..4809849 100644
a
|
b
|
|
| 1 | from functools import update_wrapper |
| 2 | |
1 | 3 | from django.conf import settings |
2 | 4 | from django.db import connection, DEFAULT_DB_ALIAS |
3 | 5 | from django.test import TestCase, skipUnlessDBFeature |
4 | | from django.utils import functional |
5 | 6 | |
6 | 7 | from models import Reporter, Article |
7 | 8 | |
… |
… |
def ignore_not_implemented(func):
|
23 | 24 | return func(*args, **kwargs) |
24 | 25 | except NotImplementedError: |
25 | 26 | return None |
26 | | functional.update_wrapper(_inner, func) |
| 27 | update_wrapper(_inner, func) |
27 | 28 | return _inner |
28 | 29 | |
29 | 30 | class IgnoreNotimplementedError(type): |
-
diff --git a/tests/regressiontests/utils/datastructures.py b/tests/regressiontests/utils/datastructures.py
index 3d01ab8..74d7d2d 100644
a
|
b
|
Tests for stuff in django.utils.datastructures.
|
3 | 3 | """ |
4 | 4 | import pickle |
5 | 5 | import unittest |
| 6 | import copy |
6 | 7 | |
7 | | from django.utils.copycompat import copy |
8 | 8 | from django.utils.datastructures import * |
9 | 9 | |
10 | 10 | |
-
diff --git a/tests/regressiontests/utils/simplelazyobject.py b/tests/regressiontests/utils/simplelazyobject.py
index 9eea8b5..44fa783 100644
a
|
b
|
|
1 | 1 | import unittest |
| 2 | import copy |
2 | 3 | |
3 | | import django.utils.copycompat as copy |
4 | 4 | from django.utils.functional import SimpleLazyObject |
5 | 5 | |
6 | 6 | class _ComplexObject(object): |