Integrates the argparse and cmd modules.
Project description
argshell
Integrates the argparse and cmd modules to create custom shells with argparse functionality.
Installation
Install with:
pip install argshell
Usage
Custom shells are created by subclassing the ArgShell class and adding functions of the form do_*()
, just like the cmd.Cmd class.
class MyShell(argshell.ArgShell): def do_echo(self, line:str): """ Print command """ print(line)
Then create a function that instantiates an ArgShellParser instance, adds arguments, and then returns the ArgShellParser object (similarly to how you would create a parser with argparse).
def get_parser()->argshell.Namespace: parser = argshell.ArgShellParser() parser.add_argument("text", type=str, help="The text to print") parser.add_argument("-u", "--uppercase", action="store_true", help="Convert text to uppercase.") return parser
For do_* functions that require args instead of just a string,
decorate the function with with_parser()
and pass your function that creates and returns an ArgShellParser
instance to with_parser
as a parameter.
class MyShell(argshell.ArgShell): @argshell.with_parser(get_parser) def do_echo(self, args:argshell.Namespace): """ Print command """ print(args.text.upper() if args.uppercase else args.text)
In terminal:
argshell>echo "howdy y'all" howdy y'all argshell>echo "howdy y'all" -u HOWDY Y'ALL
with_parser
also accepts an optional list of functions that accept and return an argshell.Namespace object.
These functions will be executed in order after the parser function parses the arguments.
def toggle_uppercase(args: argshell.Namespace)->argshell.Namespace: """ If args.uppercase is True, make it False. If it's False, make it True.""" args.uppercase = not args.uppercase return args class MyShell(argshell.ArgShell): @argshell.with_parser(get_parser, [toggle_uppercase]) def do_echo(self, args:argshell.Namespace): """ Print command """ print(args.text.upper() if args.uppercase else args.text) @argshell.with_parser(get_parser, [toggle_uppercase, toggle_uppercase]) def do_echo_double_toggle(self, args.argshell.Namespace): self.do_echo(args)
In terminal:
argshell>echo "howdy y'all" HOWDY Y'ALL argshell>echo "howdy y'all" -u howdy y'all argshell>echo_double_toggle "howdy y'all" howdy y'all argshell>echo_double_toggle "howdy y'all" -u HOWDY Y'ALL
When using your shell, entering help command
will, in addition to the command's doc string,
print the help message of the parser that decorates it, if it is decorated.
The parser help for a decorated command can also be printed by entering the command with the -h/--help flag.
Example
A shell script that takes a list of first and last names and either prints a full name per line or prints first and last initials per line.
In a .py file:
from argshell import ArgShell, ArgShellParser, Namespace, with_parser def get_parser() -> ArgShellParser: parser = ArgShellParser(prog="") parser.add_argument( "names", type=str, nargs="*", help="A list of first and last names to print." ) parser.add_argument( "-i", "--initials", action="store_true", help=""" Print initials only. """ ) return parser # Post parser function to convert list of first and last names to a list of tuples of first and last names def names_list_to_tuples(args: Namespace) -> Namespace: args.names = [ (first, last) for first, last in zip(args.names[::2], args.names[1::2]) ] if args.initials: args.names = [(name[0][0], name[1][0]) for name in args.names] return args # Post parser function to capitalize names def capitalize_names(args: Namespace) -> Namespace: args.names = [name.capitalize() for name in args.names] return args class NameShell(ArgShell): intro = "Entering nameshell...\nType 'help' or '?' to list commands" prompt = "nameshell>" # Decorated command that gets a parser from get_parser # The parsed arguments will be processed by capititalize_names and then names_list_to_tuples # before being passed to do_printnames @with_parser(get_parser, [capitalize_names, names_list_to_tuples]) def do_printnames(self, args: Namespace): """Print a list of first and last names, one per line.""" print(*[f"{name[0]} {name[1]}" for name in args.names], sep="\n") # Undecorated command that behaves like a standard cmd.Cmd command function def do_echo(self, line: str): """Print the received text.""" print(line) if __name__ == "__main__": NameShell().cmdloop()
Launch the file in a terminal:
Entering nameshell... Type 'help' or '?' to list commands nameshell>help Documented commands (type help ): ======================================== echo help printnames quit nameshell>echo yeet yeet nameshell>printnames karl marx fred hampton emma goldman angela davis nestor makhno Karl Marx Fred Hampton Emma Goldman Angela Davis Nestor Makhno nameshell>printnames karl marx fred hampton emma goldman angela davis nestor makhno -i K M F H E G A D N M nameshell>help echo Print the received text. nameshell>help printnames Print a list of first and last names, one per line. Parser help for printnames: usage: [-h] [-i] [names ...] positional arguments: names A list of first and last names to print. options: -h, --help show this help message and exit -i, --initials Print initials only. nameshell>printnames -h usage: [-h] [-i] [names ...] positional arguments: names A list of first and last names to print. options: -h, --help show this help message and exit -i, --initials Print initials only. nameshell>quit
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.