def run_from_argv(self, argv): _logger.info("Starting to crawl") parser = self._parser options, known_args = parser.parse_known_args(argv[2:]) cmd_options = vars(options) args = cmd_options.pop("args", ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: if options.traceback or not isinstance(e, CommandError): raise # SystemCheckError takes care of its own formatting. if isinstance(e, SystemCheckError): self.stderr.write(str(e), lambda x: x) else: self.stderr.write("%s: %s" % (e.__class__.__name__, e)) sys.exit(1) finally: try: connections.close_all() except ImproperlyConfigured: # Ignore if connections aren't setup at this point (e.g. no # configured settings). pass
def execute_from_command_line(argv=None): from security.command import CommandExecutor def execute_from_command_line_with_stdout(argv=None, stdout=None, stderr=None): try: from django.core.management.base import BaseCommand command_stdout = stdout command_stderr = stderr def command_init_patch(self, stdout=None, stderr=None, no_color=False, force_color=False): stdout = command_stdout if stdout is None else stdout stderr = command_stderr if stderr is None else stderr self._patched_init(stdout=stdout, stderr=stderr, no_color=no_color, force_color=force_color) BaseCommand._patched_init = BaseCommand.__init__ BaseCommand.__init__ = command_init_patch execute_from_command_line_original(argv=argv) finally: BaseCommand.__init__ = BaseCommand._patched_init if len(argv) > 1: # some arguments must be processed before django setup parser_args = (None, ) if StrictVersion( get_main_version()) < StrictVersion('2.1') else tuple() parser = CommandParser(*parser_args, usage='%(prog)s subcommand [options] [args]', add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. django.setup() return CommandExecutor( command_function=execute_from_command_line_with_stdout, command_kwargs={ 'argv': argv }, name=argv[1], input=' '.join(argv[2:]), is_executed_from_command_line=True).run() else: execute_from_command_line_original(argv=argv)
def run_from_argv(self, argv): """ Set up any environment changes requested (e.g., Python path and Django settings), then run this command. """ if '--' in argv: split_at = argv.index('--') command_argv = [argv[0]] + argv[split_at + 1:] if len(command_argv) == 1: print self.usage('daemonize') else: daemon_argv = argv[:split_at] daemon_parser = self.create_daemonize_parser(daemon_argv[0], daemon_argv[1]) daemon_options, daemon_args = daemon_parser.parse_args(daemon_argv[2:]) handle_default_options(daemon_options) parser = self.create_parser(command_argv[0], command_argv[1]) options, args = parser.parse_args(command_argv[2:]) # prepend the execute args with the original command again self.execute(daemon_args=daemon_args, daemon_options=daemon_options.__dict__, command=command_argv[1], command_args=args, command_options=options.__dict__) else: super(Command, self).run_from_argv(argv)
def run_from_argv(self, argv): from django.core.management import ( CommandError, handle_default_options, ) self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) 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', ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: # pylint: disable=broad-except if options.traceback or not isinstance(e, CommandError): raise # SystemCheckError takes care of its own formatting. if isinstance(e, CommandError): self.stderr.write(str(e), lambda x: x) else: self.stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1)
def run_from_argv(self, argv): """ Set up any environment changes requested (e.g., Python path and Django settings), then run this command. If the command raises a ``CommandError``, intercept it and print it sensibly to stderr. If the ``--traceback`` option is present or the raised ``Exception`` is not ``CommandError``, raise it. """ self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) options = parser.parse_args(argv[2:]) # self.set_default_options(options) cmd_options = vars(options) # Move positional args out of options to mimic legacy optparse args = cmd_options.pop("args", ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: if options.traceback or not isinstance(e, CommandError): raise # SystemCheckError takes care of its own formatting. if isinstance(e, SystemCheckError): self.stderr.write(str(e), lambda x: x) else: self.stderr.write("%s: %s" % (e.__class__.__name__, e)) sys.exit(1) finally: connections.close_all()
def __call__(self, argv=None): if argv is None: argv = sys.argv[1:] warnings.filterwarnings('ignore', module="IPython", category=DeprecationWarning) warnings.filterwarnings("ignore", module="distutils") try: warnings.filterwarnings("ignore", category=ResourceWarning) except NameError: pass warnings.filterwarnings("ignore", "invalid escape sequence", DeprecationWarning) # Ignore a deprecation warning in distutils.spawn for python 3.4+ if sys.version_info > (3, 4): warnings.filterwarnings("ignore", "the imp module", Warning) warnings.filterwarnings('once', 'Selenium support for PhantomJS', Warning) import django from django.core.management import CommandParser, handle_default_options # Ignore a python 3.6 DeprecationWarning in ModelBase.__new__ that isn't # fixed in Django 1.x if sys.version_info > (3, 6) and django.VERSION < (2, ): warnings.filterwarnings("ignore", "__class__ not set defining", DeprecationWarning) parser = CommandParser(None, usage="%(prog)s [options] [args]", add_help=False) default_settings = os.environ.get('DJANGO_SETTINGS_MODULE', self.default_settings_module) parser.add_argument('--settings', default=default_settings) parser.add_argument('--pythonpath') parser.add_argument('--testrunner', action='store', default='django_admin_testutils.DiscoverRunner') parser.add_argument('args', nargs='*') options, remaining_args = parser.parse_known_args(argv) handle_default_options(options) test_labels = options.args or [self.default_test_label] flags = ['--testrunner=%s' % options.testrunner] + remaining_args from django.conf import settings if 'grappelli' in settings.INSTALLED_APPS: # Grappelli uses the deprecated django.conf.urls.patterns, but we # don't want this to fail our tests. warnings.filterwarnings("ignore", "django.conf.urls.patterns", Warning) self.execute(flags, test_labels)
def run_command(self, parser, argv): self._make_subcommand_optional(parser) options = self.parse_command(parser, argv) cmd_options = vars(options) args = cmd_options.pop('args', ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: self.handle_exception(e, options) finally: connections.close_all()
def run_from_argv(self, argv): """ Override django's run_from_argv to parse a subcommand. If the subcommand is present, then mangle argv and defer to the subcommand """ self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) try: # first find if we have a known subcommand known, __ = parser.parse_known_args(argv[2:]) except SubcommandsError: known = None is_subcommand = ( known and hasattr(known, "subcommand") and known.subcommand in self.subcommands) if is_subcommand: # if there is a subcommand then move it in argv to the front of other # params and defer to the the subcommand del argv[argv.index(known.subcommand)] argv[1] = "%s %s" % (argv[1], known.subcommand) return self.subcommands[known.subcommand]().run_from_argv(argv) # continue with the normal parsing/execution # and make subcommand optional for action in parser._actions: if action.dest == "subcommand": action.option_strings = [""] try: options = parser.parse_args(argv[2:]) except SubcommandsError as e: # we have to raise SystemExit here if necessary parser.print_usage(sys.stderr) return parser.exit(2, "%s\n" % e) cmd_options = vars(options) args = cmd_options.pop('args', ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: if options.traceback or not isinstance(e, CommandError): raise e if isinstance(e, SystemCheckError): self.stderr.write(str(e), lambda x: x) else: self.stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1) finally: connections.close_all()
def execute_from_command_line(argv=None): # some arguments must be processed before django setup parser = ArgumentParser() parser.add_argument('--settings') parser.add_argument('--pythonpath') options, args = parser.parse_known_args(argv[2:]) handle_default_options(options) django.setup() from security.utils import CommandLogger return CommandLogger( command_function=lambda: execute_from_command_line_original(argv), command_name=argv[1], command_options=' '.join(argv[2:]), executed_from_command_line=True).run()
def run_from_argv(self, argv): """ Set up any environment changes requested (e.g., Python path and Django settings), then run this command. If the command raises a ``CommandError``, intercept it and print it sensibly to stderr. If the ``--traceback`` option is present or the raised ``Exception`` is not ``CommandError``, raise it. """ options = None try: if argv[2:] and not argv[2].startswith("-"): project_code = argv[2] try: Project.objects.get(code=project_code) except Project.DoesNotExist: raise CommandError( "Unrecognised project: %s" % project_code) if argv[3:]: subcommand = argv[3] else: subcommand = "info" try: subcommand = self.subcommands[subcommand]() except KeyError: raise CommandError( "Unrecognised command: %s" % subcommand) return subcommand.run_from_argv( argv[:1] + [subcommand, project_code] + argv[4:]) parser = self.create_parser(argv[0], argv[1]) options, args = parser.parse_args(argv[2:]) handle_default_options(options) self.execute(*args, **options.__dict__) except Exception as e: do_raise = ( "--traceback" in argv or (options and options.traceback or not isinstance(e, CommandError))) if do_raise: raise # self.stderr is not guaranteed to be set here stderr = getattr( self, 'stderr', OutputWrapper(sys.stderr, self.style.ERROR)) stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1)
def execute_from_command_line(argv=None): def execute_from_command_line_with_stdout(argv=None, stdout=None, stderr=None): try: if stdout: sys.stdout = stdout if stderr: sys.stderr = stderr execute_from_command_line_original(argv=argv) finally: if stdout: sys.stdout = sys.__stdout__ if stderr: sys.stderr = sys.__stderr__ if len(argv) > 1: from security.utils import CommandLogger # some arguments must be processed before django setup parser_args = (None, ) if StrictVersion( get_main_version()) < StrictVersion('2.1') else tuple() parser = CommandParser(*parser_args, usage='%(prog)s subcommand [options] [args]', add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. django.setup() return CommandLogger( command_function=execute_from_command_line_with_stdout, command_kwargs={ 'argv': argv }, name=argv[1], input=' '.join(argv[2:]), executed_from_command_line=True).run() else: execute_from_command_line_original(argv=argv)
def __call__(self, argv=None): from django.conf import settings from django.core.management import CommandParser, handle_default_options if argv is None: argv = sys.argv[1:] try: warnings.filterwarnings("ignore", category=ResourceWarning) except NameError: pass warnings.filterwarnings('ignore', module="IPython", category=DeprecationWarning) warnings.filterwarnings("ignore", module="distutils") warnings.filterwarnings("ignore", "invalid escape sequence", DeprecationWarning) warnings.filterwarnings("ignore", "the imp module", Warning) warnings.filterwarnings('once', 'Selenium support for PhantomJS', Warning) default_settings = os.environ.get('DJANGO_SETTINGS_MODULE', self.default_settings_module) parser = CommandParser(usage="%(prog)s [options] [args]", add_help=False) parser.add_argument('--settings', default=default_settings) parser.add_argument('--pythonpath') parser.add_argument('--testrunner', action='store', default='selenosis.DiscoverRunner') parser.add_argument('args', nargs='*') options, remaining_args = parser.parse_known_args(argv) handle_default_options(options) test_labels = options.args or [self.default_test_label] flags = ['--testrunner=%s' % options.testrunner] + remaining_args if 'grappelli' in settings.INSTALLED_APPS: # Grappelli uses the deprecated django.conf.urls.patterns, but we # don't want this to fail our tests. warnings.filterwarnings("ignore", "django.conf.urls.patterns", Warning) self.execute(flags, test_labels)
def execute_from_command_line(argv=None): # some arguments must be processed before django setup parser = ArgumentParser() parser.add_argument('--settings') parser.add_argument('--pythonpath') options, args = parser.parse_known_args(argv[2:]) handle_default_options(options) django.setup() from security.utils import CommandLogger return CommandLogger( command_function=lambda: execute_from_command_line_original(argv), command_name=argv[1], command_options=' '.join(argv[2:]), executed_from_command_line=True ).run()
def run_from_argv(self, argv): """ Set up any environment changes requested (e.g., Python path and Django settings), then run this command. If the command raises a ``CommandError``, intercept it and print it sensibly to stderr. If the ``--traceback`` option is present or the raised ``Exception`` is not ``CommandError``, raise it. """ options = None try: if argv[2:] and not argv[2].startswith("-"): project_code = argv[2] try: Project.objects.get(code=project_code) except Project.DoesNotExist: raise CommandError("Unrecognised project: %s" % project_code) if argv[3:]: subcommand = argv[3] else: subcommand = "info" try: subcommand = self.subcommands[subcommand]() except KeyError: raise CommandError("Unrecognised command: %s" % subcommand) return subcommand.run_from_argv(argv[:1] + [subcommand, project_code] + argv[4:]) parser = self.create_parser(argv[0], argv[1]) options, args = parser.parse_args(argv[2:]) handle_default_options(options) self.execute(*args, **options.__dict__) except Exception as e: do_raise = ("--traceback" in argv or (options and options.traceback or not isinstance(e, CommandError))) if do_raise: raise # self.stderr is not guaranteed to be set here stderr = getattr(self, 'stderr', OutputWrapper(sys.stderr, self.style.ERROR)) stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1)
def run_from_argv(self, argv): """ Override django's run_from_argv to parse a subcommand. If the subcommand is present, then mangle argv and defer to the subcommand """ self._called_from_command_line = True parser = self.create_parser(argv[0], argv[1]) try: # first find if we have a known subcommand known, __ = parser.parse_known_args(argv[2:]) except SubcommandsError: known = None except Exception as e: self.handle_exception(e) is_subcommand = (known and hasattr(known, "subcommand") and known.subcommand in self.subcommands) if is_subcommand: # if there is a subcommand then move it in argv to the front of other # params and defer to the the subcommand del argv[argv.index(known.subcommand)] argv[1] = "%s %s" % (argv[1], known.subcommand) return self.subcommands[known.subcommand]().run_from_argv(argv) # continue with the normal parsing/execution # and make subcommand optional for action in parser._actions: if action.dest == "subcommand": action.option_strings = [""] try: options = parser.parse_args(argv[2:]) except SubcommandsError as e: # we have to raise SystemExit here if necessary parser.print_usage(sys.stderr) return parser.exit(2, "%s\n" % e) cmd_options = vars(options) args = cmd_options.pop('args', ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: self.handle_exception(e, options) finally: connections.close_all()
def run_from_argv(self, argv): global crawler_clazz, crawler crawler_name = argv[2] _logger.info("Calling crawler: {}".format(crawler_name)) crawler_clazz = CrawlersRegistry().get_crawler(crawler_name) crawler = crawler_clazz() parser = crawler.get_parser() options, known_args = \ parser.parse_known_args(argv[2:]) cmd_options = vars(options) cmd_options["crawler"] = crawler.__crawler_name__ # Move positional args out of options to mimic legacy optparse args = cmd_options.pop('args', ()) handle_default_options(options) try: self.execute(*args, **cmd_options) except Exception as e: if options.traceback or not isinstance(e, CommandError): raise # SystemCheckError takes care of its own formatting. if isinstance(e, SystemCheckError): self.stderr.write(str(e), lambda x: x) else: self.stderr.write('%s: %s' % (e.__class__.__name__, e)) sys.exit(1) finally: try: connections.close_all() except ImproperlyConfigured: # Ignore if connections aren't setup at this point (e.g. no # configured settings). pass
def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ # --settings-dir option # will remove it later to avoid django commands from raising errors option_list = BaseCommand.option_list + ( make_option('--settings-dir', action='store', dest='settings_dir', default=None, help='Load *.conf files from directory as settings'),) # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = LaxOptionParser(usage="%prog subcommand [options] [args]", version=get_component_version('webproject'), option_list=option_list) self.autocomplete() try: options, args = parser.parse_args(self.argv) handle_default_options(options) except: pass # Ignore any option errors at this point. # user provides custom settings dir # set it as environmental variable and remove it from self.argv if options.settings_dir: os.environ['SYNNEFO_SETTINGS_DIR'] = options.settings_dir for arg in self.argv: if arg.startswith('--settings-dir'): self.argv.remove(arg) try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Encode stdout. This check is required because of the way python # checks if something is tty: # https://bugzilla.redhat.com/show_bug.cgi?id=841152 if not subcommand in ['test'] and not 'shell' in subcommand: sys.stdout = EncodedStdOut(sys.stdout) if subcommand == 'help': if len(args) > 2: self.fetch_command(args[2]).print_help(self.prog_name, args[2]) else: parser.print_lax_help() sys.stdout.write(self.main_help_text() + '\n') sys.exit(1) # Special-cases: We want 'django-admin.py --version' and # 'django-admin.py --help' to work, for backwards compatibility. elif self.argv[1:] == ['--version']: # LaxOptionParser already takes care of printing the version. pass elif self.argv[1:] in (['--help'], ['-h']): parser.print_lax_help() sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
from django.core.management import execute_manager, handle_default_options, setup_environ import sys, os sys.path.append(os.getcwd()) try: import settings except ImportError: import sys sys.stderr.write( "Error: Can't find the file 'settings.py' in the current directory %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % os.getcwd() ) sys.exit(1) if __name__ == "__main__": from django_install.management.commands import install ## ## TODO ## import logging ## logging.basicConfig(level=logging.DEBUG) ## TODO cmd = install.Command() parser = cmd.create_parser(__file__, "install") options, args = parser.parse_args(sys.argv) setup_environ(settings) handle_default_options(options) cmd.handle(*args[1:]) ## TODO
def execute(self): try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. # Compatible with the processing django_version = django.get_version().split('.') if int(django_version[0]) == 2 and int(django_version[1]) < 1: parser = CommandParser( None, usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False) else: parser = CommandParser( usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc except ImportError as exc: self.settings_exception = exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif not options.args: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ # --settings-dir option # will remove it later to avoid django commands from raising errors option_list = BaseCommand.option_list + ( make_option( '--settings-dir', action='store', dest='settings_dir', default=None, help='Load *.conf files from directory as settings'),) # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = LaxOptionParser(usage="%prog subcommand [options] [args]", version=get_component_version('webproject'), option_list=option_list) self.autocomplete() try: options, args = parser.parse_args(self.argv) handle_default_options(options) except: pass # Ignore any option errors at this point. # user provides custom settings dir # set it as environmental variable and remove it from self.argv if options.settings_dir: os.environ['SYNNEFO_SETTINGS_DIR'] = options.settings_dir for arg in self.argv: if arg.startswith('--settings-dir'): self.argv.remove(arg) try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Encode stdout. This check is required because of the way python # checks if something is tty: # https://bugzilla.redhat.com/show_bug.cgi?id=841152 if subcommand not in ['test'] and 'shell' not in subcommand: sys.stdout = EncodedStream(sys.stdout) sys.stderr = EncodedStream(sys.stderr) if subcommand == 'help': if len(args) > 2: self.fetch_command(args[2]).print_help(self.prog_name, args[2]) else: parser.print_lax_help() sys.stdout.write(self.main_help_text() + '\n') sys.exit(1) # Special-cases: We want 'django-admin.py --version' and # 'django-admin.py --help' to work, for backwards compatibility. elif self.argv[1:] == ['--version']: # LaxOptionParser already takes care of printing the version. pass elif self.argv[1:] in (['--help'], ['-h']): parser.print_lax_help() sys.stdout.write(self.main_help_text() + '\n') else: sub_command = self.fetch_command(subcommand) # NOTE: This is an ugly workaround to bypass the problem with # the required permissions for the named pipes that Pithos backend # is creating in order to communicate with XSEG. if subcommand == 'test' or\ subcommand.startswith('image-') or\ subcommand.startswith('snapshot-') or\ subcommand.startswith('file-'): # Set common umask for known commands os.umask(0o007) # Allow command to define a custom umask cmd_umask = getattr(sub_command, 'umask', None) if cmd_umask is not None: os.umask(cmd_umask) sub_command.run_from_argv(self.argv)
#!/usr/bin/env python from django.core.management import execute_manager, handle_default_options, setup_environ import sys, os sys.path.append(os.getcwd()) try: import settings except ImportError: import sys sys.stderr.write( "Error: Can't find the file 'settings.py' in the current directory %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % os.getcwd()) sys.exit(1) if __name__ == "__main__": from django_install.management.commands import install ## ## TODO ## import logging ## logging.basicConfig(level=logging.DEBUG) ## TODO cmd = install.Command() parser = cmd.create_parser(__file__, "install") options, args = parser.parse_args(sys.argv) setup_environ(settings) handle_default_options(options) cmd.handle(*args[1:]) ## TODO