Removed a bunch of Python 2.4 workarounds now that we don't support it. Refs #15702 -- thanks to jonash for the patch. Splitting this over muliple commits to make it more manageable.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15926 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2011-03-28 01:40:43 +00:00
parent 18ef901e5f
commit a87be3554f
20 changed files with 50 additions and 63 deletions

View File

@ -1,3 +1,4 @@
from functools import update_wrapper, partial
from django import forms, template from django import forms, template
from django.forms.formsets import all_valid from django.forms.formsets import all_valid
from django.forms.models import (modelform_factory, modelformset_factory, from django.forms.models import (modelform_factory, modelformset_factory,
@ -17,10 +18,8 @@ from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response from django.shortcuts import get_object_or_404, render_to_response
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.functional import update_wrapper
from django.utils.html import escape, escapejs from django.utils.html import escape, escapejs
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.functional import curry
from django.utils.text import capfirst, get_text_list from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext from django.utils.translation import ungettext
@ -426,7 +425,7 @@ class ModelAdmin(BaseModelAdmin):
"form": self.form, "form": self.form,
"fields": fields, "fields": fields,
"exclude": exclude, "exclude": exclude,
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
return modelform_factory(self.model, **defaults) return modelform_factory(self.model, **defaults)
@ -457,7 +456,7 @@ class ModelAdmin(BaseModelAdmin):
Returns a Form class for use in the Formset on the changelist page. Returns a Form class for use in the Formset on the changelist page.
""" """
defaults = { defaults = {
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
return modelform_factory(self.model, **defaults) return modelform_factory(self.model, **defaults)
@ -468,7 +467,7 @@ class ModelAdmin(BaseModelAdmin):
is used. is used.
""" """
defaults = { defaults = {
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
return modelformset_factory(self.model, return modelformset_factory(self.model,
@ -1327,7 +1326,7 @@ class InlineModelAdmin(BaseModelAdmin):
"fk_name": self.fk_name, "fk_name": self.fk_name,
"fields": fields, "fields": fields,
"exclude": exclude, "exclude": exclude,
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
"extra": self.extra, "extra": self.extra,
"max_num": self.max_num, "max_num": self.max_num,
"can_delete": self.can_delete, "can_delete": self.can_delete,

View File

@ -1,4 +1,5 @@
import re import re
from functools import update_wrapper
from django import http, template from django import http, template
from django.contrib.admin import ModelAdmin, actions from django.contrib.admin import ModelAdmin, actions
from django.contrib.admin.forms import AdminAuthenticationForm from django.contrib.admin.forms import AdminAuthenticationForm
@ -9,7 +10,6 @@ from django.db.models.base import ModelBase
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.utils.functional import update_wrapper
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _

View File

@ -1,8 +1,4 @@
try: from functools import wraps
from functools import wraps
except ImportError:
from django.utils.functional import wraps # Python 2.4 fallback.
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.contrib.admin.forms import AdminAuthenticationForm from django.contrib.admin.forms import AdminAuthenticationForm
from django.contrib.auth.views import login from django.contrib.auth.views import login

View File

@ -2,8 +2,7 @@
Form Widget classes specific to the Django admin site. Form Widget classes specific to the Django admin site.
""" """
import django.utils.copycompat as copy import copy
from django import forms from django import forms
from django.forms.widgets import RadioFieldRenderer from django.forms.widgets import RadioFieldRenderer
from django.forms.util import flatatt from django.forms.util import flatatt

View File

@ -1,9 +1,5 @@
import urlparse import urlparse
try: from functools import wraps
from functools import wraps
except ImportError:
from django.utils.functional import wraps # Python 2.4 fallback.
from django.conf import settings from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth import REDIRECT_FIELD_NAME
from django.utils.decorators import available_attrs from django.utils.decorators import available_attrs

View File

@ -1,4 +1,5 @@
import datetime import datetime
import hashlib
import urllib import urllib
from django.contrib import auth from django.contrib import auth
@ -8,7 +9,6 @@ from django.db import models
from django.db.models.manager import EmptyManager from django.db.models.manager import EmptyManager
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.utils.hashcompat import md5_constructor, sha_constructor
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.crypto import constant_time_compare from django.utils.crypto import constant_time_compare
@ -29,9 +29,9 @@ def get_hexdigest(algorithm, salt, raw_password):
return crypt.crypt(raw_password, salt) return crypt.crypt(raw_password, salt)
if algorithm == 'md5': if algorithm == 'md5':
return md5_constructor(salt + raw_password).hexdigest() return hashlib.md5(salt + raw_password).hexdigest()
elif algorithm == 'sha1': elif algorithm == 'sha1':
return sha_constructor(salt + raw_password).hexdigest() return hashlib.sha1(salt + raw_password).hexdigest()
raise ValueError("Got unknown password algorithm type in password.") raise ValueError("Got unknown password algorithm type in password.")
def check_password(raw_password, enc_password): def check_password(raw_password, enc_password):

View File

@ -58,14 +58,14 @@ class TokenGeneratorTest(TestCase):
# Hard code in the Django 1.2 algorithm (not the result, as it is time # Hard code in the Django 1.2 algorithm (not the result, as it is time
# dependent) # dependent)
def _make_token(user): def _make_token(user):
from django.utils.hashcompat import sha_constructor import hashlib
from django.utils.http import int_to_base36 from django.utils.http import int_to_base36
timestamp = (date.today() - date(2001,1,1)).days timestamp = (date.today() - date(2001,1,1)).days
ts_b36 = int_to_base36(timestamp) ts_b36 = int_to_base36(timestamp)
hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + hash = hashlib.sha1(settings.SECRET_KEY + unicode(user.id) +
user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') +
unicode(timestamp)).hexdigest()[::2] unicode(timestamp)).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash) return "%s-%s" % (ts_b36, hash)
user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw') user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')

View File

@ -1,7 +1,6 @@
from datetime import date from datetime import date
import hashlib
from django.conf import settings from django.conf import settings
from django.utils.hashcompat import sha_constructor
from django.utils.http import int_to_base36, base36_to_int from django.utils.http import int_to_base36, base36_to_int
from django.utils.crypto import constant_time_compare, salted_hmac from django.utils.crypto import constant_time_compare, salted_hmac
@ -67,9 +66,9 @@ class PasswordResetTokenGenerator(object):
def _make_token_with_timestamp_old(self, user, timestamp): def _make_token_with_timestamp_old(self, user, timestamp):
# The Django 1.2 method # The Django 1.2 method
ts_b36 = int_to_base36(timestamp) ts_b36 = int_to_base36(timestamp)
hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + hash = hashlib.sha1(settings.SECRET_KEY + unicode(user.id) +
user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + user.password + user.last_login.strftime('%Y-%m-%d %H:%M:%S') +
unicode(timestamp)).hexdigest()[::2] unicode(timestamp)).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash) return "%s-%s" % (ts_b36, hash)
def _num_days(self, dt): def _num_days(self, dt):

View File

@ -1,6 +1,6 @@
import time
import datetime import datetime
import hashlib
import time
from django import forms from django import forms
from django.forms.util import ErrorDict from django.forms.util import ErrorDict
from django.conf import settings from django.conf import settings
@ -8,7 +8,6 @@ from django.contrib.contenttypes.models import ContentType
from models import Comment from models import Comment
from django.utils.crypto import salted_hmac, constant_time_compare from django.utils.crypto import salted_hmac, constant_time_compare
from django.utils.encoding import force_unicode from django.utils.encoding import force_unicode
from django.utils.hashcompat import sha_constructor
from django.utils.text import get_text_list from django.utils.text import get_text_list
from django.utils.translation import ungettext, ugettext_lazy as _ from django.utils.translation import ungettext, ugettext_lazy as _
@ -100,7 +99,7 @@ class CommentSecurityForm(forms.Form):
"""Generate a (SHA1) security hash from the provided info.""" """Generate a (SHA1) security hash from the provided info."""
# Django 1.2 compatibility # Django 1.2 compatibility
info = (content_type, object_pk, timestamp, settings.SECRET_KEY) info = (content_type, object_pk, timestamp, settings.SECRET_KEY)
return sha_constructor("".join(info)).hexdigest() return hashlib.sha1("".join(info)).hexdigest()
class CommentDetailsForm(CommentSecurityForm): class CommentDetailsForm(CommentSecurityForm):
""" """

View File

@ -2,6 +2,7 @@
Classes allowing "generic" relations through ContentType and object-id fields. Classes allowing "generic" relations through ContentType and object-id fields.
""" """
from functools import partial
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import connection from django.db import connection
from django.db.models import signals from django.db.models import signals
@ -11,11 +12,8 @@ from django.db.models.loading import get_model
from django.forms import ModelForm from django.forms import ModelForm
from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance
from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets
from django.utils.encoding import smart_unicode
from django.utils.functional import curry
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_unicode
class GenericForeignKey(object): class GenericForeignKey(object):
""" """
@ -414,7 +412,7 @@ class GenericInlineModelAdmin(InlineModelAdmin):
"ct_field": self.ct_field, "ct_field": self.ct_field,
"fk_field": self.ct_fk_field, "fk_field": self.ct_fk_field,
"form": self.form, "form": self.form,
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
"formset": self.formset, "formset": self.formset,
"extra": self.extra, "extra": self.extra,
"can_delete": self.can_delete, "can_delete": self.can_delete,

View File

@ -2,13 +2,15 @@
Formtools Preview application. Formtools Preview application.
""" """
import cPickle as pickle try:
import cPickle as pickle
except ImportError:
import pickle
from django.conf import settings from django.conf import settings
from django.http import Http404 from django.http import Http404
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template.context import RequestContext from django.template.context import RequestContext
from django.utils.hashcompat import md5_constructor
from django.utils.crypto import constant_time_compare from django.utils.crypto import constant_time_compare
from django.contrib.formtools.utils import security_hash from django.contrib.formtools.utils import security_hash

View File

@ -3,10 +3,10 @@ try:
except ImportError: except ImportError:
import pickle import pickle
import hashlib
from django.conf import settings from django.conf import settings
from django.forms import BooleanField from django.forms import BooleanField
from django.utils.crypto import salted_hmac from django.utils.crypto import salted_hmac
from django.utils.hashcompat import md5_constructor
def security_hash(request, form, *args): def security_hash(request, form, *args):
@ -39,7 +39,7 @@ def security_hash(request, form, *args):
# Python 2.3, but Django requires 2.4 anyway, so that's OK. # Python 2.3, but Django requires 2.4 anyway, so that's OK.
pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
return md5_constructor(pickled).hexdigest() return hashlib.md5(pickled).hexdigest()
def form_hmac(form): def form_hmac(form):

View File

@ -4,7 +4,10 @@ step and storing the form's state as HTML hidden fields so that no state is
stored on the server side. stored on the server side.
""" """
import cPickle as pickle try:
import cPickle as pickle
except ImportError:
import pickle
from django import forms from django import forms
from django.conf import settings from django.conf import settings
@ -13,7 +16,6 @@ from django.http import Http404
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template.context import RequestContext from django.template.context import RequestContext
from django.utils.crypto import constant_time_compare from django.utils.crypto import constant_time_compare
from django.utils.hashcompat import md5_constructor
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect

View File

@ -820,7 +820,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
def test22_copy(self): def test22_copy(self):
"Testing use with the Python `copy` module." "Testing use with the Python `copy` module."
import django.utils.copycompat as copy import copy
poly = GEOSGeometry('POLYGON((0 0, 0 23, 23 23, 23 0, 0 0), (5 5, 5 10, 10 10, 10 5, 5 5))') poly = GEOSGeometry('POLYGON((0 0, 0 23, 23 23, 23 0, 0 0), (5 5, 5 10, 10 10, 10 5, 5 5))')
cpy1 = copy.copy(poly) cpy1 = copy.copy(poly)
cpy2 = copy.deepcopy(poly) cpy2 = copy.deepcopy(poly)

View File

@ -2,8 +2,7 @@
# Modified from original contribution by Aryeh Leib Taurog, which was # Modified from original contribution by Aryeh Leib Taurog, which was
# released under the New BSD license. # released under the New BSD license.
import django.utils.copycompat as copy import copy
from django.contrib.gis.geos import * from django.contrib.gis.geos import *
from django.contrib.gis.geos.error import GEOSIndexError from django.contrib.gis.geos.error import GEOSIndexError
from django.utils import unittest from django.utils import unittest

View File

@ -1,7 +1,7 @@
import copy
import os import os
from decimal import Decimal from decimal import Decimal
from django.utils.copycompat import copy
from django.utils.unittest import TestCase from django.utils.unittest import TestCase
from django.contrib.gis.gdal import DataSource, OGRException from django.contrib.gis.gdal import DataSource, OGRException

View File

@ -1,4 +1,5 @@
import base64 import base64
import hashlib
import os import os
import random import random
import sys import sys
@ -11,7 +12,6 @@ except ImportError:
from django.conf import settings from django.conf import settings
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.utils.hashcompat import md5_constructor
from django.utils.crypto import constant_time_compare, salted_hmac from django.utils.crypto import constant_time_compare, salted_hmac
# Use the system (hardware-based) random number generator if it exists. # Use the system (hardware-based) random number generator if it exists.
@ -119,7 +119,7 @@ class SessionBase(object):
def _decode_old(self, session_data): def _decode_old(self, session_data):
encoded_data = base64.decodestring(session_data) encoded_data = base64.decodestring(session_data)
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
if not constant_time_compare(md5_constructor(pickled + settings.SECRET_KEY).hexdigest(), if not constant_time_compare(hashlib.md5(pickled + settings.SECRET_KEY).hexdigest(),
tamper_check): tamper_check):
raise SuspiciousOperation("User tampered with session cookie.") raise SuspiciousOperation("User tampered with session cookie.")
return pickle.loads(pickled) return pickle.loads(pickled)
@ -161,7 +161,7 @@ class SessionBase(object):
# No getpid() in Jython, for example # No getpid() in Jython, for example
pid = 1 pid = 1
while 1: while 1:
session_key = md5_constructor("%s%s%s%s" session_key = hashlib.md5("%s%s%s%s"
% (randrange(0, MAX_SESSION_KEY), pid, time.time(), % (randrange(0, MAX_SESSION_KEY), pid, time.time(),
settings.SECRET_KEY)).hexdigest() settings.SECRET_KEY)).hexdigest()
if not self.exists(session_key): if not self.exists(session_key):

View File

@ -1,5 +1,6 @@
import base64 import base64
from datetime import datetime, timedelta from datetime import datetime, timedelta
import hashlib
import pickle import pickle
import shutil import shutil
import tempfile import tempfile
@ -15,7 +16,6 @@ from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.http import HttpResponse from django.http import HttpResponse
from django.test import TestCase, RequestFactory from django.test import TestCase, RequestFactory
from django.utils import unittest from django.utils import unittest
from django.utils.hashcompat import md5_constructor
class SessionTestsMixin(object): class SessionTestsMixin(object):
@ -257,7 +257,7 @@ class SessionTestsMixin(object):
# Hard code the Django 1.2 method here: # Hard code the Django 1.2 method here:
def encode(session_dict): def encode(session_dict):
pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() pickled_md5 = hashlib.md5(pickled + settings.SECRET_KEY).hexdigest()
return base64.encodestring(pickled + pickled_md5) return base64.encodestring(pickled + pickled_md5)
data = {'a test key': 'a test value'} data = {'a test key': 'a test value'}

View File

@ -1,15 +1,15 @@
"File-based cache backend" "File-based cache backend"
import hashlib
import os import os
import time
import shutil import shutil
import time
try: try:
import cPickle as pickle import cPickle as pickle
except ImportError: except ImportError:
import pickle import pickle
from django.core.cache.backends.base import BaseCache from django.core.cache.backends.base import BaseCache
from django.utils.hashcompat import md5_constructor
class FileBasedCache(BaseCache): class FileBasedCache(BaseCache):
def __init__(self, dir, params): def __init__(self, dir, params):
@ -145,7 +145,7 @@ class FileBasedCache(BaseCache):
Thus, a cache key of "foo" gets turnned into a file named Thus, a cache key of "foo" gets turnned into a file named
``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``. ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
""" """
path = md5_constructor(key).hexdigest() path = hashlib.md5(key).hexdigest()
path = os.path.join(path[:2], path[2:4], path[4:]) path = os.path.join(path[:2], path[2:4], path[4:])
return os.path.join(self._dir, path) return os.path.join(self._dir, path)

View File

@ -77,12 +77,10 @@ class LocMemCache(BaseCache):
key = self.make_key(key, version=version) key = self.make_key(key, version=version)
self.validate_key(key) self.validate_key(key)
self._lock.writer_enters() self._lock.writer_enters()
# Python 2.4 doesn't allow combined try-except-finally blocks.
try: try:
try: self._set(key, pickle.dumps(value), timeout)
self._set(key, pickle.dumps(value), timeout) except pickle.PickleError:
except pickle.PickleError: pass
pass
finally: finally:
self._lock.writer_leaves() self._lock.writer_leaves()