Commit f17b24e4 authored by Claude Paroz's avatar Claude Paroz
Browse files

Converted remaining management commands to argparse

parent 4b452429
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
from __future__ import unicode_literals

import getpass
from optparse import make_option

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand, CommandError
@@ -10,10 +9,6 @@ from django.utils.encoding import force_str


class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--database', action='store', dest='database',
            default=DEFAULT_DB_ALIAS, help='Specifies the database to use. Default is "default".'),
    )
    help = "Change a user's password for django.contrib.auth."

    requires_system_checks = False
@@ -24,12 +19,16 @@ class Command(BaseCommand):
            raise CommandError("aborted")
        return p

    def handle(self, *args, **options):
        if len(args) > 1:
            raise CommandError("need exactly one or zero arguments for username")
    def add_arguments(self, parser):
        parser.add_argument('username', nargs='?',
            help='Username to change password for; by default, it\'s the current username.')
        parser.add_argument('--database', action='store', dest='database',
            default=DEFAULT_DB_ALIAS,
            help='Specifies the database to use. Default is "default".')

        if args:
            username, = args
    def handle(self, *args, **options):
        if options.get('username'):
            username = options['username']
        else:
            username = getpass.getuser()

+18 −25
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@ from __future__ import unicode_literals

import getpass
import sys
from optparse import make_option

from django.contrib.auth import get_user_model
from django.contrib.auth.management import get_default_username
@@ -22,33 +21,29 @@ class NotRunningInTTYException(Exception):


class Command(BaseCommand):
    help = 'Used to create a superuser.'

    def __init__(self, *args, **kwargs):
        # Options are defined in an __init__ method to support swapping out
        # custom user models in tests.
        super(Command, self).__init__(*args, **kwargs)
        self.UserModel = get_user_model()
        self.username_field = self.UserModel._meta.get_field(self.UserModel.USERNAME_FIELD)

        self.option_list = BaseCommand.option_list + (
            make_option('--%s' % self.UserModel.USERNAME_FIELD, dest=self.UserModel.USERNAME_FIELD, default=None,
                help='Specifies the login for the superuser.'),
            make_option('--noinput', action='store_false', dest='interactive', default=True,
    def add_arguments(self, parser):
        parser.add_argument('--%s' % self.UserModel.USERNAME_FIELD,
            dest=self.UserModel.USERNAME_FIELD, default=None,
            help='Specifies the login for the superuser.')
        parser.add_argument('--noinput', action='store_false', dest='interactive', default=True,
            help=('Tells Django to NOT prompt the user for input of any kind. '
                  'You must use --%s with --noinput, along with an option for '
                  'any other required field. Superusers created with --noinput will '
                  ' not be able to log in until they\'re given a valid password.' %
                    self.UserModel.USERNAME_FIELD)),
            make_option('--database', action='store', dest='database',
                default=DEFAULT_DB_ALIAS, help='Specifies the database to use. Default is "default".'),
        ) + tuple(
            make_option('--%s' % field, dest=field, default=None,
                  self.UserModel.USERNAME_FIELD))
        parser.add_argument('--database', action='store', dest='database',
                default=DEFAULT_DB_ALIAS,
                help='Specifies the database to use. Default is "default".')
        for field in self.UserModel.REQUIRED_FIELDS:
            parser.add_argument('--%s' % field, dest=field, default=None,
                help='Specifies the %s for the superuser.' % field)
            for field in self.UserModel.REQUIRED_FIELDS
        )

    option_list = BaseCommand.option_list
    help = 'Used to create a superuser.'

    def execute(self, *args, **options):
        self.stdin = options.get('stdin', sys.stdin)  # Used for testing
@@ -56,8 +51,6 @@ class Command(BaseCommand):

    def handle(self, *args, **options):
        username = options.get(self.UserModel.USERNAME_FIELD, None)
        interactive = options.get('interactive')
        verbosity = int(options.get('verbosity', 1))
        database = options.get('database')

        # If not provided, create the user with an unusable password
@@ -65,7 +58,7 @@ class Command(BaseCommand):
        user_data = {}

        # Do quick and dirty validation if --noinput
        if not interactive:
        if not options['interactive']:
            try:
                if not username:
                    raise CommandError("You must use --%s with --noinput." %
@@ -158,5 +151,5 @@ class Command(BaseCommand):
            user_data[self.UserModel.USERNAME_FIELD] = username
            user_data['password'] = password
            self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
            if verbosity >= 1:
            if options['verbosity'] >= 1:
                self.stdout.write("Superuser created successfully.")
+5 −3
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ class ChangepasswordManagementCommandTestCase(TestCase):
        command = changepassword.Command()
        command._get_pass = lambda *args: 'not qwerty'

        command.execute("joe", stdout=self.stdout)
        command.execute(username="joe", stdout=self.stdout)
        command_output = self.stdout.getvalue().strip()

        self.assertEqual(command_output, "Changing password for user 'joe'\nPassword changed successfully for user 'joe'")
@@ -133,7 +133,7 @@ class ChangepasswordManagementCommandTestCase(TestCase):
        command._get_pass = lambda *args: args or 'foo'

        with self.assertRaises(CommandError):
            command.execute("joe", stdout=self.stdout, stderr=self.stderr)
            command.execute(username="joe", stdout=self.stdout, stderr=self.stderr)

    def test_that_changepassword_command_works_with_nonascii_output(self):
        """
@@ -146,7 +146,7 @@ class ChangepasswordManagementCommandTestCase(TestCase):
        command = changepassword.Command()
        command._get_pass = lambda *args: 'not qwerty'

        command.execute("J\xfalia", stdout=self.stdout)
        command.execute(username="J\xfalia", stdout=self.stdout)


@skipIfCustomUser
@@ -333,6 +333,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
            stdin=sentinel,
            stdout=six.StringIO(),
            interactive=False,
            verbosity=0,
            username='janet',
            email='janet@example.com',
        )
@@ -342,6 +343,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
        command.execute(
            stdout=six.StringIO(),
            interactive=False,
            verbosity=0,
            username='joe',
            email='joe@example.com',
        )
+58 −63
Original line number Diff line number Diff line
import argparse
import inspect
from optparse import make_option

from django.contrib.gis import gdal
from django.core.management.base import LabelCommand, CommandError
from django.core.management.base import BaseCommand, CommandError


def layer_option(option, opt, value, parser):
class LayerOptionAction(argparse.Action):
    """
    Callback for `make_option` for the `ogrinspect` `layer_key`
    keyword option which may be an integer or a string.
    Custom argparse action for the `ogrinspect` `layer_key` keyword option
    which may be an integer or a string.
    """
    def __call__(self, parser, namespace, value, option_string=None):
        try:
        dest = int(value)
            setattr(namespace, self.dest, int(value))
        except ValueError:
        dest = value
    setattr(parser.values, option.dest, dest)
            setattr(namespace, self.dest, value)


def list_option(option, opt, value, parser):
class ListOptionAction(argparse.Action):
    """
    Callback for `make_option` for `ogrinspect` keywords that require
    Custom argparse action for `ogrinspect` keywords that require
    a string list. If the string is 'True'/'true' then the option
    value will be a boolean instead.
    """
    def __call__(self, parser, namespace, value, option_string=None):
        if value.lower() == 'true':
        dest = True
            setattr(namespace, self.dest, True)
        else:
        dest = [s for s in value.split(',')]
    setattr(parser.values, option.dest, dest)
            setattr(namespace, self.dest, value.split(','))


class Command(LabelCommand):
class Command(BaseCommand):
    help = ('Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n'
            'a GeoDjango model with the given model name. For example:\n'
            ' ./manage.py ogrinspect zipcode.shp Zipcode')
    args = '[data_source] [model_name]'

    option_list = LabelCommand.option_list + (
        make_option('--blank', dest='blank', type='string', action='callback',
                    callback=list_option, default=False,
    requires_system_checks = False

    def add_arguments(self, parser):
        parser.add_argument('data_source', help='Path to the data source.')
        parser.add_argument('model_name', help='Name of the model to create.')
        parser.add_argument('--blank', dest='blank',
            action=ListOptionAction, default=False,
            help='Use a comma separated list of OGR field names to add '
                    'the `blank=True` option to the field definition.  Set with'
                    '`true` to apply to all applicable fields.'),
        make_option('--decimal', dest='decimal', type='string', action='callback',
                    callback=list_option, default=False,
            'the `blank=True` option to the field definition. Set to `true` '
            'to apply to all applicable fields.')
        parser.add_argument('--decimal', dest='decimal',
            action=ListOptionAction, default=False,
            help='Use a comma separated list of OGR float fields to '
            'generate `DecimalField` instead of the default '
                    '`FloatField`. Set to `true` to apply to all OGR float fields.'),
        make_option('--geom-name', dest='geom_name', type='string', default='geom',
            '`FloatField`. Set to `true` to apply to all OGR float fields.')
        parser.add_argument('--geom-name', dest='geom_name', default='geom',
            help='Specifies the model name for the Geometry Field '
                    '(defaults to `geom`)'),
        make_option('--layer', dest='layer_key', type='string', action='callback',
                    callback=layer_option, default=0,
            '(defaults to `geom`)')
        parser.add_argument('--layer', dest='layer_key',
            action=LayerOptionAction, default=0,
            help='The key for specifying which layer in the OGR data '
            'source to use. Defaults to 0 (the first layer). May be '
                    'an integer or a string identifier for the layer.'),
        make_option('--multi-geom', action='store_true', dest='multi_geom', default=False,
                    help='Treat the geometry in the data source as a geometry collection.'),
        make_option('--name-field', dest='name_field',
                    help='Specifies a field name to return for the `__unicode__`/`__str__` function.'),
        make_option('--no-imports', action='store_false', dest='imports', default=True,
                    help='Do not include `from django.contrib.gis.db import models` '
                    'statement.'),
        make_option('--null', dest='null', type='string', action='callback',
                    callback=list_option, default=False,
            'an integer or a string identifier for the layer.')
        parser.add_argument('--multi-geom', action='store_true',
            dest='multi_geom', default=False,
            help='Treat the geometry in the data source as a geometry collection.')
        parser.add_argument('--name-field', dest='name_field',
            help='Specifies a field name to return for the `__unicode__`/`__str__` function.')
        parser.add_argument('--no-imports', action='store_false', dest='imports', default=True,
            help='Do not include `from django.contrib.gis.db import models` statement.')
        parser.add_argument('--null', dest='null', action=ListOptionAction, default=False,
            help='Use a comma separated list of OGR field names to add '
                    'the `null=True` option to the field definition.  Set with'
                    '`true` to apply to all applicable fields.'),
        make_option('--srid', dest='srid',
            'the `null=True` option to the field definition. Set to `true` '
            'to apply to all applicable fields.')
        parser.add_argument('--srid', dest='srid',
            help='The SRID to use for the Geometry Field. If it can be '
                    'determined, the SRID of the data source is used.'),
        make_option('--mapping', action='store_true', dest='mapping',
            'determined, the SRID of the data source is used.')
        parser.add_argument('--mapping', action='store_true', dest='mapping',
            help='Generate mapping dictionary for use with `LayerMapping`.')
    )

    requires_system_checks = False

    def handle(self, *args, **options):
        try:
            data_source, model_name = args
        except ValueError:
            raise CommandError('Invalid arguments, must provide: %s' % self.args)

        data_source, model_name = options.pop('data_source'), options.pop('model_name')
        if not gdal.HAS_GDAL:
            raise CommandError('GDAL is required to inspect geospatial data sources.')

+27 −28
Original line number Diff line number Diff line
@@ -2,7 +2,6 @@ from __future__ import unicode_literals

import os
from collections import OrderedDict
from optparse import make_option

from django.core.files.storage import FileSystemStorage
from django.core.management.base import CommandError, NoArgsCommand
@@ -18,32 +17,6 @@ class Command(NoArgsCommand):
    Command that allows to copy or symlink static files from different
    locations to the settings.STATIC_ROOT.
    """
    option_list = NoArgsCommand.option_list + (
        make_option('--noinput',
            action='store_false', dest='interactive', default=True,
            help="Do NOT prompt the user for input of any kind."),
        make_option('--no-post-process',
            action='store_false', dest='post_process', default=True,
            help="Do NOT post process collected files."),
        make_option('-i', '--ignore', action='append', default=[],
            dest='ignore_patterns', metavar='PATTERN',
            help="Ignore files or directories matching this glob-style "
                "pattern. Use multiple times to ignore more."),
        make_option('-n', '--dry-run',
            action='store_true', dest='dry_run', default=False,
            help="Do everything except modify the filesystem."),
        make_option('-c', '--clear',
            action='store_true', dest='clear', default=False,
            help="Clear the existing files using the storage "
                 "before trying to copy or link the original file."),
        make_option('-l', '--link',
            action='store_true', dest='link', default=False,
            help="Create a symbolic link to each file instead of copying."),
        make_option('--no-default-ignore', action='store_false',
            dest='use_default_ignore_patterns', default=True,
            help="Don't ignore the common private glob-style patterns 'CVS', "
                "'.*' and '*~'."),
    )
    help = "Collect static files in a single location."
    requires_system_checks = False

@@ -61,12 +34,38 @@ class Command(NoArgsCommand):
        else:
            self.local = True

    def add_arguments(self, parser):
        parser.add_argument('--noinput',
            action='store_false', dest='interactive', default=True,
            help="Do NOT prompt the user for input of any kind.")
        parser.add_argument('--no-post-process',
            action='store_false', dest='post_process', default=True,
            help="Do NOT post process collected files.")
        parser.add_argument('-i', '--ignore', action='append', default=[],
            dest='ignore_patterns', metavar='PATTERN',
            help="Ignore files or directories matching this glob-style "
                "pattern. Use multiple times to ignore more.")
        parser.add_argument('-n', '--dry-run',
            action='store_true', dest='dry_run', default=False,
            help="Do everything except modify the filesystem.")
        parser.add_argument('-c', '--clear',
            action='store_true', dest='clear', default=False,
            help="Clear the existing files using the storage "
                 "before trying to copy or link the original file.")
        parser.add_argument('-l', '--link',
            action='store_true', dest='link', default=False,
            help="Create a symbolic link to each file instead of copying.")
        parser.add_argument('--no-default-ignore', action='store_false',
            dest='use_default_ignore_patterns', default=True,
            help="Don't ignore the common private glob-style patterns 'CVS', "
                "'.*' and '*~'.")

    def set_options(self, **options):
        """
        Set instance variables based on an options dict
        """
        self.interactive = options['interactive']
        self.verbosity = int(options.get('verbosity', 1))
        self.verbosity = options['verbosity']
        self.symlink = options['link']
        self.clear = options['clear']
        self.dry_run = options['dry_run']
Loading