import sys from optparse import NO_DEFAULT, OptionParser from django.core.management.base import CommandError, BaseCommand, handle_default_options from django.utils.importlib import import_module import sys from optparse import NO_DEFAULT, OptionParser from django.core.management.base import CommandError, BaseCommand, handle_default_options from django.utils.importlib import import_module class Subcommander(BaseCommand): help = "A wrapper for subcommands" subcommands = {} import_template = '{app_name}.management.subcommands.{module_name}' def print_subcommands(self, prog_name): usage = ['', 'Available subcommands:'] for name in sorted(self.subcommands): usage.append(' {0}'.format(name)) return '\n'.join(usage) def usage(self, subcommand): usage = '%prog {0} subcommand [options] [args]'.format(subcommand) if self.help: return '{0}\n\n{1}'.format(usage, self.help) return usage def print_help(self, prog_name, subcommand): super(Subcommander, self).print_help(prog_name, subcommand) sys.stdout.write('{0}\n\n'.format(self.print_subcommands(prog_name))) def get_subcommand(self, subcommand): try: module = import_module(self.import_template.format(app_name=self.app_name, module_name=self.subcommands[subcommand])) return module.Command() except KeyError: raise CommandError('Unknown subcommand: {0} {1}'.format(self.app_name, subcommand)) def run_from_argv(self, argv): """Set up any environment changes requested (e.g., Python path and Django settings), then run this command. """ if len(argv) > 2 and not argv[2].startswith('-') and argv[2] in self.subcommands.keys(): subcommand = argv[2] klass = self.get_subcommand(subcommand) parser = OptionParser(prog=argv[0], usage=klass.usage('{0} {1}'.format(argv[1], subcommand)), version=klass.get_version(), option_list=klass.option_list) options, args = parser.parse_args(argv[3:]) args = [subcommand] + args else: parser = self.create_parser(argv[0], argv[1]) options, args = parser.parse_args(argv[2:]) handle_default_options(options) self.execute(*args, **options.__dict__) def handle(self, *args, **options): if not args or args[0] not in self.subcommands.keys(): return self.print_help('./manage.py', self.app_name) subcommand, args = args[0], args[1:] klass = self.get_subcommand(subcommand) # Grab out a list of defaults from the options. optparse does this for # us when the script runs from the command line, but since # call_command can be called programatically, we need to simulate the # loading and handling of defaults (see #10080 for details). defaults = {} for opt in klass.option_list: if opt.default is NO_DEFAULT: defaults[opt.dest] = None else: defaults[opt.dest] = opt.default defaults.update(options) return klass.execute(*args, **defaults)