Skip to main content

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

Project description

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

Latest release 20220429:

  • BaseCommand: fold dots in argv[0] into underscores, supports subcommands like "setup.py".
  • BaseCommand: new popargv(argv[,help_text[,parse[,validate[,unvalidated_message]]]]) helper class method.
  • BaseCommand: accept dashed-form of the underscored_form subcommand name.
  • BaseCommand: new self.options.runstate_signals=SIGINT,SIGTERM specifying singals to catch-and-cancel, shuffle run() context managers.

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!
    """
    ...

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:

MyCommand(argv).run()

or via the convenience method:

MyCommand.run_argv(argv)

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

... imports etc ...
... other code ...
class MyCommand(BaseCommand):
... other code ...
if __name__ == '__main__':
    sys.exit(MyCommand.run_argv(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) 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 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 arguments 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.

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

Release Log

Release 20220429:

  • BaseCommand: fold dots in argv[0] into underscores, supports subcommands like "setup.py".
  • BaseCommand: new popargv(argv[,help_text[,parse[,validate[,unvalidated_message]]]]) helper class method.
  • BaseCommand: accept dashed-form of the underscored_form subcommand name.
  • BaseCommand: new self.options.runstate_signals=SIGINT,SIGTERM specifying singals to catch-and-cancel, shuffle run() context managers.

Release 20220318: BaseCommand.init: handle main() method in the New Scheme.

Release 20220315: _BaseSubCommand.init: hook in the class USAGE_KEYWORDS for methods.

Release 20220311: BaseCommand: big refactor of subcommand internals and make the "cmd_foo=FooCommand" implementation work properly.

Release 20211208: BaseCommand: better handle an unknown subcommand.

Release 20210927:

  • Usage: show only the per subcommand usage for in-subcommand GetoptError.
  • Usage: show terse usage when the subcommand cannot be recognised.
  • Usage: support bare -h, -help, --help.

Release 20210913: New BaseCommand.apply_preargv method to gather special arguments before subcommands.

Release 20210906:

  • BaseCommand.cmd_help: bugfix obsolete parameter list.
  • BaseCommand.SUBCOMMAND_ARGV_DEFAULT: support a single str value, turn into list.

Release 20210809: Bugfix BaseCommand.cmd_help for modern API.

Release 20210731:

  • BaseCommand.run: apply optional keyword arguments to self.options during the run.
  • Look for self.SUBCOMMAND_ARGV_DEFAULT if no subcommand is supplied.
  • Bugfix case for "main" method and no "cmd_*" methods.
  • Bugfix BaseCommand.cmd_help.

Release 20210420:

  • BaseCommand.getopt_error_handler: replace error print() with warning().
  • Docstring improvements.

Release 20210407.1: BaseCommand: bugfix for init_subclass docstring update.

Release 20210407:

  • BaseCommand.init_subclass: behave sanely if the subclass has no initial doc.
  • BaseCommand: new .run_argv convenience method, obviates the "def main" boilerplate.

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cs.cmdutils-20220429.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

cs.cmdutils-20220429-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file cs.cmdutils-20220429.tar.gz.

File metadata

  • Download URL: cs.cmdutils-20220429.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.1 readme-renderer/30.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.7 tqdm/4.62.3 importlib-metadata/4.8.2 keyring/23.3.0 rfc3986/1.5.0 colorama/0.4.4 CPython/3.9.12

File hashes

Hashes for cs.cmdutils-20220429.tar.gz
Algorithm Hash digest
SHA256 719183ac8a06cc0d1979222f57f4078c49e1889d4d2643af6891be16f586f112
MD5 ed41ba3af631c3b479caaca925a530ce
BLAKE2b-256 56dbe7294ef6af2336eb58f9b14cdf07403bfa873afd89489c74c8d8728ee9b7

See more details on using hashes here.

File details

Details for the file cs.cmdutils-20220429-py3-none-any.whl.

File metadata

  • Download URL: cs.cmdutils-20220429-py3-none-any.whl
  • Upload date:
  • Size: 14.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.8.1 readme-renderer/30.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.7 tqdm/4.62.3 importlib-metadata/4.8.2 keyring/23.3.0 rfc3986/1.5.0 colorama/0.4.4 CPython/3.9.12

File hashes

Hashes for cs.cmdutils-20220429-py3-none-any.whl
Algorithm Hash digest
SHA256 561810be09a9e07157c89df73a57a65fa020e283b0f9a3a4ef3962d09e2c33a8
MD5 ecb5a76914eba208b860a51fe91eedfd
BLAKE2b-256 8610df0d46944d92236290143290351a1c745d991a0c41574137dacbf4c28b18

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page