Ticket #5516: user_commands.patch
File user_commands.patch, 8.1 KB (added by , 17 years ago) |
---|
-
django/core/management/base.py
Property changes on: . ___________________________________________________________________ Name: svn:ignore - build dist *.egg-info MANIFEST + build dist *.egg-info MANIFEST .settings .project .pydevproject
9 9 class CommandError(Exception): 10 10 pass 11 11 12 def handle_default_options(options): 13 """ 14 Include any default options that all commands should accept 15 here so that ManagementUtility can handle them before searching 16 for user commands. 17 """ 18 if options.settings: 19 os.environ['DJANGO_SETTINGS_MODULE'] = options.settings 20 if options.pythonpath: 21 sys.path.insert(0, options.pythonpath) 22 12 23 class BaseCommand(object): 13 24 # Metadata about this command. 14 25 option_list = ( … … 51 62 def print_help(self, prog_name, subcommand): 52 63 parser = self.create_parser(prog_name, subcommand) 53 64 parser.print_help() 54 65 55 66 def run_from_argv(self, argv): 56 67 parser = self.create_parser(argv[0], argv[1]) 57 68 options, args = parser.parse_args(argv[2:]) 58 if options.settings: 59 os.environ['DJANGO_SETTINGS_MODULE'] = options.settings 60 if options.pythonpath: 61 sys.path.insert(0, options.pythonpath) 69 handle_default_options(options) 62 70 self.execute(*args, **options.__dict__) 63 71 64 72 def execute(self, *args, **options): -
django/core/management/__init__.py
28 28 klass = load_command_class(name) 29 29 return klass.execute(*args, **options) 30 30 31 def find_commands(command_dir): 32 return [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] 33 34 class LaxOptionParser(OptionParser): 35 def error(self, msg): 36 pass 37 31 38 class ManagementUtility(object): 32 39 """ 33 40 Encapsulates the logic of the django-admin.py and manage.py utilities. … … 39 46 self.argv = argv or sys.argv[:] 40 47 self.prog_name = os.path.basename(self.argv[0]) 41 48 self.commands = self.default_commands() 42 49 43 50 def default_commands(self): 44 51 """ 45 52 Returns a dictionary of instances of all available Command classes. … … 50 57 The dictionary is in the format {name: command_instance}. 51 58 """ 52 59 command_dir = os.path.join(__path__[0], 'commands') 53 names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]60 names = find_commands(command_dir) 54 61 return dict([(name, load_command_class(name)) for name in names]) 55 62 56 63 def main_help_text(self): … … 65 72 commands.sort() 66 73 for cmd in commands: 67 74 usage.append(' %s' % cmd) 75 usage += self.user_commands_usage() 68 76 return '\n'.join(usage) 77 78 79 def user_commands_usage(self): 80 """ 81 Returns a list of lines that list each app and the commands it provides. 82 """ 83 usage = [] 84 try: 85 apps = django.conf.settings.INSTALLED_APPS 86 except (KeyError, EnvironmentError): 87 apps = () 88 for app in apps: 89 mod = __import__(app) 90 components = app.split('.') 91 for comp in components[1:]: 92 mod = getattr(mod, comp) 93 command_dir = os.path.join(os.path.split(os.path.abspath(mod.__file__))[0], 94 'management', 'commands') 95 if os.path.exists(command_dir): 96 commands = find_commands(command_dir) 97 if commands: 98 commands = ['%s.%s' % (app, cmd) for cmd in commands] 99 commands.sort() 100 usage.append('') 101 usage.append('From app %s:' % app) 102 for cmd in commands: 103 usage.append(' %s' % cmd) 104 return usage 105 69 106 107 def fetch_user_command(self, subcommand): 108 """ 109 Attempts to fetch a user defined command. Commands are written in the 110 form path.to.app.command, so that the last word should correspond to a 111 module in the path.to.app.management.commands module and should 112 contain a Command class that is a subclass of BaseCommand. 113 """ 114 subcommand = subcommand.split('.') 115 app_path = '.'.join(subcommand[:-1]) 116 from django.conf import settings 117 command_name = subcommand[-1] 118 return getattr(__import__('%s.management.commands.%s' % (app_path, command_name), {}, {}, ['Command']), 'Command')() 119 70 120 def fetch_command(self, subcommand): 71 121 """ 72 122 Tries to fetch the given subcommand, printing a message with the … … 76 126 try: 77 127 return self.commands[subcommand] 78 128 except KeyError: 79 sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name))80 sys.exit(1)129 # subcommand not provided by django, may be provided by an app 130 return self.fetch_user_command(subcommand) 81 131 82 132 def execute(self): 83 133 """ 84 134 Given the command-line arguments, this figures out which subcommand is 85 135 being run, creates a parser appropriate to that command, and runs it. 86 136 """ 137 from django.core.management.base import BaseCommand, handle_default_options 138 parser = LaxOptionParser(version=get_version(), 139 option_list=BaseCommand.option_list) 140 options, args = parser.parse_args(self.argv) 141 handle_default_options(options) 87 142 try: 88 subcommand = self.argv[1]143 subcommand = args[1] 89 144 except IndexError: 90 145 sys.stderr.write("Type '%s help' for usage.\n" % self.prog_name) 91 146 sys.exit(1) 92 147 93 148 if subcommand == 'help': 94 if len(self.argv) > 2: 95 self.fetch_command(self.argv[2]).print_help(self.prog_name, self.argv[2]) 149 if len(args) > 2: 150 try: 151 self.fetch_command(args[2]).print_help(self.prog_name, self.argv[2]) 152 except (ValueError, ImportError): 153 sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (args[2], self.prog_name)) 154 sys.exit(1) 96 155 else: 97 156 sys.stderr.write(self.main_help_text() + '\n') 98 157 sys.exit(1) -
docs/django-admin.txt
735 735 * Press [TAB] to see all available options. 736 736 * Type ``sql``, then [TAB], to see all available options whose names start 737 737 with ``sql``. 738 739 Customized actions 740 ================== 741 742 **New in Django development version** 743 744 If you want to add an action of your own to ``manage.py``, you can. 745 Simply add a ``management/commands`` directory to your application. 746 Each python module in that directory will be discovered and registered as 747 a command of the form ``app_path.command`` that can be executed as an action 748 when you run ``manage.py``:: 749 750 /fancy_blog 751 __init__.py 752 models.py 753 /management 754 __init__.py 755 /commands 756 __init__.py 757 explode.py 758 views.py 759 760 In this example, the ``fancy_blog.explode`` command will be made available to 761 any project that includes the ``fancy_blog`` application in 762 ``settings.INSTALLED_APPS``. 763 764 The ``explode.py`` module has only one requirement -- it must define a class 765 called ``Command`` that extends ``django.core.management.base.BaseCommand``. 766 767 For more details on how to define your own commands, look at the code for the 768 existing ``django-admin.py`` commands, in ``/django/core/management/commands``.