Skip to main content

Convenience functions for working with the cmd stdlib module, the BaseCommand class for constructing command line programmes, and other command line related stuff.

This module provides the following main items:

  • BaseCommand: a base class for creating command line programmes with easier setup and usage than libraries like optparse or argparse
  • @popopts: a decorator which works with BaseCommand subcommand methods to parse their command line options
  • @docmd: a decorator for command methods of a cmd.Cmd class providing better quality of service

Editorial: why not arparse? I find the whole argparse add_argument thing very cumbersome and hard to use and remember. Also, when incorrectly invoked an argparse command line prints the help/usage messgae and aborts the whole programme with SystemExit.

Short summary:

  • apply_quiet: Apply a -q (quiet) option to the verbosity. If we're not quiet, make us quiet. If we're already quiet, make us quieter.

  • apply_verbose: Apply a -v (verbose) option to the verbosity. If we're not quiet, make us quiet. If we're already quiet, make us quieter.

  • BaseCommand: A base class for handling nestable command lines.

  • BaseCommandCmd: A cmd.Cmd subclass used to provide interactive use of a command's subcommands.

  • BaseCommandOptions: A base class for the BaseCommand options object.

  • cli_datetime: Parse an ISO8601 date into a datetime. Being for the command line, this assumes the local timezone has a UTC offset if not specified.

  • docmd: Decorator for cmd.Cmd subclass methods to supply some basic quality of service.

  • OptionSpec: A class to support parsing an option value.

  • popopts: A decorator to parse command line options from a cmd_method's argv, updating self.options.

  • qprint: Call print() if not options.quiet.

  • split_usage: Extract a "Usage:"paragraph from a docstring and return a 3-tuple of (preusage,usage,postusage).

  • SubCommand: An implementation for a subcommand.

  • vprint: Call print() if options.verbose.

  • vvprint: Call print() if options.verbosity>=2.

Functions

apply_quiet(opts, field_name, _)

Apply a -q (quiet) option to the verbosity. If we're not quiet, make us quiet. If we're already quiet, make us quieter.

apply_verbose(opts, field_name, _)

Apply a -v (verbose) option to the verbosity. If we're not quiet, make us quiet. If we're already quiet, make us quieter.

cli_datetime(dt_s: str) -> datetime.datetime

Parse an ISO8601 date into a datetime. Being for the command line, this assumes the local timezone has a UTC offset if not specified.

docmd(dofunc)

Decorator for cmd.Cmd subclass methods to supply some basic quality of service.

This decorator:

  • wraps the function call in a cs.pfx.Pfx for context
  • intercepts getopt.GetoptErrors, issues a warning and runs self.do_help with the method name, then returns None
  • intercepts other Exceptions, issues an exception log message and returns None

The intended use is to decorate cmd.Cmd do_* methods:

from cmd import Cmd
from cs.cmdutils import docmd
...
class MyCmd(Cmd):
    @docmd
    def do_something(...):
        ... do something ...

popopts(*da, **dkw)

A decorator to parse command line options from a cmd_method's argv, updating self.options. This also updates the method's usage message.

Example:

@popopts(x=('trace', 'Trace execution.'))
def cmd_do_something(self, argv):
    """ Usage: {cmd} [-x] blah blah
          Do some thing to blah.
    """

This arranges for cmd_do_something to call self.options.popopts(argv), and updates the usage message with an "Options:" paragraph.

This avoids needing to manually enumerate the options in the docstring usage and avoids explicitly calling self.options.popopts inside the method.

qprint(*print_a, quiet: bool, **print_kw)

Call print() if not options.quiet.

split_usage(doc: Optional[str], usage_marker='Usage:') -> Tuple[str, str, str]

Extract a "Usage:"paragraph from a docstring and return a 3-tuple of (preusage,usage,postusage).

If the usage paragraph is not present '' is returned as the middle comonpent, otherwise it is the unindented usage without the leading "Usage:".

vprint(*print_a, verbose: bool, **print_kw)

Call print() if options.verbose.

vvprint(*print_a, verbosity: int, **print_kw)

Call print() if options.verbosity>=2.

Classes

class BaseCommand

A base class for handling nestable command lines.

This class provides the basic parse and dispatch mechanisms for command lines. To implement a command line one defines a subclass of BaseCommand:

class MyCommand(BaseCommand):
    """ My command to do something. """

and provides either a main method if the command has no subcommands or a suite of cmd_subcommand methods, one per subcommand.

Running a command is done by instantiating it with argv and then calling .run():

MyCommand(argv).run()

Modules which implement a command line mode generally look like this:

... imports etc ...
def main(argv=None, **run_kw):
    """ The command line mode.
    """
    return MyCommand(argv).run(**run_kw)
... other code ...
class MyCommand(BaseCommand):
... other code ...
if __name__ == '__main__':
    sys.exit(main(sys.argv))

Instances have a self.options attribute on which optional modes are set, avoiding conflict with the attributes of self.

The self.options object is an instance of the class' Options class. The default comes from BaseCommand.Options (aka BaseCommandOptions) but classes with additional command line options will usually provide their own Options subclass:

class MyCommand(BaseCommand):

    @dataclass
    class Options(BaseCommand.Options):
        extra_mode : str = None
        some_flag : bool = False

        # extend the common options for the new fields
        COMMON_OPT_SPECS = dict(
            **BaseCommand.Options.COMMON_OPT_SPECS,
            mode_=('extra_mode', 'The extra mode to do something.'),
            flag='some_flag',
        )

This adds an additional --mode mode and a --flag command line option which affects the fields of self.options and updates the automaticly generated usage messages accordingly. See the documentation for BaseCommandOptions.popopts for explaination of the COMMON_OPT_SPECS values.

Subclasses with no subcommands generally just implement a main(argv) method.

Subclasses with subcommands should implement a cmd_subcommand(argv) instance method for each subcommand. If a subcommand is itself implemented using BaseCommand then it can be a simple attribute:

cmd_subthing = SubThingCommand

Returning to methods, if there is a paragraph in the method docstring commencing with Usage: then that paragraph is incorporated into the main usage message automatically.

Example:

@popopts(l='long_mode')
def cmd_ls(self, argv):
    """ Usage: {cmd} [-l] [paths...]
          Emit a listing for the named paths.

        Further docstring non-usage information here.
    """
    ... do the "ls" subcommand ...
    ... with use of self.options.long_mode as needed ...

The subclass is customised by overriding the following methods:

  • run_context(): a context manager to provide setup or teardown actions to occur before and after the command implementation respectively, such as to open and close a database.
  • cmd_subcmd(argv): if the command line options are followed by an argument whose value is subcmd, then the method cmd_subcmd(subcmd_argv) will be called where subcmd_argv contains the command line arguments following subcmd.
  • main(argv): if there are no cmd_subcmd methods then method main(argv) will be called where argv contains the command line arguments.A base class for handling nestable command lines.

This class provides the basic parse and dispatch mechanisms for command lines. To implement a command line one defines a subclass of BaseCommand:

class MyCommand(BaseCommand):
    """ My command to do something. """

and provides either a main method if the command has no subcommands or a suite of cmd_subcommand methods, one per subcommand.

Running a command is done by instantiating it with argv and then calling .run():

MyCommand(argv).run()

Modules which implement a command line mode generally look like this:

... imports etc ...
def main(argv=None, **run_kw):
    """ The command line mode.
    """
    return MyCommand(argv).run(**run_kw)
... other code ...
class MyCommand(BaseCommand):
... other code ...
if __name__ == '__main__':
    sys.exit(main(sys.argv))

Instances have a self.options attribute on which optional modes are set, avoiding conflict with the attributes of self.

The self.options object is an instance of the class' Options class. The default comes from BaseCommand.Options (aka BaseCommandOptions) but classes with additional command line options will usually provide their own Options subclass:

class MyCommand(BaseCommand):

    @dataclass
    class Options(BaseCommand.Options):
        extra_mode : str = None
        some_flag : bool = False

        # extend the common options for the new fields
        COMMON_OPT_SPECS = dict(
            **BaseCommand.Options.COMMON_OPT_SPECS,
            mode_=('extra_mode', 'The extra mode to do something.'),
            flag='some_flag',
        )

This adds an additional --mode mode and a --flag command line option which affects the fields of self.options and updates the automaticly generated usage messages accordingly. See the documentation for BaseCommandOptions.popopts for explaination of the COMMON_OPT_SPECS values.

Subclasses with no subcommands generally just implement a main(argv) method.

Subclasses with subcommands should implement a cmd_subcommand(argv) instance method for each subcommand. If a subcommand is itself implemented using BaseCommand then it can be a simple attribute:

cmd_subthing = SubThingCommand

Returning to methods, if there is a paragraph in the method docstring commencing with `Example:

@popopts(l='long_mode')
def cmd_ls(self, argv):
    """ Usage: {cmd} [-l] [paths...]
          Emit a listing for the named paths.

        Further docstring non-usage information here.
    """
    ... do the "ls" subcommand ...
    ... with use of self.options.long_mode as needed ...

The subclass is customised by overriding the following methods:

  • run_context(): a context manager to provide setup or teardown actions to occur before and after the command implementation respectively, such as to open and close a database.
  • cmd_subcmd(argv): if the command line options are followed by an argument whose value is subcmd, then the method cmd_subcmd(subcmd_argv) will be called where subcmd_argv contains the command line arguments following subcmd.
  • main(argv): if there are no cmd_subcmd methods then method main(argv) will be called where argv contains the command line arguments.

Usage summary:

Usage: ` then that paragraph is incorporated
  into the main usage message automatically.
  Subcommands:
    help [common-options...] [-l] [-s] [subcommand-names...]
      Print help for subcommands.
      This outputs the full help for the named subcommands,
      or the short help for all subcommands if no names are specified.
      Options:
        -l  Long listing.
        -r  Recurse into subcommands.
        -s  Short listing.
    info [common-options...] [field-names...]
      Recite general information.
      Explicit field names may be provided to override the default listing.
    repl [common-options...]
      Run a REPL (Read Evaluate Print Loop), an interactive Python prompt.
      Options:
        --banner banner  Banner.
    shell [common-options...]
      Run a command prompt via cmd.Cmd using this command's subcommands.

BaseCommand.__init__(self, argv=None, *, cmd=None, options=None, **kw_options) -> str

Initialise the command line. Return the subcommand name, or None if there is only main. Raises GetoptError for unrecognised options.

Parameters:

  • argv: optional command line arguments including the main command name if cmd is not specified. The default is sys.argv. The contents of argv are copied, permitting desctructive parsing of argv.
  • cmd: optional keyword specifying the command name for context; if this is not specified it is taken from argv.pop(0).
  • options: an optional keyword providing object for command state and context. If not specified a new self.Options instance is allocated for use as options. The default Options class is BaseCommandOptions, a dataclass with some prefilled attributes and properties to aid use later. Other keyword arguments are applied to self.options as attributes.

The cmd and argv parameters have some fiddly semantics for convenience. There are 3 basic ways to initialise:

  • BaseCommand(): argv comes from sys.argv and the value for cmd is derived from argv[0]
  • BaseCommand(argv): argv is the complete command line including the command name and the value for cmd is derived from argv[0]
  • BaseCommand(argv, cmd=foo): argv is the command arguments after the command name and cmd is set to foo

The command line arguments are parsed according to the optional GETOPT_SPEC class attribute (default ''). If getopt_spec is not empty then apply_opts(opts) is called to apply the supplied options to the state where opts is the return from getopt.getopt(argv,getopt_spec).

After the option parse, if the first command line argument foo has a corresponding method cmd_foo then that argument is removed from the start of argv and self.cmd_foo(argv,options,cmd=foo) is called and its value returned. Otherwise self.main(argv,options) is called and its value returned.

If the command implementation requires some setup or teardown then this may be provided by the run_context context manager method, called with cmd=subcmd for subcommands and with cmd=None for main.

BaseCommand.GETOPT_SPEC

''

BaseCommand.SUBCOMMAND_ARGV_DEFAULT

None

BaseCommand.SUBCOMMAND_METHOD_PREFIX

'cmd_'

BaseCommand.USAGE_FORMAT

('` then that paragraph is incorporated\n'
 '  into the main usage message automatically.')

BaseCommand.apply_opt(self, opt, val)

Handle an individual global command line option.

This default implementation raises a NotImplementedError. It only fires if getopt actually gathered arguments and would imply that a GETOPT_SPEC was supplied without an apply_opt or apply_opts method to implement the options.

BaseCommand.apply_opts(self, opts)

Apply command line options.

Subclasses can override this but it is usually easier to override apply_opt(opt,val).

BaseCommand.apply_preargv(self, argv)

Do any preparsing of argv before the subcommand/main-args. Return the remaining arguments.

This default implementation does nothing.

BaseCommand.cmd_help(self, argv)

Usage: {cmd} [-l] [-s] [subcommand-names...] Print help for subcommands. This outputs the full help for the named subcommands, or the short help for all subcommands if no names are specified. Options: -l Long listing. -r Recurse into subcommands. -s Short listing.

BaseCommand.cmd_info(self, argv, *, field_names=None, skip_names=None)

Usage: {cmd} [field-names...] Recite general information. Explicit field names may be provided to override the default listing.

This default method recites the values from self.options, excluding those enumerated by self.options.INFO_SKIP_NAMES.

This base method provides two optional parameters to allow subclasses to tune its behaviour:

  • field_namees: an explicit list of options attributes to print
  • skip_names: a list of option attributes to not print, default from self.options.INFO_SKIP_NAMES

BaseCommand.cmd_repl(self, argv)

Usage: {cmd} Run a REPL (Read Evaluate Print Loop), an interactive Python prompt. Options: --banner banner Banner.

BaseCommand.cmd_shell(*a, upd: Optional[cs.upd.Upd] = <function uses_upd.<locals>.<lambda> at 0x107c43ce0>, **kw)

Usage: {cmd} Run a command prompt via cmd.Cmd using this command's subcommands.

BaseCommand.cmdloop(self, intro=None)

Use cmd.Cmd to run a command loop which calls the cmd_* methods.

BaseCommand.extract_usage(cmd=None)

Extract the Usage: paragraph from cls__doc__ if present. Return a 2-tuple of (doc_without_usage,usage_text) being the remaining docstring and a full usage message.

Note: this actually sets cls.USAGE_FORMAT if that does not already exist.

BaseCommand.getopt_error_handler(cmd, options, e, usage, subcmd=None)

The getopt_error_handler method is used to control the handling of GetoptErrors raised during the command line parse or during the main or cmd_subcmd` calls.

This default handler issues a warning containing the exception text, prints the usage message to standard error, and returns True to indicate that the error has been handled.

The handler is called with these parameters:

  • cmd: the command name
  • options: the options object
  • e: the GetoptError exception
  • usage: the command usage or None if this was not provided
  • subcmd: optional subcommand name; if not None, is the name of the subcommand which caused the error

It returns a true value if the exception is considered handled, in which case the main run method returns 2. It returns a false value if the exception is considered unhandled, in which case the main run method reraises the GetoptError.

To let the exceptions out unhandled this can be overridden with a method which just returns False.

Otherwise, the handler may perform any suitable action and return True to contain the exception or False to cause the exception to be reraised.

BaseCommand.handle_signal(self, sig, frame, *, runstate: Optional[cs.resources.RunState] = <function uses_runstate.<locals>.<lambda> at 0x107c43100>)

The default signal handler, which cancels the default RunState.

BaseCommand.has_subcommands(self)

Test whether the class defines additional subcommands.

BaseCommand.method_cmdname(method_name: str)

The cmd value from a method name.

BaseCommand.pop_buffer(argv: List[str]) -> Tuple[str, Optional[cs.buffer.CornuCopyBuffer]]

Return a (filespec,CornuCopyBuffer) 2-tuple from thw first string in argv. The name "-" means the standard input (sys.stdin). If the file is missing or stdin is a tty the yielded buffer is None.

BaseCommand.pop_buffers(argv: List[str]) -> Iterable[Tuple[str, Optional[cs.buffer.CornuCopyBuffer]]]

A generator yielding (filespec,CornuCopyBuffer) 2-tuples for each string in argv specifying a file. The name "-" means the standard input (sys.stdin). If a file is missing or stdin is a tty the yielded buffer is None. Filespecs are consumed from argv one at a time, so ceasing iteration of the generator leaves the tail of argv unconsumed.

BaseCommand.poparg(argv: List[str], *specs, unpop_on_error: bool = False, opt_spec_class=None)

Pop the leading argument off argv and parse it. Return the parsed argument. Raises getopt.GetoptError on a missing or invalid argument.

This is expected to be used inside a main or cmd_* command handler method or inside apply_preargv.

You can just use:

value = argv.pop(0)

but this method provides conversion and valuation and a richer failure mode.

Parameters:

  • argv: the argument list, which is modified in place with argv.pop(0)
  • the argument list argv may be followed by some help text and/or an argument parser function.
  • validate: an optional function to validate the parsed value; this should return a true value if valid, or return a false value or raise a ValueError if invalid
  • unvalidated_message: an optional message after validate for values failing the validation
  • unpop_on_error: optional keyword parameter, default False; if true then push the argument back onto the front of argv if it fails to parse; GetoptError is still raised

Typical use inside a main or cmd_* method might look like:

self.options.word = self.poparg(argv, int, "a count value")
self.options.word = self.poparg(
    argv, int, "a count value",
   lambda count: count > 0, "count should be positive")

Because it raises GetoptError on a bad argument the normal usage message failure mode follows automatically.

Demonstration:

>>> argv = ['word', '3', 'nine', '4']
>>> BaseCommand.poparg(argv, "word to process")
'word'
>>> BaseCommand.poparg(argv, int, "count value")
3
>>> BaseCommand.poparg(argv, float, "length")
Traceback (most recent call last):
  ...
getopt.GetoptError: length 'nine': float('nine'): could not convert string to float: 'nine'
>>> BaseCommand.poparg(argv, float, "width", lambda width: width > 5)
Traceback (most recent call last):
  ...
getopt.GetoptError: width '4': invalid value
>>> BaseCommand.poparg(argv, float, "length")
Traceback (most recent call last):
  ...
getopt.GetoptError: length: missing argument
>>> argv = ['-5', 'zz']
>>> BaseCommand.poparg(argv, float, "size", lambda size: size > 0, "size should be >0")
Traceback (most recent call last):
  ...
getopt.GetoptError: size '-5': size should be >0
>>> argv  # -5 was still consumed
['zz']
>>> BaseCommand.poparg(argv, float, "size2", unpop_on_error=True)
Traceback (most recent call last):
  ...
getopt.GetoptError: size2 'zz': float('zz'): could not convert string to float: 'zz'
>>> argv  # zz was pushed back
['zz']

BaseCommand.popopts(self, argv, options, **opt_specs)

OBSOLETE version of popopts, suggestion: self.options.popopts

A convenience shim which returns self.options.popopts(argv,**opt_specs).

BaseCommand.repl(self, *argv, banner=None, local=None)

Run an interactive Python prompt with some predefined local names. Aka REPL (Read Evaluate Print Loop).

Parameters:

  • argv: any notional command line arguments
  • banner: optional banner string
  • local: optional local names mapping

The default local mapping is a dict containing:

  • argv: from argv
  • options: from self.options
  • self: from self
  • the attributes of options
  • the attributes of self

BaseCommand.run(self, **kw_options)

Run a command. Returns the exit status of the command. May raise GetoptError from subcommands.

Any keyword arguments are used to override self.options attributes for the duration of the run, for example to presupply a shared Upd from an outer context.

If the first command line argument foo has a corresponding method cmd_foo then that argument is removed from the start of argv and self.cmd_foo(cmd=foo) is called and its value returned. Otherwise self.main(argv) is called and its value returned.

If the command implementation requires some setup or teardown then this may be provided by the run_context() context manager method.

BaseCommand.run_context(*a, upd: Optional[cs.upd.Upd] = <function uses_upd.<locals>.<lambda> at 0x107c43420>, **kw)

The context manager which surrounds main or cmd_subcmd.

A new self.options object is prepared as a copy of the current self.options so that subcommands are free to modify its values; this is yielded from the context manager.

This default does several things, and subclasses should override it like this:

@contextmanager
def run_context(self):
  with super().run_context() as options:
    try:
      ... subclass context setup ...
      ... possibly modifying the new options ...
      yield options
    finally:
      ... any unconditional cleanup ...

This base implementation does the following things:

  • provides a self.options which is a copy of the original self.options so that it may freely be modified during the command
  • provides a prevailing RunState as self.options.runstate if one is not already present
  • provides a cs.upd.Upd context for status lines
  • catches self.options.runstate_signals and handles them with self.handle_signal

BaseCommand.subcommand

<functools.cached_property object at 0x10757f1d0>

BaseCommand.subcommand_names

<property object at 0x107c7fdd0>

BaseCommand.subcommand_usage_text(self, subcmd, usage_format_mapping=None, short=False)

Return the usage text for a subcommand.

BaseCommand.usage_text(self, **subcommand_kw)

Compute the "Usage:" message for this class. Parameters are as for SubCommand.usage_text.

class BaseCommandCmd(cmd.Cmd)

A cmd.Cmd subclass used to provide interactive use of a command's subcommands.

The BaseCommand.cmdloop() class method instantiates an instance of this and calls its .cmdloop() method i.e. cmd.Cmd.cmdloop.

BaseCommandCmd.get_names(self)

Return a list of the subcommand names.

class BaseCommandOptions(cs.threads.HasThreadState)

A base class for the BaseCommand options object.

This is the default class for the self.options object available during BaseCommand.run(), and available as the BaseCommand.Options attribute.

Any keyword arguments are applied as field updates to the instance.

It comes prefilled with:

  • .dry_run=False
  • .force=False
  • .quiet=False
  • .ssh_exe='ssh'
  • .verbose=False and a .doit property which is the inverse of .dry_run.

It is recommended that if BaseCommand subclasses use a different type for their Options that it should be a subclass of BaseCommandOptions. Since BaseCommandOptions is a data class, this typically looks like:

@dataclass
class Options(BaseCommand.Options):
    ... optional extra fields etc ...

BaseCommandOptions.COMMON_OPT_SPECS

{   'dry_run': ('dry_run', 'Dry run, aka no action.'),
    'e_': (   'ssh_exe',
              ' An ssh-like command to use for remote command execution.\n'
              '            The string is a shell-like command string parsable '
              'by shlex.split.'),
    'n': ('dry_run', 'No action, aka dry run.'),
    'q': ('quiet', <function apply_quiet at 0x107dc3a60>),
    'v': ('verbose', <function apply_verbose at 0x107c40d60>)}

BaseCommandOptions.DEFAULT_SIGNALS

(   <Signals.SIGHUP: 1>,
    <Signals.SIGINT: 2>,
    <Signals.SIGQUIT: 3>,
    <Signals.SIGTERM: 15>)

BaseCommandOptions.INFO_SKIP_NAMES

('runstate', 'runstate_signals')

BaseCommandOptions.__call__(self, **updates)

Calling the options object returns a context manager whose value is a shallow copy of the options with any updates applied.

Example showing the semantics:

>>> from cs.cmdutils import BaseCommandOptions
>>> @dataclass
... class DemoOptions(BaseCommandOptions):
...   x: int = 0
...
>>> options = DemoOptions(x=1)
>>> assert options.x == 1
>>> assert not options.verbose
>>> with options(verbose=True) as subopts:
...     assert options is not subopts
...     assert options.x == 1
...     assert not options.verbose
...     assert subopts.x == 1
...     assert subopts.verbose
...
>>> assert options.x == 1
>>> assert not options.verbose

BaseCommandOptions.__hash__

None

BaseCommandOptions.__post_init__(self)

A empty base post __init__ method so that all subclasses' __post_init__s can call their super().__post_init__.

BaseCommandOptions.as_dict(self)

Return the options as a dict. This contains all the public attributes of self.

BaseCommandOptions.cmd

None

BaseCommandOptions.copy(self, **updates)

Return a new instance of BaseCommandOptions (well, type(self)) which is a shallow copy of the public attributes from self.__dict__.

Any keyword arguments are applied as attribute updates to the copy.

BaseCommandOptions.doit

<property object at 0x107c7f9c0>

BaseCommandOptions.dry_run

False

BaseCommandOptions.fields_as_dict(self)

Return the options' fields as a dict. This contains all the field values of self.

BaseCommandOptions.force

False

BaseCommandOptions.getopt_spec_map(opt_specs_kw: Mapping, common_opt_specs=None)

Return a 3-tuple of (shortopts,longopts,getopt_spec_map) being:

  • shortopts: the getopt() short options specification string
  • longopts: the getopts() long option specification list
  • getopt_spec_map: a mapping of opt->OptionSpec where opt is as from opt,val from getopt() and opt_spec is the associated OptionSpec instance

BaseCommandOptions.perthread_state(**kw)

A Thread local object with attributes which can be used as a context manager to stack attribute values.

Example:

from cs.threads import ThreadState

S = ThreadState(verbose=False)

with S(verbose=True) as prev_attrs:
    if S.verbose:
        print("verbose! (formerly verbose=%s)" % prev_attrs['verbose'])

BaseCommandOptions.popopts(self, argv, **opt_specs_kw)

Parse option switches from argv, a list of command line strings with leading option switches and apply them to self. Modify argv in place.

Example use in a BaseCommand cmd_foo method:

def cmd_foo(self, argv):
    options = self.options
    options.popopts(
        c_='config',
        l='long',
        x='trace',
    )
    if self.options.dry_run:
        print("dry run!")

The expected options are specified by the keyword parameters in opt_specs. Each keyword name has the following semantics:

  • options not starting with a letter may be preceeded by an underscore to allow use in the parameter list, for example _1='once' for a -1 option setting the once option name
  • a single letter name specifies a short option and a multiletter name specifies a long option
  • options requiring an argument have a trailing underscore
  • options not requiring an argument normally imply a value of True; if their synonym commences with a dash they will imply a value of False, for example n='dry_run',y='-dry_run'.

The BaseCommand class provides a popopts method which is a shim for this method applied to its .options. So common use in a command method usually looks like this:

class SomeCommand(BaseCommand):

    def cmd_foo(self, argv):
        # accept a -j or --jobs options
        self.popopts(argv, jobs=1, j='jobs')
        print("jobs =", self.options.jobs)

The self.options object is preprovided as an instance of the self.Options class, which is BaseCommandOptions by default. There is presupplies support for some basic options like -v for "verbose" and so forth, and a subcommand need not describe these in a call to self.options.popopts().

Example:

>>> import os.path
>>> from typing import Optional
>>> @dataclass
... class DemoOptions(BaseCommandOptions):
...   all: bool = False
...   jobs: int = 1
...   number: int = 0
...   once: bool = False
...   path: Optional[str] = None
...   trace_exec: bool = False
...
>>> options = DemoOptions()
>>> argv = ['-1', '-v', '-y', '-j4', '--path=/foo', 'bah', '-x']
>>> opt_dict = options.popopts(
...   argv,
...   _1='once',
...   a='all',
...   j_=('jobs',int),
...   x='-trace_exec',
...   y='-dry_run',
...   dry_run=None,
...   path_=(str, os.path.isabs, 'not an absolute path'),
...   verbose=None,
... )
>>> opt_dict
{'once': True, 'verbose': True, 'dry_run': False, 'jobs': 4, 'path': '/foo'}
>>> options # doctest: +ELLIPSIS
DemoOptions(cmd=None, dry_run=False, force=False, quiet=False, runstate_signals=(...), verbose=True, all=False, jobs=4, number=0, once=True, path='/foo', trace_exec=False)

BaseCommandOptions.quiet

<property object at 0x107c7ff60>

BaseCommandOptions.runstate

None

BaseCommandOptions.runstate_signals

(   <Signals.SIGHUP: 1>,
    <Signals.SIGINT: 2>,
    <Signals.SIGQUIT: 3>,
    <Signals.SIGTERM: 15>)

BaseCommandOptions.update(self, **updates)

Modify the options in place with the mapping updates. It would be more normal to call the options in a with statement as shown for __call__.

BaseCommandOptions.usage_options_format(headline='Options:', *, _common_opt_specs=None, **opt_specs_kw)

Return an options paragraph describing opt_specs_kw. or '' if opt_specs_kw is empty.

BaseCommandOptions.verbose

<property object at 0x107c7fbf0>

BaseCommandOptions.verbosity

0

class OptionSpec

A class to support parsing an option value.

OptionSpec.UNVALIDATED_MESSAGE_DEFAULT

'invalid value'

OptionSpec.__hash__

None

OptionSpec.__post_init__(self)

Infer field_name and help_text if unspecified.

OptionSpec.accrues

False

OptionSpec.add_argument(self, parser, options=None)

Add this option to an argparser-style option parser. The optional options parameter may be used to supply an Options instance to provide a default value.

OptionSpec.apply

None

OptionSpec.arg_name

None

OptionSpec.field_default

None

OptionSpec.field_name

None

OptionSpec.from_opt_kw(opt_k: str, specs: Union[str, List, Tuple, NoneType])

Factory to produce an OptionSpec from a (key,specs) 2-tuple as from the items() from a popopts() call.

The specs is normally a list or tuple, but a bare string will be promoted to a 1-element list containing the string.

The elements of specs are considered in order for:

  • an identifier specifying the arg_name, optionally prepended with a dash to indicate an inverted option
  • a help text about the option
  • if the option expects an argument:
    • a callable to parse the option string value to obtain the actual value
    • a callable to validate the option value
    • a message for use when validation fails
  • a callable to apply the option as apply(options,field,value)

OptionSpec.getopt_long

<property object at 0x107dae980>

OptionSpec.getopt_opt

<property object at 0x107c868e0>

OptionSpec.getopt_short

<property object at 0x107cae750>

OptionSpec.help_text

None

OptionSpec.help_text_from_field_name(field_name)

Compute an inferred help_text from an option field_name.

OptionSpec.needs_arg

<property object at 0x107c79030>

OptionSpec.option_terse(self)

Return the "-x" or "--name" option string (with the arg name if expected).

OptionSpec.option_usage(self)

A 2 line usage entry for this option.

Example:

-j jobs
  Job limit.

OptionSpec.parse

None

OptionSpec.parse_value(self, value)

Parse value according to the spec. Raises GetoptError for invalid values.

OptionSpec.unvalidated_message

'invalid value'

OptionSpec.validate

None

class SubCommand

An implementation for a subcommand.

SubCommand.__call__(self, argv: List[str])

Run the subcommand.

Parameters:

  • argv: the command line arguments after the subcommand name

SubCommand.__hash__

None

SubCommand.cmd

None

SubCommand.get_subcommands(self)

Return self.method's mapping of subcommand name to SubCommand.

SubCommand.get_usage_format(self, show_common=False) -> str

Return the usage format string for this subcommand. Note: no leading "Usage:" prefix. If show_common is true, include the Common options: paragraph.

SubCommand.get_usage_keywords(self, *, cmd: Optional[str] = None, usage_mapping: Optional[Mapping] = None) -> Mapping[str, str]

Return a mapping to be used when formatting the usage format string.

This is an elaborate ChainMap of:

  • the optional cmd or self.cmd
  • the optional usage_mapping parameter
  • self.usage_mapping
  • self.method.USAGE_KEYWORDS if present
  • the attributes of self.command
  • the attributes of type(self.command)
  • the attributes of the module for type(self.command)

SubCommand.has_subcommands(self)

Whether this SubCommand's .method has subcommands.

SubCommand.instance

<property object at 0x107c7fc40>

SubCommand.short_subusages(self, subcmds: List[str], *, recurse=False, short=False)

Return a list of tabulated one line subcommand summaries.

SubCommand.subcommand_names

<property object at 0x107daf150>

SubCommand.subusage_table(self, subcmds: List[str], *, recurse=False, short=False)

Return rows for use with cs.lex.tabulate for the short subusage listing.

SubCommand.usage_commonopts_format

<functools.cached_property object at 0x107b99e50>

SubCommand.usage_default

<functools.cached_property object at 0x107b99cd0>

SubCommand.usage_format

<functools.cached_property object at 0x107b97c20>

SubCommand.usage_format_desc1

<functools.cached_property object at 0x107c402d0>

SubCommand.usage_format_parts

<functools.cached_property object at 0x107b97cd0>

SubCommand.usage_format_usage

<functools.cached_property object at 0x107c40050>

SubCommand.usage_text(self, *, cmd=None, short: bool, recurse: bool = False, show_common: bool = False, show_subcmds: Union[bool, str, Iterable[str], NoneType] = None, usage_mapping: Optional[Mapping] = None, seen_subcmds: Iterable[str] = ()) -> str

Return the filled out usage text for this subcommand.

Metadata

Release files for cs-cmdutils 20261016.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cs-cmdutils 20261016.1
File Size Uploaded
cs_cmdutils-20261016.1.tar.gz 40.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cs-cmdutils 20261016.1
File Interpreter ABI Platform
cs_cmdutils-20261016.1-py3-none-any.whl Python 3 none any Details

Total release size: 73.9 kB

Release files / cs_cmdutils-20261016.1.tar.gz

Download URL cs_cmdutils-20261016.1.tar.gz
Size 40.8 kB
Tags Source
SHA-256 checksum
How to use checksums
ca1d86416e2f4f37684fef2a6e6ec64a8609a6d75f0f5368b1ee2dee3b2ebe29
BLAKE2b-256 checksum
How to use checksums
b1e92d03eb9a8e6a226848a2f997199be4031205825b9bdf42d6dd3526e2b876
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.1

Release files / cs_cmdutils-20261016.1-py3-none-any.whl

Download URL cs_cmdutils-20261016.1-py3-none-any.whl
Size 33.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
084a8e2a3fd013996956756a30161337a644c835247a12879daa20a532708ccf
BLAKE2b-256 checksum
How to use checksums
658eedbdf63e715c81216e9525243835d59cf51fd97a4d426f24643bdb2d2a86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.1

Release history Release notifications | RSS feed

This release

20261016.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page