Convenience functions for working with the cmd stdlib module, the BaseCommand class for constructing command line programmes, and other command line related stuff.
Latest release 20260912:
- BaseCommand.repl(): improve the local vars.
- New optional apply(opts,field,value) field for option specs.
- BaseCommandOptions: replace .quiet and .verbose with .verbosity and properties for the other names, make -q and -v accrue a count via their apply functions.
- New vvprint() to print if options.verbosity>=2; qvprint is now obsolete, use vprint, since verbose and quiet are no longer independant.
This module provides the following main items:
BaseCommand: a base class for creating command line programmes with easier setup and usage than libraries likeoptparseorargparse@popopts: a decorator which works withBaseCommandsubcommand methods to parse their command line options@docmd: a decorator for command methods of acmd.Cmdclass 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: Acmd.Cmdsubclass used to provide interactive use of a command's subcommands. -
BaseCommandOptions: A base class for theBaseCommandoptionsobject. -
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 forcmd.Cmdsubclass 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 acmd_method'sargv, updatingself.options. -
qprint: Callprint()ifnot 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: Callprint()ifoptions.verbose. -
vvprint: Callprint()ifoptions.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.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 ...
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 methodcmd_subcmd(subcmd_argv)will be called wheresubcmd_argvcontains the command line arguments following subcmd.main(argv): if there are nocmd_subcmd methods then methodmain(argv)will be called whereargvcontains 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 methodcmd_subcmd(subcmd_argv)will be called wheresubcmd_argvcontains the command line arguments following subcmd.main(argv): if there are nocmd_subcmd methods then methodmain(argv)will be called whereargvcontains the command line arguments.
Usage summary:
Usage: ` then that paragraph is incorporated
into the main usage message automatically.
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 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.Optionsinstance is allocated for use asoptions. The defaultOptionsclass isBaseCommandOptions, a dataclass with some prefilled attributes and properties to aid use later. 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.
BaseCommand.GETOPT_SPEC
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
BaseCommand.Options
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=Falseand a.doitproperty 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 ...
BaseCommand.SUBCOMMAND_ARGV_DEFAULT
The type of the None singleton.
BaseCommand.SUBCOMMAND_METHOD_PREFIX
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
BaseCommand.SubCommandClass
An implementation for a subcommand.
BaseCommand.USAGE_FORMAT
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
BaseCommand.__dict__
Read-only proxy of a mapping.
BaseCommand.__firstlineno__
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
BaseCommand.__static_attributes__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
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 printskip_names: a list of option attributes to not print, default fromself.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 0x102df1580>, **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 nameoptions: theoptionsobjecte: theGetoptErrorexceptionusage: the command usage orNoneif this was not providedsubcmd: optional subcommand name; if notNone, 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 0x102df0860>)
The default signal handler, which cancels the default RunState.
BaseCommand.has_subcommands()
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 withargv.pop(0)- the argument list
argvmay 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 aValueErrorif invalidunvalidated_message: an optional message aftervalidatefor values failing the validationunpop_on_error: optional keyword parameter, defaultFalse; if true then push the argument back onto the front ofargvif it fails to parse;GetoptErroris 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 argumentsbanner: optional banner stringlocal: optional local names mapping
The default local mapping is a dict containing:
argv: fromargvoptions: fromself.optionsself: fromself- 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 0x102df0c20>, **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.optionswhich is a copy of the originalself.optionsso that it may freely be modified during the command - provides a prevailing
RunStateasself.options.runstateif one is not already present - provides a
cs.upd.Updcontext for status lines - catches
self.options.runstate_signalsand handles them withself.handle_signal
BaseCommand.subcommand
Return the SubCommand associated with subcmd.
BaseCommand.subcommand_usage_text(self, subcmd, usage_format_mapping=None, short=False)
Return the usage text for a subcommand.
BaseCommand.subcommands
Return a mapping of subcommand names to subcommand specifications
for class attributes which commence with cls.SUBCOMMAND_METHOD_PREFIX
by default 'cmd_'.
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.__firstlineno__
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
BaseCommandCmd.__static_attributes__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
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=Falseand a.doitproperty 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
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
BaseCommandOptions.DEFAULT_SIGNALS
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BaseCommandOptions.INFO_SKIP_NAMES
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BaseCommandOptions.__annotations__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
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.__dataclass_fields__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
BaseCommandOptions.__firstlineno__
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
BaseCommandOptions.__hash__
The type of the None singleton.
BaseCommandOptions.__match_args__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BaseCommandOptions.__post_init__(self)
A empty base post __init__ method so that all subclasses'
__post_init__s can call their super().__post_init__.
BaseCommandOptions.__static_attributes__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
BaseCommandOptions.as_dict(self)
Return the options as a dict.
This contains all the public attributes of self.
BaseCommandOptions.cmd
The type of the None singleton.
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
I usually use a doit flag, the inverse of dry_run.
BaseCommandOptions.dry_run
Returns True when the argument is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
BaseCommandOptions.fields_as_dict(self)
Return the options' fields as a dict.
This contains all the field values of self.
BaseCommandOptions.force
Returns True when the argument is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
BaseCommandOptions.getopt_spec_map(opt_specs_kw: Mapping, common_opt_specs=None)
Return a 3-tuple of (shortopts,longopts,getopt_spec_map) being:
shortopts: thegetopt()short options specification stringlongopts: thegetopts()long option specification listgetopt_spec_map: a mapping ofopt->OptionSpecwhereoptis as fromopt,valfromgetopt()andopt_specis the associatedOptionSpecinstance
BaseCommandOptions.opt_spec_class
A class to support parsing an option value.
BaseCommandOptions.perthread_state
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-1option setting theonceoption 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 ofFalse, for examplen='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
True if self.verbosity is negative otherwise False.
BaseCommandOptions.runstate
The type of the None singleton.
BaseCommandOptions.runstate_signals
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
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
True if self.verbosity is negative otherwise False.
BaseCommandOptions.verbosity
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
class OptionSpec
A class to support parsing an option value.
OptionSpec.UNVALIDATED_MESSAGE_DEFAULT
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
OptionSpec.__annotations__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
OptionSpec.__dataclass_fields__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
OptionSpec.__dict__
Read-only proxy of a mapping.
OptionSpec.__firstlineno__
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
OptionSpec.__hash__
The type of the None singleton.
OptionSpec.__match_args__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
OptionSpec.__post_init__(self)
Infer field_name and help_text if unspecified.
OptionSpec.__static_attributes__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
OptionSpec.accrues
Returns True when the argument is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
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
The type of the None singleton.
OptionSpec.arg_name
The type of the None singleton.
OptionSpec.field_default
The type of the None singleton.
OptionSpec.field_name
The type of the None singleton.
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
The option specification for a getopt long option.
Return None if self.opt_name is only 1 character.
OptionSpec.getopt_opt
The opt we expect from opt,val=getopt(argv,...).
OptionSpec.getopt_short
The option specification for a getopt short option.
Return '' if self.opt_name is longer than 1 character.
OptionSpec.help_text
The type of the None singleton.
OptionSpec.help_text_from_field_name(field_name)
Compute an inferred help_text from an option field_name.
OptionSpec.needs_arg
Whether we expect an argument: we have a self.arg_name.
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
The type of the None singleton.
OptionSpec.parse_value(self, value)
Parse value according to the spec.
Raises GetoptError for invalid values.
OptionSpec.unvalidated_message
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
OptionSpec.validate
The type of the None singleton.
class SubCommand
An implementation for a subcommand.
SubCommand.__annotations__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
SubCommand.__call__(self, argv: List[str])
Run the subcommand.
Parameters:
argv: the command line arguments after the subcommand name
SubCommand.__dataclass_fields__
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
SubCommand.__dict__
Read-only proxy of a mapping.
SubCommand.__firstlineno__
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.int(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by '+' or '-' and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal.
int('0b100', base=0) 4
SubCommand.__hash__
The type of the None singleton.
SubCommand.__match_args__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
SubCommand.__static_attributes__
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
SubCommand.cmd
The type of the None singleton.
SubCommand.get_cmd(self) -> str
Return the cmd string for this SubCommand,
derived from the subcommand's method name or class name
if self.cmd is not set.
SubCommand.get_subcmds(self)
Return the names of self.method's subcommands in lexical order.
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) -> str
Return a mapping to be used when formatting the usage format string.
This is an elaborate ChainMap of:
- the optional
cmdorself.get_cmd() - the optional
usage_mappingparameter self.usage_mappingself.method.USAGE_KEYWORDSif 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
An instance of the class for self.method.
SubCommand.short_subusages(self, subcmds: List[str], *, recurse=False, short=False)
Return a list of tabulated one line subcommand summaries.
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
The Common options: format string paragraph
or None if there are no common options.
SubCommand.usage_default
The fallback usage line if nothing specified:
'{cmd} [options...]' or '{cmd} subcommand [options...]'.
SubCommand.usage_format
The usage format string for this subcommand. Note: no leading "Usage:" prefix.
This first tries the legacy self.method.USAGE_FORMAT,
falling back to deriving it from obj_docstring(self.method).
When deriving from the docstring we look for a paragraph
commencing with the string Usage: and otherwise fall back
to its first parapgraph.
SubCommand.usage_format_desc1
The leading usage line part of the format string.
SubCommand.usage_format_parts
The usage description format string broken into:
- the usage line (or lines if slosh extended)
- the first line of the description, or
None - the trailing lines of the description, or
None
SubCommand.usage_format_usage
The usage line(s) part of the format string.
SubCommand.usage_text(self, *, cmd=None, short: bool, recurse: bool = False, show_common: bool = False, show_subcmds: Union[bool, str, List[str], NoneType] = None, usage_mapping: Optional[Mapping] = None, seen_subcommands: Optional[Mapping] = None) -> str
Return the filled out usage text for this subcommand.
Release Log
Release 20260912:
- BaseCommand.repl(): improve the local vars.
- New optional apply(opts,field,value) field for option specs.
- BaseCommandOptions: replace .quiet and .verbose with .verbosity and properties for the other names, make -q and -v accrue a count via their apply functions.
- New vvprint() to print if options.verbosity>=2; qvprint is now obsolete, use vprint, since verbose and quiet are no longer independant.
Release 20260531:
- BaseCOmmand.repl: fix the definition of the locals and improve the default banner.
- BaseCommand: new .pop_buffer(argv) and .pop_buffers(argv) methods to get CornuCopyBuffers from CLI filespecs.
- OptionSpec: support opt__= to indicate an accruing option.
- BaseComman.run_context: yield the new self.options object.
- BaseCommand.run: no longer detect a return from the run_context() call as early exit as it is now the options.
Release 20250724:
- BaseCommandOptions: new empty post_init so that subclasses can call super().post_init() unconditionally.
- New cli_datetime to parse a CLI supplied datetime specification, accepts ISO8601.
Release 20250531.1: Fix precedence of subcommand options over inherited common options.
Release 20250531:
- Fix @popopts internals for recent @decorator internal changes.
- Fix BaseCommandOptions.getopt_spec_map to let the subcommand options override the inherited common options.
- Fix a format string.
Release 20250528: New qprint() which prints if not quiet a bit like vprint(), which prints if verbose and not quiet.
Release 20250426: Minor changes.
Release 20250418:
- BaseCommand: honour SUBCOMMAND_ARGV_DEFAULT even when there are no subcommands.
- BaseCommand._prerun_setup: bugfix application of default argv, was setting self._argv too early.
- Some documentation updates.
Release 20250306: If a subcommand raises GetoptError, only show the usage for that subcommand.
Release 20250103: BaseCommand.cmd_info: default skip_names is self.options.INFO_SKIP_NAMES.
Release 20241222.1:
- BaseCommand.cmd_info: use pformat instead of str.
- BaseCommand.cmd_repl: enumerate the options as top level names in the banner.
- If run as main programme, run a demo command.
Release 20241222: BaseCommand.cmd_info: use compact=True with the pforat() call.
Release 20241218: BaseCommand: add cmd_repl to the default subcomands.
Release 20241212: SubCommand.short_subusages: use a single tabluate() table for the entire recursive listing, produces a much more readable short listing.
Release 20241207: BaseCommandOptions.usage_options_format: support multiline help text via the new tabulate support.
Release 20241206.1: SubComand.usage_text: normalise the show_subcmds to match the subcommands mapping.
Release 20241206:
- New @popopts decorator to run self.options.popopts and fill out the usage message.
- Add "-e ssh-command" and the .ssh_exe attribute to BaseCommandOptions.
Release 20241122.2:
- OptionSpec.getopt_long: fix construction of getopt long option specifications, lost during the recent refactor.
- Two other minor fixes.
Release 20241122.1:
- SubCommand.usage_format_parts: backport type annotation for older Pythons.
- BaseCommand.extract_usage: update parameters for usage_text().
Release 20241122:
- BaseCommand.cmd_help: new -l (long), -r (recurse) and -s (short, not long) options.
- A big rework of the help/usage output; still one rough edge left.
- BaseCommandOptions.popopts: infill with False instead of None for missing boolean options.
- SubCommand: a few new methods and properties to expose various operations.
- BaseCommand._prerun_setup: revert SUBCOMMAND_ARGV_DEFAULT to None, make a missing subcommand run "help -s" when there's no SUBCOMMAND_ARGV_DEFAULT.
Release 20241119:
- SubCommand.usage_text: small improvements and a fix.
- New BaseCommand.SubCommandClass attribute for the SubCommand subclass, supports using additional SubCommand subclasses for eg cs.djutils.
Release 20241117:
- _COMMON_OPT_SPECS: include a --dry-run option, alter for -n.
- SubCommand.usage_text: one line listing for common subcommands.
Release 20241110:
- Various fixes and enhancements to the usage text generation.
- BaseCommandOptions.COMMON_OPT_SPECS stuff, including inheritance and presentation in usage.
- BaseCommand.run: if self.run_context() yields not None, exit immediately with that value.
- Rationalise and improve OptionSpec.
- Supplant vprint with qvprint which honours quiet and verbose, provide vprint as a shim with a hardwired quiet=False.
- Make cmd_info the default subcommand and make some improvements.
- BaseCommandOptions: new fields_as_dict method, update copy() to start with fields_as_dict, overlay as_dict, overlay updates.
- OptionSpec: new add_argument(parser[,options]) method to add this option to an argparse style option parser (again, for the upcoming cs.djutils module).
- A heap of small things.
Release 20241007:
- BaseCommand: drop init_subclass, was doing too much to early.
- BaseCommand.init: no cmd and argv[0] ends with ".py" infer cmd from the class name.
- Other minor updates.
Release 20241005:
- BaseCommand: provide an options.runstate to allow the command to override the default (almost never happens).
- BaseCommand.popopts: fix reference to OptionSpec class.
- BaseCommand.run: put the try/except:CancellationError outside the self.run_context context manager call, as it can directly raise CancellationError.
- New vprint() function calling print() if options.verbose.
Release 20240709:
BaseCommand: support putting the top level Usage in the class docstring instead of as .USAGE_FORMAT, append full usage to the class docstring in BaseCommand.__init_subclass__.
Release 20240630:
- BaseCommand: make SUBCOMMAND_ARGV_DEFAULT be 'shell' for an interactive prompt, still a little unsure how sensible this is, aiming at the very cool submode stuff from the Cisco switch config command line.
- BaseCommandOptions: new as_dict() method.
- New SubCommand.usage_text() to compose the full usage text for this SubCommand.
- Many small improvements and internal refactors.
Release 20240519: BaseCommand.run_context: attach the runstate to the options.
Release 20240422:
- BaseCommandOptions.popopts: return the dict from BaseCommand.popopts().
- BaseCommand.apply_preargv: apply the default options supported by self.options.
- BaseCommandOptions.update(mapping) method, useful for dropping subcommand-specific defaults onto the options ahead of the local popopts() call.
Release 20240412:
- BaseCommand.run_context: do not store .upd and .runstate on the options (it confuses options in subcommands and we have @uses_runstate and @uses_upd forthis anyway these days).
- BaseCommand.run_context: catch SIGQUIT, present the default handler as BaseCommand.handle_signal.
Release 20240316:
- New @uses_cmd_options decorator to provide an "options" parameter being the prevailing BaseCommandOptions instance.
- BaseCommandOptions.popopts: get common options from BaseCommandOptions.COMMON_OPT_SPECS.
Release 20240211:
- Include the first sentence of the subcommand description in the short help.
- BaseCommandOptions: move the runstate_signals into this directly.
- BaseCommand: move the run() options stuff into run_context() and have it work on a copy of the original options.
- BaseCommandCmd: implement get_names(), provide docstrings for the do_* attributes, thus help.
- BaseCommand.run_context: make runstate and upd keyword only parameters.
Release 20240201:
- BaseCommand.run: catch CancellationError and return 1.
- BaseCommandCmd.getattr: recognise EOF, exit and quit to terminate the cmdloop.
Release 20231129: BaseCommandOptions: define a runstate field.
Release 20230703: Small internal changes.
Release 20230612:
- BaseCommand.cmdloop: fix intro parameter.
- Other small fixes.
Release 20230407:
- BaseCommand: use @uses_runstate when preparing the command, store as self.options.runstate.
- Make BaseCommandOptions a data class.
- Drop any pretence at python 2 support, we're long past that.
- BaseCommand: new cmdloop method to run a cmd.Cmd instance to run subcommand interactively.
- BaseCommand: rename shell to repl, add cmd_shell to call cmdloop().
- Drop BaseCommand.apply_defaults in favour of the Options dataclass.
- BaseCommand: do setup_logging before initiating the Options instance.
Release 20230212:
- BaseCommand.run_context: update RunState support.
- BaseCommand.run_context: always be having an self.options.upd.
Release 20230211: BaseCommand: new shell() method to present an interactive Python prompt for use by subclasses cmd_shell method if desired.
Release 20221228: Move a lot of the context logic from BaseCommand.run to BaseCommand.run_context, which now must be correctly overridden in subclasses.
Release 20220918:
- BaseCommand.run_context: expand default signals to include SIGHUP, expose as BaseCommand.DEFAULT_SIGNALS.
- BaseCommand.run: pass in the subclass handle_signal method if present.
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 20260912
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-20260912.tar.gz | 53.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cs_cmdutils-20260912-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details |
Total release size: 92.3 kB
Release files / cs_cmdutils-20260912.tar.gz
| Download URL | cs_cmdutils-20260912.tar.gz |
|---|---|
| Size | 53.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
709a078b381d9cad57e08dce3a143b582d4fc34ca902b548ca97d2908b689fb0
|
|
BLAKE2b-256 checksum How to use checksums |
1311ad129dd021744670efe5a25acee4cc3428146ffc9e45922916d3287af034
|
| 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-20260912-py2.py3-none-any.whl
| Download URL | cs_cmdutils-20260912-py2.py3-none-any.whl |
|---|---|
| Size | 39.1 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
0bb8c74b291d22012754c3e069adfc5316d5b9b3ba7a610bf76664a459252e85
|
|
BLAKE2b-256 checksum How to use checksums |
e44d9fbc031fcacd873ed369f8b13755543ff65b6966d134705a36f321dc6a93
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.1
|