diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 6cb0c21795..5bb53886c6 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -1,3 +1,8 @@ +import base64 +import cPickle as pickle +import datetime +import re + from django import http, template from django.contrib.admin import ModelAdmin from django.contrib.auth import authenticate, login @@ -9,11 +14,7 @@ from django.utils.text import capfirst from django.utils.translation import ugettext_lazy, ugettext as _ from django.views.decorators.cache import never_cache from django.conf import settings -import base64 -import cPickle as pickle -import datetime -import md5 -import re +from django.utils.hashcompat import md5_constructor ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") LOGIN_FORM_KEY = 'this_is_the_login_form' @@ -29,14 +30,14 @@ class NotRegistered(Exception): def _encode_post_data(post_data): from django.conf import settings pickled = pickle.dumps(post_data) - pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() + pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() return base64.encodestring(pickled + pickled_md5) def _decode_post_data(encoded_data): from django.conf import settings encoded_data = base64.decodestring(encoded_data) pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] - if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: + if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: from django.core.exceptions import SuspiciousOperation raise SuspiciousOperation, "User may have tampered with session cookie." return pickle.loads(pickled) @@ -48,10 +49,10 @@ class AdminSite(object): register() method, and the root() method can then be used as a Django view function that presents a full admin interface for the collection of registered models. """ - + index_template = None login_template = None - + def __init__(self): self._registry = {} # model_class class -> admin_class instance @@ -117,23 +118,23 @@ class AdminSite(object): return request.user.is_authenticated() and request.user.is_staff def root(self, request, url): - """ + """ Handles main URL routing for the admin app. `url` is the remainder of the URL -- e.g. 'comments/comment/'. """ if request.method == 'GET' and not request.path.endswith('/'): return http.HttpResponseRedirect(request.path + '/') - + # Figure out the admin base URL path and stash it for later use self.root_path = re.sub(re.escape(url) + '$', '', request.path) - + url = url.rstrip('/') # Trim trailing slash, if it exists. # The 'logout' view doesn't require that the person is logged in. if url == 'logout': return self.logout(request) - + # Check permission to continue or display login form. if not self.has_permission(request): return self.login(request) @@ -154,7 +155,7 @@ class AdminSite(object): match = USER_CHANGE_PASSWORD_URL_RE.match(url) if match: return self.user_change_password(request, match.group(1)) - + if '/' in url: return self.model_page(request, *url.split('/', 2)) @@ -320,14 +321,14 @@ class AdminSite(object): # Sort the models alphabetically within each app. for app in app_list: app['models'].sort(lambda x, y: cmp(x['name'], y['name'])) - + context = { 'title': _('Site administration'), 'app_list': app_list, 'root_path': self.root_path, } context.update(extra_context or {}) - return render_to_response(self.index_template or 'admin/index.html', context, + return render_to_response(self.index_template or 'admin/index.html', context, context_instance=template.RequestContext(request) ) index = never_cache(index) @@ -342,7 +343,7 @@ class AdminSite(object): post_data = _encode_post_data(request.POST) else: post_data = _encode_post_data({}) - + context = { 'title': _('Log in'), 'app_path': request.path, diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py index 57517cc821..cf0cd704c2 100644 --- a/django/contrib/admin/views/decorators.py +++ b/django/contrib/admin/views/decorators.py @@ -1,5 +1,4 @@ import base64 -import md5 import cPickle as pickle try: from functools import wraps @@ -12,6 +11,7 @@ from django.contrib.auth.models import User from django.contrib.auth import authenticate, login from django.shortcuts import render_to_response from django.utils.translation import ugettext_lazy, ugettext as _ +from django.utils.hashcompat import md5_constructor ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") LOGIN_FORM_KEY = 'this_is_the_login_form' @@ -35,13 +35,13 @@ def _display_login_form(request, error_message=''): def _encode_post_data(post_data): pickled = pickle.dumps(post_data) - pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() + pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() return base64.encodestring(pickled + pickled_md5) def _decode_post_data(encoded_data): encoded_data = base64.decodestring(encoded_data) pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] - if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: + if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: from django.core.exceptions import SuspiciousOperation raise SuspiciousOperation, "User may have tampered with session cookie." return pickle.loads(pickled) @@ -87,7 +87,7 @@ def staff_member_required(view_func): if len(users) == 1: message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username else: - # Either we cannot find the user, or if more than 1 + # Either we cannot find the user, or if more than 1 # we cannot guess which user is the correct one. message = _("Usernames cannot contain the '@' character.") return _display_login_form(request, message) diff --git a/django/contrib/auth/tokens.py b/django/contrib/auth/tokens.py index acfbc3bb9c..c9b353583c 100644 --- a/django/contrib/auth/tokens.py +++ b/django/contrib/auth/tokens.py @@ -50,17 +50,17 @@ class PasswordResetTokenGenerator(object): # last_login will also change), we produce a hash that will be # invalid as soon as it is used. # We limit the hash to 20 chars to keep URL short - import sha - hash = sha.new(settings.SECRET_KEY + unicode(user.id) + - user.password + unicode(user.last_login) + - unicode(timestamp)).hexdigest()[::2] + from django.utils.hashcompat import sha_constructor + hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + + user.password + unicode(user.last_login) + + unicode(timestamp)).hexdigest()[::2] return "%s-%s" % (ts_b36, hash) def _num_days(self, dt): - return (dt - date(2001,1,1)).days + return (dt - date(2001,1,1)).days def _today(self): # Used for mocking in tests - return date.today() + return date.today() default_token_generator = PasswordResetTokenGenerator() diff --git a/django/contrib/comments/models.py b/django/contrib/comments/models.py index a13fec9e6e..fdf34c8997 100644 --- a/django/contrib/comments/models.py +++ b/django/contrib/comments/models.py @@ -29,8 +29,8 @@ class CommentManager(models.Manager): 'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to validate that submitted form options have not been tampered-with. """ - import md5 - return md5.new(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest() + from django.utils.hashcompat import md5_constructor + return md5_constructor(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest() def get_rating_options(self, rating_string): """ diff --git a/django/contrib/csrf/middleware.py b/django/contrib/csrf/middleware.py index 1a75a5d6ab..24c1511c91 100644 --- a/django/contrib/csrf/middleware.py +++ b/django/contrib/csrf/middleware.py @@ -2,44 +2,45 @@ Cross Site Request Forgery Middleware. This module provides a middleware that implements protection -against request forgeries from other sites. - +against request forgeries from other sites. """ -from django.conf import settings -from django.http import HttpResponseForbidden -from django.utils.safestring import mark_safe -import md5 + import re import itertools +from django.conf import settings +from django.http import HttpResponseForbidden +from django.utils.hashcompat import md5_constructor +from django.utils.safestring import mark_safe + _ERROR_MSG = mark_safe('

403 Forbidden

Cross Site Request Forgery detected. Request aborted.

') _POST_FORM_RE = \ re.compile(r'(]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE) - -_HTML_TYPES = ('text/html', 'application/xhtml+xml') + +_HTML_TYPES = ('text/html', 'application/xhtml+xml') def _make_token(session_id): - return md5.new(settings.SECRET_KEY + session_id).hexdigest() + return md5_constructor(settings.SECRET_KEY + session_id).hexdigest() class CsrfMiddleware(object): """Django middleware that adds protection against Cross Site - Request Forgeries by adding hidden form fields to POST forms and - checking requests for the correct value. - - In the list of middlewares, SessionMiddleware is required, and must come - after this middleware. CsrfMiddleWare must come after compression + Request Forgeries by adding hidden form fields to POST forms and + checking requests for the correct value. + + In the list of middlewares, SessionMiddleware is required, and must come + after this middleware. CsrfMiddleWare must come after compression middleware. - - If a session ID cookie is present, it is hashed with the SECRET_KEY - setting to create an authentication token. This token is added to all - outgoing POST forms and is expected on all incoming POST requests that + + If a session ID cookie is present, it is hashed with the SECRET_KEY + setting to create an authentication token. This token is added to all + outgoing POST forms and is expected on all incoming POST requests that have a session ID cookie. - - If you are setting cookies directly, instead of using Django's session + + If you are setting cookies directly, instead of using Django's session framework, this middleware will not work. """ - + def process_request(self, request): if request.method == 'POST': try: @@ -54,10 +55,10 @@ class CsrfMiddleware(object): request_csrf_token = request.POST['csrfmiddlewaretoken'] except KeyError: return HttpResponseForbidden(_ERROR_MSG) - + if request_csrf_token != csrf_token: return HttpResponseForbidden(_ERROR_MSG) - + return None def process_response(self, request, response): @@ -66,7 +67,7 @@ class CsrfMiddleware(object): cookie = response.cookies[settings.SESSION_COOKIE_NAME] csrf_token = _make_token(cookie.value) except KeyError: - # No outgoing cookie to set session, but + # No outgoing cookie to set session, but # a session might already exist. try: session_id = request.COOKIES[settings.SESSION_COOKIE_NAME] @@ -74,12 +75,12 @@ class CsrfMiddleware(object): except KeyError: # no incoming or outgoing cookie pass - + if csrf_token is not None and \ response['Content-Type'].split(';')[0] in _HTML_TYPES: - + # ensure we don't add the 'id' attribute twice (HTML validity) - idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), + idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), itertools.repeat('')) def add_csrf_field(match): """Returns the matched
tag plus the added element""" diff --git a/django/contrib/formtools/preview.py b/django/contrib/formtools/preview.py index db5d58e971..c56fdff628 100644 --- a/django/contrib/formtools/preview.py +++ b/django/contrib/formtools/preview.py @@ -2,12 +2,13 @@ Formtools Preview application. """ +import cPickle as pickle + from django.conf import settings from django.http import Http404 from django.shortcuts import render_to_response from django.template.context import RequestContext -import cPickle as pickle -import md5 +from django.utils.hashcompat import md5_constructor AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter. @@ -109,7 +110,7 @@ class FormPreview(object): # Use HIGHEST_PROTOCOL because it's the most efficient. It requires # Python 2.3, but Django requires 2.3 anyway, so that's OK. pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) - return md5.new(pickled).hexdigest() + return md5_constructor(pickled).hexdigest() def failed_hash(self, request): "Returns an HttpResponse in the case of an invalid security hash." diff --git a/django/contrib/formtools/wizard.py b/django/contrib/formtools/wizard.py index 7b96d91187..984b6e487e 100644 --- a/django/contrib/formtools/wizard.py +++ b/django/contrib/formtools/wizard.py @@ -4,13 +4,14 @@ step and storing the form's state as HTML hidden fields so that no state is stored on the server side. """ +import cPickle as pickle + from django import forms from django.conf import settings from django.http import Http404 from django.shortcuts import render_to_response from django.template.context import RequestContext -import cPickle as pickle -import md5 +from django.utils.hashcompat import md5_constructor class FormWizard(object): # Dictionary of extra template context variables. @@ -150,7 +151,7 @@ class FormWizard(object): # Use HIGHEST_PROTOCOL because it's the most efficient. It requires # Python 2.3, but Django requires 2.3 anyway, so that's OK. pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) - return md5.new(pickled).hexdigest() + return md5_constructor(pickled).hexdigest() def determine_step(self, request, *args, **kwargs): """ diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py index b40fba6e6e..7153b8a267 100644 --- a/django/contrib/sessions/backends/base.py +++ b/django/contrib/sessions/backends/base.py @@ -1,5 +1,4 @@ import base64 -import md5 import os import random import sys @@ -12,6 +11,7 @@ except ImportError: from django.conf import settings from django.core.exceptions import SuspiciousOperation +from django.utils.hashcompat import md5_constructor class SessionBase(object): @@ -73,13 +73,13 @@ class SessionBase(object): def encode(self, session_dict): "Returns the given session dictionary pickled and encoded as a string." pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL) - pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() + pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() return base64.encodestring(pickled + pickled_md5) def decode(self, session_data): encoded_data = base64.decodestring(session_data) pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] - if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: + if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: raise SuspiciousOperation("User tampered with session cookie.") try: return pickle.loads(pickled) @@ -117,8 +117,8 @@ class SessionBase(object): # No getpid() in Jython, for example pid = 1 while 1: - session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), - pid, time.time(), settings.SECRET_KEY)).hexdigest() + session_key = md5_constructor("%s%s%s%s" % (random.randint(0, sys.maxint - 1), + pid, time.time(), settings.SECRET_KEY)).hexdigest() if not self.exists(session_key): break return session_key diff --git a/django/contrib/sessions/models.py b/django/contrib/sessions/models.py index 70fce3b226..cf2865fcc8 100644 --- a/django/contrib/sessions/models.py +++ b/django/contrib/sessions/models.py @@ -1,10 +1,10 @@ import base64 -import md5 import cPickle as pickle from django.db import models from django.utils.translation import ugettext_lazy as _ from django.conf import settings +from django.utils.hashcompat import md5_constructor class SessionManager(models.Manager): @@ -13,7 +13,7 @@ class SessionManager(models.Manager): Returns the given session dictionary pickled and encoded as a string. """ pickled = pickle.dumps(session_dict) - pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() + pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() return base64.encodestring(pickled + pickled_md5) def save(self, session_key, session_dict, expire_date): @@ -56,7 +56,7 @@ class Session(models.Model): def get_decoded(self): encoded_data = base64.decodestring(self.session_data) pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] - if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: + if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: from django.core.exceptions import SuspiciousOperation raise SuspiciousOperation, "User tampered with session cookie." try: diff --git a/django/core/cache/backends/filebased.py b/django/core/cache/backends/filebased.py index c1277bf20c..0ad586d477 100644 --- a/django/core/cache/backends/filebased.py +++ b/django/core/cache/backends/filebased.py @@ -1,29 +1,31 @@ "File-based cache backend" -import md5 -import os, time +import os +import time try: import cPickle as pickle except ImportError: import pickle + from django.core.cache.backends.base import BaseCache +from django.utils.hashcompat import md5_constructor class CacheClass(BaseCache): def __init__(self, dir, params): BaseCache.__init__(self, params) - + max_entries = params.get('max_entries', 300) try: self._max_entries = int(max_entries) except (ValueError, TypeError): self._max_entries = 300 - + cull_frequency = params.get('cull_frequency', 3) try: self._cull_frequency = int(cull_frequency) except (ValueError, TypeError): self._cull_frequency = 3 - + self._dir = dir if not os.path.exists(self._dir): self._createdir() @@ -31,7 +33,7 @@ class CacheClass(BaseCache): def add(self, key, value, timeout=None): if self.has_key(key): return None - + self.set(key, value, timeout) def get(self, key, default=None): @@ -52,12 +54,12 @@ class CacheClass(BaseCache): def set(self, key, value, timeout=None): fname = self._key_to_file(key) dirname = os.path.dirname(fname) - + if timeout is None: timeout = self.default_timeout - + self._cull() - + try: if not os.path.exists(dirname): os.makedirs(dirname) @@ -103,12 +105,12 @@ class CacheClass(BaseCache): def _cull(self): if int(self._num_entries) < self._max_entries: return - + try: filelist = os.listdir(self._dir) except (IOError, OSError): return - + if self._cull_frequency == 0: doomed = filelist else: @@ -133,11 +135,11 @@ class CacheClass(BaseCache): Convert the filename into an md5 string. We'll turn the first couple bits of the path into directory prefixes to be nice to filesystems that have problems with large numbers of files in a directory. - + Thus, a cache key of "foo" gets turnned into a file named ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``. """ - path = md5.new(key.encode('utf-8')).hexdigest() + path = md5_constructor(key.encode('utf-8')).hexdigest() path = os.path.join(path[:2], path[2:4], path[4:]) return os.path.join(self._dir, path) @@ -147,4 +149,3 @@ class CacheClass(BaseCache): count += len(files) return count _num_entries = property(_get_num_entries) - diff --git a/django/db/backends/util.py b/django/db/backends/util.py index 25b41e3fb6..7228b4046b 100644 --- a/django/db/backends/util.py +++ b/django/db/backends/util.py @@ -1,7 +1,8 @@ import datetime -import md5 from time import time +from django.utils.hashcompat import md5_constructor + try: import decimal except ImportError: @@ -114,7 +115,7 @@ def truncate_name(name, length=None): if length is None or len(name) <= length: return name - hash = md5.md5(name).hexdigest()[:4] + hash = md5_constructor(name).hexdigest()[:4] return '%s%s' % (name[:length-4], hash) diff --git a/django/middleware/common.py b/django/middleware/common.py index 5cb7ca1bd3..a564017ed6 100644 --- a/django/middleware/common.py +++ b/django/middleware/common.py @@ -1,4 +1,3 @@ -import md5 import re from django.conf import settings @@ -6,6 +5,7 @@ from django import http from django.core.mail import mail_managers from django.utils.http import urlquote from django.core import urlresolvers +from django.utils.hashcompat import md5_constructor class CommonMiddleware(object): """ @@ -21,7 +21,7 @@ class CommonMiddleware(object): slash, and it is not found in urlpatterns, a new URL is formed by appending a slash at the end. If this new URL is found in urlpatterns, then an HTTP-redirect is returned to this new URL; - otherwise the initial URL is processed as usual. + otherwise the initial URL is processed as usual. - ETags: If the USE_ETAGS setting is set, ETags will be calculated from the entire page content and Not Modified responses will be returned @@ -108,7 +108,7 @@ class CommonMiddleware(object): if response.has_header('ETag'): etag = response['ETag'] else: - etag = '"%s"' % md5.new(response.content).hexdigest() + etag = '"%s"' % md5_constructor(response.content).hexdigest() if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag: cookies = response.cookies response = http.HttpResponseNotModified() diff --git a/django/utils/cache.py b/django/utils/cache.py index 603199cc7e..78063c6b11 100644 --- a/django/utils/cache.py +++ b/django/utils/cache.py @@ -17,7 +17,6 @@ An example: i18n middleware would need to distinguish caches by the "Accept-language" header. """ -import md5 import re import time try: @@ -29,6 +28,7 @@ from django.conf import settings from django.core.cache import cache from django.utils.encoding import smart_str, iri_to_uri from django.utils.http import http_date +from django.utils.hashcompat import md5_constructor cc_delim_re = re.compile(r'\s*,\s*') @@ -104,7 +104,7 @@ def patch_response_headers(response, cache_timeout=None): if cache_timeout < 0: cache_timeout = 0 # Can't have max-age negative if not response.has_header('ETag'): - response['ETag'] = '"%s"' % md5.new(response.content).hexdigest() + response['ETag'] = '"%s"' % md5_constructor(response.content).hexdigest() if not response.has_header('Last-Modified'): response['Last-Modified'] = http_date() if not response.has_header('Expires'): @@ -138,7 +138,7 @@ def patch_vary_headers(response, newheaders): def _generate_cache_key(request, headerlist, key_prefix): """Returns a cache key from the headers given in the header list.""" - ctx = md5.new() + ctx = md5_constructor() for header in headerlist: value = request.META.get(header, None) if value is not None: diff --git a/django/utils/hashcompat.py b/django/utils/hashcompat.py new file mode 100644 index 0000000000..8880d92646 --- /dev/null +++ b/django/utils/hashcompat.py @@ -0,0 +1,16 @@ +""" +The md5 and sha modules are deprecated since Python 2.5, replaced by the +hashlib module containing both hash algorithms. Here, we provide a common +interface to the md5 and sha constructors, preferring the hashlib module when +available. +""" + +try: + import hashlib + md5_constructor = hashlib.md5 + sha_constructor = hashlib.sha1 +except ImportError: + import md5 + md5_constructor = md5.new + import sha + sha_constructor = sha.new diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py index f050348c77..78c32288b6 100644 --- a/tests/regressiontests/cache/tests.py +++ b/tests/regressiontests/cache/tests.py @@ -3,11 +3,17 @@ # Unit tests for cache framework # Uses whatever cache backend is set in the test settings file. +import os +import shutil +import tempfile import time import unittest + from django.core.cache import cache -from django.utils.cache import patch_vary_headers +from django.core.cache.backends.filebased import CacheClass as FileCache from django.http import HttpResponse +from django.utils.cache import patch_vary_headers +from django.utils.hashcompat import md5_constructor # functions/classes for complex data type tests def f(): @@ -27,7 +33,7 @@ class Cache(unittest.TestCase): cache.add("addkey1", "value") cache.add("addkey1", "newvalue") self.assertEqual(cache.get("addkey1"), "value") - + def test_non_existent(self): # get with non-existent keys self.assertEqual(cache.get("does_not_exist"), None) @@ -80,9 +86,9 @@ class Cache(unittest.TestCase): cache.set('expire2', 'very quickly', 1) cache.set('expire3', 'very quickly', 1) - time.sleep(2) + time.sleep(2) self.assertEqual(cache.get("expire1"), None) - + cache.add("expire2", "newvalue") self.assertEqual(cache.get("expire2"), "newvalue") self.assertEqual(cache.has_key("expire3"), False) @@ -98,11 +104,6 @@ class Cache(unittest.TestCase): cache.set(key, value) self.assertEqual(cache.get(key), value) -import os -import md5 -import shutil -import tempfile -from django.core.cache.backends.filebased import CacheClass as FileCache class FileBasedCacheTests(unittest.TestCase): """ @@ -112,23 +113,23 @@ class FileBasedCacheTests(unittest.TestCase): self.dirname = tempfile.mktemp() os.mkdir(self.dirname) self.cache = FileCache(self.dirname, {}) - + def tearDown(self): shutil.rmtree(self.dirname) - + def test_hashing(self): """Test that keys are hashed into subdirectories correctly""" self.cache.set("foo", "bar") - keyhash = md5.new("foo").hexdigest() + keyhash = md5_constructor("foo").hexdigest() keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:]) self.assert_(os.path.exists(keypath)) - + def test_subdirectory_removal(self): """ Make sure that the created subdirectories are correctly removed when empty. """ self.cache.set("foo", "bar") - keyhash = md5.new("foo").hexdigest() + keyhash = md5_constructor("foo").hexdigest() keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:]) self.assert_(os.path.exists(keypath)) @@ -139,9 +140,9 @@ class FileBasedCacheTests(unittest.TestCase): class CacheUtils(unittest.TestCase): """TestCase for django.utils.cache functions.""" - + def test_patch_vary_headers(self): - headers = ( + headers = ( # Initial vary, new headers, resulting vary. (None, ('Accept-Encoding',), 'Accept-Encoding'), ('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'), diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py index aada1e1ff2..dd6b7c4181 100644 --- a/tests/regressiontests/file_uploads/tests.py +++ b/tests/regressiontests/file_uploads/tests.py @@ -1,6 +1,5 @@ import os import errno -import sha import shutil import unittest @@ -8,6 +7,7 @@ from django.core.files import temp as tempfile from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase, client from django.utils import simplejson +from django.utils.hashcompat import sha_constructor from models import FileModel, UPLOAD_ROOT, UPLOAD_TO @@ -45,10 +45,10 @@ class FileUploadTests(TestCase): for key in post_data.keys(): try: - post_data[key + '_hash'] = sha.new(post_data[key].read()).hexdigest() + post_data[key + '_hash'] = sha_constructor(post_data[key].read()).hexdigest() post_data[key].seek(0) except AttributeError: - post_data[key + '_hash'] = sha.new(post_data[key]).hexdigest() + post_data[key + '_hash'] = sha_constructor(post_data[key]).hexdigest() response = self.client.post('/file_uploads/verify/', post_data) diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py index 47e34641fb..3518df3b9f 100644 --- a/tests/regressiontests/test_client_regress/models.py +++ b/tests/regressiontests/test_client_regress/models.py @@ -1,12 +1,10 @@ """ Regression tests for the Test Client, especially the customized assertions. - """ + from django.test import Client, TestCase from django.core.urlresolvers import reverse from django.core.exceptions import SuspiciousOperation -import os -import sha class AssertContainsTests(TestCase): def test_contains(self): @@ -24,7 +22,7 @@ class AssertContainsTests(TestCase): self.assertNotContains(response, 'once') except AssertionError, e: self.assertEquals(str(e), "Response should not contain 'once'") - + try: self.assertContains(response, 'never', 1) except AssertionError, e: @@ -287,7 +285,7 @@ class URLEscapingTests(TestCase): class ExceptionTests(TestCase): fixtures = ['testdata.json'] - + def test_exception_cleared(self): "#5836 - A stale user exception isn't re-raised by the test client." @@ -300,7 +298,7 @@ class ExceptionTests(TestCase): pass # At this point, an exception has been raised, and should be cleared. - + # This next operation should be successful; if it isn't we have a problem. login = self.client.login(username='staff', password='password') self.failUnless(login, 'Could not log in')