Fixed #7919 -- md5 and sha modules are deprecated since Python 2.5, use hashlib module when available. Patch from Karen Tracey.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8193 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Gary Wilson Jr 2008-08-02 05:56:57 +00:00
parent 8a58f2216c
commit c85c8f8891
17 changed files with 138 additions and 117 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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()

View File

@ -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):
"""

View File

@ -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('<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>')
_POST_FORM_RE = \
re.compile(r'(<form\W[^>]*\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 <form> tag plus the added <input> element"""

View File

@ -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."

View File

@ -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):
"""

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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:

View File

@ -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

View File

@ -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'),

View File

@ -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)

View File

@ -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')