Ticket #14087: namespaced_managment_commands.diff

File namespaced_managment_commands.diff, 10.7 KB (added by nfg, 4 years ago)

find_managment_module with support for namespaced packages, with tests.

  • django/core/management/__init__.py

    diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
    index 85bf324..f34a60c 100644
    a b  
    11import os
    22import sys
    33from optparse import OptionParser, NO_DEFAULT
    4 import imp
    54
    65import django
    76from django.core.management.base import BaseCommand, CommandError, handle_default_options
    8 from django.utils.importlib import import_module
     7from django.utils.importlib import import_module, find_modules
    98
    109# For backwards compatibility: get_version() used to be in this module.
    1110get_version = django.get_version
    def find_management_module(app_name): 
    3938    parts.append('management')
    4039    parts.reverse()
    4140    part = parts.pop()
    42     path = None
     41    paths = None
    4342
    4443    # When using manage.py, the project module is added to the path,
    4544    # loaded, then removed from the path. This means that
    def find_management_module(app_name): 
    4847    # module, we need look for the case where the project name is part
    4948    # of the app_name but the project directory itself isn't on the path.
    5049    try:
    51         f, path, descr = imp.find_module(part,path)
     50        modules = find_modules(part, paths)
     51        paths = [m[1] for m in modules]
    5252    except ImportError,e:
    5353        if os.path.basename(os.getcwd()) != part:
    5454            raise e
    5555
    5656    while parts:
    5757        part = parts.pop()
    58         f, path, descr = imp.find_module(part, path and [path] or None)
    59     return path
     58        modules = find_modules(part, paths)
     59        paths = [m[1] for m in modules]
     60    return paths[0]
    6061
    6162def load_command_class(app_name, name):
    6263    """
  • django/utils/importlib.py

    diff --git a/django/utils/importlib.py b/django/utils/importlib.py
    index ef4d0e4..1507a2b 100644
    a b  
    11# Taken from Python 2.7 with permission from/by the original author.
    22import sys
     3import imp
    34
    45def _resolve_name(name, package, level):
    56    """Return the absolute name of the module to be imported."""
    def import_module(name, package=None): 
    3435        name = _resolve_name(name[level:], package, level)
    3536    __import__(name)
    3637    return sys.modules[name]
     38
     39
     40def find_modules(name, path=None):
     41    """Find all modules with name 'name'
     42   
     43    Unlike find_module in the imp package this returns a list of all
     44    matched modules.
     45    """
     46    results = []
     47    if path is None: path = sys.path
     48    for p in path:
     49        importer = sys.path_importer_cache.get(p, None)
     50        if importer is None:
     51            find_module = imp.find_module
     52        else:
     53            find_module = importer.find_module
     54       
     55        try:
     56            result = find_module(name, [p])
     57            if result is not None:
     58                results.append(result)
     59        except ImportError:
     60            pass
     61    if not results:
     62        raise ImportError("No module named %.200s" % name)
     63    return results
  • new file tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py

    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
    - +  
     1from django.core.management.base import BaseCommand
     2
     3class Command(BaseCommand):
     4    help = 'Test managment commands in non-namespaced app'
     5    requires_model_validation = False
     6    args = ''
     7
     8    def handle(self, *labels, **options):
     9        print 'EXECUTE:nons_app_command1'
  • new file tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py

    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/nsapps/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py
    new file mode 100644
    index 0000000..32f26d8
    - +  
     1# http://packages.python.org/distribute/setuptools.html#namespace-packages
     2try:
     3    __import__('pkg_resources').declare_namespace(__name__)
     4except ImportError:
     5    from pkgutil import extend_path
     6    __path__ = extend_path(__path__, __name__)
  • new file tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/commands/app1_command1.py

    diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/app1/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/app1/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/commands/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/commands/app1_command1.py b/tests/regressiontests/admin_scripts/lib1/nsapps/app1/management/commands/app1_command1.py
    new file mode 100644
    index 0000000..2f479bb
    - +  
     1from django.core.management.base import BaseCommand
     2
     3class Command(BaseCommand):
     4    help = 'Test managment commands in namespaced apps'
     5    requires_model_validation = False
     6    args = ''
     7
     8    def handle(self, *labels, **options):
     9        print 'EXECUTE:app1_command1'
  • new file tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py

    diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/app1/models.py b/tests/regressiontests/admin_scripts/lib1/nsapps/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
    - +  
     1# http://packages.python.org/distribute/setuptools.html#namespace-packages
     2try:
     3    __import__('pkg_resources').declare_namespace(__name__)
     4except ImportError:
     5    from pkgutil import extend_path
     6    __path__ = extend_path(__path__, __name__)
  • new file tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/commands/app2_command1.py

    diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/app2/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/app2/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/commands/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/commands/app2_command1.py b/tests/regressiontests/admin_scripts/lib2/nsapps/app2/management/commands/app2_command1.py
    new file mode 100644
    index 0000000..b9e20a7
    - +  
     1from django.core.management.base import BaseCommand
     2
     3class Command(BaseCommand):
     4    help = 'Test managment commands in namespaced apps'
     5    requires_model_validation = False
     6    args = ''
     7
     8    def handle(self, *labels, **options):
     9        print 'EXECUTE:app2_command1'
  • tests/regressiontests/admin_scripts/tests.py

    diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/app2/models.py b/tests/regressiontests/admin_scripts/lib2/nsapps/app2/models.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
    index 94d8f93..9a29808 100644
    a b class AdminScriptTestCase(unittest.TestCase): 
    8484        test_dir = os.path.dirname(os.path.dirname(__file__))
    8585        project_dir = os.path.dirname(test_dir)
    8686        base_dir = os.path.dirname(project_dir)
     87        lib1_dir = os.path.join(os.path.dirname(__file__), 'lib1')
     88        lib2_dir = os.path.join(os.path.dirname(__file__), 'lib2')
    8789        ext_backend_base_dirs = self._ext_backend_paths()
    8890
    8991        # Remember the old environment
    class AdminScriptTestCase(unittest.TestCase): 
    101103            os.environ['DJANGO_SETTINGS_MODULE'] = settings_file
    102104        elif 'DJANGO_SETTINGS_MODULE' in os.environ:
    103105            del os.environ['DJANGO_SETTINGS_MODULE']
    104         python_path = [test_dir, base_dir]
     106        python_path = [test_dir, base_dir, lib1_dir, lib2_dir]
    105107        python_path.extend(ext_backend_base_dirs)
    106108        os.environ[python_path_var_name] = os.pathsep.join(python_path)
    107109
    class ArgumentOrder(AdminScriptTestCase): 
    11971199        out, err = self.run_manage(args)
    11981200        self.assertNoOutput(err)
    11991201        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None), ('verbosity', '1')]")
     1202
     1203
     1204class NamespacePackagedApps(AdminScriptTestCase):
     1205    def setUp(self):
     1206        self.write_settings('settings.py', apps=['nons_app', 'nsapps.app1','nsapps.app2'])
     1207       
     1208    def tearDown(self):
     1209        self.remove_settings('settings.py')
     1210
     1211    def test_help(self):
     1212        out, err = self.run_manage(['help'])
     1213        self.assertOutput(err, "nons_app_command1")
     1214        self.assertOutput(err, "app1_command1")
     1215        self.assertOutput(err, "app2_command1")
     1216
     1217    def test_nons_app(self):
     1218        args = ['nons_app_command1']
     1219        out, err = self.run_manage(args)
     1220        self.assertNoOutput(err)
     1221        self.assertOutput(out, "EXECUTE:nons_app_command1")
     1222
     1223    def test_nsapps(self):
     1224        args = ['app1_command1']
     1225        out, err = self.run_manage(args)
     1226        self.assertNoOutput(err)
     1227        self.assertOutput(out, "EXECUTE:app1_command1")
     1228
     1229        args = ['app2_command1']
     1230        out, err = self.run_manage(args)
     1231        self.assertNoOutput(err)
     1232        self.assertOutput(out, "EXECUTE:app2_command1")
     1233
Back to Top