Metadata-Version: 2.4
Name: cs-cmdutils
Version: 20261016.1
Summary: Convenience functions for working with the cmd stdlib module, the BaseCommand class for constructing command line programmes, and other command line related stuff.
Keywords: python2,python3
Author-email: Cameron Simpson <cs@cskk.id.au>
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Requires-Dist: cs.buffer>=20260915.1
Requires-Dist: cs.context>=20250528
Requires-Dist: cs.deco>=20250531
Requires-Dist: cs.lex>=20261016
Requires-Dist: cs.logutils>=20260912
Requires-Dist: cs.mapping
Requires-Dist: cs.pfx>=20260912
Requires-Dist: cs.printt>=20261016
Requires-Dist: cs.py.doc>=20261016
Requires-Dist: cs.resources>=20250915
Requires-Dist: cs.result>=20261016
Requires-Dist: cs.threads>=20260912
Requires-Dist: cs.typingutils>=20260525
Requires-Dist: cs.upd>=20260912
Requires-Dist: typeguard
Project-URL: MonoRepo Commits, https://bitbucket.org/cameron_simpson/css/commits/branch/main
Project-URL: Monorepo Git Mirror, https://github.com/cameron-simpson/css
Project-URL: Monorepo Hg/Mercurial Mirror, https://hg.sr.ht/~cameron-simpson/css
Project-URL: Source, https://github.com/cameron-simpson/css/blob/main/lib/python/cs/cmdutils.py

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.GetoptError`s, issues a `warning`
  and runs `self.do_help` with the method name,
  then returns `None`
- intercepts other `Exception`s,
  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 `GetoptError`s 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.
