diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
index 8f32898..88d3945 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 76c9bfc..158357c 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
@@ -121,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)
 
@@ -140,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
@@ -150,11 +169,7 @@ 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)
 
         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 68ebda0..cbdc54b 100644
--- a/tests/regressiontests/admin_scripts/tests.py
+++ b/tests/regressiontests/admin_scripts/tests.py
@@ -90,6 +90,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
@@ -107,7 +111,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)
 
@@ -1552,3 +1556,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..37b082e54f2cbbf5f7b7e88e61e34a15b22a9d6e
GIT binary patch
literal 1855
zcmWIWW@Zs#W&naGrL7Ji8V0z5jH1-y{G8H~%=|q40H8uHu)>3(z78-&AX*HFkrc+q
zXXa&=#K-FuRD$$iH(Ur+PfmVvVooa94(#ehv8qqOr$rH$79Zz$U)SJZM|am?xQ!eP
zAYX;5aAqbjGBCUZVl85{r(`AOrRVGA=7&x=>vzaO;P~t72j}&q^FQ`Y7K>77)Nxu7
zz~R}=E5d)QS$j?C#y4iWyDzeT+*rdp@90Xo3n%}j{hR#fdvaNI)sL46G79M)%$80{
zOM2X&NF<(6{M2Rh#?r6xE6Y!(w@G)Cjy`>3z1u?LazkX?)}*s@xA=61Y46*RvPY#n
zMtY%2>(j22K8;V0NtK`CUaH&at2XUP+GNQ|T3mTWvnTC)cIFXZ&^*tD&wk2%%sP_a
zaDU0yU!vdSq)txR&-wZM^XYc$IqT;B(s=cvd&WkUt3I>lL@w3jc^=3zS%L4NRZnx_
z6>hfXOpDp27qvF?p0@C`j1KN-I+-EYb3xp7Z%oLPbG!0v`VQZ9sXJQy+bc@%V_$z$
zu*|!=Vcl~$Z?+xfzT9^EoQ>?HYv;oEJ)M~?bgDIqYi3}EE$3^spKhDy@Jx-9=Gycl
z(|7r`w)mSnCluUc{C`RJf7Rx7_lgrADtS!ue%}9w4VIE1@$~Z4M5bfFI6A^aT09lx
z$4<=8zhxkB?Ed%QI}eUJ%x*leEbQHkS**+#ojQerS6;ri<B8NA)v^@p%Rjz(|5$u!
z->17jzyH|zxl}QBy~LRaDV4-ChuPU|o(M|Elqz1hdhbNd^9ABx9!~tp`9Zb$27lcz
z?r(;z39|NT50g$N?(9p`$uy}^*R?s#w9wKxbM8d{t%rHCrY>aM?z~}<i^dbNsjdRs
z*3P}(;+6BiLniur<%}gVe|Y293I8}2Rwr@y=jO;mm%jXd?rhFm8hR@x?ZV3~j>*^D
z=H7TAe#c5E?FnP=)TqD{aV@7zEw-Hd7sfj!VQH`O>M;MhD?3$Vf-Pc>X8SQUA2Rha
z66VwFalhBmbL_}(rhBGyee6tszF?Wm^55%s+t;YF65e|)RlWw68z*k)D^Q-I+j6<>
zP>rx_!Ta?$elz;-IF&t7`Jsjv*Tnk$H-2=t^)A}&#JA;S{~fKEjn_T*9=xb?;nc#c
zKi@=y3VxjDUG3yi%6)sTf!N)W!_S{QYqI_Nt*6ak>(!YdmaVhZU-mVNZ53plnH?O(
zwaRKqnbp45WQ(_&KMYvc-@g<d%eC~}h7HYG{_4+73nL%BURAfS<ih92JO0Og_^Ojp
zU-CjPG<T(5`}AA?QOlzL^HK|diGcxxMNo5XZhlH?PBE|~QV#HDWU^<*UbuitItUPG
z`0EH_Ar)s3jkrrbh(?8mEsdI}8d1tY+?In%LI?m^9t&h5Sq?83aq9<_j1U0Q-wR}7
z>IavTxQ$SRnZN)t;s7oqP|Ho2ao9^vh>4(3`A>{-@NyIpP1tif!rbM+ypPqV$j*eC
mTab?)i|A<vVeVEI6m#JzD8QSQ4Wx<#2pxfTzW}OZU;qGci;V67

literal 0
HcmV?d00001

diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index faed4e5..4287573 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -4,6 +4,7 @@ from __future__ import absolute_import
 import datetime
 import decimal
 import os
+import sys
 import pickle
 from threading import local
 
@@ -868,6 +869,33 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests):
         with self.settings(INSTALLED_APPS=extended_apps):
             self.assertUgettext('Time', 'LOCALE_PATHS')
 
+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 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 e166f7e..d6d6991 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,
