diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
index 8e83304..74bb558 100644
--- a/django/core/management/__init__.py
+++ b/django/core/management/__init__.py
@@ -3,11 +3,12 @@ import os
 import sys
 from optparse import OptionParser, NO_DEFAULT
 import imp
+import pkgutil
 import warnings
 
 from django.core.management.base import BaseCommand, CommandError, handle_default_options
 from django.core.management.color import color_style
-from django.utils.importlib import import_module
+from django.utils.importlib import import_module, find_package_path
 
 # For backwards compatibility: get_version() used to be in this module.
 from django import get_version
@@ -23,11 +24,11 @@ def find_commands(management_dir):
 
     Returns an empty list if no commands are defined.
     """
-    command_dir = os.path.join(management_dir, 'commands')
     try:
-        return [f[:-3] for f in os.listdir(command_dir)
-                if not f.startswith('_') and f.endswith('.py')]
-    except OSError:
+        commands_dir = find_package_path('commands', [management_dir])[0]
+        return [name for loader,name,ispkg in pkgutil.iter_modules([commands_dir])
+                if not name.startswith('_') ]
+    except ImportError:
         return []
 
 def find_management_module(app_name):
@@ -39,26 +40,39 @@ def find_management_module(app_name):
     """
     parts = app_name.split('.')
     parts.append('management')
-    parts.reverse()
-    part = parts.pop()
-    path = None
-
-    # When using manage.py, the project module is added to the path,
-    # loaded, then removed from the path. This means that
-    # testproject.testapp.models can be loaded in future, even if
-    # testproject isn't in the path. When looking for the management
-    # module, we need look for the case where the project name is part
-    # of the app_name but the project directory itself isn't on the path.
-    try:
-        f, path, descr = imp.find_module(part,path)
-    except ImportError,e:
-        if os.path.basename(os.getcwd()) != part:
-            raise e
+
+    for i in range(len(parts), 0, -1):
+        try:
+            path = sys.modules['.'.join(parts[:i])].__path__
+        except AttributeError:
+            raise ImportError("No package named %s" % parts[i-1])
+        except KeyError:
+            continue
+
+        parts = parts[i:]
+        parts.reverse()
+        break
+    else:
+        parts.reverse()
+        part = parts.pop()
+        path = None
+
+        # When using manage.py, the project module is added to the path,
+        # loaded, then removed from the path. This means that
+        # testproject.testapp.models can be loaded in future, even if
+        # testproject isn't in the path. When looking for the management
+        # module, we need look for the case where the project name is part
+        # of the app_name but the project directory itself isn't on the path.
+        try:
+            path = find_package_path(part, path)
+        except ImportError,e:
+            if os.path.basename(os.getcwd()) != part:
+                raise e
 
     while parts:
         part = parts.pop()
-        f, path, descr = imp.find_module(part, path and [path] or None)
-    return path
+        path = find_package_path(part, path)
+    return path[0]
 
 def load_command_class(app_name, name):
     """
diff --git a/django/db/utils.py b/django/db/utils.py
index 3f5b86e..5c4740f 100644
--- a/django/db/utils.py
+++ b/django/db/utils.py
@@ -1,5 +1,6 @@
 import os
 from threading import local
+import pkgutil
 
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
@@ -25,13 +26,10 @@ def load_backend(backend_name):
     except ImportError, e_user:
         # The database backend wasn't found. Display a helpful error message
         # listing all possible (built-in) database backends.
-        backend_dir = os.path.join(os.path.dirname(__file__), 'backends')
-        try:
-            available_backends = [f for f in os.listdir(backend_dir)
-                    if os.path.isdir(os.path.join(backend_dir, f))
-                    and not f.startswith('.')]
-        except EnvironmentError:
-            available_backends = []
+        backend_path = import_module('django.db.backends').__path__
+        available_backends = [ name for loader, name, ispkg
+                in pkgutil.iter_modules(backend_path)
+                if ispkg ]
         full_notation = backend_name.startswith('django.db.backends.')
         if full_notation:
             backend_name = backend_name[19:] # See #15621.
diff --git a/django/template/loader.py b/django/template/loader.py
index 4185017..98ea96c 100644
--- a/django/template/loader.py
+++ b/django/template/loader.py
@@ -3,10 +3,9 @@
 # This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
 # Each loader is expected to have this interface:
 #
-#    callable(name, dirs=[])
+#    callable(name)
 #
 # name is the template name.
-# dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
 #
 # The loader should return a tuple of (template_source, path). The path returned
 # might be shown to the user for debugging purposes, so it should identify where
@@ -38,12 +37,12 @@ class BaseLoader(object):
     def __init__(self, *args, **kwargs):
         pass
 
-    def __call__(self, template_name, template_dirs=None):
-        return self.load_template(template_name, template_dirs)
+    def __call__(self, template_name):
+        return self.load_template(template_name)
 
-    def load_template(self, template_name, template_dirs=None):
-        source, display_name = self.load_template_source(template_name, template_dirs)
-        origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
+    def load_template(self, template_name):
+        source, display_name = self.load_template_source(template_name)
+        origin = make_origin(display_name, self.load_template_source, template_name)
         try:
             template = get_template_from_string(source, origin, template_name)
             return template, None
@@ -54,7 +53,7 @@ class BaseLoader(object):
             # not exist.
             return source, display_name
 
-    def load_template_source(self, template_name, template_dirs=None):
+    def load_template_source(self, template_name):
         """
         Returns a tuple containing the source and origin for the given template
         name.
@@ -71,16 +70,16 @@ class BaseLoader(object):
         pass
 
 class LoaderOrigin(Origin):
-    def __init__(self, display_name, loader, name, dirs):
+    def __init__(self, display_name, loader, name):
         super(LoaderOrigin, self).__init__(display_name)
-        self.loader, self.loadname, self.dirs = loader, name, dirs
+        self.loader, self.loadname = loader, name
 
     def reload(self):
-        return self.loader(self.loadname, self.dirs)[0]
+        return self.loader(self.loadname)[0]
 
-def make_origin(display_name, loader, name, dirs):
+def make_origin(display_name, loader, name):
     if settings.TEMPLATE_DEBUG and display_name:
-        return LoaderOrigin(display_name, loader, name, dirs)
+        return LoaderOrigin(display_name, loader, name)
     else:
         return None
 
@@ -117,7 +116,7 @@ def find_template_loader(loader):
     else:
         raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader')
 
-def find_template(name, dirs=None):
+def find_template(name):
     # Calculate template_source_loaders the first time the function is executed
     # because putting this logic in the module-level namespace may cause
     # circular import errors. See Django ticket #1292.
@@ -131,8 +130,8 @@ def find_template(name, dirs=None):
         template_source_loaders = tuple(loaders)
     for loader in template_source_loaders:
         try:
-            source, display_name = loader(name, dirs)
-            return (source, make_origin(display_name, loader, name, dirs))
+            source, display_name = loader(name)
+            return (source, make_origin(display_name, loader, name))
         except TemplateDoesNotExist:
             pass
     raise TemplateDoesNotExist(name)
diff --git a/django/template/loaders/app_directories.py b/django/template/loaders/app_directories.py
index b0560b4..2db1a47 100644
--- a/django/template/loaders/app_directories.py
+++ b/django/template/loaders/app_directories.py
@@ -3,62 +3,27 @@ Wrapper for loading templates from "templates" directories in INSTALLED_APPS
 packages.
 """
 
-import os
-import sys
+import pkgutil
 
 from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
 from django.template.base import TemplateDoesNotExist
 from django.template.loader import BaseLoader
 from django.utils._os import safe_join
-from django.utils.importlib import import_module
 
-# At compile time, cache the directories to search.
-fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
-app_template_dirs = []
-for app in settings.INSTALLED_APPS:
-    try:
-        mod = import_module(app)
-    except ImportError, e:
-        raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
-    template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
-    if os.path.isdir(template_dir):
-        app_template_dirs.append(template_dir.decode(fs_encoding))
-
-# It won't change, so convert it to a tuple to save memory.
-app_template_dirs = tuple(app_template_dirs)
 
 class Loader(BaseLoader):
     is_usable = True
 
-    def get_template_sources(self, template_name, template_dirs=None):
-        """
-        Returns the absolute paths to "template_name", when appended to each
-        directory in "template_dirs". Any paths that don't lie inside one of the
-        template dirs are excluded from the result set, for security reasons.
-        """
-        if not template_dirs:
-            template_dirs = app_template_dirs
-        for template_dir in template_dirs:
+    def load_template_source(self, template_name):
+        for app in settings.INSTALLED_APPS:
+            resource = safe_join('/templates', template_name)[1:]
             try:
-                yield safe_join(template_dir, template_name)
-            except UnicodeDecodeError:
-                # The template dir name was a bytestring that wasn't valid UTF-8.
-                raise
-            except ValueError:
-                # The joined path was located outside of template_dir.
+                data = pkgutil.get_data(app, resource)
+                if data is not None:
+                    return data, 'app:' + app + ':'+resource
+            except Exception:
                 pass
 
-    def load_template_source(self, template_name, template_dirs=None):
-        for filepath in self.get_template_sources(template_name, template_dirs):
-            try:
-                file = open(filepath)
-                try:
-                    return (file.read().decode(settings.FILE_CHARSET), filepath)
-                finally:
-                    file.close()
-            except IOError:
-                pass
         raise TemplateDoesNotExist(template_name)
 
 _loader = Loader()
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index 4c25acd..eeb1e6e 100644
--- a/django/template/loaders/cached.py
+++ b/django/template/loaders/cached.py
@@ -27,23 +27,18 @@ class Loader(BaseLoader):
             self._cached_loaders = cached_loaders
         return self._cached_loaders
 
-    def find_template(self, name, dirs=None):
+    def find_template(self, name):
         for loader in self.loaders:
             try:
-                template, display_name = loader(name, dirs)
-                return (template, make_origin(display_name, loader, name, dirs))
+                template, display_name = loader(name)
+                return (template, make_origin(display_name, loader, name))
             except TemplateDoesNotExist:
                 pass
         raise TemplateDoesNotExist(name)
 
-    def load_template(self, template_name, template_dirs=None):
-        key = template_name
-        if template_dirs:
-            # If template directories were specified, use a hash to differentiate
-            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)
+    def load_template(self, template_name):
+        if template_name not in self.template_cache:
+            template, origin = self.find_template(template_name)
             if not hasattr(template, 'render'):
                 try:
                     template = get_template_from_string(template, origin, template_name)
@@ -53,8 +48,8 @@ class Loader(BaseLoader):
                     # we were asked to load. This allows for correct identification (later)
                     # of the actual template that does not exist.
                     return template, origin
-            self.template_cache[key] = template
-        return self.template_cache[key], None
+            self.template_cache[template_name] = template
+        return self.template_cache[template_name], None
 
     def reset(self):
         "Empty the template cache."
diff --git a/django/template/loaders/eggs.py b/django/template/loaders/eggs.py
deleted file mode 100644
index 42f87a4..0000000
--- a/django/template/loaders/eggs.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Wrapper for loading templates from eggs via pkg_resources.resource_string.
-
-try:
-    from pkg_resources import resource_string
-except ImportError:
-    resource_string = None
-
-from django.template.base import TemplateDoesNotExist
-from django.template.loader import BaseLoader
-from django.conf import settings
-
-class Loader(BaseLoader):
-    is_usable = resource_string is not None
-
-    def load_template_source(self, template_name, template_dirs=None):
-        """
-        Loads templates from Python eggs via pkg_resource.resource_string.
-
-        For every installed app, it tries to get the resource (app, template_name).
-        """
-        if resource_string is not None:
-            pkg_name = 'templates/' + template_name
-            for app in settings.INSTALLED_APPS:
-                try:
-                    return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name))
-                except:
-                    pass
-        raise TemplateDoesNotExist(template_name)
-
-_loader = Loader()
diff --git a/django/template/loaders/filesystem.py b/django/template/loaders/filesystem.py
index 51025ac..b926c6b 100644
--- a/django/template/loaders/filesystem.py
+++ b/django/template/loaders/filesystem.py
@@ -10,15 +10,16 @@ from django.utils._os import safe_join
 class Loader(BaseLoader):
     is_usable = True
 
-    def get_template_sources(self, template_name, template_dirs=None):
+    def __init__(self, template_dirs=None):
+        self.template_dirs = template_dirs or settings.TEMPLATE_DIRS
+
+    def get_template_sources(self, template_name):
         """
         Returns the absolute paths to "template_name", when appended to each
         directory in "template_dirs". Any paths that don't lie inside one of the
         template dirs are excluded from the result set, for security reasons.
         """
-        if not template_dirs:
-            template_dirs = settings.TEMPLATE_DIRS
-        for template_dir in template_dirs:
+        for template_dir in self.template_dirs:
             try:
                 yield safe_join(template_dir, template_name)
             except UnicodeDecodeError:
@@ -30,9 +31,9 @@ class Loader(BaseLoader):
                 # fatal).
                 pass
 
-    def load_template_source(self, template_name, template_dirs=None):
+    def load_template_source(self, template_name):
         tried = []
-        for filepath in self.get_template_sources(template_name, template_dirs):
+        for filepath in self.get_template_sources(template_name):
             try:
                 file = open(filepath)
                 try:
diff --git a/django/utils/importlib.py b/django/utils/importlib.py
index ef4d0e4..f53abd9 100644
--- a/django/utils/importlib.py
+++ b/django/utils/importlib.py
@@ -1,5 +1,9 @@
 # Taken from Python 2.7 with permission from/by the original author.
+import os
 import sys
+import imp
+import pkgutil
+import warnings
 
 def _resolve_name(name, package, level):
     """Return the absolute name of the module to be imported."""
@@ -34,3 +38,86 @@ def import_module(name, package=None):
         name = _resolve_name(name[level:], package, level)
     __import__(name)
     return sys.modules[name]
+
+
+def find_package_path(name, path=None):
+    """Finds search path for package with given name.
+
+    The 'path' argument defaults to ``sys.path``.
+
+    Raises ImportError if no search path could be found.
+    """
+    if path is None:
+        path = sys.path
+
+    results = []
+
+    for path_item in path:
+        importer = get_importer(path_item)
+
+        if importer is None:
+            continue
+
+        try:
+            loader = importer.find_module(name)
+
+            if loader is not None:
+
+                if not hasattr(loader, 'is_package'):
+                    warnings.warn(
+                        "Django cannot find search path for package '%s' ",
+                        "under '%s', because the loader returned by '%s' does ",
+                        "not implement 'is_package' method."%(
+                            name,
+                            path_item,
+                            importer.__class__.__name__))
+                    continue
+
+                if not hasattr(loader, 'get_filename'):
+                    warnings.warn(
+                        "Django cannot find search path for package '%s' ",
+                        "under '%s', because the loader returned by '%s' does ",
+                        "not implement 'get_filename' method."%(
+                            name,
+                            path_item,
+                            importer.__class__.__name__))
+                    continue
+
+                if loader.is_package(name):
+                    results.append(os.path.dirname(loader.get_filename(name)))
+        except ImportError:
+            pass
+
+    if not results:
+        raise ImportError("No package named %s" % name)
+
+    return results
+
+
+get_importer = pkgutil.get_importer
+
+try:
+    import zipimport
+
+    if hasattr(zipimport.zipimporter, 'get_filename'):
+        class ZipImporter(zipimport.zipimporter):
+            def get_filename(self, fullname):
+                archivepath = os.path.join(self.archive, self.prefix)
+                if self.is_package(fullname):
+                    return os.path.join(archivepath, fullname, '__init__.py')
+
+                return os.path.join(archivepath, fullname + '.py')
+
+        def get_importer(path_item):
+            importer = pkgutil.get_importer(path_item)
+
+            if isinstance(importer, zipimport.zipimporter):
+                archivepath = os.path.join(importer.archive, importer.prefix)
+                importer = ZipImporter(os.path.dirname(archivepath))
+
+            return importer
+
+except ImportError:
+    pass
+
+
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 82072b1..115f964 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -6,6 +6,8 @@ import re
 import sys
 import gettext as gettext_module
 from threading import local
+import pkgutil
+import copy
 
 try:
     from cStringIO import StringIO
@@ -111,13 +113,6 @@ def translation(language):
 
     globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
 
-    if settings.SETTINGS_MODULE is not None:
-        parts = settings.SETTINGS_MODULE.split('.')
-        project = import_module(parts[0])
-        projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
-    else:
-        projectpath = None
-
     def _fetch(lang, fallback=None):
 
         global _translations
@@ -128,13 +123,30 @@ def translation(language):
 
         loc = to_locale(lang)
 
-        def _translation(path):
-            try:
-                t = gettext_module.translation('django', path, [loc], DjangoTranslation)
-                t.set_language(lang)
-                return t
-            except IOError:
-                return None
+        def _translation(path_or_appname, is_appname=False):
+            if is_appname:
+                nelangs = gettext_module._expand_lang(loc)
+                for nelang in nelangs:
+                    locpath = os.path.join('locale', nelang, 'LC_MESSAGES', 'django.mo')
+                    try:
+                        data = pkgutil.get_data(path_or_appname, locpath)
+                    except:
+                        continue
+
+                    if data is not None:
+                        t = DjangoTranslation(StringIO(data))
+                        t = copy.copy(t)
+                        break
+                else:
+                    return None
+            else:
+                try:
+                    t = gettext_module.translation('django', path_or_appname, [loc], DjangoTranslation)
+                except IOError:
+                    return None
+
+            t.set_language(lang)
+            return t
 
         res = _translation(globalpath)
 
@@ -147,8 +159,8 @@ def translation(language):
             res._info = res._info.copy()
             res._catalog = res._catalog.copy()
 
-        def _merge(path):
-            t = _translation(path)
+        def _merge(path_or_appname, is_appname=False):
+            t = _translation(path_or_appname, is_appname)
             if t is not None:
                 if res is None:
                     return t
@@ -157,16 +169,9 @@ def translation(language):
             return res
 
         for appname in reversed(settings.INSTALLED_APPS):
-            app = import_module(appname)
-            apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
-
-            if os.path.isdir(apppath):
-                res = _merge(apppath)
+            res = _merge(appname, is_appname=True)
 
-        localepaths = [os.path.normpath(path) for path in settings.LOCALE_PATHS]
-        if (projectpath and os.path.isdir(projectpath) and
-                os.path.normpath(projectpath) not in localepaths):
-            res = _merge(projectpath)
+        res = _merge(settings.SETTINGS_MODULE, is_appname=True)
 
         for localepath in reversed(settings.LOCALE_PATHS):
             if os.path.isdir(localepath):
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
index 03fef1d..8154d2c 100644
--- a/docs/ref/templates/api.txt
+++ b/docs/ref/templates/api.txt
@@ -655,9 +655,9 @@ class. Here are the template loaders that come with Django:
     This loader is enabled by default.
 
 ``django.template.loaders.app_directories.Loader``
-    Loads templates from Django apps on the filesystem. For each app in
-    :setting:`INSTALLED_APPS`, the loader looks for a ``templates``
-    subdirectory. If the directory exists, Django looks for templates in there.
+    Loads templates from Django apps. For each app in :setting:`INSTALLED_APPS`,
+    the loader looks for a ``templates`` subdirectory. If the directory exists, 
+    Django looks for templates in there.
 
     This means you can store templates with your individual apps. This also
     makes it easy to distribute Django apps with default templates.
@@ -672,18 +672,8 @@ class. Here are the template loaders that come with Django:
     * ``/path/to/myproject/polls/templates/foo.html``
     * ``/path/to/myproject/music/templates/foo.html``
 
-    Note that the loader performs an optimization when it is first imported: It
-    caches a list of which :setting:`INSTALLED_APPS` packages have a
-    ``templates`` subdirectory.
-
     This loader is enabled by default.
 
-``django.template.loaders.eggs.Loader``
-    Just like ``app_directories`` above, but it loads templates from Python
-    eggs rather than from the filesystem.
-
-    This loader is disabled by default.
-
 ``django.template.loaders.cached.Loader``
     By default, the templating system will read and compile your templates every
     time they need to be rendered. While the Django templating system is quite
@@ -838,8 +828,8 @@ of the ``load_template_source()`` method implemented there::
     class Loader(app_directories.Loader):
         is_usable = True
 
-        def load_template(self, template_name, template_dirs=None):
-            source, origin = self.load_template_source(template_name, template_dirs)
+        def load_template(self, template_name):
+            source, origin = self.load_template_source(template_name)
             template = Template(source)
             return template, origin
 
diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py
new file mode 100644
index 0000000..a393663
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py
@@ -0,0 +1,9 @@
+from django.core.management.base import BaseCommand
+
+class Command(BaseCommand):
+    help = 'Test managment commands in non-namespaced app'
+    requires_model_validation = False
+    args = ''
+
+    def handle(self, *labels, **options):
+        print 'EXECUTE:nons_app_command1'
diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/models.py b/tests/regressiontests/admin_scripts/lib1/nons_app/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/npapp/__init__.py b/tests/regressiontests/admin_scripts/lib1/npapp/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/npapp/management.py b/tests/regressiontests/admin_scripts/lib1/npapp/management.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/npapp/models.py b/tests/regressiontests/admin_scripts/lib1/npapp/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py
new file mode 100644
index 0000000..32f26d8
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py
@@ -0,0 +1,6 @@
+# http://packages.python.org/distribute/setuptools.html#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py
new file mode 100644
index 0000000..32f26d8
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py
@@ -0,0 +1,6 @@
+# http://packages.python.org/distribute/setuptools.html#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py
new file mode 100644
index 0000000..2f479bb
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py
@@ -0,0 +1,9 @@
+from django.core.management.base import BaseCommand
+
+class Command(BaseCommand):
+    help = 'Test managment commands in namespaced apps'
+    requires_model_validation = False
+    args = ''
+
+    def handle(self, *labels, **options):
+        print 'EXECUTE:app1_command1'
diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/models.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py
new file mode 100644
index 0000000..32f26d8
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py
@@ -0,0 +1,6 @@
+# http://packages.python.org/distribute/setuptools.html#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py
new file mode 100644
index 0000000..32f26d8
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py
@@ -0,0 +1,6 @@
+# http://packages.python.org/distribute/setuptools.html#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py
new file mode 100644
index 0000000..b9e20a7
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py
@@ -0,0 +1,9 @@
+from django.core.management.base import BaseCommand
+
+class Command(BaseCommand):
+    help = 'Test managment commands in namespaced apps'
+    requires_model_validation = False
+    args = ''
+
+    def handle(self, *labels, **options):
+        print 'EXECUTE:app2_command1'
diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/models.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib3/_addsitedir.py b/tests/regressiontests/admin_scripts/lib3/_addsitedir.py
new file mode 100644
index 0000000..9e264d2
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib3/_addsitedir.py
@@ -0,0 +1 @@
+import os.path, site; site.addsitedir(os.path.dirname(__file__))
diff --git a/tests/regressiontests/admin_scripts/lib3/egg_module.pth b/tests/regressiontests/admin_scripts/lib3/egg_module.pth
new file mode 100644
index 0000000..9367ab5
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib3/egg_module.pth
@@ -0,0 +1 @@
+test_egg.egg
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth b/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth
new file mode 100644
index 0000000..1f31155
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth
@@ -0,0 +1 @@
+import sys,new,os; p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('exapps',)); ie = os.path.exists(os.path.join(p,'__init__.py')); m = not ie and sys.modules.setdefault('exapps',new.module('exapps')); mp = (m or []) and m.__dict__.setdefault('__path__',[]); (p not in mp) and mp.append(p)
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py
new file mode 100644
index 0000000..97f5d33
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py
@@ -0,0 +1,9 @@
+from django.core.management.base import BaseCommand
+
+class Command(BaseCommand):
+    help = 'Test managment commands in namespaced apps'
+    requires_model_validation = False
+    args = ''
+
+    def handle(self, *labels, **options):
+        print 'EXECUTE:app3_command1'
diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/models.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_scripts/lib3/test_egg.egg b/tests/regressiontests/admin_scripts/lib3/test_egg.egg
new file mode 100644
index 0000000000000000000000000000000000000000..d9e57de006a3d602515293f8e980bf3a16fb42c0
GIT binary patch
literal 2210
zcmWIWW@Zs#W&na+g#z{<8U{Fl3|Dt|T~9wZfBgWcG7g3{KxHDAuKle5O78$-K~!ZB
z^|5C+avd@dV0&QeKT+IcWwzNt$AHBOuWGiW^E|0~S|nLhZ9Ow6Z`b?h&-X7l#KHBh
zGf2q)-n(7*SQNg9C6^pYKAZ6`^S*BSyQv&cUcXhIbLgw+nTectc?6~3uC9yNw%@sF
z%ItZU8-gRR@<p(DZr01@&6oUg*2%XH)tT;p3*R&VooCL-z#xL`%wYe}AZOQLy^@NO
zseK1QE_HeT&--$}fT-Y_2pj#SlFkL2Ia9R1z3&YW$hEDwHMjD;fuxnn<YS_977M&R
zu%dHMh3c<Wrx~B0zcgk0r=s4kFE_0Ic06}8$L(iDarse;`D34maV9DL^?37iT78$4
zu;IH0CoB42FDd2_n0t1<bS;nS%|HFW4h3s`69&1M3mpESfSt^C-3aJd1`w7-c5zB-
zL26z~YF=_>d`@Owb}`85T&Q|ip0Nz)2I>J}F=V|Z`33Pgsb#4-AWf<1>G8SwDWy57
zXxfpjMv2p^%mUrw#59O{NK!eBmQ+AiA`Av67Koo#6`-amkh_o+#>Z#oWtPOp>lIYO
zVvd0U-EcHLxrup+>8ZJ?c_m2p+{#0>M-kN?Bt1k~DUVZoa(*t*u#{pvc54yVjKvWg
z3_F2gHQm(j`*xsy9$*5{C2S5TD4{L_2BB}CcONJzf46gee`Y}-UxUeP$C<(gLc3RV
zY9Cwi_n@qWz2AwZxYCuY=4Gw2oV2^}(@yDPS8>aY?k=--b8BlHne^Ic|6BWKH)7Jy
zXsq#?eWx}ep56KFx(QD9DgGB`hCMj6_@itPSErDB#zVor9U@z^*FXBlA!>Exjl$u{
zsuuH{{dm6}Ulb7>vsbSqJM5*w#jS~~)~!DGw}|g^*kb!TX4*Er&D*q1x2SHj|9<>`
zaDBt~!)B*vi6f<AwA2F1vq-50m~2yXiot1xkx7IZcc}%`1_S~P2OL2(QW*x*hP@O6
zDP~|$XxP%I4y2K^LCUlMZ&dB*r3+X$So=9-?MP(}#01>A9brNPF#h2Vz?S#XjY7}-
z2&48O8--F7pqqhS0wB!zjcf+2JV1m8W}XEV2oL~@1#Kpjcto}rTLA&l2#SXgRE;Rv
z1{N8ZmV*im2mo2$focX)QGo0YYy}9!43Ina;536sCxHqS2mm?hH%{Y_iWiXoAV~$?
zZJ+`M0zhuF09GEznFLWh!VSafNbCg;!rTVJ=Asrq$icY=OHM`@-Nb_GWJJDZWdo_=
P1Hv0X>$d>aF)#oC`tnrE

literal 0
HcmV?d00001

diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
index 669c6e8..6408b97 100644
--- a/tests/regressiontests/admin_scripts/tests.py
+++ b/tests/regressiontests/admin_scripts/tests.py
@@ -91,6 +91,10 @@ class AdminScriptTestCase(unittest.TestCase):
     def run_test(self, script, args, settings_file=None, apps=None):
         project_dir = os.path.dirname(test_dir)
         base_dir = os.path.dirname(project_dir)
+        lib1_dir = os.path.join(os.path.dirname(__file__), 'lib1')
+        lib2_dir = os.path.join(os.path.dirname(__file__), 'lib2')
+        lib3_dir = os.path.join(os.path.dirname(__file__), 'lib3')
+        eggs_dir = os.path.join(os.path.dirname(__file__), 'eggs')
         ext_backend_base_dirs = self._ext_backend_paths()
 
         # Remember the old environment
@@ -108,7 +112,7 @@ class AdminScriptTestCase(unittest.TestCase):
             os.environ['DJANGO_SETTINGS_MODULE'] = settings_file
         elif 'DJANGO_SETTINGS_MODULE' in os.environ:
             del os.environ['DJANGO_SETTINGS_MODULE']
-        python_path = [project_dir, base_dir]
+        python_path = [project_dir, base_dir, lib1_dir, lib2_dir, lib3_dir]
         python_path.extend(ext_backend_base_dirs)
         os.environ[python_path_var_name] = os.pathsep.join(python_path)
 
@@ -1563,3 +1567,95 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
         self.assertOutput(err, "Destination directory '%s' does not exist, please create it first." % testproject_dir)
         self.assertFalse(os.path.exists(testproject_dir))
 
+
+class NamespacePackagedApps(AdminScriptTestCase):
+    def setUp(self):
+        self.write_settings('settings.py', apps=['nons_app', 'nsapps.contrib.app1','nsapps.contrib.app2','exapps.app3', 'egg_module'])
+        settings_file = open(os.path.join(test_dir, 'settings.py'), 'a')
+        settings_file.write('import _addsitedir')
+        settings_file.close()
+        
+    def tearDown(self):
+        self.remove_settings('settings.py')
+
+    def test_help(self):
+        out, err = self.run_manage(['help'])
+        self.assertNoOutput(err)
+        self.assertOutput(out, "nons_app_command1")
+        self.assertOutput(out, "app1_command1")
+        self.assertOutput(out, "app2_command1")
+        self.assertOutput(out, "app3_command1")
+        self.assertOutput(out, "egg_command")
+
+    def test_nons_app(self):
+        args = ['nons_app_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:nons_app_command1")
+
+    def test_nsapps(self):
+        args = ['app1_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:app1_command1")
+
+        args = ['app2_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:app2_command1")
+
+    def test_exapps(self):
+        args = ['app3_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:app3_command1")
+
+    def test_exapps(self):
+        args = ['egg_command']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:egg_command")
+
+
+class PreloadedNamespacePackagedApps(AdminScriptTestCase):
+    def setUp(self):
+        self.write_settings('settings.py', apps=['nsapps.contrib.app1','nsapps.contrib.app2'])
+        settings_file = open(os.path.join(test_dir, 'settings.py'), 'a')
+        settings_file.write('import nsapps')
+        settings_file.close()
+        
+    def tearDown(self):
+        self.remove_settings('settings.py')
+
+    def test_help(self):
+        out, err = self.run_manage(['help'])
+        self.assertNoOutput(err)
+        self.assertOutput(out, "app1_command1")
+        self.assertOutput(out, "app2_command1")
+
+    def test_nsapps(self):
+        args = ['app1_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:app1_command1")
+
+        args = ['app2_command1']
+        out, err = self.run_manage(args)
+        self.assertNoOutput(err)
+        self.assertOutput(out, "EXECUTE:app2_command1")
+
+
+class NonPackageManagementApps(AdminScriptTestCase):
+    def setUp(self):
+        self.write_settings('settings.py', apps=['npapp'])
+        settings_file = open(os.path.join(test_dir, 'settings.py'), 'a')
+        settings_file.write('import npapp.management')
+        settings_file.close()
+
+    def tearDown(self):
+        self.remove_settings('settings.py')
+
+    def test_help(self):
+        out, err = self.run_manage(['help'])
+        self.assertNoOutput(err)
+
diff --git a/tests/regressiontests/i18n/eggs/localeegg.egg b/tests/regressiontests/i18n/eggs/localeegg.egg
new file mode 100644
index 0000000000000000000000000000000000000000..c3b13d05d974f9bea7fddd20c88f8979f56026a5
GIT binary patch
literal 3353
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

literal 0
HcmV?d00001

diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 99a55bd..5fbccaf 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -4,6 +4,7 @@ from __future__ import with_statement, absolute_import
 import datetime
 import decimal
 import os
+import sys
 import pickle
 from threading import local
 
@@ -892,6 +893,52 @@ class ProjectResolutionOrderI18NTests(ResolutionOrderI18NTests):
         with self.settings(INSTALLED_APPS=extended_apps):
             self.assertUgettext('Date/time', 'PROJECT')
 
+class EggResolutionOrderI18NTests(ResolutionOrderI18NTests):
+
+    def setUp(self):
+        self.old_path = sys.path[:]
+        self.egg_dir = '%s/eggs' % os.path.dirname(__file__)
+        egg_name = '%s/localeegg.egg' % self.egg_dir
+        sys.path.insert(0, egg_name)
+        super(EggResolutionOrderI18NTests, self).setUp()
+
+    def tearDown(self):
+        super(EggResolutionOrderI18NTests, self).tearDown()
+        sys.path = self.old_path
+
+class EggAppResolutionOrderI18NTests(EggResolutionOrderI18NTests):
+
+    def setUp(self):
+        self.old_installed_apps = settings.INSTALLED_APPS
+        settings.INSTALLED_APPS = ['resolution'] + list(settings.INSTALLED_APPS)
+        super(EggAppResolutionOrderI18NTests, self).setUp()
+
+    def tearDown(self):
+        settings.INSTALLED_APPS = self.old_installed_apps
+        super(EggAppResolutionOrderI18NTests, self).tearDown()
+
+    def test_app_translation(self):
+        self.assertUgettext('Date/time', 'APP')
+
+class EggProjectResolutionOrderI18NTests(EggResolutionOrderI18NTests):
+
+    def setUp(self):
+        self.old_settings_module = settings.SETTINGS_MODULE
+        settings.SETTINGS_MODULE = 'eggtests'
+        super(EggProjectResolutionOrderI18NTests, self).setUp()
+
+    def tearDown(self):
+        super(EggProjectResolutionOrderI18NTests, self).tearDown()
+        settings.SETTINGS_MODULE = self.old_settings_module
+
+    def test_project_translation(self):
+        self.assertUgettext('Date/time', 'PROJECT')
+
+    def test_project_override_app_translation(self):
+        extended_apps = list(settings.INSTALLED_APPS) + ['resolution']
+        with self.settings(INSTALLED_APPS=extended_apps):
+            self.assertUgettext('Date/time', 'PROJECT')
+
 class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests):
 
     def test_django_fallback(self):
diff --git a/tests/regressiontests/templates/eggs/templatesegg.egg b/tests/regressiontests/templates/eggs/templatesegg.egg
new file mode 100644
index 0000000000000000000000000000000000000000..9a8f315f883b1d895f1d5926ca7ad3134c23287f
GIT binary patch
literal 663
zcmWIWW@Zs#W&naW+0_mp8V1;ajMVh>ctiaFpc*c)npbFQ1mSAp<1_OzOXB183MxU$
zAx3^eQ!W5kUXq$ykds)FT8v~kNVTZi?ca<*RUj;eMRlcKMoDfCk`>R<tl)xb0-9e^
ziDWpsI#CpLD6VH@vS-E}BtU&YAkgsF5k$iR2&4yh5P?)OFeo%^X;cBy5Is1o#1>>=
z-C!$&;o6Y{5MepCAcW`!S>A|6HzYs<yb+#84=GTHLIB9q+ki}v2Vmigup3<;D1;#Z
cWcNKF6QK{q^Q@qh#=r)I1;A(*1Vudq052GO+5i9m

literal 0
HcmV?d00001

diff --git a/tests/regressiontests/templates/loaders.py b/tests/regressiontests/templates/loaders.py
index 5c11916..287bfdd 100644
--- a/tests/regressiontests/templates/loaders.py
+++ b/tests/regressiontests/templates/loaders.py
@@ -1,7 +1,5 @@
 """
 Test cases for the template loaders
-
-Note: This test requires setuptools!
 """
 
 from django.conf import settings
@@ -10,65 +8,27 @@ if __name__ == '__main__':
     settings.configure()
 
 import sys
-import pkg_resources
 import imp
 import StringIO
 import os.path
 
 from django.template import TemplateDoesNotExist, Context
-from django.template.loaders.eggs import Loader as EggLoader
+from django.template.loaders.app_directories import Loader as EggLoader
 from django.template import loader
 from django.utils import unittest
 
 
-# Mock classes and objects for pkg_resources functions.
-class MockProvider(pkg_resources.NullProvider):
-    def __init__(self, module):
-        pkg_resources.NullProvider.__init__(self, module)
-        self.module = module
-
-    def _has(self, path):
-        return path in self.module._resources
-
-    def _isdir(self,path):
-        return False
-
-    def get_resource_stream(self, manager, resource_name):
-        return self.module._resources[resource_name]
-
-    def _get(self, path):
-        return self.module._resources[path].read()
-
-class MockLoader(object):
-    pass
-
-def create_egg(name, resources):
-    """
-    Creates a mock egg with a list of resources.
-
-    name: The name of the module.
-    resources: A dictionary of resources. Keys are the names and values the data.
-    """
-    egg = imp.new_module(name)
-    egg.__loader__ = MockLoader()
-    egg._resources = resources
-    sys.modules[name] = egg
-
-
 class EggLoaderTest(unittest.TestCase):
     def setUp(self):
-        pkg_resources._provider_factories[MockLoader] = MockProvider
-
-        self.empty_egg = create_egg("egg_empty", {})
-        self.egg_1 = create_egg("egg_1", {
-            os.path.normcase('templates/y.html') : StringIO.StringIO("y"),
-            os.path.normcase('templates/x.txt') : StringIO.StringIO("x"),
-        })
-        self._old_installed_apps = settings.INSTALLED_APPS
-        settings.INSTALLED_APPS = []
+        self.old_path = sys.path[:]
+        self.old_apps = settings.INSTALLED_APPS
+        self.egg_dir = '%s/eggs' % os.path.dirname(__file__)
+        egg_name = '%s/templatesegg.egg' % self.egg_dir
+        sys.path.append(egg_name)
 
     def tearDown(self):
-        settings.INSTALLED_APPS = self._old_installed_apps
+        settings.INSTALLED_APPS = self.old_apps
+        sys.path = self.old_path
 
     def test_empty(self):
         "Loading any template on an empty egg should fail"
@@ -88,7 +48,7 @@ class EggLoaderTest(unittest.TestCase):
         egg_loader = EggLoader()
         contents, template_name = egg_loader.load_template_source("y.html")
         self.assertEqual(contents, "y")
-        self.assertEqual(template_name, "egg:egg_1:templates/y.html")
+        self.assertEqual(template_name, u"app:egg_1:templates/y.html")
 
     def test_not_installed(self):
         "Loading an existent template from an egg not included in INSTALLED_APPS should fail"
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index f74aa75..a13c157 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -39,14 +39,8 @@ from .nodelist import NodelistTest, ErrorIndexTest
 from .smartif import SmartIfTests
 from .response import (TemplateResponseTest, BaseTemplateResponseTest,
     CacheMiddlewareTest, SimpleTemplateResponseTest, CustomURLConfTest)
+from .loaders import RenderToStringTest, EggLoaderTest
 
-try:
-    from .loaders import RenderToStringTest, EggLoaderTest
-except ImportError, e:
-    if "pkg_resources" in e.message:
-        pass # If setuptools isn't installed, that's fine. Just move on.
-    else:
-        raise
 
 from . import filters
 
@@ -167,20 +161,16 @@ class Templates(unittest.TestCase):
         restore_warnings_state(self._warnings_state)
 
     def test_loaders_security(self):
-        ad_loader = app_directories.Loader()
-        fs_loader = filesystem.Loader()
         def test_template_sources(path, template_dirs, expected_sources):
             if isinstance(expected_sources, list):
                 # Fix expected sources so they are abspathed
                 expected_sources = [os.path.abspath(s) for s in expected_sources]
-            # Test the two loaders (app_directores and filesystem).
-            func1 = lambda p, t: list(ad_loader.get_template_sources(p, t))
-            func2 = lambda p, t: list(fs_loader.get_template_sources(p, t))
-            for func in (func1, func2):
-                if isinstance(expected_sources, list):
-                    self.assertEqual(func(path, template_dirs), expected_sources)
-                else:
-                    self.assertRaises(expected_sources, func, path, template_dirs)
+            # Test filesystem loader.
+            func = lambda p, t: list(filesystem.Loader(t).get_template_sources(p))
+            if isinstance(expected_sources, list):
+                self.assertEqual(func(path, template_dirs), expected_sources)
+            else:
+                self.assertRaises(expected_sources, func, path, template_dirs)
 
         template_dirs = ['/dir1', '/dir2']
         test_template_sources('index.html', template_dirs,
