
Property changes on: /home/tobryan1/workspace/django
___________________________________________________________________
Name: svn:ignore
   - build
dist
*.egg-info
MANIFEST

   + build
dist
*.egg-info
MANIFEST
.settings
.project
.pydevproject


Index: /home/tobryan1/workspace/django/django/core/management/__init__.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/__init__.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/__init__.py	(working copy)
@@ -52,76 +52,50 @@
         names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
         return dict([(name, load_command_class(name)) for name in names])
 
-    def usage(self):
-        """
-        Returns a usage string, for use with optparse.
-
-        The string doesn't include the options (e.g., "--verbose"), because
-        optparse puts those in automatically.
-        """
-        usage = ["%prog command [options]\nactions:"]
+    def print_help(self, argv):
+        prog_name = os.path.basename(argv[0])
+        usage = ['%s <subcommand> [options] [args]' % prog_name]
+        usage.append('Django command line tool, version %s' % django.get_version())
+        usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % prog_name)
+        usage.append('Available subcommands:')
         commands = self.commands.items()
         commands.sort()
         for name, cmd in commands:
-            usage.append('  %s %s' % (name, cmd.args))
-            usage.extend(textwrap.wrap(cmd.help, initial_indent='    ', subsequent_indent='    '))
-            usage.append('')
-        return '\n'.join(usage[:-1]) # Cut off the last list element, an empty space.
+            usage.append('  %s' % name)
+        print '\n'.join(usage)
+        
+    def fetch_command(self, subcommand, command_name):
+        """
+        Tries to fetch the given subcommand, printing a message with the
+        appropriate command called from the command line (usually
+        django-admin.py or manage.py) if it can't be found
+        """
+        try:
+            return self.commands[subcommand]
+        except KeyError:
+            sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, command_name))
+            sys.exit(1)
 
     def execute(self, argv=None):
         """
-        Parses the given argv from the command line, determines which command
-        to run and runs the command.
+        Figures out which command is being run (the first arg), creates a parser
+        appropriate to that command, and runs it
         """
         if argv is None:
             argv = sys.argv
-
-        # Create the parser object and parse the command-line args.
-        # TODO: Ideally each Command class would register its own options for
-        # add_option(), but we'd need to figure out how to allow for multiple
-        # Commands using the same options. The optparse library gets in the way
-        # by checking for conflicts:
-        # http://docs.python.org/lib/optparse-conflicts-between-options.html
-        parser = OptionParser(usage=self.usage(), version=get_version())
-        parser.add_option('--settings',
-            help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
-        parser.add_option('--pythonpath',
-            help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".')
-        parser.add_option('--plain', action='store_true', dest='plain',
-            help='When using "shell": Tells Django to use plain Python, not IPython.')
-        parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
-            help='Tells Django to NOT prompt the user for input of any kind.')
-        parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
-            help='When using "runserver": Tells Django to NOT use the auto-reloader.')
-        parser.add_option('--format', default='json', dest='format',
-            help='Specifies the output serialization format for fixtures')
-        parser.add_option('--indent', default=None, dest='indent',
-            type='int', help='Specifies the indent level to use when pretty-printing output')
-        parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
-            type='choice', choices=['0', '1', '2'],
-            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
-        parser.add_option('--adminmedia', dest='admin_media_path', default='',
-            help='When using "runserver": Specifies the directory from which to serve admin media.')
-        options, args = parser.parse_args(argv[1:])
-
-        # If the 'settings' or 'pythonpath' options were submitted, activate those.
-        if options.settings:
-            os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
-        if options.pythonpath:
-            sys.path.insert(0, options.pythonpath)
-
-        # Run the appropriate command.
         try:
-            command_name = args[0]
+            command_name = argv[1]
         except IndexError:
-            sys.stderr.write("Type '%s --help' for usage.\n" % os.path.basename(argv[0]))
+            sys.stderr.write("Type '%s help' for usage.\n" % os.path.basename(argv[0]))
             sys.exit(1)
-        try:
-            command = self.commands[command_name]
-        except KeyError:
-            sys.stderr.write("Unknown command: %r\nType '%s --help' for usage.\n" % (command_name, os.path.basename(argv[0])))
-            sys.exit(1)
-        command.execute(*args[1:], **options.__dict__)
+        if command_name == 'help':
+            if len(argv) > 2:
+                self.fetch_command(argv[2], argv[0]).print_help(argv[2:])
+            else:
+                self.print_help(argv)
+        else:
+            self.fetch_command(command_name, argv[0]).run(argv[1:])
+        
 
 class ProjectManagementUtility(ManagementUtility):
     """
Index: /home/tobryan1/workspace/django/django/core/management/base.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/base.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/base.py	(working copy)
@@ -1,7 +1,12 @@
+import django
 from django.core.exceptions import ImproperlyConfigured
 from django.core.management.color import color_style
+
+import itertools
+from optparse import make_option, OptionParser
 import sys
 import os
+from traceback import print_exc
 
 class CommandError(Exception):
     pass
@@ -8,6 +13,12 @@
 
 class BaseCommand(object):
     # Metadata about this command.
+    option_list = (
+        make_option('--settings', 
+                    help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.'),
+        make_option('--pythonpath',
+                    help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
+    )
     help = ''
     args = ''
 
@@ -18,6 +29,69 @@
 
     def __init__(self):
         self.style = color_style()
+    
+    def get_version(self):
+        """
+        returns the Django version, which should be correct for all built-in
+        Django commands. User-supplied commands should override this method.
+        """
+        return django.get_version()
+    
+    def usage(self):
+        usage = '%prog [options] ' + self.args
+        if self.help:
+            return '%s\n%s' % (self.help, usage)
+        else:
+            return usage
+    
+    @classmethod
+    def get_option_list(cls):
+        """
+        Builds up a list of parameters to the OptionParser.add_option command
+        by recursively adding option parameters up the class hierarchy. Requires
+        BaseCommand subclasses to only extend a single superclass.
+        """
+        if cls is BaseCommand:
+            option_list = BaseCommand.option_list
+        else:
+            option_list = cls.__base__.get_option_list()
+        if cls.option_list is option_list:
+            return option_list
+        else:
+            # this class adds new option_params not in superclasses
+            # get a list of all options so far
+            opt_strs = list(itertools.chain(*[op._short_opts + op._long_opts for op in option_list]))
+            # check for duplicates
+            for option in cls.option_list:
+                strs = option._short_opts + option._long_opts
+                for opt_str in strs:
+                    if opt_str in opt_strs:
+                        raise CommandError("%s attempts to redefine the option '%s', which appears in a superclass." %
+                                       (cls, opt_str))
+            return option_list + cls.option_list           
+        
+    def create_parser(self, prog_name):
+        return OptionParser(prog=prog_name,
+                            usage=self.usage(), 
+                            version=self.get_version(),
+                            option_list=self.__class__.get_option_list())
+        
+    def print_help(self, args):
+        parser = self.create_parser(args[0])
+        parser.print_help()
+            
+    def run(self, args):
+        parser = self.create_parser(args[0])
+        (options, args) = parser.parse_args(args[1:])
+        if options.settings:
+            os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
+        if options.pythonpath:
+            sys.path.insert(0, options.pythonpath)
+        try:
+            self.execute(*args, **options.__dict__)
+        except Exception, e:
+            print_exc()
+            parser.print_usage()
 
     def execute(self, *args, **options):
         # Switch to English, because django-admin.py creates database content
@@ -119,7 +193,7 @@
 
     def handle_noargs(self, **options):
         raise NotImplementedError()
-
+    
 def copy_helper(style, app_or_project, name, directory, other_name=''):
     import django
     import re
Index: /home/tobryan1/workspace/django/django/core/management/commands/dumpdata.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/dumpdata.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/dumpdata.py	(working copy)
@@ -1,8 +1,16 @@
 from django.core.management.base import BaseCommand, CommandError
 
+from optparse import make_option
+
 class Command(BaseCommand):
+    option_list = (
+        make_option('--format', default='json', dest='format',
+            help='Specifies the output serialization format for fixtures'),
+        make_option('--indent', default=None, dest='indent', type='int',
+            help='Specifies the indent level to use when pretty-printing output'),
+    )
     help = 'Output the contents of the database as a fixture of the given format.'
-    args = '[--format] [--indent] [appname ...]'
+    args = '[appname ...]'
 
     def handle(self, *app_labels, **options):
         from django.db.models import get_app, get_apps, get_models
Index: /home/tobryan1/workspace/django/django/core/management/commands/flush.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/flush.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/flush.py	(working copy)
@@ -1,9 +1,17 @@
 from django.core.management.base import NoArgsCommand, CommandError
 from django.core.management.color import no_style
 
+from optparse import make_option
+
 class Command(NoArgsCommand):
+    option_list = (
+        make_option('--verbosity', action='store', dest='verbosity', default='1',
+            type='choice', choices=['0', '1', '2'],
+            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+        make_option('--noinput', action='store_false', dest='interactive', default=True,
+            help='Tells Django to NOT prompt the user for input of any kind.'),
+    )
     help = "Executes ``sqlflush`` on the current database."
-    args = '[--verbosity] [--noinput]'
 
     def handle_noargs(self, **options):
         from django.conf import settings
Index: /home/tobryan1/workspace/django/django/core/management/commands/loaddata.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/loaddata.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/loaddata.py	(working copy)
@@ -1,5 +1,7 @@
 from django.core.management.base import BaseCommand
 from django.core.management.color import no_style
+
+from optparse import make_option
 import sys
 import os
 
@@ -9,8 +11,13 @@
     from sets import Set as set   # Python 2.3 fallback
 
 class Command(BaseCommand):
+    option_list = (
+        make_option('--verbosity', action='store', dest='verbosity', default='1',
+            type='choice', choices=['0', '1', '2'],
+            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+        )
     help = 'Installs the named fixture(s) in the database.'
-    args = "[--verbosity] fixture, fixture, ..."
+    args = "fixture [fixture ...]"
 
     def handle(self, *fixture_labels, **options):
         from django.db.models import get_apps
Index: /home/tobryan1/workspace/django/django/core/management/commands/reset.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/reset.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/reset.py	(working copy)
@@ -1,9 +1,15 @@
 from django.core.management.base import AppCommand, CommandError
 from django.core.management.color import no_style
 
+from optparse import make_option
+
 class Command(AppCommand):
+    option_list = (
+        make_option('--noinput', action='store_false', dest='interactive', default=True,
+            help='Tells Django to NOT prompt the user for input of any kind.'),
+    )
     help = "Executes ``sqlreset`` for the given app(s) in the current database."
-    args = '[--noinput] [appname ...]'
+    args = '[appname ...]'
 
     output_transaction = True
 
Index: /home/tobryan1/workspace/django/django/core/management/commands/runfcgi.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/runfcgi.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/runfcgi.py	(working copy)
@@ -14,3 +14,7 @@
             pass
         from django.core.servers.fastcgi import runfastcgi
         runfastcgi(args)
+        
+    def usage(self):
+        from django.core.servers.fastcgi import FASTCGI_HELP
+        return FASTCGI_HELP
Index: /home/tobryan1/workspace/django/django/core/management/commands/runserver.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/runserver.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/runserver.py	(working copy)
@@ -1,4 +1,6 @@
 from django.core.management.base import BaseCommand, CommandError
+
+from optparse import make_option
 import os
 import sys
 
@@ -3,8 +5,14 @@
 import sys
 
 class Command(BaseCommand):
+    option_list = (
+        make_option('--noreload', action='store_false', dest='use_reloader', default=True,
+            help='When using "runserver": Tells Django to NOT use the auto-reloader.'),
+        make_option('--adminmedia', dest='admin_media_path', default='',
+            help='When using "runserver": Specifies the directory from which to serve admin media.'),
+    )
     help = "Starts a lightweight Web server for development."
-    args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port number, or ipaddr:port]'
+    args = '[optional port number, or ipaddr:port]'
 
     # Validation is called explicitly each time the server is reloaded.
     requires_model_validation = False
Index: /home/tobryan1/workspace/django/django/core/management/commands/shell.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/shell.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/shell.py	(working copy)
@@ -1,8 +1,13 @@
 from django.core.management.base import NoArgsCommand
 
+from optparse import make_option
+
 class Command(NoArgsCommand):
+    option_list = (
+        make_option('--plain', action='store_true', dest='plain',
+            help='When using "shell": Tells Django to use plain Python, not IPython.'),
+    )
     help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available."
-    args = '[--plain]'
 
     requires_model_validation = False
 
Index: /home/tobryan1/workspace/django/django/core/management/commands/syncdb.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/syncdb.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/syncdb.py	(working copy)
@@ -1,5 +1,7 @@
 from django.core.management.base import NoArgsCommand
 from django.core.management.color import no_style
+
+from optparse import make_option
 import sys
 
 try:
@@ -8,8 +10,14 @@
     from sets import Set as set   # Python 2.3 fallback
 
 class Command(NoArgsCommand):
+    option_list = (
+        make_option('--verbosity', action='store', dest='verbosity', default='1',
+            type='choice', choices=['0', '1', '2'],
+            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+        make_option('--noinput', action='store_false', dest='interactive', default=True,
+            help='Tells Django to NOT prompt the user for input of any kind.'),
+    )
     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
-    args = '[--verbosity] [--noinput]'
 
     def handle_noargs(self, **options):
         from django.db import connection, transaction, models
Index: /home/tobryan1/workspace/django/django/core/management/commands/test.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/test.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/test.py	(working copy)
@@ -1,9 +1,18 @@
 from django.core.management.base import BaseCommand
+
+from optparse import make_option
 import sys
 
 class Command(BaseCommand):
+    option_list = (
+        make_option('--verbosity', action='store', dest='verbosity', default='1',
+            type='choice', choices=['0', '1', '2'],
+            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+        make_option('--noinput', action='store_false', dest='interactive', default=True,
+            help='Tells Django to NOT prompt the user for input of any kind.'),
+    )
     help = 'Runs the test suite for the specified applications, or the entire site if no apps are specified.'
-    args = '[--verbosity] [--noinput] [appname ...]'
+    args = '[appname ...]'
 
     requires_model_validation = False
 
Index: /home/tobryan1/workspace/django/django/core/management/commands/testserver.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/management/commands/testserver.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/management/commands/testserver.py	(working copy)
@@ -1,6 +1,13 @@
 from django.core.management.base import BaseCommand
 
+from optparse import make_option
+
 class Command(BaseCommand):
+    option_list = (
+        make_option('--verbosity', action='store', dest='verbosity', default='1',
+            type='choice', choices=['0', '1', '2'],
+            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
+    )
     help = 'Runs a development server with data from the given fixture(s).'
     args = '[fixture ...]'
 
Index: /home/tobryan1/workspace/django/django/core/servers/fastcgi.py
===================================================================
--- /home/tobryan1/workspace/django/django/core/servers/fastcgi.py	(revision 6069)
+++ /home/tobryan1/workspace/django/django/core/servers/fastcgi.py	(working copy)
@@ -17,7 +17,7 @@
 __version__ = "0.1"
 __all__ = ["runfastcgi"]
 
-FASTCGI_HELP = r"""runfcgi:
+FASTCGI_HELP = r"""
   Run this project as a fastcgi (or some other protocol supported
   by flup) application. To do this, the flup package from
   http://www.saddi.com/software/flup/ is required.
@@ -22,9 +22,7 @@
   by flup) application. To do this, the flup package from
   http://www.saddi.com/software/flup/ is required.
 
-Usage:
-   django-admin.py runfcgi --settings=yourproject.settings [fcgi settings]
-   manage.py runfcgi [fcgi settings]
+   runfcgi [options] [fcgi settings]
 
 Optional Fcgi settings: (setting=value)
   protocol=PROTOCOL    fcgi, scgi, ajp, ... (default fcgi)
