Django

Code

Changeset 7888

Show
Ignore:
Timestamp:
07/11/08 08:18:19 (4 months ago)
Author:
russellm
Message:

Fixed #6017 -- Modified the Lax parser to allow --settings and the other core management arguments to appear anywhere in the argument list. Thanks to Todd O'Bryan for the suggestion and patch.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/management/__init__.py

    r7316 r7888  
    135135    def error(self, msg): 
    136136        pass 
     137     
     138    def _process_args(self, largs, rargs, values): 
     139        """ 
     140        Overrides OptionParser._process_args to exclusively handle default 
     141        options and ignore args and other options.  
     142         
     143        This overrides the behavior of the super class, which stop parsing  
     144        at the first unrecognized option. 
     145        """ 
     146        while rargs: 
     147            arg = rargs[0] 
     148            try: 
     149                if arg[0:2] == "--" and len(arg) > 2: 
     150                    # process a single long option (possibly with value(s)) 
     151                    # the superclass code pops the arg off rargs 
     152                    self._process_long_opt(rargs, values) 
     153                elif arg[:1] == "-" and len(arg) > 1: 
     154                    # process a cluster of short options (possibly with 
     155                    # value(s) for the last one only) 
     156                    # the superclass code pops the arg off rargs 
     157                    self._process_short_opts(rargs, values) 
     158                else: 
     159                    # it's either a non-default option or an arg 
     160                    # either way, add it to the args list so we can keep 
     161                    # dealing with options 
     162                    del rargs[0] 
     163                    raise error 
     164            except: 
     165                largs.append(arg) 
    137166 
    138167class ManagementUtility(object): 
  • django/trunk/tests/regressiontests/admin_scripts/management/commands/base_command.py

    r7876 r7888  
    11from django.core.management.base import BaseCommand 
     2from optparse import make_option 
    23 
    34class Command(BaseCommand): 
     5    option_list = BaseCommand.option_list + ( 
     6        make_option('--option_a','-a', action='store', dest='option_a', default='1'), 
     7        make_option('--option_b','-b', action='store', dest='option_b', default='2'), 
     8        make_option('--option_c','-c', action='store', dest='option_c', default='3'), 
     9    ) 
    410    help = 'Test basic commands' 
    511    requires_model_validation = False 
  • django/trunk/tests/regressiontests/admin_scripts/tests.py

    r7887 r7888  
    88import shutil 
    99 
    10 from django import conf, bin 
     10from django import conf, bin, get_version 
    1111from django.conf import settings 
    1212 
     
    726726        self.remove_settings('settings.py') 
    727727     
     728    def test_version(self): 
     729        "--version is handled as a special case" 
     730        args = ['--version'] 
     731        out, err = self.run_manage(args) 
     732        self.assertNoOutput(err) 
     733        # Only check the first part of the version number 
     734        self.assertOutput(out, get_version().split('-')[0]) 
     735 
     736    def test_help(self): 
     737        "--help is handled as a special case" 
     738        args = ['--help'] 
     739        out, err = self.run_manage(args) 
     740        self.assertOutput(out, "Usage: manage.py [options]") 
     741        self.assertOutput(err, "Type 'manage.py help <subcommand>' for help on a specific subcommand.") 
     742 
     743    def test_specific_help(self): 
     744        "--help can be used on a specific command" 
     745        args = ['sqlall','--help'] 
     746        out, err = self.run_manage(args) 
     747        self.assertNoOutput(err) 
     748        self.assertOutput(out, "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the given model module name(s).") 
     749     
    728750    def test_base_command(self): 
    729751        "User BaseCommands can execute when a label is provided" 
     
    731753        out, err = self.run_manage(args) 
    732754        self.assertNoOutput(err) 
    733         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('pythonpath', None), ('settings', None), ('traceback', None)]") 
     755        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None)]") 
    734756         
    735757    def test_base_command_no_label(self): 
     
    738760        out, err = self.run_manage(args) 
    739761        self.assertNoOutput(err) 
    740         self.assertOutput(out, "EXECUTE:BaseCommand labels=(), options=[('pythonpath', None), ('settings', None), ('traceback', None)]") 
     762        self.assertOutput(out, "EXECUTE:BaseCommand labels=(), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None)]") 
    741763 
    742764    def test_base_command_multiple_label(self): 
     
    745767        out, err = self.run_manage(args) 
    746768        self.assertNoOutput(err) 
    747         self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel', 'anotherlabel'), options=[('pythonpath', None), ('settings', None), ('traceback', None)]") 
     769        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel', 'anotherlabel'), options=[('option_a', '1'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None)]") 
     770 
     771    def test_base_command_with_option(self): 
     772        "User BaseCommands can execute with options when a label is provided" 
     773        args = ['base_command','testlabel','--option_a=x'] 
     774        out, err = self.run_manage(args) 
     775        self.assertNoOutput(err) 
     776        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None)]") 
     777 
     778    def test_base_command_with_options(self): 
     779        "User BaseCommands can execute with multiple options when a label is provided" 
     780        args = ['base_command','testlabel','-a','x','--option_b=y'] 
     781        out, err = self.run_manage(args) 
     782        self.assertNoOutput(err) 
     783        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', None), ('traceback', None)]") 
    748784                 
    749785    def test_noargs(self): 
     
    816852        self.assertOutput(out, "EXECUTE:LabelCommand label=testlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None)]") 
    817853        self.assertOutput(out, "EXECUTE:LabelCommand label=anotherlabel, options=[('pythonpath', None), ('settings', None), ('traceback', None)]") 
     854 
     855class ArgumentOrder(AdminScriptTestCase): 
     856    """Tests for 2-stage argument parsing scheme. 
     857 
     858    django-admin command arguments are parsed in 2 parts; the core arguments 
     859    (--settings, --traceback and --pythonpath) are parsed using a Lax parser. 
     860    This Lax parser ignores any unknown options. Then the full settings are  
     861    passed to the command parser, which extracts commands of interest to the 
     862    individual command.     
     863    """ 
     864    def setUp(self): 
     865        self.write_settings('settings.py', apps=['django.contrib.auth','django.contrib.contenttypes']) 
     866        self.write_settings('alternate_settings.py') 
     867         
     868    def tearDown(self): 
     869        self.remove_settings('settings.py') 
     870        self.remove_settings('alternate_settings.py') 
     871 
     872    def test_setting_then_option(self): 
     873        "Options passed after settings are correctly handled" 
     874        args = ['base_command','testlabel','--settings=alternate_settings','--option_a=x'] 
     875        out, err = self.run_manage(args) 
     876        self.assertNoOutput(err) 
     877        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None)]") 
     878 
     879    def test_setting_then_short_option(self): 
     880        "Short options passed after settings are correctly handled" 
     881        args = ['base_command','testlabel','--settings=alternate_settings','--option_a=x'] 
     882        out, err = self.run_manage(args) 
     883        self.assertNoOutput(err) 
     884        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None)]") 
     885 
     886    def test_option_then_setting(self): 
     887        "Options passed before settings are correctly handled" 
     888        args = ['base_command','testlabel','--option_a=x','--settings=alternate_settings'] 
     889        out, err = self.run_manage(args) 
     890        self.assertNoOutput(err) 
     891        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None)]") 
     892 
     893    def test_short_option_then_setting(self): 
     894        "Short options passed before settings are correctly handled" 
     895        args = ['base_command','testlabel','-a','x','--settings=alternate_settings'] 
     896        out, err = self.run_manage(args) 
     897        self.assertNoOutput(err) 
     898        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', '2'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None)]") 
     899 
     900    def test_option_then_setting_then_option(self): 
     901        "Options are correctly handled when they are passed before and after a setting" 
     902        args = ['base_command','testlabel','--option_a=x','--settings=alternate_settings','--option_b=y'] 
     903        out, err = self.run_manage(args) 
     904        self.assertNoOutput(err) 
     905        self.assertOutput(out, "EXECUTE:BaseCommand labels=('testlabel',), options=[('option_a', 'x'), ('option_b', 'y'), ('option_c', '3'), ('pythonpath', None), ('settings', 'alternate_settings'), ('traceback', None)]") 
     906