Convenience functions for working with the Cmd module
and other command line related stuff.

*Latest release 20210404*:
BaseCommand subclasses: automatically add the main usage message to the subclass docstring.

## 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 instantiates a subclass of `BaseCommand`:

    class MyCommand(BaseCommand):
        GETOPT_SPEC = 'ab:c'
        USAGE_FORMAT = r"""Usage: {cmd} [-a] [-b bvalue] [-c] [--] arguments...
          -a    Do it all.
          -b    But using bvalue.
          -c    The 'c' option!
        """
        ...

Running a command is done by:

    MyCommand(argv).run()

Modules which implement a command line mode generally look like:

    ... imports etc ...
    def main(argv=None):
        return MyCommand(argv).run()
    ... 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`.

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

Subclasses with subcommands
should implement a `cmd_`*subcommand*`(argv)` method
for each subcommand.
If there is a paragraph in the method docstring
commencing with `Usage:`
then that paragraph is incorporated automatically
into the main usage message.
Example:

    def cmd_ls(self, argv):
        """ Usage: {cmd} [paths...]
              Emit a listing for the named paths.

            Further docstring non-usage information here.
        """
        ... do the "ls" subcommand ...

The subclass is customised by overriding the following methods:
* `apply_defaults()`:
  prepare the initial state of `self.options`
  before any command line options are applied.
* `apply_opt(opt,val)`:
  apply an individual getopt global command line option
  to `self.options`.
* `apply_opts(opts)`:
  apply the `opts` to `self.options`.
  `opts` is an `(option,value)` sequence
  as returned by `getopot.getopt`.
  The default implementation iterates over these and calls `apply_opt`.
* `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 command line aguments after the options
  or the first argument does not have a corresponding
  `cmd_`*subcmd* method
  then method `main(argv)`
  will be called where `argv` contains the command line arguments.
* `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.

Editorial: why not arparse?
Primarily because when incorrectly invoked
an argparse command line prints the help/usage messgae
and aborts the whole programme with `SystemExit`.

### Method `BaseCommand.__init__(self, argv=None, *, cmd=None, **kw_options)`

Initialise the command line.
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`.
* `options`:
  a optional object for command state and context.
  If not specified a new `SimpleNamespace`
  is allocated for use as `options`,
  and prefilled with `.cmd` set to `cmd`
  and other values as set by `.apply_defaults()`
  if such a method is provided.
* `cmd`:
  optional command name for context;
  if this is not specified it is taken from `argv.pop(0)`.
Other keyword arguments are applied to `self.options`
as attributes.

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.OPTIONS_CLASS`

### Method `BaseCommand.__init_subclass__()`

Update subclasses of `BaseCommand`.

Appends the usage message to the class docstring.

### Method `BaseCommand.apply_defaults(self)`

Stub `apply_defaults` method.

Subclasses can override this to set up the initial state of `self.options`.

### Method `BaseCommand.apply_opt(self, opt, val)`

Handle a individual global command line option.

### Method `BaseCommand.apply_opts(self, opts)`

Apply command line options.

### Method `BaseCommand.cmd_help(argv, options)`

Usage: {cmd} [subcommand-names...]
Print the help for the named subcommands,
or for all subcommands if no names are specified.

### Method `BaseCommand.getopt_error_handler(cmd, options, e, usage)`

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.

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

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`.

This default handler prints an error message to standard error,
prints the usage message (if specified) to standard error,
and returns `True` to indicate that the error has been handled.

To let the exceptions out unhandled
this can be overridden with a method which just returns `False`
or even by setting the `getopt_error_handler` attribute to `None`.

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

### Method `BaseCommand.run(self)`

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

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,
called with `cmd=`*subcmd* for subcommands
and with `cmd=None` for `main`.

### Method `BaseCommand.run_context()`

Stub context manager which surrounds `main` or `cmd_`*subcmd*.

### Method `BaseCommand.subcommand_usage_text(subcmd, fulldoc=False, usage_format_mapping=None)`

Return the usage text for a subcommand.

Parameters:
* `subcmd`: the subcommand name
* `fulldoc`: if true (default `False`)
  return the full docstring with the Usage section expanded
  otherwise just return the Usage section.

### Method `BaseCommand.subcommands()`

Return a mapping of subcommand names to class attributes
for attributes which commence with `cls.SUBCOMMAND_METHOD_PREFIX`
by default `'cmd_'`.

### Method `BaseCommand.usage_text(*a, **kw)`

Compute the "Usage:" message for this class
from the top level `USAGE_FORMAT`
and the `'Usage:'`-containing docstrings
from its `cmd_*` methods.

This is a cached method because it tries to update the
method docstrings after formatting, which is bad if it
happens more than once.

## Function `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 ...

# Release Log



*Release 20210404*:
BaseCommand subclasses: automatically add the main usage message to the subclass docstring.

*Release 20210306*:
* BREAKING CHANGE: rework BaseCommand as a more normal class instantiated with argv and with most methods being instance methods, getting the former `options` parameter from self.options.
* BaseCommand: provide default `apply_opt` and `apply_opts` methods; subclasses will generally just override the former.

*Release 20210123*:
BaseCommand: propagate the format mapping (cmd, USAGE_KEYWORDS) to the subusage generation.

*Release 20201102*:
* BaseCommand.cmd_help: supply usage only for "all commands", full docstring for specified commands.
* BaseCommand: honour presupplied options.log_level.
* BaseCommand.usage_text: handle missing USAGE_FORMAT better.
* BaseCommand.run: provide options.upd.
* BaseCommand subclasses may now override BaseCommand.OPTIONS_CLASS (default SimpleNamespace) in order to provide convenience methods on the options.
* BaseCommand.run: separate variable for subcmd with dash translated to underscore to match method names.
* Minor fixes.

*Release 20200615*:
BaseCommand.usage_text: do not mention the "help" command if it is the only subcommand (it won't be available if there are no other subcommands).

*Release 20200521.1*:
Fix DISTINFO.install_requires.

*Release 20200521*:
* BaseCommand.run: support using BaseCommand subclasses as cmd_* names to make it easy to nest BaseCommands.
* BaseCommand: new hack_postopts_argv method called after parsing the main command line options, for inferring subcommands or the like.
* BaseCommand: extract "Usage:" paragraphs from subcommand method docstrings to build the main usage message.
* BaseCommand: new cmd_help default command.
* Assorted bugfixes and small improvements.

*Release 20200318*:
* BaseCommand.run: make argv optional, get additional usage keywords from self.USAGE_KEYWORDS.
* @BaseCommand.add_usage_to_docstring: honour cls.USAGE_KEYWORDS.
* BaseCommand: do not require GETOPT_SPEC for commands with no defined options.
* BaseCommand.run: call cs.logutils.setup_logging.

*Release 20200229*:
Improve subcommand selection logic, replace StackableValues with stackattrs, drop `cmd` from arguments passed to main/cmd_* methods (present in `options`).

*Release 20200210*:
* New BaseCommand.add_usage_to_docstring class method to be called after class setup, to append the usage message to the class docstring.
* BaseCommand.run: remove spurious Pfx(cmd), as logutils does this for us already.

*Release 20190729*:
BaseCommand: support for a USAGE_FORMAT usage message format string and a getopt_error_handler method.

*Release 20190619.1*:
Another niggling docstring formatting fix.

*Release 20190619*:
Minor documentation updates.

*Release 20190617.2*:
Lint.

*Release 20190617.1*:
Initial release with @docmd decorator and alpha quality BaseCommand command line assistance class.
