web/lib/django/core/management/__init__.py
author ymh <ymh.work@gmail.com>
Thu, 05 Aug 2010 17:28:09 +0200
changeset 50 012451a812f1
parent 38 77b6da96e6f1
permissions -rw-r--r--
Merge with a2711e44ba5de8b1675d7e0ee6aaa4a6c56a9b46
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import os
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import sys
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
from optparse import OptionParser, NO_DEFAULT
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
import imp
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
import django
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
from django.core.management.base import BaseCommand, CommandError, handle_default_options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
from django.utils.importlib import import_module
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
# For backwards compatibility: get_version() used to be in this module.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
get_version = django.get_version
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
# A cache of loaded commands, so that call_command
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
# doesn't have to reload every time it's called.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
_commands = None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
def find_commands(management_dir):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
    Given a path to a management directory, returns a list of all the command
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    names that are available.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
    Returns an empty list if no commands are defined.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    command_dir = os.path.join(management_dir, 'commands')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        return [f[:-3] for f in os.listdir(command_dir)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
                if not f.startswith('_') and f.endswith('.py')]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
    except OSError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        return []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
def find_management_module(app_name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
    Determines the path to the management module for the given app_name,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
    without actually importing the application or the management module.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    Raises ImportError if the management module cannot be found for any reason.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    parts = app_name.split('.')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    parts.append('management')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    parts.reverse()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    part = parts.pop()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    path = None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    # When using manage.py, the project module is added to the path,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    # loaded, then removed from the path. This means that
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    # testproject.testapp.models can be loaded in future, even if
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    # testproject isn't in the path. When looking for the management
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
    # module, we need look for the case where the project name is part
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
    # of the app_name but the project directory itself isn't on the path.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        f, path, descr = imp.find_module(part,path)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
    except ImportError,e:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
        if os.path.basename(os.getcwd()) != part:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
            raise e
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
    while parts:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        part = parts.pop()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        f, path, descr = imp.find_module(part, path and [path] or None)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
    return path
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
def load_command_class(app_name, name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    Given a command name and an application name, returns the Command
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    class instance. All errors raised by the import process
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    (ImportError, AttributeError) are allowed to propagate.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
    module = import_module('%s.management.commands.%s' % (app_name, name))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
    return module.Command()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
def get_commands():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
    Returns a dictionary mapping command names to their callback applications.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
    This works by looking for a management.commands package in django.core, and
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    in each installed application -- if a commands package exists, all commands
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
    in that package are registered.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
    Core commands are always included. If a settings module has been
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
    specified, user-defined commands will also be included, the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
    startproject command will be disabled, and the startapp command
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    will be modified to use the directory in which the settings module appears.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
    The dictionary is in the format {command_name: app_name}. Key-value
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
    pairs from this dictionary can then be used in calls to
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
    load_command_class(app_name, command_name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    If a specific version of a command must be loaded (e.g., with the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
    startapp command), the instantiated module can be placed in the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
    dictionary in place of the application name.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
    The dictionary is cached on the first call and reused on subsequent
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
    calls.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    global _commands
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
    if _commands is None:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        _commands = dict([(name, 'django.core') for name in find_commands(__path__[0])])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
        # Find the installed apps
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
            from django.conf import settings
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            apps = settings.INSTALLED_APPS
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        except (AttributeError, EnvironmentError, ImportError):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
            apps = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        # Find the project directory
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
            from django.conf import settings
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
            module = import_module(settings.SETTINGS_MODULE)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
            project_directory = setup_environ(module, settings.SETTINGS_MODULE)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
        except (AttributeError, EnvironmentError, ImportError, KeyError):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
            project_directory = None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        # Find and load the management module for each installed app.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
        for app_name in apps:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
            try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
                path = find_management_module(app_name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
                _commands.update(dict([(name, app_name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
                                       for name in find_commands(path)]))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
            except ImportError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
                pass # No management module - ignore this app
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
        if project_directory:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
            # Remove the "startproject" command from self.commands, because
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
            # that's a django-admin.py command, not a manage.py command.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
            del _commands['startproject']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
            # Override the startapp command so that it always uses the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
            # project_directory, not the current working directory
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
            # (which is default).
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
            from django.core.management.commands.startapp import ProjectCommand
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
            _commands['startapp'] = ProjectCommand(project_directory)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
    return _commands
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
def call_command(name, *args, **options):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
    Calls the given command, with the given options and args/kwargs.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
    This is the primary API you should use for calling specific commands.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
    Some examples:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
        call_command('syncdb')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        call_command('shell', plain=True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        call_command('sqlall', 'myapp')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
    # Load the command object.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
    try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
        app_name = get_commands()[name]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
        if isinstance(app_name, BaseCommand):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
            # If the command is already loaded, use it directly.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
            klass = app_name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
            klass = load_command_class(app_name, name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
    except KeyError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
        raise CommandError("Unknown command: %r" % name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
    # Grab out a list of defaults from the options. optparse does this for us
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
    # when the script runs from the command line, but since call_command can
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
    # be called programatically, we need to simulate the loading and handling
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
    # of defaults (see #10080 for details).
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
    defaults = dict([(o.dest, o.default)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
                     for o in klass.option_list
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
                     if o.default is not NO_DEFAULT])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
    defaults.update(options)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
    return klass.execute(*args, **defaults)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
class LaxOptionParser(OptionParser):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
    An option parser that doesn't raise any errors on unknown options.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
    This is needed because the --settings and --pythonpath options affect
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
    the commands (and thus the options) that are available to the user.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
    def error(self, msg):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
        pass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
    def print_help(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
        """Output nothing.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
        The lax options are included in the normal option parser, so under
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
        normal usage, we don't need to print the lax options.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
        pass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
    def print_lax_help(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
        """Output the basic options available to every command.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
        This just redirects to the default print_help() behaviour.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
        OptionParser.print_help(self)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
    def _process_args(self, largs, rargs, values):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
        Overrides OptionParser._process_args to exclusively handle default
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
        options and ignore args and other options.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
        This overrides the behavior of the super class, which stop parsing
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
        at the first unrecognized option.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
        while rargs:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
            arg = rargs[0]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
            try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
                if arg[0:2] == "--" and len(arg) > 2:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
                    # process a single long option (possibly with value(s))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
                    # the superclass code pops the arg off rargs
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
                    self._process_long_opt(rargs, values)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
                elif arg[:1] == "-" and len(arg) > 1:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
                    # process a cluster of short options (possibly with
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
                    # value(s) for the last one only)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
                    # the superclass code pops the arg off rargs
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
                    self._process_short_opts(rargs, values)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
                else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
                    # it's either a non-default option or an arg
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
                    # either way, add it to the args list so we can keep
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
                    # dealing with options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
                    del rargs[0]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
                    raise Exception
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
            except:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
                largs.append(arg)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
class ManagementUtility(object):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
    Encapsulates the logic of the django-admin.py and manage.py utilities.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
    A ManagementUtility has a number of commands, which can be manipulated
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
    by editing the self.commands dictionary.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
    def __init__(self, argv=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
        self.argv = argv or sys.argv[:]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
        self.prog_name = os.path.basename(self.argv[0])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
    def main_help_text(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
        Returns the script's main help text, as a string.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
        usage = ['',"Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name,'']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
        usage.append('Available subcommands:')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
        commands = get_commands().keys()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
        commands.sort()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
        for cmd in commands:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
            usage.append('  %s' % cmd)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
        return '\n'.join(usage)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
    def fetch_command(self, subcommand):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
        Tries to fetch the given subcommand, printing a message with the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
        appropriate command called from the command line (usually
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
        "django-admin.py" or "manage.py") if it can't be found.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
            app_name = get_commands()[subcommand]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
            if isinstance(app_name, BaseCommand):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
                # If the command is already loaded, use it directly.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
                klass = app_name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
            else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
                klass = load_command_class(app_name, subcommand)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
        except KeyError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
            sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % \
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
                (subcommand, self.prog_name))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
            sys.exit(1)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
        return klass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
    def autocomplete(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
        Output completion suggestions for BASH.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
        The output of this function is passed to BASH's `COMREPLY` variable and
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
        treated as completion suggestions. `COMREPLY` expects a space
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
        separated string as the result.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
        The `COMP_WORDS` and `COMP_CWORD` BASH environment variables are used
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
        to get information about the cli input. Please refer to the BASH
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
        man-page for more information about this variables.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
        Subcommand options are saved as pairs. A pair consists of
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
        the long option string (e.g. '--exclude') and a boolean
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
        value indicating if the option requires arguments. When printing to
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
        stdout, a equal sign is appended to options which require arguments.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
        Note: If debugging this function, it is recommended to write the debug
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
        output in a separate file. Otherwise the debug output will be treated
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
        and formatted as potential completion suggestions.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
        # Don't complete if user hasn't sourced bash_completion file.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
        if not os.environ.has_key('DJANGO_AUTO_COMPLETE'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
            return
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
        cwords = os.environ['COMP_WORDS'].split()[1:]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
        cword = int(os.environ['COMP_CWORD'])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
            curr = cwords[cword-1]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
        except IndexError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
            curr = ''
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
        subcommands = get_commands().keys() + ['help']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
        options = [('--help', None)]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
        # subcommand
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
        if cword == 1:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
            print ' '.join(sorted(filter(lambda x: x.startswith(curr), subcommands)))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
        # subcommand options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
        # special case: the 'help' subcommand has no options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
        elif cwords[0] in subcommands and cwords[0] != 'help':
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
            subcommand_cls = self.fetch_command(cwords[0])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
            # special case: 'runfcgi' stores additional options as
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
            # 'key=value' pairs
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
            if cwords[0] == 'runfcgi':
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
                from django.core.servers.fastcgi import FASTCGI_OPTIONS
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
                options += [(k, 1) for k in FASTCGI_OPTIONS]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
            # special case: add the names of installed apps to options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
            elif cwords[0] in ('dumpdata', 'reset', 'sql', 'sqlall',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
                               'sqlclear', 'sqlcustom', 'sqlindexes',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
                               'sqlreset', 'sqlsequencereset', 'test'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
                try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
                    from django.conf import settings
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
                    # Get the last part of the dotted path as the app name.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
                    options += [(a.split('.')[-1], 0) for a in settings.INSTALLED_APPS]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
                except ImportError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
                    # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
                    # user will find out once they execute the command.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
                    pass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
            options += [(s_opt.get_opt_string(), s_opt.nargs) for s_opt in
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
                        subcommand_cls.option_list]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
            # filter out previously specified options from available options
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
            prev_opts = [x.split('=')[0] for x in cwords[1:cword-1]]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
            options = filter(lambda (x, v): x not in prev_opts, options)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
            # filter options by current input
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
            options = sorted([(k, v) for k, v in options if k.startswith(curr)])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
            for option in options:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
                opt_label = option[0]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
                # append '=' to options which require args
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
                if option[1]:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
                    opt_label += '='
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
                print opt_label
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
        sys.exit(1)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
    def execute(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
        Given the command-line arguments, this figures out which subcommand is
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
        being run, creates a parser appropriate to that command, and runs it.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
        # Preprocess options to extract --settings and --pythonpath.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
        # These options could affect the commands that are available, so they
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
        # must be processed early.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
        parser = LaxOptionParser(usage="%prog subcommand [options] [args]",
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
                                 version=get_version(),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
                                 option_list=BaseCommand.option_list)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
        self.autocomplete()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
            options, args = parser.parse_args(self.argv)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
            handle_default_options(options)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
        except:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
            pass # Ignore any option errors at this point.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
            subcommand = self.argv[1]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
        except IndexError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
            subcommand = 'help' # Display help if no arguments were given.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
        if subcommand == 'help':
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
            if len(args) > 2:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
                self.fetch_command(args[2]).print_help(self.prog_name, args[2])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
            else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
                parser.print_lax_help()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
                sys.stderr.write(self.main_help_text() + '\n')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
                sys.exit(1)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
        # Special-cases: We want 'django-admin.py --version' and
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
        # 'django-admin.py --help' to work, for backwards compatibility.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
        elif self.argv[1:] == ['--version']:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
            # LaxOptionParser already takes care of printing the version.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
            pass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
        elif self.argv[1:] == ['--help']:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
            parser.print_lax_help()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
            sys.stderr.write(self.main_help_text() + '\n')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
            self.fetch_command(subcommand).run_from_argv(self.argv)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
def setup_environ(settings_mod, original_settings_path=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
    Configures the runtime environment. This can also be used by external
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
    scripts wanting to set up a similar environment to manage.py.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
    Returns the project directory (assuming the passed settings module is
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
    directly in the project directory).
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
    The "original_settings_path" parameter is optional, but recommended, since
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
    trying to work out the original path from the module can be problematic.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
    # Add this project to sys.path so that it's importable in the conventional
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
    # way. For example, if this file (manage.py) lives in a directory
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
    # "myproject", this code would add "/path/to/myproject" to sys.path.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
    if '__init__.py' in settings_mod.__file__:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
        p = os.path.dirname(settings_mod.__file__)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
        p = settings_mod.__file__
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
    project_directory, settings_filename = os.path.split(p)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
    if project_directory == os.curdir or not project_directory:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
        project_directory = os.getcwd()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
    project_name = os.path.basename(project_directory)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
    # Strip filename suffix to get the module name.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
    settings_name = os.path.splitext(settings_filename)[0]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
    # Strip $py for Jython compiled files (like settings$py.class)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
    if settings_name.endswith("$py"):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
        settings_name = settings_name[:-3]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
    # Set DJANGO_SETTINGS_MODULE appropriately.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
    if original_settings_path:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
        os.environ['DJANGO_SETTINGS_MODULE'] = original_settings_path
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
        os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
    # Import the project module. We add the parent directory to PYTHONPATH to
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
    # avoid some of the path errors new users can have.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
    sys.path.append(os.path.join(project_directory, os.pardir))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
    project_module = import_module(project_name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
    sys.path.pop()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
    return project_directory
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
def execute_from_command_line(argv=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
    A simple method that runs a ManagementUtility.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
    utility = ManagementUtility(argv)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
    utility.execute()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
def execute_manager(settings_mod, argv=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
    Like execute_from_command_line(), but for use by manage.py, a
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
    project-specific django-admin.py utility.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
    setup_environ(settings_mod)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
    utility = ManagementUtility(argv)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
    utility.execute()