Loading django/core/management/__init__.py +14 −19 Original line number Diff line number Diff line Loading @@ -100,19 +100,16 @@ def call_command(name, *args, **options): # Simulate argument parsing to get the option defaults (see #10080 for details). parser = command.create_parser('', name) if command.use_argparse: # Use the `dest` option name from the parser option opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest for s_opt in parser._actions if s_opt.option_strings} opt_mapping = { sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest for s_opt in parser._actions if s_opt.option_strings } arg_options = {opt_mapping.get(key, key): value for key, value in options.items()} defaults = parser.parse_args(args=args) defaults = dict(defaults._get_kwargs(), **arg_options) # Move positional args out of options to mimic legacy optparse args = defaults.pop('args', ()) else: # Legacy optparse method defaults, _ = parser.parse_args(args=[]) defaults = dict(defaults.__dict__, **options) if 'skip_checks' not in options: defaults['skip_checks'] = True Loading Loading @@ -249,12 +246,10 @@ class ManagementUtility(object): # user will find out once they execute the command. pass parser = subcommand_cls.create_parser('', cwords[0]) if subcommand_cls.use_argparse: options.extend((sorted(s_opt.option_strings)[0], s_opt.nargs != 0) for s_opt in parser._actions if s_opt.option_strings) else: options.extend((s_opt.get_opt_string(), s_opt.nargs != 0) for s_opt in parser.option_list) options.extend( (sorted(s_opt.option_strings)[0], s_opt.nargs != 0) for s_opt in parser._actions if s_opt.option_strings ) # filter out previously specified options from available options prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] options = [opt for opt in options if opt[0] not in prev_opts] Loading django/core/management/base.py +24 −80 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ import os import sys import warnings from argparse import ArgumentParser from optparse import OptionParser import django from django.core import checks Loading Loading @@ -152,12 +151,6 @@ class BaseCommand(object): Several attributes affect behavior at various steps along the way: ``args`` A string listing the arguments accepted by the command, suitable for use in help messages; e.g., a command which takes a list of application names might set this to '<app_label app_label ...>'. ``can_import_settings`` A boolean indicating whether the command needs to be able to import Django settings; if ``True``, ``execute()`` will verify Loading @@ -168,12 +161,6 @@ class BaseCommand(object): A short description of the command, which will be printed in help messages. ``option_list`` This is the list of ``optparse`` options which will be fed into the command's ``OptionParser`` for parsing arguments. Deprecated and will be removed in Django 1.10. Use ``add_arguments`` instead. ``output_transaction`` A boolean indicating whether the command outputs SQL statements; if ``True``, the output will automatically be Loading Loading @@ -207,9 +194,7 @@ class BaseCommand(object): to settings. This condition will generate a CommandError. """ # Metadata about this command. option_list = () help = '' args = '' # Configuration shortcuts that alter various logic. _called_from_command_line = False Loading @@ -227,10 +212,6 @@ class BaseCommand(object): self.style = color_style() self.stderr.style_func = self.style.ERROR @property def use_argparse(self): return not bool(self.option_list) def get_version(self): """ Return the Django version, which should be correct for all Loading @@ -255,36 +236,6 @@ class BaseCommand(object): Create and return the ``ArgumentParser`` which will be used to parse the arguments to this command. """ if not self.use_argparse: def store_as_int(option, opt_str, value, parser): setattr(parser.values, option.dest, int(value)) # Backwards compatibility: use deprecated optparse module warnings.warn("OptionParser usage for Django management commands " "is deprecated, use ArgumentParser instead", RemovedInDjango110Warning) parser = OptionParser(prog=prog_name, usage=self.usage(subcommand), version=self.get_version()) parser.add_option('-v', '--verbosity', action='callback', dest='verbosity', default=1, type='choice', choices=['0', '1', '2', '3'], callback=store_as_int, help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output') 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('--traceback', action='store_true', help='Raise on CommandError exceptions') parser.add_option('--no-color', action='store_true', dest='no_color', default=False, help="Don't colorize the command output.") for opt in self.option_list: parser.add_option(opt) else: parser = CommandParser(self, prog="%s %s" % (os.path.basename(prog_name), subcommand), description=self.help or None) parser.add_argument('--version', action='version', version=self.get_version()) Loading @@ -304,9 +255,6 @@ class BaseCommand(object): help='Raise on CommandError exceptions') parser.add_argument('--no-color', action='store_true', dest='no_color', default=False, help="Don't colorize the command output.") if self.args: # Keep compatibility and always accept positional arguments, like optparse when args is set parser.add_argument('args', nargs='*') self.add_arguments(parser) return parser Loading Loading @@ -335,14 +283,10 @@ class BaseCommand(object): self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) if self.use_argparse: options = parser.parse_args(argv[2:]) cmd_options = vars(options) # Move positional args out of options to mimic legacy optparse args = cmd_options.pop('args', ()) else: options, args = parser.parse_args(argv[2:]) cmd_options = vars(options) handle_default_options(options) try: self.execute(*args, **cmd_options) Loading django/core/management/commands/test.py +0 −7 Original line number Diff line number Diff line Loading @@ -50,13 +50,6 @@ class Command(BaseCommand): 'default value is localhost:8081-8179.'), test_runner_class = get_runner(settings, self.test_runner) if hasattr(test_runner_class, 'option_list'): # Keeping compatibility with both optparse and argparse at this level # would be too heavy for a non-critical item raise RuntimeError( "The method to extend accepted command-line arguments by the " "test management command has changed in Django 1.8. Please " "create an add_arguments class method to achieve this.") if hasattr(test_runner_class, 'add_arguments'): test_runner_class.add_arguments(parser) Loading docs/howto/custom-management-commands.txt +0 −40 Original line number Diff line number Diff line Loading @@ -69,16 +69,6 @@ look like this:: self.stdout.write('Successfully closed poll "%s"' % poll_id) .. versionchanged:: 1.8 Before Django 1.8, management commands were based on the :py:mod:`optparse` module, and positional arguments were passed in ``*args`` while optional arguments were passed in ``**options``. Now that management commands use :py:mod:`argparse` for argument parsing, all arguments are passed in ``**options`` by default, unless you name your positional arguments to ``args`` (compatibility mode). You are encouraged to exclusively use ``**options`` for new commands. .. _management-commands-output: .. note:: Loading Loading @@ -128,12 +118,6 @@ options can be added in the :meth:`~BaseCommand.add_arguments` method like this: poll.delete() # ... .. versionchanged:: 1.8 Previously, only the standard :py:mod:`optparse` library was supported and you would have to extend the command ``option_list`` variable with ``optparse.make_option()``. The option (``delete`` in our example) is available in the options dict parameter of the handle method. See the :py:mod:`argparse` Python documentation for more about ``add_argument`` usage. Loading Loading @@ -227,19 +211,6 @@ Attributes All attributes can be set in your derived class and can be used in :class:`BaseCommand`’s :ref:`subclasses<ref-basecommand-subclasses>`. .. attribute:: BaseCommand.args A string listing the arguments accepted by the command, suitable for use in help messages; e.g., a command which takes a list of application names might set this to '<app_label app_label ...>'. .. deprecated:: 1.8 This should be done now in the :meth:`~BaseCommand.add_arguments()` method, by calling the ``parser.add_argument()`` method. See the ``closepoll`` example above. .. attribute:: BaseCommand.can_import_settings A boolean indicating whether the command needs to be able to Loading @@ -261,17 +232,6 @@ All attributes can be set in your derived class and can be used in the message error returned in the case of missing arguments. The default is output by :py:mod:`argparse` ("too few arguments"). .. attribute:: BaseCommand.option_list This is the list of ``optparse`` options which will be fed into the command's ``OptionParser`` for parsing arguments. .. deprecated:: 1.8 You should now override the :meth:`~BaseCommand.add_arguments` method to add custom arguments accepted by your command. See :ref:`the example above <custom-commands-options>`. .. attribute:: BaseCommand.output_transaction A boolean indicating whether the command outputs SQL statements; if Loading docs/releases/1.8.txt +7 −8 Original line number Diff line number Diff line Loading @@ -738,15 +738,14 @@ Management commands that only accept positional arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you have written a custom management command that only accepts positional arguments and you didn't specify the :attr:`~django.core.management.BaseCommand.args` command variable, you might get an error like ``Error: unrecognized arguments: ...``, as variable parsing is now based on :py:mod:`argparse` which doesn't implicitly accept positional arguments and you didn't specify the ``args`` command variable, you might get an error like ``Error: unrecognized arguments: ...``, as variable parsing is now based on :py:mod:`argparse` which doesn't implicitly accept positional arguments. You can make your command backwards compatible by simply setting the :attr:`~django.core.management.BaseCommand.args` class variable. However, if you don't have to keep compatibility with older Django versions, it's better to implement the new :meth:`~django.core.management.BaseCommand.add_arguments` method as described in :doc:`/howto/custom-management-commands`. ``args`` class variable. However, if you don't have to keep compatibility with older Django versions, it's better to implement the new :meth:`~django.core.management.BaseCommand.add_arguments` method as described in :doc:`/howto/custom-management-commands`. Custom test management command arguments through test runner ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loading Loading
django/core/management/__init__.py +14 −19 Original line number Diff line number Diff line Loading @@ -100,19 +100,16 @@ def call_command(name, *args, **options): # Simulate argument parsing to get the option defaults (see #10080 for details). parser = command.create_parser('', name) if command.use_argparse: # Use the `dest` option name from the parser option opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest for s_opt in parser._actions if s_opt.option_strings} opt_mapping = { sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest for s_opt in parser._actions if s_opt.option_strings } arg_options = {opt_mapping.get(key, key): value for key, value in options.items()} defaults = parser.parse_args(args=args) defaults = dict(defaults._get_kwargs(), **arg_options) # Move positional args out of options to mimic legacy optparse args = defaults.pop('args', ()) else: # Legacy optparse method defaults, _ = parser.parse_args(args=[]) defaults = dict(defaults.__dict__, **options) if 'skip_checks' not in options: defaults['skip_checks'] = True Loading Loading @@ -249,12 +246,10 @@ class ManagementUtility(object): # user will find out once they execute the command. pass parser = subcommand_cls.create_parser('', cwords[0]) if subcommand_cls.use_argparse: options.extend((sorted(s_opt.option_strings)[0], s_opt.nargs != 0) for s_opt in parser._actions if s_opt.option_strings) else: options.extend((s_opt.get_opt_string(), s_opt.nargs != 0) for s_opt in parser.option_list) options.extend( (sorted(s_opt.option_strings)[0], s_opt.nargs != 0) for s_opt in parser._actions if s_opt.option_strings ) # filter out previously specified options from available options prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] options = [opt for opt in options if opt[0] not in prev_opts] Loading
django/core/management/base.py +24 −80 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ import os import sys import warnings from argparse import ArgumentParser from optparse import OptionParser import django from django.core import checks Loading Loading @@ -152,12 +151,6 @@ class BaseCommand(object): Several attributes affect behavior at various steps along the way: ``args`` A string listing the arguments accepted by the command, suitable for use in help messages; e.g., a command which takes a list of application names might set this to '<app_label app_label ...>'. ``can_import_settings`` A boolean indicating whether the command needs to be able to import Django settings; if ``True``, ``execute()`` will verify Loading @@ -168,12 +161,6 @@ class BaseCommand(object): A short description of the command, which will be printed in help messages. ``option_list`` This is the list of ``optparse`` options which will be fed into the command's ``OptionParser`` for parsing arguments. Deprecated and will be removed in Django 1.10. Use ``add_arguments`` instead. ``output_transaction`` A boolean indicating whether the command outputs SQL statements; if ``True``, the output will automatically be Loading Loading @@ -207,9 +194,7 @@ class BaseCommand(object): to settings. This condition will generate a CommandError. """ # Metadata about this command. option_list = () help = '' args = '' # Configuration shortcuts that alter various logic. _called_from_command_line = False Loading @@ -227,10 +212,6 @@ class BaseCommand(object): self.style = color_style() self.stderr.style_func = self.style.ERROR @property def use_argparse(self): return not bool(self.option_list) def get_version(self): """ Return the Django version, which should be correct for all Loading @@ -255,36 +236,6 @@ class BaseCommand(object): Create and return the ``ArgumentParser`` which will be used to parse the arguments to this command. """ if not self.use_argparse: def store_as_int(option, opt_str, value, parser): setattr(parser.values, option.dest, int(value)) # Backwards compatibility: use deprecated optparse module warnings.warn("OptionParser usage for Django management commands " "is deprecated, use ArgumentParser instead", RemovedInDjango110Warning) parser = OptionParser(prog=prog_name, usage=self.usage(subcommand), version=self.get_version()) parser.add_option('-v', '--verbosity', action='callback', dest='verbosity', default=1, type='choice', choices=['0', '1', '2', '3'], callback=store_as_int, help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output') 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('--traceback', action='store_true', help='Raise on CommandError exceptions') parser.add_option('--no-color', action='store_true', dest='no_color', default=False, help="Don't colorize the command output.") for opt in self.option_list: parser.add_option(opt) else: parser = CommandParser(self, prog="%s %s" % (os.path.basename(prog_name), subcommand), description=self.help or None) parser.add_argument('--version', action='version', version=self.get_version()) Loading @@ -304,9 +255,6 @@ class BaseCommand(object): help='Raise on CommandError exceptions') parser.add_argument('--no-color', action='store_true', dest='no_color', default=False, help="Don't colorize the command output.") if self.args: # Keep compatibility and always accept positional arguments, like optparse when args is set parser.add_argument('args', nargs='*') self.add_arguments(parser) return parser Loading Loading @@ -335,14 +283,10 @@ class BaseCommand(object): self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) if self.use_argparse: options = parser.parse_args(argv[2:]) cmd_options = vars(options) # Move positional args out of options to mimic legacy optparse args = cmd_options.pop('args', ()) else: options, args = parser.parse_args(argv[2:]) cmd_options = vars(options) handle_default_options(options) try: self.execute(*args, **cmd_options) Loading
django/core/management/commands/test.py +0 −7 Original line number Diff line number Diff line Loading @@ -50,13 +50,6 @@ class Command(BaseCommand): 'default value is localhost:8081-8179.'), test_runner_class = get_runner(settings, self.test_runner) if hasattr(test_runner_class, 'option_list'): # Keeping compatibility with both optparse and argparse at this level # would be too heavy for a non-critical item raise RuntimeError( "The method to extend accepted command-line arguments by the " "test management command has changed in Django 1.8. Please " "create an add_arguments class method to achieve this.") if hasattr(test_runner_class, 'add_arguments'): test_runner_class.add_arguments(parser) Loading
docs/howto/custom-management-commands.txt +0 −40 Original line number Diff line number Diff line Loading @@ -69,16 +69,6 @@ look like this:: self.stdout.write('Successfully closed poll "%s"' % poll_id) .. versionchanged:: 1.8 Before Django 1.8, management commands were based on the :py:mod:`optparse` module, and positional arguments were passed in ``*args`` while optional arguments were passed in ``**options``. Now that management commands use :py:mod:`argparse` for argument parsing, all arguments are passed in ``**options`` by default, unless you name your positional arguments to ``args`` (compatibility mode). You are encouraged to exclusively use ``**options`` for new commands. .. _management-commands-output: .. note:: Loading Loading @@ -128,12 +118,6 @@ options can be added in the :meth:`~BaseCommand.add_arguments` method like this: poll.delete() # ... .. versionchanged:: 1.8 Previously, only the standard :py:mod:`optparse` library was supported and you would have to extend the command ``option_list`` variable with ``optparse.make_option()``. The option (``delete`` in our example) is available in the options dict parameter of the handle method. See the :py:mod:`argparse` Python documentation for more about ``add_argument`` usage. Loading Loading @@ -227,19 +211,6 @@ Attributes All attributes can be set in your derived class and can be used in :class:`BaseCommand`’s :ref:`subclasses<ref-basecommand-subclasses>`. .. attribute:: BaseCommand.args A string listing the arguments accepted by the command, suitable for use in help messages; e.g., a command which takes a list of application names might set this to '<app_label app_label ...>'. .. deprecated:: 1.8 This should be done now in the :meth:`~BaseCommand.add_arguments()` method, by calling the ``parser.add_argument()`` method. See the ``closepoll`` example above. .. attribute:: BaseCommand.can_import_settings A boolean indicating whether the command needs to be able to Loading @@ -261,17 +232,6 @@ All attributes can be set in your derived class and can be used in the message error returned in the case of missing arguments. The default is output by :py:mod:`argparse` ("too few arguments"). .. attribute:: BaseCommand.option_list This is the list of ``optparse`` options which will be fed into the command's ``OptionParser`` for parsing arguments. .. deprecated:: 1.8 You should now override the :meth:`~BaseCommand.add_arguments` method to add custom arguments accepted by your command. See :ref:`the example above <custom-commands-options>`. .. attribute:: BaseCommand.output_transaction A boolean indicating whether the command outputs SQL statements; if Loading
docs/releases/1.8.txt +7 −8 Original line number Diff line number Diff line Loading @@ -738,15 +738,14 @@ Management commands that only accept positional arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you have written a custom management command that only accepts positional arguments and you didn't specify the :attr:`~django.core.management.BaseCommand.args` command variable, you might get an error like ``Error: unrecognized arguments: ...``, as variable parsing is now based on :py:mod:`argparse` which doesn't implicitly accept positional arguments and you didn't specify the ``args`` command variable, you might get an error like ``Error: unrecognized arguments: ...``, as variable parsing is now based on :py:mod:`argparse` which doesn't implicitly accept positional arguments. You can make your command backwards compatible by simply setting the :attr:`~django.core.management.BaseCommand.args` class variable. However, if you don't have to keep compatibility with older Django versions, it's better to implement the new :meth:`~django.core.management.BaseCommand.add_arguments` method as described in :doc:`/howto/custom-management-commands`. ``args`` class variable. However, if you don't have to keep compatibility with older Django versions, it's better to implement the new :meth:`~django.core.management.BaseCommand.add_arguments` method as described in :doc:`/howto/custom-management-commands`. Custom test management command arguments through test runner ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loading