Captain#
Examples#
Single-command CLI#
example.py file:
#! /usr/bin/env python3
from libjam import captain
# Creating the CLI
@captain()
def shout(text: str, *, world=False):
"""Shouts the given text back."""
if world:
text += ' world'
print(text + '!')
return 'anything'
# Adding an option to the CLI
shout.add_option(
'world', "Adds ' world' before the exclamation mark.", 'w',
)
# Running the CLI
returned = shout()
# This assertion will succeed
assert returned == 'anything'
Here is what the user will see when running this CLI:
$ ./example.py
shout: missing argument <TEXT>
Try 'shout --help' for more information.
$ ./example.py Hello
Hello!
$ ./example.py Hello --world
Hello world!
$ ./example.py --help
Usage:
shout [OPTION]... <TEXT>
Description:
Shouts the given text back.
Options:
-w, --world - Adds ' world' before the exclamation mark.
-h, --help - Prints this page.
Multi-command CLI#
example.py file:
#! /usr/bin/env python3
# Imports
from libjam import captain
import sys
# Creating the CLI
@captain('very-smart-ai')
class cli:
"Trust me, it's the smartest one out there."
def shout(text, suffix=None):
"""I will be loud!"""
text += '!'
if suffix:
text += suffix
print(text)
def whisper(*lines):
"""Shhhh! You don't want them to hear you..."""
lines = [l + '...' for l in lines]
text = '\n'.join(lines)
print(text)
def wonder(**opts):
"""Where's my copy of My Weekend in Stevenage by Filthy Henderson?"""
if opts['mcbeth']:
print("I just want to be a fish.")
elif opts['quiet']:
print('I REFUSE!')
else:
print('Thanks for staying quiet.')
# Adding options to the wonder command
cli.wonder_command.add_option(
'mcbeth', 'Ponder whether to be or not to be.',
)
cli.wonder_command.add_option('quiet', 'Be quiet.', 'q')
# Running the CLI
if __name__ == '__main__':
sys.exit(cli())
Here is what the user will see when running this CLI:
$ ./example.py
very-smart-ai: no command specified.
Try 'very-smart-ai --help' for more information.
$ ./example.py shout "I like crisps"
I like crisps!
$ ./example.py wonder -h
Usage:
very-smart-ai wonder
Description:
Where's my copy of My weekend in Stevenage by Filthy Henderson?
Options:
--mcbeth - Ponder whether to be or not to be.
-q --quiet - Be quiet.
-h --help - Prints this page.
$ ./example.py wonder --mcbeth
I just want to be a fish.
$ ./example.py --help
Trust me, it's the smartest one out there.
Synopsis:
very-smart-ai <COMMAND> ...
Commands:
shout - I will be loud!
whisper - Shhhh! You don't want them to hear you...
wonder - Where's my copy of My weekend in Stevenage by Filthy Henderson?
Usage:
shout <TEXT> [SUFFIX]
whisper [LINES]...
wonder
Options:
-h --help - Prints this page.
API#
- class libjam.Captain(ship: callable, name: str = None, pass_self: bool = False, add_help: bool = True, compact_help: bool = None, child_kwargs: dict = {})#
Creates a CLI around a given function or class.
The
shipcan be either a function, to make a single-command CLI, or a class, to make a multi-command CLI. Its docstring will be used as the CLI’s description, shown on the help page.If the
shipis a function, then its parameters will be used to create the CLI’s arguments. Supports required, optional and arbitrary parameters.If the
shipis a class, then its attributes will be used to create the CLI’s commands. Theship’s attributes can be either otherCaptains, functions or classes. If the attribute is a function or a class, then a newCaptainwill be created using that attribute; the name of this new captain will be set to the parentCaptain’s name plus the name of the attribute, as it appears within the class, with a space in the middle. For example, if the parentCaptain’s name is “hello” and the function’s name, as it appears in the class, is “world”, then the name for the newCaptaincreated from that function will be “hello world”. However, if the attribute is already aCaptainthen it’s name will remain unchanged. All newCaptains created by thisCaptain, will be added to thisCaptain, under the name of the attribute, as it appeared in the class, plus “_command”. This is done to improve ease of access, for example to enabled adding options to these createdCaptains. This is not done for attributes which were alreadyCaptains.If the
nameis not specified, thensys.argv[0]will be used to determine the name of the program.The
compact_helpparameter decides whether the help page sections should be separated by one or two newlines. If not specified, then it will be set toFalseif the specifiedshipis a function, andTrueif it’s a class.The
child_kwargsdictionary is passed as keyword arguments to childrenCaptains created by thisCaptain(only applies if the givenshipis a class).The
pass_selfparameter can be set toTrueif you want your function to get theCaptainthat was created using it as its first argument when running.To run the CLI, call it.
Example single-command CLI:
from libjam import Captain import sys def echo(text, **options): if options['world']: text += ' world!' print(echo) cli = Captain(echo) cli.add_option('world', 'Appends " world!"', 'w') if __name__ == '__main__': sys.exit(cli())
Example multi-command CLI:
from libjam import Captain import sys class express: def sadness(**opts): print("I'm sad") def happiness(*, help=False): print("I'm happy") cli = Captain(express) if __name__ == '__main__': sys.exit(cli())
- add_option(name: str, description: str = None, shorthand: str = None, call: callable = None)#
Adds an option to the CLI.
The
nameparameter will used as the key in thedictthat theparsemethod returns and to create the long flag for the CLI.The
descriptionparameter, if specified, will be shown in the help page, after the option’s flags.The
shorthandparameter, if specified, will be used to create the short flag for the CLI. It must be 1 a character-long string.The
callparameter, if specified, will be called during parsing. If the option was set by the user. The default help option sets it to theprint_help_and_exitmethod of theCaptain.When running the CLI, the option will be passed as a keyword argument to the appropriate function, if it can accept it.
- error(exit_code: int, *lines: str)#
Prints an error message to stderr and calls
sys.exitwith the given exit code.
- usage_error(*lines: str)#
Prints an error message to stderr and calls
sys.exitwith an appropriate exit code.
- build_help() str#
Builds the help page.
- print_help()#
Prints the help page.
- print_help_and_exit()#
Prints the help page and calls
sys.exitwith the appropriate exit code.
- libjam.captain(name: str = None, pass_self: bool = False, add_help: bool = True, compact_help: bool = None, child_kwargs: dict = {}) callable#
Returns a decorator that takes either a function or a class and returns a
Captain.Example usage:
@captain(name='echo') def cli(text): print(text)