diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py
index fa71f3816f..705497520a 100644
--- a/django/core/mail/backends/console.py
+++ b/django/core/mail/backends/console.py
@@ -18,20 +18,17 @@ class EmailBackend(BaseEmailBackend):
             return
         self._lock.acquire()
         try:
-            # The try-except is nested to allow for
-            # Python 2.4 support (Refs #12147)
-            try:
-                stream_created = self.open()
-                for message in email_messages:
-                    self.stream.write('%s\n' % message.message().as_string())
-                    self.stream.write('-'*79)
-                    self.stream.write('\n')
-                    self.stream.flush()  # flush after each message
-                if stream_created:
-                    self.close()
-            except:
-                if not self.fail_silently:
-                    raise
+            stream_created = self.open()
+            for message in email_messages:
+                self.stream.write('%s\n' % message.message().as_string())
+                self.stream.write('-'*79)
+                self.stream.write('\n')
+                self.stream.flush()  # flush after each message
+            if stream_created:
+                self.close()
+        except:
+            if not self.fail_silently:
+                raise
         finally:
             self._lock.release()
         return len(email_messages)
diff --git a/django/core/mail/message.py b/django/core/mail/message.py
index 01bb1d62d1..bed4966ef9 100644
--- a/django/core/mail/message.py
+++ b/django/core/mail/message.py
@@ -3,10 +3,7 @@ import os
 import random
 import time
 from email import Charset, Encoders
-try:
-    from email.generator import Generator
-except ImportError:
-    from email.Generator import Generator # TODO: Remove when remove Python 2.4 support
+from email.generator import Generator
 from email.MIMEText import MIMEText
 from email.MIMEMultipart import MIMEMultipart
 from email.MIMEBase import MIMEBase
diff --git a/django/core/management/validation.py b/django/core/management/validation.py
index 2eb6340de9..bb4fa552ff 100644
--- a/django/core/management/validation.py
+++ b/django/core/management/validation.py
@@ -4,11 +4,6 @@ from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelati
 from django.core.management.color import color_style
 from django.utils.itercompat import is_iterable
 
-try:
-    any
-except NameError:
-    from django.utils.itercompat import any
-
 class ModelErrorCollection:
     def __init__(self, outfile=sys.stdout):
         self.errors = []
diff --git a/django/db/__init__.py b/django/db/__init__.py
index 3f9645a452..7446a7fa60 100644
--- a/django/db/__init__.py
+++ b/django/db/__init__.py
@@ -3,7 +3,6 @@ from django.core import signals
 from django.core.exceptions import ImproperlyConfigured
 from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS, \
                             DatabaseError, IntegrityError
-from django.utils.functional import curry
 
 __all__ = ('backend', 'connection', 'connections', 'router', 'DatabaseError',
     'IntegrityError', 'DEFAULT_DB_ALIAS')
diff --git a/django/db/backends/util.py b/django/db/backends/util.py
index 2f92a30c9e..0766f87787 100644
--- a/django/db/backends/util.py
+++ b/django/db/backends/util.py
@@ -1,8 +1,8 @@
 import datetime
 import decimal
+import hashlib
 from time import time
 
-from django.utils.hashcompat import md5_constructor
 from django.utils.log import getLogger
 
 
@@ -130,9 +130,8 @@ def truncate_name(name, length=None, hash_len=4):
     if length is None or len(name) <= length:
         return name
 
-    hash = md5_constructor(name).hexdigest()[:hash_len]
-
-    return '%s%s' % (name[:length-hash_len], hash)
+    hsh = hashlib.md5(name).hexdigest()[:hash_len]
+    return '%s%s' % (name[:length-hash_len], hsh)
 
 def format_number(value, max_digits, decimal_places):
     """
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 286f9b0de6..4aa6cfa741 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -1,5 +1,7 @@
-import types
+import copy
 import sys
+import types
+from functools import update_wrapper
 from itertools import izip
 
 import django.db.models.manager     # Imported to register signal handler.
@@ -17,8 +19,7 @@ from django.db import (connections, router, transaction, DatabaseError,
 from django.db.models import signals
 from django.db.models.loading import register_models, get_model
 from django.utils.translation import ugettext_lazy as _
-import django.utils.copycompat as copy
-from django.utils.functional import curry, update_wrapper
+from django.utils.functional import curry
 from django.utils.encoding import smart_str, force_unicode
 from django.utils.text import get_text_list, capfirst
 from django.conf import settings
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 73960f5e3c..a52fa24a01 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -1,17 +1,16 @@
+from functools import wraps
 from operator import attrgetter
 
 from django.db import connections, transaction, IntegrityError
 from django.db.models import signals, sql
 from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE
 from django.utils.datastructures import SortedDict
-from django.utils.functional import wraps
 
 
 class ProtectedError(IntegrityError):
     def __init__(self, msg, protected_objects):
         self.protected_objects = protected_objects
-        # TODO change this to use super() when we drop Python 2.4
-        IntegrityError.__init__(self, msg, protected_objects)
+        super(ProtectedError, self).__init__(msg, protected_objects)
 
 
 def CASCADE(collector, field, sub_objs, using):
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 8b9c934bbb..a71f4a33ef 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -1,7 +1,5 @@
 import datetime
-
 from django.utils import tree
-from django.utils.copycompat import deepcopy
 
 class ExpressionNode(tree.Node):
     """
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 8081cf3954..ccb57da69e 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -1,3 +1,4 @@
+import copy
 import datetime
 import decimal
 import re
@@ -5,8 +6,6 @@ import time
 import math
 from itertools import tee
 
-import django.utils.copycompat as copy
-
 from django.db import connection
 from django.db.models.fields.subclassing import LegacyConnection
 from django.db.models.query_utils import QueryWrapper
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index aaf1fbb0ec..50dc236902 100644
--- a/django/db/models/fields/files.py
+++ b/django/db/models/fields/files.py
@@ -1,8 +1,6 @@
 import datetime
 import os
 
-import django.utils.copycompat as copy
-
 from django.conf import settings
 from django.db.models.fields import Field
 from django.core.files.base import File, ContentFile
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
index 6a62c254ef..9528d66812 100644
--- a/django/db/models/manager.py
+++ b/django/db/models/manager.py
@@ -1,4 +1,4 @@
-from django.utils import copycompat as copy
+import copy
 from django.conf import settings
 from django.db import router
 from django.db.models.query import QuerySet, EmptyQuerySet, insert_query, RawQuerySet
diff --git a/django/db/models/options.py b/django/db/models/options.py
index 10617dc9e9..6d8ab6f6d6 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -11,11 +11,6 @@ from django.utils.translation import activate, deactivate_all, get_language, str
 from django.utils.encoding import force_unicode, smart_str
 from django.utils.datastructures import SortedDict
 
-try:
-    all
-except NameError:
-    from django.utils.itercompat import all
-
 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
 
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 0fc48f8a41..58f9313e3d 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -2,6 +2,7 @@
 The main QuerySet implementation. This provides the public API for the ORM.
 """
 
+import copy
 from itertools import izip
 
 from django.db import connections, router, transaction, IntegrityError
@@ -11,7 +12,6 @@ from django.db.models.query_utils import (Q, select_related_descend,
     deferred_class_factory, InvalidQuery)
 from django.db.models.deletion import Collector
 from django.db.models import signals, sql
-from django.utils.copycompat import deepcopy
 
 # Used to control how many objects are worked with at once in some cases (e.g.
 # when deleting objects).
@@ -51,7 +51,7 @@ class QuerySet(object):
             if k in ('_iter','_result_cache'):
                 obj.__dict__[k] = None
             else:
-                obj.__dict__[k] = deepcopy(v, memo)
+                obj.__dict__[k] = copy.deepcopy(v, memo)
         return obj
 
     def __getstate__(self):
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 80485e0482..69b19f1806 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -7,7 +7,6 @@ circular import difficulties.
 """
 
 import weakref
-from django.utils.copycompat import deepcopy
 
 from django.db.backends import util
 from django.utils import tree
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index ea89771ed1..449c83b495 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -7,7 +7,7 @@ databases). The abstraction barrier only works one way: this module has to know
 all about the internals of models in order to get the information it needs.
 """
 
-from django.utils.copycompat import deepcopy
+import copy
 from django.utils.tree import Node
 from django.utils.datastructures import SortedDict
 from django.utils.encoding import force_unicode
@@ -244,19 +244,19 @@ class Query(object):
         obj.dupe_avoidance = self.dupe_avoidance.copy()
         obj.select = self.select[:]
         obj.tables = self.tables[:]
-        obj.where = deepcopy(self.where, memo=memo)
+        obj.where = copy.deepcopy(self.where, memo=memo)
         obj.where_class = self.where_class
         if self.group_by is None:
             obj.group_by = None
         else:
             obj.group_by = self.group_by[:]
-        obj.having = deepcopy(self.having, memo=memo)
+        obj.having = copy.deepcopy(self.having, memo=memo)
         obj.order_by = self.order_by[:]
         obj.low_mark, obj.high_mark = self.low_mark, self.high_mark
         obj.distinct = self.distinct
         obj.select_related = self.select_related
         obj.related_select_cols = []
-        obj.aggregates = deepcopy(self.aggregates, memo=memo)
+        obj.aggregates = copy.deepcopy(self.aggregates, memo=memo)
         if self.aggregate_select_mask is None:
             obj.aggregate_select_mask = None
         else:
@@ -279,7 +279,7 @@ class Query(object):
             obj._extra_select_cache = self._extra_select_cache.copy()
         obj.extra_tables = self.extra_tables
         obj.extra_order_by = self.extra_order_by
-        obj.deferred_loading = deepcopy(self.deferred_loading, memo=memo)
+        obj.deferred_loading = copy.deepcopy(self.deferred_loading, memo=memo)
         if self.filter_is_sticky and self.used_aliases:
             obj.used_aliases = self.used_aliases.copy()
         else:
@@ -476,7 +476,7 @@ class Query(object):
         # Now relabel a copy of the rhs where-clause and add it to the current
         # one.
         if rhs.where:
-            w = deepcopy(rhs.where)
+            w = copy.deepcopy(rhs.where)
             w.relabel_aliases(change_map)
             if not self.where:
                 # Since 'self' matches everything, add an explicit "include
@@ -497,7 +497,7 @@ class Query(object):
             if isinstance(col, (list, tuple)):
                 self.select.append((change_map.get(col[0], col[0]), col[1]))
             else:
-                item = deepcopy(col)
+                item = copy.deepcopy(col)
                 item.relabel_aliases(change_map)
                 self.select.append(item)
         self.select_fields = rhs.select_fields[:]
diff --git a/django/db/transaction.py b/django/db/transaction.py
index b5584dd8b9..cf7350c02f 100644
--- a/django/db/transaction.py
+++ b/django/db/transaction.py
@@ -11,12 +11,9 @@ called, a commit is made.
 Managed transactions don't do those commits, but will need some kind of manual
 or implicit commits or rollbacks.
 """
-import sys
 
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
+import sys
+from functools import wraps
 
 from django.conf import settings
 from django.db import connections, DEFAULT_DB_ALIAS
@@ -209,18 +206,8 @@ class Transaction(object):
     def __call__(self, func):
         @wraps(func)
         def inner(*args, **kwargs):
-            # Once we drop support for Python 2.4 this block should become:
-            # with self:
-            #     func(*args, **kwargs)
-            self.__enter__()
-            try:
-                res = func(*args, **kwargs)
-            except:
-                self.__exit__(*sys.exc_info())
-                raise
-            else:
-                self.__exit__(None, None, None)
-                return res
+            with self:
+                func(*args, **kwargs)
         return inner
 
 def _transaction_func(entering, exiting, using):
diff --git a/django/dispatch/saferef.py b/django/dispatch/saferef.py
index 8bcfd8a140..f446447b46 100644
--- a/django/dispatch/saferef.py
+++ b/django/dispatch/saferef.py
@@ -230,7 +230,7 @@ class BoundNonDescriptorMethodWeakref(BoundMethodWeakref):
         if target is not None:
             function = self.weakFunc()
             if function is not None:
-                # Using curry() would be another option, but it erases the
+                # Using partial() would be another option, but it erases the
                 # "signature" of the function. That is, after a function is
                 # curried, the inspect module can't be used to determine how
                 # many arguments the function expects, nor what keyword
diff --git a/django/forms/extras/widgets.py b/django/forms/extras/widgets.py
index e8bacf2b1e..d75e903f56 100644
--- a/django/forms/extras/widgets.py
+++ b/django/forms/extras/widgets.py
@@ -68,11 +68,7 @@ class SelectDateWidget(Widget):
                 if settings.USE_L10N:
                     try:
                         input_format = get_format('DATE_INPUT_FORMATS')[0]
-                        # Python 2.4 compatibility:
-                        #     v = datetime.datetime.strptime(value, input_format)
-                        # would be clearer, but datetime.strptime was added in
-                        # Python 2.5
-                        v = datetime.datetime(*(time.strptime(value, input_format)[0:6]))
+                        v = datetime.datetime.strptime(value, input_format)
                         year_val, month_val, day_val = v.year, v.month, v.day
                     except ValueError:
                         pass
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 4d7728f58c..eebe0c44ff 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -2,6 +2,7 @@
 Field classes.
 """
 
+import copy
 import datetime
 import os
 import re
@@ -16,7 +17,6 @@ except ImportError:
 
 from django.core.exceptions import ValidationError
 from django.core import validators
-import django.utils.copycompat as copy
 from django.utils import formats
 from django.utils.translation import ugettext_lazy as _
 from django.utils.encoding import smart_unicode, smart_str
diff --git a/django/forms/forms.py b/django/forms/forms.py
index f776861948..ad398c4cb7 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -2,8 +2,8 @@
 Form classes
 """
 
+import copy
 from django.core.exceptions import ValidationError
-from django.utils.copycompat import deepcopy
 from django.utils.datastructures import SortedDict
 from django.utils.html import conditional_escape
 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
@@ -89,7 +89,7 @@ class BaseForm(StrAndUnicode):
         # alter self.fields, we create self.fields here by copying base_fields.
         # Instances should always modify self.fields; they should not modify
         # self.base_fields.
-        self.fields = deepcopy(self.base_fields)
+        self.fields = copy.deepcopy(self.base_fields)
 
     def __unicode__(self):
         return self.as_table()
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index dd5868f479..03152eaa24 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -1,13 +1,14 @@
 """
 HTML Widget classes
 """
+
+import copy
 import datetime
-from itertools import chain
 import time
+from itertools import chain
 from urlparse import urljoin
 from util import flatatt
 
-import django.utils.copycompat as copy
 from django.conf import settings
 from django.utils.datastructures import MultiValueDict, MergeDict
 from django.utils.html import escape, conditional_escape
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 714d552938..62e327d926 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -364,7 +364,7 @@ class QueryDict(MultiValueDict):
         return result
 
     def __deepcopy__(self, memo):
-        import django.utils.copycompat as copy
+        import copy
         result = self.__class__('', mutable=True, encoding=self.encoding)
         memo[id(self)] = result
         for key, value in dict.items(self):
diff --git a/django/middleware/common.py b/django/middleware/common.py
index 2252c8f9f0..eb145edf19 100644
--- a/django/middleware/common.py
+++ b/django/middleware/common.py
@@ -1,3 +1,4 @@
+import hashlib
 import re
 
 from django.conf import settings
@@ -5,7 +6,6 @@ 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
 from django.utils.log import getLogger
 
 logger = getLogger('django.request')
@@ -113,7 +113,7 @@ class CommonMiddleware(object):
             if response.has_header('ETag'):
                 etag = response['ETag']
             else:
-                etag = '"%s"' % md5_constructor(response.content).hexdigest()
+                etag = '"%s"' % hashlib.md5(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/middleware/csrf.py b/django/middleware/csrf.py
index b5a85795b2..3247358ed5 100644
--- a/django/middleware/csrf.py
+++ b/django/middleware/csrf.py
@@ -5,6 +5,7 @@ This module provides a middleware that implements protection
 against request forgeries from other sites.
 """
 
+import hashlib
 import itertools
 import re
 import random
@@ -12,7 +13,6 @@ import random
 from django.conf import settings
 from django.core.urlresolvers import get_callable
 from django.utils.cache import patch_vary_headers
-from django.utils.hashcompat import md5_constructor
 from django.utils.http import same_origin
 from django.utils.log import getLogger
 from django.utils.safestring import mark_safe
@@ -47,12 +47,11 @@ def _get_failure_view():
 
 
 def _get_new_csrf_key():
-    return md5_constructor("%s%s"
-                % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest()
+    return hashlib.md5("%s%s" % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest()
 
 
 def _make_legacy_session_token(session_id):
-    return md5_constructor(settings.SECRET_KEY + session_id).hexdigest()
+    return hashlib.md5(settings.SECRET_KEY + session_id).hexdigest()
 
 
 def get_token(request):
diff --git a/django/template/base.py b/django/template/base.py
index 49ef0b85eb..b8d6c139de 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -1,12 +1,13 @@
 import imp
 import re
+from functools import partial
 from inspect import getargspec
 
 from django.conf import settings
 from django.template.context import Context, RequestContext, ContextPopException
 from django.utils.importlib import import_module
 from django.utils.itercompat import is_iterable
-from django.utils.functional import curry, Promise
+from django.utils.functional import Promise
 from django.utils.text import smart_split, unescape_string_literal, get_text_list
 from django.utils.encoding import smart_unicode, force_unicode, smart_str
 from django.utils.translation import ugettext_lazy
@@ -884,7 +885,7 @@ class Library(object):
                         func_args = resolved_vars
                     return func(*func_args)
 
-            compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
+            compile_func = partial(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
             compile_func.__doc__ = func.__doc__
             self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
             return func
@@ -936,7 +937,7 @@ class Library(object):
                         new_context['csrf_token'] = csrf_token
                     return self.nodelist.render(new_context)
 
-            compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
+            compile_func = partial(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
             compile_func.__doc__ = func.__doc__
             self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
             return func
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index d923d8a0e5..60fa59e04d 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -1,12 +1,9 @@
 """Default variable filters."""
 
 import re
-from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
 import random as random_module
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
+from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
+from functools import wraps
 
 from django.template.base import Variable, Library
 from django.conf import settings
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index 715542adf7..5b351ad0aa 100644
--- a/django/template/loaders/cached.py
+++ b/django/template/loaders/cached.py
@@ -3,10 +3,10 @@ Wrapper class that takes a list of template loaders as an argument and attempts
 to load templates from them in order, caching the result.
 """
 
+import hashlib
 from django.core.exceptions import ImproperlyConfigured
 from django.template.base import TemplateDoesNotExist
 from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
-from django.utils.hashcompat import sha_constructor
 from django.utils.importlib import import_module
 
 class Loader(BaseLoader):
@@ -38,7 +38,7 @@ class Loader(BaseLoader):
         key = template_name
         if template_dirs:
             # If template directories were specified, use a hash to differentiate
-            key = '-'.join([template_name, sha_constructor('|'.join(template_dirs)).hexdigest()])
+            key = '-'.join([template_name, hashlib.sha1('|'.join(template_dirs)).hexdigest()])
 
         if key not in self.template_cache:
             template, origin = self.find_template(template_name, template_dirs)
diff --git a/django/templatetags/cache.py b/django/templatetags/cache.py
index 4fe3c3bb8d..0440d10cb8 100644
--- a/django/templatetags/cache.py
+++ b/django/templatetags/cache.py
@@ -1,9 +1,9 @@
+import hashlib
 from django.template import Library, Node, TemplateSyntaxError, Variable, VariableDoesNotExist
 from django.template import resolve_variable
 from django.core.cache import cache
 from django.utils.encoding import force_unicode
 from django.utils.http import urlquote
-from django.utils.hashcompat import md5_constructor
 
 register = Library()
 
@@ -24,7 +24,7 @@ class CacheNode(Node):
         except (ValueError, TypeError):
             raise TemplateSyntaxError('"cache" tag got a non-integer timeout value: %r' % expire_time)
         # Build a unicode key for this fragment and all vary-on's.
-        args = md5_constructor(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on]))
+        args = hashlib.md5(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on]))
         cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest())
         value = cache.get(cache_key)
         if value is None:
diff --git a/django/test/client.py b/django/test/client.py
index dd0d811b02..15147c51fa 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -1,11 +1,11 @@
 import urllib
-from urlparse import urlparse, urlunparse, urlsplit
 import sys
 import os
 import re
 import mimetypes
 import warnings
 from copy import copy
+from urlparse import urlparse, urlunparse, urlsplit
 try:
     from cStringIO import StringIO
 except ImportError:
diff --git a/django/test/simple.py b/django/test/simple.py
index d0b9a70257..41b2a421ed 100644
--- a/django/test/simple.py
+++ b/django/test/simple.py
@@ -7,12 +7,6 @@ from django.test.utils import setup_test_environment, teardown_test_environment
 from django.test.testcases import OutputChecker, DocTestRunner, TestCase
 from django.utils import unittest
 
-try:
-    all
-except NameError:
-    from django.utils.itercompat import all
-
-
 __all__ = ('DjangoTestRunner', 'DjangoTestSuiteRunner', 'run_tests')
 
 # The module name for tests outside models.py
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 02cd00c27f..81e028c3dc 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -1,5 +1,6 @@
 import re
 import sys
+from functools import wraps
 from urlparse import urlsplit, urlunsplit
 from xml.dom.minidom import parseString, Node
 
@@ -16,21 +17,13 @@ from django.test.client import Client
 from django.test.utils import get_warnings_state, restore_warnings_state
 from django.utils import simplejson, unittest as ut2
 from django.utils.encoding import smart_str
-from django.utils.functional import wraps
 
 __all__ = ('DocTestRunner', 'OutputChecker', 'TestCase', 'TransactionTestCase',
            'skipIfDBFeature', 'skipUnlessDBFeature')
 
-
-try:
-    all
-except NameError:
-    from django.utils.itercompat import all
-
 normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
 normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)", lambda m: "Decimal(\"%s\")" % m.groups()[0], s)
 
-
 def to_list(value):
     """
     Puts value into a list if it's not already one.
@@ -550,11 +543,9 @@ class TransactionTestCase(ut2.TestCase):
 
 def connections_support_transactions():
     """
-    Returns True if all connections support transactions.  This is messy
-    because 2.4 doesn't support any or all.
+    Returns True if all connections support transactions.
     """
-    return all(conn.features.supports_transactions
-        for conn in connections.all())
+    return all(conn.features.supports_transactions for conn in connections.all())
 
 class TestCase(TransactionTestCase):
     """
diff --git a/django/utils/cache.py b/django/utils/cache.py
index 63c4af3494..bd23940180 100644
--- a/django/utils/cache.py
+++ b/django/utils/cache.py
@@ -17,6 +17,7 @@ An example: i18n middleware would need to distinguish caches by the
 "Accept-language" header.
 """
 
+import hashlib
 import re
 import time
 
@@ -24,7 +25,6 @@ from django.conf import settings
 from django.core.cache import get_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
 from django.utils.translation import get_language
 from django.http import HttpRequest
 
@@ -102,7 +102,7 @@ def patch_response_headers(response, cache_timeout=None):
     if cache_timeout < 0:
         cache_timeout = 0 # Can't have max-age negative
     if settings.USE_ETAGS and not response.has_header('ETag'):
-        response['ETag'] = '"%s"' % md5_constructor(response.content).hexdigest()
+        response['ETag'] = '"%s"' % hashlib.md5(response.content).hexdigest()
     if not response.has_header('Last-Modified'):
         response['Last-Modified'] = http_date()
     if not response.has_header('Expires'):
@@ -155,19 +155,19 @@ def _i18n_cache_key_suffix(request, cache_key):
 
 def _generate_cache_key(request, method, headerlist, key_prefix):
     """Returns a cache key from the headers given in the header list."""
-    ctx = md5_constructor()
+    ctx = hashlib.md5()
     for header in headerlist:
         value = request.META.get(header, None)
         if value is not None:
             ctx.update(value)
-    path = md5_constructor(iri_to_uri(request.get_full_path()))
+    path = hashlib.md5(iri_to_uri(request.get_full_path()))
     cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % (
         key_prefix, request.method, path.hexdigest(), ctx.hexdigest())
     return _i18n_cache_key_suffix(request, cache_key)
 
 def _generate_cache_header_key(key_prefix, request):
     """Returns a cache key for the header cache."""
-    path = md5_constructor(iri_to_uri(request.get_full_path()))
+    path = hashlib.md5(iri_to_uri(request.get_full_path()))
     cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
         key_prefix, path.hexdigest())
     return _i18n_cache_key_suffix(request, cache_key)
diff --git a/django/utils/copycompat.py b/django/utils/copycompat.py
deleted file mode 100644
index 22b3cfbef7..0000000000
--- a/django/utils/copycompat.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""
-Fixes Python 2.4's failure to deepcopy unbound functions.
-"""
-
-import copy
-import types
-
-# Monkeypatch copy's deepcopy registry to handle functions correctly.
-if (hasattr(copy, '_deepcopy_dispatch') and types.FunctionType not in copy._deepcopy_dispatch):
-    copy._deepcopy_dispatch[types.FunctionType] = copy._deepcopy_atomic
-
-# Pose as the copy module now.
-del copy, types
-from copy import *
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
index 87cd0b9fb0..95af6808fa 100644
--- a/django/utils/crypto.py
+++ b/django/utils/crypto.py
@@ -1,11 +1,10 @@
 """
 Django's standard crypto functions and utilities.
 """
+
+import hashlib
 import hmac
-
 from django.conf import settings
-from django.utils.hashcompat import sha_constructor, sha_hmac
-
 
 def salted_hmac(key_salt, value, secret=None):
     """
@@ -20,16 +19,13 @@ def salted_hmac(key_salt, value, secret=None):
     # We need to generate a derived key from our base key.  We can do this by
     # passing the key_salt and our base key through a pseudo-random function and
     # SHA1 works nicely.
-
-    key = sha_constructor(key_salt + secret).digest()
+    key = hashlib.sha1(key_salt + secret).digest()
 
     # If len(key_salt + secret) > sha_constructor().block_size, the above
     # line is redundant and could be replaced by key = key_salt + secret, since
     # the hmac module does the same thing for keys longer than the block size.
     # However, we need to ensure that we *always* do this.
-
-    return hmac.new(key, msg=value, digestmod=sha_hmac)
-
+    return hmac.new(key, msg=value, digestmod=hashlib.sha1)
 
 def constant_time_compare(val1, val2):
     """
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 7425ea2ce2..ff281b032a 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -1,8 +1,6 @@
+import copy
 from types import GeneratorType
 
-from django.utils.copycompat import copy, deepcopy
-
-
 class MergeDict(object):
     """
     A simple class for creating new "virtual" dictionaries that actually look
@@ -127,7 +125,7 @@ class SortedDict(dict):
                     seen.add(key)
 
     def __deepcopy__(self, memo):
-        return self.__class__([(key, deepcopy(value, memo))
+        return self.__class__([(key, copy.deepcopy(value, memo))
                                for key, value in self.iteritems()])
 
     def __setitem__(self, key, value):
@@ -269,7 +267,6 @@ class MultiValueDict(dict):
         ])
 
     def __deepcopy__(self, memo=None):
-        import django.utils.copycompat as copy
         if memo is None:
             memo = {}
         result = self.__class__()
@@ -365,7 +362,7 @@ class MultiValueDict(dict):
 
     def copy(self):
         """Returns a shallow copy of this object."""
-        return copy(self)
+        return copy.copy(self)
 
     def update(self, *args, **kwargs):
         """
diff --git a/django/utils/decorators.py b/django/utils/decorators.py
index 17f2ea30b3..6099f88266 100644
--- a/django/utils/decorators.py
+++ b/django/utils/decorators.py
@@ -1,9 +1,6 @@
 "Functions that help with dynamically creating decorators for views."
 
-try:
-    from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS
-except ImportError:
-    from django.utils.functional import wraps, update_wrapper, WRAPPER_ASSIGNMENTS  # Python 2.4 fallback.
+from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS
 
 class classonlymethod(classmethod):
     def __get__(self, instance, owner):
diff --git a/django/utils/functional.py b/django/utils/functional.py
index ccfbcb0250..5dc0a45e7a 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -49,66 +49,13 @@
 # agrees to be bound by the terms and conditions of this License
 # Agreement.
 
+from functools import wraps
 
 def curry(_curried_func, *args, **kwargs):
     def _curried(*moreargs, **morekwargs):
         return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
     return _curried
 
-### Begin from Python 2.5 functools.py ########################################
-
-# Summary of changes made to the Python 2.5 code below:
-#   * swapped ``partial`` for ``curry`` to maintain backwards-compatibility
-#     in Django.
-
-# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation.
-# All Rights Reserved.
-
-###############################################################################
-
-# update_wrapper() and wraps() are tools to help write
-# wrapper functions that can handle naive introspection
-
-WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
-WRAPPER_UPDATES = ('__dict__',)
-def update_wrapper(wrapper,
-                   wrapped,
-                   assigned = WRAPPER_ASSIGNMENTS,
-                   updated = WRAPPER_UPDATES):
-    """Update a wrapper function to look like the wrapped function
-
-       wrapper is the function to be updated
-       wrapped is the original function
-       assigned is a tuple naming the attributes assigned directly
-       from the wrapped function to the wrapper function (defaults to
-       functools.WRAPPER_ASSIGNMENTS)
-       updated is a tuple naming the attributes off the wrapper that
-       are updated with the corresponding attribute from the wrapped
-       function (defaults to functools.WRAPPER_UPDATES)
-    """
-    for attr in assigned:
-        setattr(wrapper, attr, getattr(wrapped, attr))
-    for attr in updated:
-        getattr(wrapper, attr).update(getattr(wrapped, attr))
-    # Return the wrapper so this can be used as a decorator via curry()
-    return wrapper
-
-def wraps(wrapped,
-          assigned = WRAPPER_ASSIGNMENTS,
-          updated = WRAPPER_UPDATES):
-    """Decorator factory to apply update_wrapper() to a wrapper function
-
-       Returns a decorator that invokes update_wrapper() with the decorated
-       function as the wrapper argument and the arguments to wraps() as the
-       remaining arguments. Default arguments are as for update_wrapper().
-       This is a convenience function to simplify applying curry() to
-       update_wrapper().
-    """
-    return curry(update_wrapper, wrapped=wrapped,
-                 assigned=assigned, updated=updated)
-
-### End from Python 2.5 functools.py ##########################################
-
 def memoize(func, cache, num_args):
     """
     Wrap a function so that results for any argument tuple are stored in
@@ -343,10 +290,8 @@ class SimpleLazyObject(LazyObject):
             memo[id(self)] = result
             return result
         else:
-            # Changed to use deepcopy from copycompat, instead of copy
-            # For Python 2.4.
-            from django.utils.copycompat import deepcopy
-            return deepcopy(self._wrapped, memo)
+            import copy
+            return copy.deepcopy(self._wrapped, memo)
 
     # Need to pretend to be the wrapped class, for the sake of objects that care
     # about this (especially in equality tests)
diff --git a/django/utils/hashcompat.py b/django/utils/hashcompat.py
deleted file mode 100644
index 4d9b76f3a6..0000000000
--- a/django/utils/hashcompat.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-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, depending on system version.
-"""
-
-import sys
-if sys.version_info >= (2, 5):
-    import hashlib
-    md5_constructor = hashlib.md5
-    md5_hmac = md5_constructor
-    sha_constructor = hashlib.sha1
-    sha_hmac = sha_constructor
-else:
-    import md5
-    md5_constructor = md5.new
-    md5_hmac = md5
-    import sha
-    sha_constructor = sha.new
-    sha_hmac = sha
diff --git a/django/utils/itercompat.py b/django/utils/itercompat.py
index d4ff2503c7..b302e22b2a 100644
--- a/django/utils/itercompat.py
+++ b/django/utils/itercompat.py
@@ -31,15 +31,3 @@ def is_iterable(x):
         return False
     else:
         return True
-
-def all(iterable):
-    for item in iterable:
-        if not item:
-            return False
-    return True
-
-def any(iterable):
-    for item in iterable:
-        if item:
-            return True
-    return False
diff --git a/django/utils/log.py b/django/utils/log.py
index 4fb75b1504..e4aec73ee8 100644
--- a/django/utils/log.py
+++ b/django/utils/log.py
@@ -18,27 +18,7 @@ try:
 except ImportError:
     from django.utils.dictconfig import dictConfig
 
-if sys.version_info < (2, 5):
-    class LoggerCompat(object):
-        def __init__(self, logger):
-            self._logger = logger
-
-        def __getattr__(self, name):
-            val = getattr(self._logger, name)
-            if callable(val):
-                def _wrapper(*args, **kwargs):
-                    # Python 2.4 logging module doesn't support 'extra' parameter to
-                    # methods of Logger
-                    kwargs.pop('extra', None)
-                    return val(*args, **kwargs)
-                return _wrapper
-            else:
-                return val
-
-    def getLogger(name=None):
-        return LoggerCompat(logging.getLogger(name=name))
-else:
-    getLogger = logging.getLogger
+getLogger = logging.getLogger
 
 # Ensure the creation of the Django logger
 # with a null handler. This ensures we don't get any
@@ -49,7 +29,7 @@ if not logger.handlers:
 
 class AdminEmailHandler(logging.Handler):
     def __init__(self, include_html=False):
-        logging.Handler.__init__(self)        
+        logging.Handler.__init__(self)
         self.include_html = include_html
 
     """An exception log handler that e-mails log entries to site admins.
@@ -63,15 +43,7 @@ class AdminEmailHandler(logging.Handler):
         from django.views.debug import ExceptionReporter
 
         try:
-            if sys.version_info < (2,5):
-                # A nasty workaround required because Python 2.4's logging
-                # module doesn't support passing in extra context.
-                # For this handler, the only extra data we need is the
-                # request, and that's in the top stack frame.
-                request = record.exc_info[2].tb_frame.f_locals['request']
-            else:
-                request = record.request
-
+            request = record.request
             subject = '%s (%s IP): %s' % (
                 record.levelname,
                 (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'),
@@ -97,5 +69,4 @@ class AdminEmailHandler(logging.Handler):
         message = "%s\n\n%s" % (stack_trace, request_repr)
         reporter = ExceptionReporter(request, is_email=True, *exc_info)
         html_message = self.include_html and reporter.get_traceback_html() or None
-        mail.mail_admins(subject, message, fail_silently=True,
-                         html_message=html_message)
+        mail.mail_admins(subject, message, fail_silently=True, html_message=html_message)
diff --git a/django/utils/tree.py b/django/utils/tree.py
index a6cfec27ad..36b5977942 100644
--- a/django/utils/tree.py
+++ b/django/utils/tree.py
@@ -3,7 +3,7 @@ A class for storing a tree graph. Primarily used for filter constructs in the
 ORM.
 """
 
-from django.utils.copycompat import deepcopy
+import copy
 
 class Node(object):
     """
@@ -58,8 +58,8 @@ class Node(object):
         """
         obj = Node(connector=self.connector, negated=self.negated)
         obj.__class__ = self.__class__
-        obj.children = deepcopy(self.children, memodict)
-        obj.subtree_parents = deepcopy(self.subtree_parents, memodict)
+        obj.children = copy.deepcopy(self.children, memodict)
+        obj.subtree_parents = copy.deepcopy(self.subtree_parents, memodict)
         return obj
 
     def __len__(self):
diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py
index a836ac5c28..279649d35f 100644
--- a/django/views/decorators/cache.py
+++ b/django/views/decorators/cache.py
@@ -1,8 +1,4 @@
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
-
+from functools import wraps
 from django.utils.decorators import decorator_from_middleware_with_args, available_attrs
 from django.utils.cache import patch_cache_control, add_never_cache_headers
 from django.middleware.cache import CacheMiddleware
diff --git a/django/views/decorators/csrf.py b/django/views/decorators/csrf.py
index 578854a529..19fa4f7218 100644
--- a/django/views/decorators/csrf.py
+++ b/django/views/decorators/csrf.py
@@ -1,10 +1,6 @@
 from django.middleware.csrf import CsrfViewMiddleware
 from django.utils.decorators import decorator_from_middleware, available_attrs
-
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
+from functools import wraps
 
 csrf_protect = decorator_from_middleware(CsrfViewMiddleware)
 csrf_protect.__name__ = "csrf_protect"
diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py
index fb3181e10e..dc90cc348b 100644
--- a/django/views/decorators/http.py
+++ b/django/views/decorators/http.py
@@ -2,13 +2,9 @@
 Decorators for views based on HTTP headers.
 """
 
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
-
 from calendar import timegm
 from datetime import timedelta
+from functools import wraps
 
 from django.utils.decorators import decorator_from_middleware, available_attrs
 from django.utils.http import http_date, parse_http_date_safe, parse_etags, quote_etag
diff --git a/django/views/decorators/vary.py b/django/views/decorators/vary.py
index a10896cccf..939b8c3413 100644
--- a/django/views/decorators/vary.py
+++ b/django/views/decorators/vary.py
@@ -1,8 +1,4 @@
-try:
-    from functools import wraps
-except ImportError:
-    from django.utils.functional import wraps  # Python 2.4 fallback.
-
+from functools import wraps
 from django.utils.cache import patch_vary_headers
 from django.utils.decorators import available_attrs
 
diff --git a/django/views/generic/base.py b/django/views/generic/base.py
index d732af5d66..f2c6d3f9f5 100644
--- a/django/views/generic/base.py
+++ b/django/views/generic/base.py
@@ -1,8 +1,8 @@
+from functools import update_wrapper
 from django import http
 from django.core.exceptions import ImproperlyConfigured
 from django.template import RequestContext, loader
 from django.template.response import TemplateResponse
-from django.utils.functional import update_wrapper
 from django.utils.log import getLogger
 from django.utils.decorators import classonlymethod
 
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
index 2832bcbdd9..2f46c0b1aa 100644
--- a/tests/regressiontests/cache/tests.py
+++ b/tests/regressiontests/cache/tests.py
@@ -3,6 +3,7 @@
 # Unit tests for cache framework
 # Uses whatever cache backend is set in the test settings file.
 
+import hashlib
 import os
 import tempfile
 import time
@@ -19,7 +20,6 @@ from django.test.utils import get_warnings_state, restore_warnings_state
 from django.utils import translation
 from django.utils import unittest
 from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key
-from django.utils.hashcompat import md5_constructor
 from django.views.decorators.cache import cache_page
 
 from regressiontests.cache.models import Poll, expensive_calculation
@@ -850,7 +850,7 @@ class FileBasedCacheTests(unittest.TestCase, BaseCacheTests):
         """Test that keys are hashed into subdirectories correctly"""
         self.cache.set("foo", "bar")
         key = self.cache.make_key("foo")
-        keyhash = md5_constructor(key).hexdigest()
+        keyhash = hashlib.md5(key).hexdigest()
         keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
         self.assertTrue(os.path.exists(keypath))
 
@@ -860,7 +860,7 @@ class FileBasedCacheTests(unittest.TestCase, BaseCacheTests):
         """
         self.cache.set("foo", "bar")
         key = self.cache.make_key("foo")
-        keyhash = md5_constructor(key).hexdigest()
+        keyhash = hashlib.md5(key).hexdigest()
         keypath = os.path.join(self.dirname, keyhash[:2], keyhash[2:4], keyhash[4:])
         self.assertTrue(os.path.exists(keypath))
 
diff --git a/tests/regressiontests/comment_tests/tests/comment_form_tests.py b/tests/regressiontests/comment_tests/tests/comment_form_tests.py
index 57dad3625c..956ca53bfd 100644
--- a/tests/regressiontests/comment_tests/tests/comment_form_tests.py
+++ b/tests/regressiontests/comment_tests/tests/comment_form_tests.py
@@ -1,9 +1,9 @@
+import hashlib
 import time
 
 from django.conf import settings
 from django.contrib.comments.forms import CommentForm
 from django.contrib.comments.models import Comment
-from django.utils.hashcompat import sha_constructor
 
 from regressiontests.comment_tests.models import Article
 from regressiontests.comment_tests.tests import CommentTestCase
@@ -57,7 +57,7 @@ class CommentFormTests(CommentTestCase):
 
         # The Django 1.2 method hard-coded here:
         info = (content_type, object_pk, timestamp, settings.SECRET_KEY)
-        security_hash = sha_constructor("".join(info)).hexdigest()
+        security_hash = hashlib.sha1("".join(info)).hexdigest()
 
         d['security_hash'] = security_hash
         f = CommentForm(a, data=d)
diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py
index 2ad5b0c67a..a16d8e24f5 100644
--- a/tests/regressiontests/dispatch/tests/test_dispatcher.py
+++ b/tests/regressiontests/dispatch/tests/test_dispatcher.py
@@ -3,7 +3,6 @@ import sys
 
 from django.dispatch import Signal
 from django.utils import unittest
-import django.utils.copycompat as copy
 
 if sys.platform.startswith('java'):
     def garbage_collect():
diff --git a/tests/regressiontests/extra_regress/models.py b/tests/regressiontests/extra_regress/models.py
index 073157a38a..11218202f0 100644
--- a/tests/regressiontests/extra_regress/models.py
+++ b/tests/regressiontests/extra_regress/models.py
@@ -1,7 +1,6 @@
+import copy
 import datetime
 
-import django.utils.copycompat as copy
-
 from django.contrib.auth.models import User
 from django.db import models
 
diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py
index 6dba4731fd..5da0a5fafc 100644
--- a/tests/regressiontests/file_uploads/tests.py
+++ b/tests/regressiontests/file_uploads/tests.py
@@ -1,5 +1,7 @@
 #! -*- coding: utf-8 -*-
+
 import errno
+import hashlib
 import os
 import shutil
 from StringIO import StringIO
@@ -10,7 +12,6 @@ from django.http.multipartparser import MultiPartParser
 from django.test import TestCase, client
 from django.utils import simplejson
 from django.utils import unittest
-from django.utils.hashcompat import sha_constructor
 
 from models import FileModel, temp_storage, UPLOAD_TO
 import uploadhandler
@@ -46,10 +47,10 @@ class FileUploadTests(TestCase):
 
         for key in post_data.keys():
             try:
-                post_data[key + '_hash'] = sha_constructor(post_data[key].read()).hexdigest()
+                post_data[key + '_hash'] = hashlib.sha1(post_data[key].read()).hexdigest()
                 post_data[key].seek(0)
             except AttributeError:
-                post_data[key + '_hash'] = sha_constructor(post_data[key]).hexdigest()
+                post_data[key + '_hash'] = hashlib.sha1(post_data[key]).hexdigest()
 
         response = self.client.post('/file_uploads/verify/', post_data)
 
diff --git a/tests/regressiontests/file_uploads/views.py b/tests/regressiontests/file_uploads/views.py
index 9f4ce69b5f..0fd0b6502d 100644
--- a/tests/regressiontests/file_uploads/views.py
+++ b/tests/regressiontests/file_uploads/views.py
@@ -1,10 +1,10 @@
+import hashlib
 import os
 from django.core.files.uploadedfile import UploadedFile
 from django.http import HttpResponse, HttpResponseServerError
 from django.utils import simplejson
 from models import FileModel, UPLOAD_TO
 from uploadhandler import QuotaUploadHandler, ErroringUploadHandler
-from django.utils.hashcompat import sha_constructor
 from tests import UNICODE_FILENAME
 
 def file_upload_view(request):
@@ -37,9 +37,9 @@ def file_upload_view_verify(request):
             continue
         submitted_hash = form_data[key + '_hash']
         if isinstance(value, UploadedFile):
-            new_hash = sha_constructor(value.read()).hexdigest()
+            new_hash = hashlib.sha1(value.read()).hexdigest()
         else:
-            new_hash = sha_constructor(value).hexdigest()
+            new_hash = hashlib.sha1(value).hexdigest()
         if new_hash != submitted_hash:
             return HttpResponseServerError()
 
diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
index 4c5aeb0147..0a8a87949c 100644
--- a/tests/regressiontests/forms/tests/widgets.py
+++ b/tests/regressiontests/forms/tests/widgets.py
@@ -1,13 +1,14 @@
 # -*- coding: utf-8 -*-
+
+import copy
 import datetime
-from decimal import Decimal
 import re
 import time
+from decimal import Decimal
 from django.conf import settings
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.forms import *
 from django.forms.widgets import RadioFieldRenderer
-from django.utils import copycompat as copy
 from django.utils import formats
 from django.utils.safestring import mark_safe
 from django.utils.translation import activate, deactivate
diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py
index 90dea9203c..7481641fb5 100644
--- a/tests/regressiontests/introspection/tests.py
+++ b/tests/regressiontests/introspection/tests.py
@@ -1,7 +1,7 @@
+from functools import update_wrapper
 from django.conf import settings
 from django.db import connection, DEFAULT_DB_ALIAS
 from django.test import TestCase, skipUnlessDBFeature
-from django.utils import functional
 
 from models import Reporter, Article
 
@@ -23,7 +23,7 @@ def ignore_not_implemented(func):
             return func(*args, **kwargs)
         except NotImplementedError:
             return None
-    functional.update_wrapper(_inner, func)
+    update_wrapper(_inner, func)
     return _inner
 
 class IgnoreNotimplementedError(type):
diff --git a/tests/regressiontests/utils/datastructures.py b/tests/regressiontests/utils/datastructures.py
index 3d01ab8b6f..6ae652cdba 100644
--- a/tests/regressiontests/utils/datastructures.py
+++ b/tests/regressiontests/utils/datastructures.py
@@ -1,10 +1,11 @@
 """
 Tests for stuff in django.utils.datastructures.
 """
+
+import copy
 import pickle
 import unittest
 
-from django.utils.copycompat import copy
 from django.utils.datastructures import *
 
 
diff --git a/tests/regressiontests/utils/simplelazyobject.py b/tests/regressiontests/utils/simplelazyobject.py
index 9eea8b5901..e29729df60 100644
--- a/tests/regressiontests/utils/simplelazyobject.py
+++ b/tests/regressiontests/utils/simplelazyobject.py
@@ -1,6 +1,6 @@
+import copy
 import unittest
 
-import django.utils.copycompat as copy
 from django.utils.functional import SimpleLazyObject
 
 class _ComplexObject(object):