Convenience functions for working with the Cmd module, the BaseCommand class for constructing command line programmes, and other command line related stuff.
Latest release 20220626:
- BaseCommand.poparg: fix positional argument handling.
- BaseCommand.poparg: new unpop_on_error=False parameter to support pushing a bad argument back onto the front of the argument list.
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()
Modules which implement a command line mode generally look like this:
... imports etc ...
def main(argv=None):
""" The command line mode.
"""
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) 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 ofself.optionsbefore any command line options are applied.apply_opt(opt,val): apply an individual getopt global command line option toself.options.apply_opts(opts): apply theoptstoself.options.optsis an(option,value)sequence as returned bygetopot.getopt. The default implementation iterates over these and callsapply_opt.cmd_subcmd(argv): if the command line options are followed by an argument whose value is subcmd, then the methodcmd_subcmd(subcmd_argv)will be called wheresubcmd_argvcontains 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 correspondingcmd_subcmd method then methodmain(argv)will be called whereargvcontains 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, options=None, **kw_options):
Initialise the command line.
Raises GetoptError for unrecognised options.
Parameters:
argv: optional command line arguments including the main command name ifcmdis not specified. The default issys.argv. The contents ofargvare copied, permitting desctructive parsing ofargv.cmd: optional keyword specifying the command name for context; if this is not specified it is taken fromargv.pop(0).options: an optional keyword providing object for command state and context. If not specified a newself.OPTIONS_CLASSinstance is allocated for use asoptions. The defaultOPTIONS_CLASSisBaseCommandOptions, aSimpleNamespacewith some prefilled attributes and properties to aid use later. These can be further updated by the.apply_default()method. Other keyword arguments are applied toself.optionsas attributes.
The cmd and argv parameters have some fiddly semantics for convenience.
There are 3 basic ways to initialise:
BaseCommand():argvcomes fromsys.argvand the value forcmdis derived fromargv[0]BaseCommand(argv):argvis the complete command line including the command name and the value forcmdis derived fromargv[0]BaseCommand(argv, cmd=foo):argvis the command arguments after the command name andcmdis set tofoo
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.
Class BaseCommandOptions(types.SimpleNamespace)
A base class for the BaseCommand options object.
This is the default class for the self.options object
available during BaseCommand.run().
It comes prefilled with:
.dry_run=False.force=False.quiet=False.verbose=Falseand a.doitproperty which is the inverse of.dry_run.
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.Pfxfor context - intercepts
getopt.GetoptErrors, issues awarningand runsself.do_helpwith the method name, then returnsNone - intercepts other
Exceptions, issues anexceptionlog message and returnsNone
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 20220626:
- BaseCommand.poparg: fix positional argument handling.
- BaseCommand.poparg: new unpop_on_error=False parameter to support pushing a bad argument back onto the front of the argument list.
Release 20220606: BaseCommand.run: remove the Upd bodge, too annoying, now fixed in cs.upd I believe.
Release 20220605:
- BaseCommand: new popopts(argv,...) compact getopt wrapper.
- BaseCommand: new poparg(argv,...) compact validating argument consumer.
- BaseCommand: drop run_argv, provided no utility.
- BaseCommand.run: get the RunState signal list from self.options.runstate_signals.
- BaseCommand.apply_opts: support multiple individual options raising GetoptError, as I hate commands which abort at the first bad option.
- Assorted other small things.
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
optionsparameter from self.options. - BaseCommand: provide default
apply_optandapply_optsmethods; 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.
Release files for cs-cmdutils 20220626
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cs.cmdutils-20220626.tar.gz | 23.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cs.cmdutils-20220626-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 40.8 kB
Release files / cs.cmdutils-20220626.tar.gz
| Download URL | cs.cmdutils-20220626.tar.gz |
|---|---|
| Size | 23.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b6c6ccf42d61f1cd14360102157c1f5d57e20f50aac227f07d588dd91d60216c
|
|
BLAKE2b-256 checksum How to use checksums |
8be086c0e6657d08b758999ac573167f001161f155f51e39686a6772033544b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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.13
|
Release files / cs.cmdutils-20220626-py3-none-any.whl
| Download URL | cs.cmdutils-20220626-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff53b0c48ebc8ee005b5d69c7b9a87a53c2c10b86aa27419e34742f561acdc56
|
|
BLAKE2b-256 checksum How to use checksums |
b049d4d41abd8510cdfd323f043ffa2ae83bfa16698ac9e742910b7de34e35aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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.13
|