Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #7919 -- md5 and sha modules are deprecated since Python 2.5, u…

…se hashlib module when available. Patch from Karen Tracey.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8193 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c85c8f88914cdba05813cc5768377841340bd09d 1 parent 8a58f22
Gary Wilson Jr. authored August 02, 2008
35  django/contrib/admin/sites.py
... ...
@@ -1,3 +1,8 @@
  1
+import base64
  2
+import cPickle as pickle
  3
+import datetime
  4
+import re
  5
+
1 6
 from django import http, template
2 7
 from django.contrib.admin import ModelAdmin
3 8
 from django.contrib.auth import authenticate, login
@@ -9,11 +14,7 @@
9 14
 from django.utils.translation import ugettext_lazy, ugettext as _
10 15
 from django.views.decorators.cache import never_cache
11 16
 from django.conf import settings
12  
-import base64
13  
-import cPickle as pickle
14  
-import datetime
15  
-import md5
16  
-import re
  17
+from django.utils.hashcompat import md5_constructor
17 18
 
18 19
 ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
19 20
 LOGIN_FORM_KEY = 'this_is_the_login_form'
@@ -29,14 +30,14 @@ class NotRegistered(Exception):
29 30
 def _encode_post_data(post_data):
30 31
     from django.conf import settings
31 32
     pickled = pickle.dumps(post_data)
32  
-    pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
  33
+    pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
33 34
     return base64.encodestring(pickled + pickled_md5)
34 35
 
35 36
 def _decode_post_data(encoded_data):
36 37
     from django.conf import settings
37 38
     encoded_data = base64.decodestring(encoded_data)
38 39
     pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
39  
-    if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
  40
+    if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
40 41
         from django.core.exceptions import SuspiciousOperation
41 42
         raise SuspiciousOperation, "User may have tampered with session cookie."
42 43
     return pickle.loads(pickled)
@@ -48,10 +49,10 @@ class AdminSite(object):
48 49
     register() method, and the root() method can then be used as a Django view function
49 50
     that presents a full admin interface for the collection of registered models.
50 51
     """
51  
-    
  52
+
52 53
     index_template = None
53 54
     login_template = None
54  
-    
  55
+
55 56
     def __init__(self):
56 57
         self._registry = {} # model_class class -> admin_class instance
57 58
 
@@ -117,23 +118,23 @@ def has_permission(self, request):
117 118
         return request.user.is_authenticated() and request.user.is_staff
118 119
 
119 120
     def root(self, request, url):
120  
-        """ 
  121
+        """
121 122
         Handles main URL routing for the admin app.
122 123
 
123 124
         `url` is the remainder of the URL -- e.g. 'comments/comment/'.
124 125
         """
125 126
         if request.method == 'GET' and not request.path.endswith('/'):
126 127
             return http.HttpResponseRedirect(request.path + '/')
127  
-        
  128
+
128 129
         # Figure out the admin base URL path and stash it for later use
129 130
         self.root_path = re.sub(re.escape(url) + '$', '', request.path)
130  
-        
  131
+
131 132
         url = url.rstrip('/') # Trim trailing slash, if it exists.
132 133
 
133 134
         # The 'logout' view doesn't require that the person is logged in.
134 135
         if url == 'logout':
135 136
             return self.logout(request)
136  
-        
  137
+
137 138
         # Check permission to continue or display login form.
138 139
         if not self.has_permission(request):
139 140
             return self.login(request)
@@ -154,7 +155,7 @@ def root(self, request, url):
154 155
             match = USER_CHANGE_PASSWORD_URL_RE.match(url)
155 156
             if match:
156 157
                 return self.user_change_password(request, match.group(1))
157  
-                
  158
+
158 159
             if '/' in url:
159 160
                 return self.model_page(request, *url.split('/', 2))
160 161
 
@@ -320,14 +321,14 @@ def index(self, request, extra_context=None):
320 321
         # Sort the models alphabetically within each app.
321 322
         for app in app_list:
322 323
             app['models'].sort(lambda x, y: cmp(x['name'], y['name']))
323  
-        
  324
+
324 325
         context = {
325 326
             'title': _('Site administration'),
326 327
             'app_list': app_list,
327 328
             'root_path': self.root_path,
328 329
         }
329 330
         context.update(extra_context or {})
330  
-        return render_to_response(self.index_template or 'admin/index.html', context, 
  331
+        return render_to_response(self.index_template or 'admin/index.html', context,
331 332
             context_instance=template.RequestContext(request)
332 333
         )
333 334
     index = never_cache(index)
@@ -342,7 +343,7 @@ def display_login_form(self, request, error_message='', extra_context=None):
342 343
             post_data = _encode_post_data(request.POST)
343 344
         else:
344 345
             post_data = _encode_post_data({})
345  
-        
  346
+
346 347
         context = {
347 348
             'title': _('Log in'),
348 349
             'app_path': request.path,
8  django/contrib/admin/views/decorators.py
... ...
@@ -1,5 +1,4 @@
1 1
 import base64
2  
-import md5
3 2
 import cPickle as pickle
4 3
 try:
5 4
     from functools import wraps
@@ -12,6 +11,7 @@
12 11
 from django.contrib.auth import authenticate, login
13 12
 from django.shortcuts import render_to_response
14 13
 from django.utils.translation import ugettext_lazy, ugettext as _
  14
+from django.utils.hashcompat import md5_constructor
15 15
 
16 16
 ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
17 17
 LOGIN_FORM_KEY = 'this_is_the_login_form'
@@ -35,13 +35,13 @@ def _display_login_form(request, error_message=''):
35 35
 
36 36
 def _encode_post_data(post_data):
37 37
     pickled = pickle.dumps(post_data)
38  
-    pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
  38
+    pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
39 39
     return base64.encodestring(pickled + pickled_md5)
40 40
 
41 41
 def _decode_post_data(encoded_data):
42 42
     encoded_data = base64.decodestring(encoded_data)
43 43
     pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
44  
-    if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
  44
+    if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
45 45
         from django.core.exceptions import SuspiciousOperation
46 46
         raise SuspiciousOperation, "User may have tampered with session cookie."
47 47
     return pickle.loads(pickled)
@@ -87,7 +87,7 @@ def _checklogin(request, *args, **kwargs):
87 87
                 if len(users) == 1:
88 88
                     message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username
89 89
                 else:
90  
-                    # Either we cannot find the user, or if more than 1 
  90
+                    # Either we cannot find the user, or if more than 1
91 91
                     # we cannot guess which user is the correct one.
92 92
                     message = _("Usernames cannot contain the '@' character.")
93 93
             return _display_login_form(request, message)
12  django/contrib/auth/tokens.py
@@ -50,17 +50,17 @@ def _make_token_with_timestamp(self, user, timestamp):
50 50
         # last_login will also change), we produce a hash that will be
51 51
         # invalid as soon as it is used.
52 52
         # We limit the hash to 20 chars to keep URL short
53  
-        import sha
54  
-        hash = sha.new(settings.SECRET_KEY + unicode(user.id) + 
55  
-                       user.password + unicode(user.last_login) + 
56  
-                       unicode(timestamp)).hexdigest()[::2]
  53
+        from django.utils.hashcompat import sha_constructor
  54
+        hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) +
  55
+                               user.password + unicode(user.last_login) +
  56
+                               unicode(timestamp)).hexdigest()[::2]
57 57
         return "%s-%s" % (ts_b36, hash)
58 58
 
59 59
     def _num_days(self, dt):
60  
-        return (dt - date(2001,1,1)).days 
  60
+        return (dt - date(2001,1,1)).days
61 61
 
62 62
     def _today(self):
63 63
         # Used for mocking in tests
64  
-        return date.today()        
  64
+        return date.today()
65 65
 
66 66
 default_token_generator = PasswordResetTokenGenerator()
4  django/contrib/comments/models.py
@@ -29,8 +29,8 @@ def get_security_hash(self, options, photo_options, rating_options, target):
29 29
         'pa,ra') and target (something like 'lcom.eventtimes:5157'). Used to
30 30
         validate that submitted form options have not been tampered-with.
31 31
         """
32  
-        import md5
33  
-        return md5.new(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
  32
+        from django.utils.hashcompat import md5_constructor
  33
+        return md5_constructor(options + photo_options + rating_options + target + settings.SECRET_KEY).hexdigest()
34 34
 
35 35
     def get_rating_options(self, rating_string):
36 36
         """
53  django/contrib/csrf/middleware.py
@@ -2,44 +2,45 @@
2 2
 Cross Site Request Forgery Middleware.
3 3
 
4 4
 This module provides a middleware that implements protection
5  
-against request forgeries from other sites. 
6  
-
  5
+against request forgeries from other sites.
7 6
 """
  7
+
  8
+import re
  9
+import itertools
  10
+
8 11
 from django.conf import settings
9 12
 from django.http import HttpResponseForbidden
  13
+from django.utils.hashcompat import md5_constructor
10 14
 from django.utils.safestring import mark_safe
11  
-import md5
12  
-import re
13  
-import itertools
14 15
 
15 16
 _ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
16 17
 
17 18
 _POST_FORM_RE = \
18 19
     re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE)
19  
-    
20  
-_HTML_TYPES = ('text/html', 'application/xhtml+xml')    
  20
+
  21
+_HTML_TYPES = ('text/html', 'application/xhtml+xml')
21 22
 
22 23
 def _make_token(session_id):
23  
-    return md5.new(settings.SECRET_KEY + session_id).hexdigest()
  24
+    return md5_constructor(settings.SECRET_KEY + session_id).hexdigest()
24 25
 
25 26
 class CsrfMiddleware(object):
26 27
     """Django middleware that adds protection against Cross Site
27  
-    Request Forgeries by adding hidden form fields to POST forms and 
28  
-    checking requests for the correct value.  
29  
-    
30  
-    In the list of middlewares, SessionMiddleware is required, and must come 
31  
-    after this middleware.  CsrfMiddleWare must come after compression 
  28
+    Request Forgeries by adding hidden form fields to POST forms and
  29
+    checking requests for the correct value.
  30
+
  31
+    In the list of middlewares, SessionMiddleware is required, and must come
  32
+    after this middleware.  CsrfMiddleWare must come after compression
32 33
     middleware.
33  
-   
34  
-    If a session ID cookie is present, it is hashed with the SECRET_KEY 
35  
-    setting to create an authentication token.  This token is added to all 
36  
-    outgoing POST forms and is expected on all incoming POST requests that 
  34
+
  35
+    If a session ID cookie is present, it is hashed with the SECRET_KEY
  36
+    setting to create an authentication token.  This token is added to all
  37
+    outgoing POST forms and is expected on all incoming POST requests that
37 38
     have a session ID cookie.
38  
-    
39  
-    If you are setting cookies directly, instead of using Django's session 
  39
+
  40
+    If you are setting cookies directly, instead of using Django's session
40 41
     framework, this middleware will not work.
41 42
     """
42  
-    
  43
+
43 44
     def process_request(self, request):
44 45
         if request.method == 'POST':
45 46
             try:
@@ -54,10 +55,10 @@ def process_request(self, request):
54 55
                 request_csrf_token = request.POST['csrfmiddlewaretoken']
55 56
             except KeyError:
56 57
                 return HttpResponseForbidden(_ERROR_MSG)
57  
-            
  58
+
58 59
             if request_csrf_token != csrf_token:
59 60
                 return HttpResponseForbidden(_ERROR_MSG)
60  
-                
  61
+
61 62
         return None
62 63
 
63 64
     def process_response(self, request, response):
@@ -66,7 +67,7 @@ def process_response(self, request, response):
66 67
             cookie = response.cookies[settings.SESSION_COOKIE_NAME]
67 68
             csrf_token = _make_token(cookie.value)
68 69
         except KeyError:
69  
-            # No outgoing cookie to set session, but 
  70
+            # No outgoing cookie to set session, but
70 71
             # a session might already exist.
71 72
             try:
72 73
                 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
@@ -74,12 +75,12 @@ def process_response(self, request, response):
74 75
             except KeyError:
75 76
                 # no incoming or outgoing cookie
76 77
                 pass
77  
-            
  78
+
78 79
         if csrf_token is not None and \
79 80
                 response['Content-Type'].split(';')[0] in _HTML_TYPES:
80  
-            
  81
+
81 82
             # ensure we don't add the 'id' attribute twice (HTML validity)
82  
-            idattributes = itertools.chain(("id='csrfmiddlewaretoken'",), 
  83
+            idattributes = itertools.chain(("id='csrfmiddlewaretoken'",),
83 84
                                             itertools.repeat(''))
84 85
             def add_csrf_field(match):
85 86
                 """Returns the matched <form> tag plus the added <input> element"""
7  django/contrib/formtools/preview.py
@@ -2,12 +2,13 @@
2 2
 Formtools Preview application.
3 3
 """
4 4
 
  5
+import cPickle as pickle
  6
+
5 7
 from django.conf import settings
6 8
 from django.http import Http404
7 9
 from django.shortcuts import render_to_response
8 10
 from django.template.context import RequestContext
9  
-import cPickle as pickle
10  
-import md5
  11
+from django.utils.hashcompat import md5_constructor
11 12
 
12 13
 AUTO_ID = 'formtools_%s' # Each form here uses this as its auto_id parameter.
13 14
 
@@ -109,7 +110,7 @@ def security_hash(self, request, form):
109 110
         # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
110 111
         # Python 2.3, but Django requires 2.3 anyway, so that's OK.
111 112
         pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
112  
-        return md5.new(pickled).hexdigest()
  113
+        return md5_constructor(pickled).hexdigest()
113 114
 
114 115
     def failed_hash(self, request):
115 116
         "Returns an HttpResponse in the case of an invalid security hash."
7  django/contrib/formtools/wizard.py
@@ -4,13 +4,14 @@
4 4
 stored on the server side.
5 5
 """
6 6
 
  7
+import cPickle as pickle
  8
+
7 9
 from django import forms
8 10
 from django.conf import settings
9 11
 from django.http import Http404
10 12
 from django.shortcuts import render_to_response
11 13
 from django.template.context import RequestContext
12  
-import cPickle as pickle
13  
-import md5
  14
+from django.utils.hashcompat import md5_constructor
14 15
 
15 16
 class FormWizard(object):
16 17
     # Dictionary of extra template context variables.
@@ -150,7 +151,7 @@ def security_hash(self, request, form):
150 151
         # Use HIGHEST_PROTOCOL because it's the most efficient. It requires
151 152
         # Python 2.3, but Django requires 2.3 anyway, so that's OK.
152 153
         pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
153  
-        return md5.new(pickled).hexdigest()
  154
+        return md5_constructor(pickled).hexdigest()
154 155
 
155 156
     def determine_step(self, request, *args, **kwargs):
156 157
         """
10  django/contrib/sessions/backends/base.py
... ...
@@ -1,5 +1,4 @@
1 1
 import base64
2  
-import md5
3 2
 import os
4 3
 import random
5 4
 import sys
@@ -12,6 +11,7 @@
12 11
 
13 12
 from django.conf import settings
14 13
 from django.core.exceptions import SuspiciousOperation
  14
+from django.utils.hashcompat import md5_constructor
15 15
 
16 16
 
17 17
 class SessionBase(object):
@@ -73,13 +73,13 @@ def delete_test_cookie(self):
73 73
     def encode(self, session_dict):
74 74
         "Returns the given session dictionary pickled and encoded as a string."
75 75
         pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
76  
-        pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
  76
+        pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
77 77
         return base64.encodestring(pickled + pickled_md5)
78 78
 
79 79
     def decode(self, session_data):
80 80
         encoded_data = base64.decodestring(session_data)
81 81
         pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
82  
-        if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
  82
+        if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
83 83
             raise SuspiciousOperation("User tampered with session cookie.")
84 84
         try:
85 85
             return pickle.loads(pickled)
@@ -117,8 +117,8 @@ def _get_new_session_key(self):
117 117
             # No getpid() in Jython, for example
118 118
             pid = 1
119 119
         while 1:
120  
-            session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
121  
-                                  pid, time.time(), settings.SECRET_KEY)).hexdigest()
  120
+            session_key = md5_constructor("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
  121
+                                          pid, time.time(), settings.SECRET_KEY)).hexdigest()
122 122
             if not self.exists(session_key):
123 123
                 break
124 124
         return session_key
6  django/contrib/sessions/models.py
... ...
@@ -1,10 +1,10 @@
1 1
 import base64
2  
-import md5
3 2
 import cPickle as pickle
4 3
 
5 4
 from django.db import models
6 5
 from django.utils.translation import ugettext_lazy as _
7 6
 from django.conf import settings
  7
+from django.utils.hashcompat import md5_constructor
8 8
 
9 9
 
10 10
 class SessionManager(models.Manager):
@@ -13,7 +13,7 @@ def encode(self, session_dict):
13 13
         Returns the given session dictionary pickled and encoded as a string.
14 14
         """
15 15
         pickled = pickle.dumps(session_dict)
16  
-        pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
  16
+        pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest()
17 17
         return base64.encodestring(pickled + pickled_md5)
18 18
 
19 19
     def save(self, session_key, session_dict, expire_date):
@@ -56,7 +56,7 @@ class Meta:
56 56
     def get_decoded(self):
57 57
         encoded_data = base64.decodestring(self.session_data)
58 58
         pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
59  
-        if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
  59
+        if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
60 60
             from django.core.exceptions import SuspiciousOperation
61 61
             raise SuspiciousOperation, "User tampered with session cookie."
62 62
         try:
29  django/core/cache/backends/filebased.py
... ...
@@ -1,29 +1,31 @@
1 1
 "File-based cache backend"
2 2
 
3  
-import md5
4  
-import os, time
  3
+import os
  4
+import time
5 5
 try:
6 6
     import cPickle as pickle
7 7
 except ImportError:
8 8
     import pickle
  9
+
9 10
 from django.core.cache.backends.base import BaseCache
  11
+from django.utils.hashcompat import md5_constructor
10 12
 
11 13
 class CacheClass(BaseCache):
12 14
     def __init__(self, dir, params):
13 15
         BaseCache.__init__(self, params)
14  
-        
  16
+
15 17
         max_entries = params.get('max_entries', 300)
16 18
         try:
17 19
             self._max_entries = int(max_entries)
18 20
         except (ValueError, TypeError):
19 21
             self._max_entries = 300
20  
-            
  22
+
21 23
         cull_frequency = params.get('cull_frequency', 3)
22 24
         try:
23 25
             self._cull_frequency = int(cull_frequency)
24 26
         except (ValueError, TypeError):
25 27
             self._cull_frequency = 3
26  
-            
  28
+
27 29
         self._dir = dir
28 30
         if not os.path.exists(self._dir):
29 31
             self._createdir()
@@ -31,7 +33,7 @@ def __init__(self, dir, params):
31 33
     def add(self, key, value, timeout=None):
32 34
         if self.has_key(key):
33 35
             return None
34  
-        
  36
+
35 37
         self.set(key, value, timeout)
36 38
 
37 39
     def get(self, key, default=None):
@@ -52,12 +54,12 @@ def get(self, key, default=None):
52 54
     def set(self, key, value, timeout=None):
53 55
         fname = self._key_to_file(key)
54 56
         dirname = os.path.dirname(fname)
55  
-        
  57
+
56 58
         if timeout is None:
57 59
             timeout = self.default_timeout
58  
-            
  60
+
59 61
         self._cull()
60  
-        
  62
+
61 63
         try:
62 64
             if not os.path.exists(dirname):
63 65
                 os.makedirs(dirname)
@@ -103,12 +105,12 @@ def has_key(self, key):
103 105
     def _cull(self):
104 106
         if int(self._num_entries) < self._max_entries:
105 107
             return
106  
-        
  108
+
107 109
         try:
108 110
             filelist = os.listdir(self._dir)
109 111
         except (IOError, OSError):
110 112
             return
111  
-        
  113
+
112 114
         if self._cull_frequency == 0:
113 115
             doomed = filelist
114 116
         else:
@@ -133,11 +135,11 @@ def _key_to_file(self, key):
133 135
         Convert the filename into an md5 string. We'll turn the first couple
134 136
         bits of the path into directory prefixes to be nice to filesystems
135 137
         that have problems with large numbers of files in a directory.
136  
-        
  138
+
137 139
         Thus, a cache key of "foo" gets turnned into a file named
138 140
         ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``.
139 141
         """
140  
-        path = md5.new(key.encode('utf-8')).hexdigest()
  142
+        path = md5_constructor(key.encode('utf-8')).hexdigest()
141 143
         path = os.path.join(path[:2], path[2:4], path[4:])
142 144
         return os.path.join(self._dir, path)
143 145
 
@@ -147,4 +149,3 @@ def _get_num_entries(self):
147 149
             count += len(files)
148 150
         return count
149 151
     _num_entries = property(_get_num_entries)
150  
-
5  django/db/backends/util.py
... ...
@@ -1,7 +1,8 @@
1 1
 import datetime
2  
-import md5
3 2
 from time import time
4 3
 
  4
+from django.utils.hashcompat import md5_constructor
  5
+
5 6
 try:
6 7
     import decimal
7 8
 except ImportError:
@@ -114,7 +115,7 @@ def truncate_name(name, length=None):
114 115
     if length is None or len(name) <= length:
115 116
         return name
116 117
 
117  
-    hash = md5.md5(name).hexdigest()[:4]
  118
+    hash = md5_constructor(name).hexdigest()[:4]
118 119
 
119 120
     return '%s%s' % (name[:length-4], hash)
120 121
 
6  django/middleware/common.py
... ...
@@ -1,4 +1,3 @@
1  
-import md5
2 1
 import re
3 2
 
4 3
 from django.conf import settings
@@ -6,6 +5,7 @@
6 5
 from django.core.mail import mail_managers
7 6
 from django.utils.http import urlquote
8 7
 from django.core import urlresolvers
  8
+from django.utils.hashcompat import md5_constructor
9 9
 
10 10
 class CommonMiddleware(object):
11 11
     """
@@ -21,7 +21,7 @@ class CommonMiddleware(object):
21 21
               slash, and it is not found in urlpatterns, a new URL is formed by
22 22
               appending a slash at the end. If this new URL is found in
23 23
               urlpatterns, then an HTTP-redirect is returned to this new URL;
24  
-              otherwise the initial URL is processed as usual. 
  24
+              otherwise the initial URL is processed as usual.
25 25
 
26 26
         - ETags: If the USE_ETAGS setting is set, ETags will be calculated from
27 27
           the entire page content and Not Modified responses will be returned
@@ -108,7 +108,7 @@ def process_response(self, request, response):
108 108
             if response.has_header('ETag'):
109 109
                 etag = response['ETag']
110 110
             else:
111  
-                etag = '"%s"' % md5.new(response.content).hexdigest()
  111
+                etag = '"%s"' % md5_constructor(response.content).hexdigest()
112 112
             if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
113 113
                 cookies = response.cookies
114 114
                 response = http.HttpResponseNotModified()
6  django/utils/cache.py
@@ -17,7 +17,6 @@
17 17
 "Accept-language" header.
18 18
 """
19 19
 
20  
-import md5
21 20
 import re
22 21
 import time
23 22
 try:
@@ -29,6 +28,7 @@
29 28
 from django.core.cache import cache
30 29
 from django.utils.encoding import smart_str, iri_to_uri
31 30
 from django.utils.http import http_date
  31
+from django.utils.hashcompat import md5_constructor
32 32
 
33 33
 cc_delim_re = re.compile(r'\s*,\s*')
34 34
 
@@ -104,7 +104,7 @@ def patch_response_headers(response, cache_timeout=None):
104 104
     if cache_timeout < 0:
105 105
         cache_timeout = 0 # Can't have max-age negative
106 106
     if not response.has_header('ETag'):
107  
-        response['ETag'] = '"%s"' % md5.new(response.content).hexdigest()
  107
+        response['ETag'] = '"%s"' % md5_constructor(response.content).hexdigest()
108 108
     if not response.has_header('Last-Modified'):
109 109
         response['Last-Modified'] = http_date()
110 110
     if not response.has_header('Expires'):
@@ -138,7 +138,7 @@ def patch_vary_headers(response, newheaders):
138 138
 
139 139
 def _generate_cache_key(request, headerlist, key_prefix):
140 140
     """Returns a cache key from the headers given in the header list."""
141  
-    ctx = md5.new()
  141
+    ctx = md5_constructor()
142 142
     for header in headerlist:
143 143
         value = request.META.get(header, None)
144 144
         if value is not None:
16  django/utils/hashcompat.py
... ...
@@ -0,0 +1,16 @@
  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, preferring the hashlib module when
  5
+available.
  6
+"""
  7
+
  8
+try:
  9
+    import hashlib
  10
+    md5_constructor = hashlib.md5
  11
+    sha_constructor = hashlib.sha1
  12
+except ImportError:
  13
+    import md5
  14
+    md5_constructor = md5.new
  15
+    import sha
  16
+    sha_constructor = sha.new
33  tests/regressiontests/cache/tests.py
@@ -3,11 +3,17 @@
3 3
 # Unit tests for cache framework
4 4
 # Uses whatever cache backend is set in the test settings file.
5 5
 
  6
+import os
  7
+import shutil
  8
+import tempfile
6 9
 import time
7 10
 import unittest
  11
+
8 12
 from django.core.cache import cache
9  
-from django.utils.cache import patch_vary_headers
  13
+from django.core.cache.backends.filebased import CacheClass as FileCache
10 14
 from django.http import HttpResponse
  15
+from django.utils.cache import patch_vary_headers
  16
+from django.utils.hashcompat import md5_constructor
11 17
 
12 18
 # functions/classes for complex data type tests
13 19
 def f():
@@ -27,7 +33,7 @@ def test_add(self):
27 33
         cache.add("addkey1", "value")
28 34
         cache.add("addkey1", "newvalue")
29 35
         self.assertEqual(cache.get("addkey1"), "value")
30  
-        
  36
+
31 37
     def test_non_existent(self):
32 38
         # get with non-existent keys
33 39
         self.assertEqual(cache.get("does_not_exist"), None)
@@ -80,9 +86,9 @@ def test_expiration(self):
80 86
         cache.set('expire2', 'very quickly', 1)
81 87
         cache.set('expire3', 'very quickly', 1)
82 88
 
83  
-        time.sleep(2)        
  89
+        time.sleep(2)
84 90
         self.assertEqual(cache.get("expire1"), None)
85  
-        
  91
+
86 92
         cache.add("expire2", "newvalue")
87 93
         self.assertEqual(cache.get("expire2"), "newvalue")
88 94
         self.assertEqual(cache.has_key("expire3"), False)
@@ -98,11 +104,6 @@ def test_unicode(self):
98 104
             cache.set(key, value)
99 105
             self.assertEqual(cache.get(key), value)
100 106
 
101  
-import os
102  
-import md5
103  
-import shutil
104  
-import tempfile
105  
-from django.core.cache.backends.filebased import CacheClass as FileCache
106 107
 
107 108
 class FileBasedCacheTests(unittest.TestCase):
108 109
     """
@@ -112,23 +113,23 @@ def setUp(self):
112 113
         self.dirname = tempfile.mktemp()
113 114
         os.mkdir(self.dirname)
114 115
         self.cache = FileCache(self.dirname, {})
115  
-        
  116
+
116 117
     def tearDown(self):
117 118
         shutil.rmtree(self.dirname)
118  
-        
  119
+
119 120
     def test_hashing(self):
120 121
         """Test that keys are hashed into subdirectories correctly"""
121 122
         self.cache.set("foo", "bar")
122  
-        keyhash = md5.new("foo").hexdigest()
  123
+        keyhash = md5_constructor("foo").hexdigest()
123 124
         keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
124 125
         self.assert_(os.path.exists(keypath))
125  
-        
  126
+
126 127
     def test_subdirectory_removal(self):
127 128
         """
128 129
         Make sure that the created subdirectories are correctly removed when empty.
129 130
         """
130 131
         self.cache.set("foo", "bar")
131  
-        keyhash = md5.new("foo").hexdigest()
  132
+        keyhash = md5_constructor("foo").hexdigest()
132 133
         keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
133 134
         self.assert_(os.path.exists(keypath))
134 135
 
@@ -139,9 +140,9 @@ def test_subdirectory_removal(self):
139 140
 
140 141
 class CacheUtils(unittest.TestCase):
141 142
     """TestCase for django.utils.cache functions."""
142  
-    
  143
+
143 144
     def test_patch_vary_headers(self):
144  
-        headers = ( 
  145
+        headers = (
145 146
             # Initial vary, new headers, resulting vary.
146 147
             (None, ('Accept-Encoding',), 'Accept-Encoding'),
147 148
             ('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'),
6  tests/regressiontests/file_uploads/tests.py
... ...
@@ -1,6 +1,5 @@
1 1
 import os
2 2
 import errno
3  
-import sha
4 3
 import shutil
5 4
 import unittest
6 5
 
@@ -8,6 +7,7 @@
8 7
 from django.core.files.uploadedfile import SimpleUploadedFile
9 8
 from django.test import TestCase, client
10 9
 from django.utils import simplejson
  10
+from django.utils.hashcompat import sha_constructor
11 11
 
12 12
 from models import FileModel, UPLOAD_ROOT, UPLOAD_TO
13 13
 
@@ -45,10 +45,10 @@ def test_large_upload(self):
45 45
 
46 46
         for key in post_data.keys():
47 47
             try:
48  
-                post_data[key + '_hash'] = sha.new(post_data[key].read()).hexdigest()
  48
+                post_data[key + '_hash'] = sha_constructor(post_data[key].read()).hexdigest()
49 49
                 post_data[key].seek(0)
50 50
             except AttributeError:
51  
-                post_data[key + '_hash'] = sha.new(post_data[key]).hexdigest()
  51
+                post_data[key + '_hash'] = sha_constructor(post_data[key]).hexdigest()
52 52
 
53 53
         response = self.client.post('/file_uploads/verify/', post_data)
54 54
 
10  tests/regressiontests/test_client_regress/models.py
... ...
@@ -1,12 +1,10 @@
1 1
 """
2 2
 Regression tests for the Test Client, especially the customized assertions.
3  
-
4 3
 """
  4
+
5 5
 from django.test import Client, TestCase
6 6
 from django.core.urlresolvers import reverse
7 7
 from django.core.exceptions import SuspiciousOperation
8  
-import os
9  
-import sha
10 8
 
11 9
 class AssertContainsTests(TestCase):
12 10
     def test_contains(self):
@@ -24,7 +22,7 @@ def test_contains(self):
24 22
             self.assertNotContains(response, 'once')
25 23
         except AssertionError, e:
26 24
             self.assertEquals(str(e), "Response should not contain 'once'")
27  
-            
  25
+
28 26
         try:
29 27
             self.assertContains(response, 'never', 1)
30 28
         except AssertionError, e:
@@ -287,7 +285,7 @@ def test_argument_with_space_post(self):
287 285
 
288 286
 class ExceptionTests(TestCase):
289 287
     fixtures = ['testdata.json']
290  
-    
  288
+
291 289
     def test_exception_cleared(self):
292 290
         "#5836 - A stale user exception isn't re-raised by the test client."
293 291
 
@@ -300,7 +298,7 @@ def test_exception_cleared(self):
300 298
             pass
301 299
 
302 300
         # At this point, an exception has been raised, and should be cleared.
303  
-        
  301
+
304 302
         # This next operation should be successful; if it isn't we have a problem.
305 303
         login = self.client.login(username='staff', password='password')
306 304
         self.failUnless(login, 'Could not log in')

0 notes on commit c85c8f8

Please sign in to comment.
Something went wrong with that request. Please try again.