Commit ec7d8b7c authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #5943 -- Modified django-admin to behave like manage.py if settings are...

Fixed #5943 -- Modified django-admin to behave like manage.py if settings are provided, either as --settings or DJANGO_SETTINGS_MODULE. Thanks to Joseph Kocherhans and Todd O'Bryan for their work on this ticket.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8282 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 7610983b
Loading
Loading
Loading
Loading
+27 −31
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ def load_command_class(app_name, name):
    return getattr(__import__('%s.management.commands.%s' % (app_name, name),
                   {}, {}, ['Command']), 'Command')()

def get_commands(load_user_commands=True, project_directory=None):
def get_commands():
    """
    Returns a dictionary mapping command names to their callback applications.

@@ -77,7 +77,7 @@ def get_commands(load_user_commands=True, project_directory=None):
    Core commands are always included. If a settings module has been
    specified, user-defined commands will also be included, the
    startproject command will be disabled, and the startapp command
    will be modified to use the directory in which that module appears.
    will be modified to use the directory in which the settings module appears.

    The dictionary is in the format {command_name: app_name}. Key-value
    pairs from this dictionary can then be used in calls to
@@ -94,15 +94,28 @@ def get_commands(load_user_commands=True, project_directory=None):
    if _commands is None:
        _commands = dict([(name, 'django.core') for name in find_commands(__path__[0])])

        if load_user_commands:
            # Get commands from all installed apps.
        # Find the installed apps
        try:
            from django.conf import settings
            for app_name in settings.INSTALLED_APPS:
            apps = settings.INSTALLED_APPS
        except (AttributeError, EnvironmentError, ImportError):
            apps = []

        # Find the project directory
        try:
            from django.conf import settings
            project_directory = setup_environ(__import__(settings.SETTINGS_MODULE))
        except (AttributeError, EnvironmentError, ImportError):
            project_directory = None

        # Find and load the management module for each installed app.
        for app_name in apps:
            try:
                path = find_management_module(app_name)
                    _commands.update(dict([(name, app_name) for name in find_commands(path)]))
                _commands.update(dict([(name, app_name)
                                       for name in find_commands(path)]))
            except ImportError:
                    pass # No management module -- ignore this app.
                pass # No management module - ignore this app

        if project_directory:
            # Remove the "startproject" command from self.commands, because
@@ -203,8 +216,6 @@ class ManagementUtility(object):
    def __init__(self, argv=None):
        self.argv = argv or sys.argv[:]
        self.prog_name = os.path.basename(self.argv[0])
        self.project_directory = None
        self.user_commands = False

    def main_help_text(self):
        """
@@ -212,7 +223,7 @@ class ManagementUtility(object):
        """
        usage = ['',"Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name,'']
        usage.append('Available subcommands:')
        commands = get_commands(self.user_commands, self.project_directory).keys()
        commands = get_commands().keys()
        commands.sort()
        for cmd in commands:
            usage.append('  %s' % cmd)
@@ -225,7 +236,7 @@ class ManagementUtility(object):
        "django-admin.py" or "manage.py") if it can't be found.
        """
        try:
            app_name = get_commands(self.user_commands, self.project_directory)[subcommand]
            app_name = get_commands()[subcommand]
            if isinstance(app_name, BaseCommand):
                # If the command is already loaded, use it directly.
                klass = app_name
@@ -278,20 +289,6 @@ class ManagementUtility(object):
        else:
            self.fetch_command(subcommand).run_from_argv(self.argv)

class ProjectManagementUtility(ManagementUtility):
    """
    A ManagementUtility that is specific to a particular Django project.
    As such, its commands are slightly different than those of its parent
    class.

    In practice, this class represents manage.py, whereas ManagementUtility
    represents django-admin.py.
    """
    def __init__(self, argv, project_directory):
        super(ProjectManagementUtility, self).__init__(argv)
        self.project_directory = project_directory
        self.user_commands = True

def setup_environ(settings_mod):
    """
    Configures the runtime environment. This can also be used by external
@@ -313,7 +310,6 @@ def setup_environ(settings_mod):

    # Set DJANGO_SETTINGS_MODULE appropriately.
    os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
    return project_directory

def execute_from_command_line(argv=None):
    """
@@ -327,6 +323,6 @@ def execute_manager(settings_mod, argv=None):
    Like execute_from_command_line(), but for use by manage.py, a
    project-specific django-admin.py utility.
    """
    project_directory = setup_environ(settings_mod)
    utility = ProjectManagementUtility(argv, project_directory)
    setup_environ(settings_mod)
    utility = ManagementUtility(argv)
    utility.execute()
+8 −3
Original line number Diff line number Diff line
@@ -82,9 +82,14 @@ class BaseCommand(object):
        # But only do this if we can assume we have a working settings file,
        # because django.utils.translation requires settings.
        if self.can_import_settings:
            try:
                from django.utils import translation
                translation.activate('en-us')

            except ImportError, e:
                # If settings should be available, but aren't, 
                # raise the error and quit.
                sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
                sys.exit(1)
        try:
            if self.requires_model_validation:
                self.validate()
+35 −35
Original line number Diff line number Diff line
@@ -223,25 +223,25 @@ class DjangoAdminDefaultSettings(AdminScriptTestCase):
        self.assertOutput(err, "Could not import settings 'bad_settings'")

    def test_custom_command(self):
        "default: django-admin can't execute user commands"
        "default: django-admin can't execute user commands if it isn't provided settings"
        args = ['noargs_command']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")

    def test_custom_command_with_settings(self):
        "default: django-admin can't execute user commands, even if settings are provided as argument"
        "default: django-admin can execute user commands if settings are provided as argument"
        args = ['noargs_command', '--settings=settings']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

    def test_custom_command_with_environment(self):
        "default: django-admin can't execute user commands, even if settings are provided in environment"
        "default: django-admin can execute user commands if settings are provided in environment"
        args = ['noargs_command']
        out, err = self.run_django_admin(args,'settings')
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
    """A series of tests for django-admin.py when using a settings.py file that
@@ -261,18 +261,18 @@ class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
        self.assertOutput(err, 'environment variable DJANGO_SETTINGS_MODULE is undefined')

    def test_builtin_with_settings(self):
        "fulldefault: django-admin builtin commands fail if user app isn't on path"
        "fulldefault: django-admin builtin commands succeed if a settings file is provided"
        args = ['sqlall','--settings=settings', 'admin_scripts']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, 'ImportError: No module named regressiontests')
        self.assertNoOutput(err)
        self.assertOutput(out, 'CREATE TABLE')

    def test_builtin_with_environment(self):
        "fulldefault: django-admin builtin commands fail if user app isn't on path"
        "fulldefault: django-admin builtin commands succeed if the environment contains settings"
        args = ['sqlall','admin_scripts']
        out, err = self.run_django_admin(args,'settings')
        self.assertNoOutput(out)
        self.assertOutput(err, 'ImportError: No module named regressiontests')
        self.assertNoOutput(err)
        self.assertOutput(out, 'CREATE TABLE')

    def test_builtin_with_bad_settings(self):
        "fulldefault: django-admin builtin commands fail if settings file (from argument) doesn't exist"
@@ -289,25 +289,25 @@ class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase):
        self.assertOutput(err, "Could not import settings 'bad_settings'")

    def test_custom_command(self):
        "fulldefault: django-admin can't execute user commands"
        "fulldefault: django-admin can't execute user commands unless settings are provided"
        args = ['noargs_command']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")

    def test_custom_command_with_settings(self):
        "fulldefault: django-admin can't execute user commands, even if settings are provided as argument"
        "fulldefault: django-admin can execute user commands if settings are provided as argument"
        args = ['noargs_command', '--settings=settings']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

    def test_custom_command_with_environment(self):
        "fulldefault: django-admin can't execute user commands, even if settings are provided in environment"
        "fulldefault: django-admin can execute user commands if settings are provided in environment"
        args = ['noargs_command']
        out, err = self.run_django_admin(args,'settings')
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

class DjangoAdminMinimalSettings(AdminScriptTestCase):
    """A series of tests for django-admin.py when using a settings.py file that
@@ -355,7 +355,7 @@ class DjangoAdminMinimalSettings(AdminScriptTestCase):
        self.assertOutput(err, "Could not import settings 'bad_settings'")

    def test_custom_command(self):
        "minimal: django-admin can't execute user commands"
        "minimal: django-admin can't execute user commands unless settings are provided"
        args = ['noargs_command']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
@@ -421,25 +421,25 @@ class DjangoAdminAlternateSettings(AdminScriptTestCase):
        self.assertOutput(err, "Could not import settings 'bad_settings'")

    def test_custom_command(self): 
        "alternate: django-admin can't execute user commands"
        "alternate: django-admin can't execute user commands unless settings are provided"
        args = ['noargs_command']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")

    def test_custom_command_with_settings(self):
        "alternate: django-admin can't execute user commands, even if settings are provided as argument"
        "alternate: django-admin can execute user commands if settings are provided as argument"
        args = ['noargs_command', '--settings=alternate_settings']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

    def test_custom_command_with_environment(self):
        "alternate: django-admin can't execute user commands, even if settings are provided in environment"
        "alternate: django-admin can execute user commands if settings are provided in environment"
        args = ['noargs_command']
        out, err = self.run_django_admin(args,'alternate_settings')
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")


class DjangoAdminMultipleSettings(AdminScriptTestCase):
@@ -491,7 +491,7 @@ class DjangoAdminMultipleSettings(AdminScriptTestCase):
        self.assertOutput(err, "Could not import settings 'bad_settings'")

    def test_custom_command(self): 
        "alternate: django-admin can't execute user commands"
        "alternate: django-admin can't execute user commands unless settings are provided"
        args = ['noargs_command']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
@@ -501,15 +501,15 @@ class DjangoAdminMultipleSettings(AdminScriptTestCase):
        "alternate: django-admin can't execute user commands, even if settings are provided as argument"
        args = ['noargs_command', '--settings=alternate_settings']
        out, err = self.run_django_admin(args)
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

    def test_custom_command_with_environment(self):
        "alternate: django-admin can't execute user commands, even if settings are provided in environment"
        args = ['noargs_command']
        out, err = self.run_django_admin(args,'alternate_settings')
        self.assertNoOutput(out)
        self.assertOutput(err, "Unknown command: 'noargs_command'")
        self.assertNoOutput(err)
        self.assertOutput(out, "EXECUTE:NoArgsCommand")

##########################################################################
# MANAGE.PY TESTS