Documentation¶
This module contains a framework for interactive command line demonstrations.
Examples
Making a simple CodeDemo subclass:
# spam.py
from cli_demo import CodeDemo
def scramble(num):
return "SCRAMBLE " * num
class SpamDemo(CodeDemo):
help_text = "An eggs and bacon bonanza."
setup_code = '''\
eggs = 6
spam = 42'''
commands = [
"eggs + spam # yum",
"bacon = spam % eggs",
"eggs // bacon",
"scramble(eggs)",
"response + ' was your response!'"
]
Running a Demo:
>>> from spam import SpamDemo
>>> demo = SpamDemo()
>>> demo.run()
Welcome to SpamDemo!
Options:
*: Any response.
h: Help.
o: Options.
r: Restart.
q: Quit.
Select an option, or type something random: h
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
====
Help
====
SpamDemo
--------
An eggs and bacon bonanza.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Select an option, or type something random: noodles
Setup:
>>> eggs = 6
>>> spam = 42
Options:
0: "eggs + spam # yum"
1: "bacon = spam % eggs"
2: "eggs // bacon"
3: "scramble(eggs)"
4: "response + ' was your response!'"
a: Execute all of the above.
c: Setup code.
o: Options.
r: Restart.
q: Quit.
Choose a command: a
>>> eggs + spam # yum
48
>>> bacon = spam % eggs
>>> bacon
0
>>> eggs // bacon
ZeroDivisionError: integer division or modulo by zero
>>> scramble(eggs)
'SCRAMBLE SCRAMBLE SCRAMBLE SCRAMBLE SCRAMBLE SCRAMBLE '
>>> response + ' was your response!'
'noodles was your response!'
Choose a command: c
Setup:
>>> spam = 6
>>> eggs = 42
Choose a command: q
Goodbye!
Making a Demo script:
# spam.py
...
...
if __name__ == "__main__":
demo = SpamDemo()
demo.run()
>>> python spam.py
Welcome to SpamDemo!
...
...
>>> python3 spam.py
Welcome to SpamDemo!
...
...
Demo¶
-
class
cli_demo.demo.Demo[source]¶ A basic framework for interactive demonstrations in a command line interface.
-
help_text¶ str – The help text used in
print_help().
-
setup_prompt¶ str – The input prompt for
run_setup().
-
options¶ A
DemoOptionsinstance forregisteringoption callbacks anddesignatingoptions to input functions.
Warning
When inheriting
optionsfrom aDemosuperclass, either a newDemoOptionsinstance should be created:class NewDemo(Demo): options = DemoOptions() ...
Or a copy should be made by calling
copy():class DemoSubclass(Demo): options = Demo.options.copy() ...
This is to avoid mangling options between superclass and subclasses.
-
Program logic of a Demo instance¶
-
Demo.run(*args, **kwargs)[source]¶ The main logic of a
Demoprogram.First, call
print_intro(), then print the options forrun_setup()usingprint_options()before callingrun_setup().Note
run()is decorated with:@catch_exc def run(self): ...
For more information, refer to
catch_exc().
setup process of a Demo instance¶
-
Demo.run_setup(*args, **kwargs)[source]¶ Prompt the user for input for the setup process.
Note
run_setup()is decorated with:@options("h", "o", "r", "q", key="setup") def run_setup(self): ...
For more information, refer to
options.
-
Demo.setup_callback(response)[source]¶ Handle user input to
run_setup().Parameters: response (str) – The user input to run_setup().Note
setup_callback()is decorated with:@options.register("setup", retry=True) def setup_callback(self, response): ...
For more information, refer to
options.register.
-
Demo.setup_options()[source]¶ Provide options for
run_setup().Note
The default option is
"*"with description"Any response.".
Print functions of a Demo instance¶
-
Demo.print_intro()[source]¶ Print the welcome text once.
Note
After
print_intro()is called for the first time, calling it again will no longer have any effect.
-
Demo.print_options(*opts, **key)[source]¶ Print what responses are allowed for an input function.
Parameters: - *opts (str) – Which options to print.
- **key (str) – An input function key.
Note
If an input function key is provided,
print_options()will do the following:- Retrieve options and descriptions (in a tuple) from
key_options()- a function that starts with key and ends in ‘_options’- if it is defined. - Get options from
get_options()using the input function key.
- Retrieve options and descriptions (in a tuple) from
Options are printed in the following order:
- Options from
key_options() - Keyword options from
get_options() - Argument options from
get_options() - Argument options passed into
print_options()
- Options from
Besides the options from
key_options(), option descriptions are taken from thedescof theOptioninstance registered under it. If an option is notregistered, then""is used for the description.print_options()is decorated with:@options.register("o", "Options", retry=True, lock=True, newline=True) def print_options(self, *opts, **key): ...
For more information, refer to
options.register.
-
Demo.print_help(**kwargs)[source]¶ Format and print
help_text.Parameters: - symbols (list) – A list of symbols for each level of indentation. Defaults to
[" ", "●", "○", "▸", "▹"]. - width (int) – The maximum width for a line printed. Defaults to
60. - indent (int) – The number of spaces per indent for the text printed. Defaults to
4. - border (str) – The character used for the border for
help_text. Defaults to"~". - title (str) – The character used for the border for the
"Help"title. Defaults to"=". - subtitle (str) – The character used for the border for the name of each
Demosubclass. Defaults to"-". - include (bool) – Whether to include the
help_textof all superclasses that are subclasses ofDemo. Defaults toFalse.
Note
print_help()is decorated with:@options.register("h", "Help.", retry=True, newline=True) def print_help(self, **kwargs): ...
For more information, refer to
options.register.- symbols (list) – A list of symbols for each level of indentation. Defaults to
Control flow tools of a Demo instance¶
-
Demo.restart(text=None)[source]¶ Restart the main
run()loop.Parameters: text (str, optional) – The text to print when restarting. Raises: DemoRestartNote
restart()is decorated with:@options.register("r") def restart(self, text=None): ...
For more information, refer to
options.register.
-
Demo.quit(text=None)[source]¶ Break out of the main
run()loop.Parameters: text (str, optional) – The text to print when quitting. Raises: DemoQuitNote
quit()is decorated with:@options.register("q") def quit(self, text=None): ...
For more information, refer to
options.register.
CodeDemo¶
-
class
cli_demo.code.CodeDemo[source]¶ Bases:
cli_demo.demo.DemoCodeDemo improves Demo by introducing a feature called
commands, which allows the user to select from a set of code snippets and view the result of it being passed intoexecute().-
setup_code¶ str – The code to run in
setup_callback().
-
command_prompt¶ str – The input prompt for
get_commands().
-
commands¶ list[str] – The code snippets for the user to choose from in
get_commands().
-
locals¶ dict – The local namespace populated in
setup_callback().
-
globals¶ dict – The global namespace populated in
setup_callback().
-
Program logic of a CodeDemo instance¶
-
CodeDemo.run(*args, **kwargs)[source]¶ The main logic of a
CodeDemoprogram.First, call
print_intro(), then print the options forrun_setup()usingprint_options()before callingrun_setup(), and then repeat the same process forget_commands().
setup process of a CodeDemo instance¶
-
CodeDemo.setup_callback(response)[source]¶ Handle user input to
run_setup().Set
localsto the global namespace of__main__before updating with response. Then, copy the__builtins__of__main__intoglobals. Finally,execsetup_codeinlocalsandglobalsbefore printing it usingprint_setup().Parameters: response (str) – The user input to run_setup().Note
The
CodeDemoinstance is available inlocalsunder the name demo, and the user response under response.setup_callback()is decorated with:@options.register("setup") def setup_callback(self, response): ...
For more information, refer to
options.register.
commands process of a CodeDemo instance¶
-
CodeDemo.get_commands(*args, **kwargs)[source]¶ Prompt the user to select a command from
commands.Note
get_commands()is decorated with:@options("c", "o", "r", "q", key="commands") def get_commands(self): ...
For more information, refer to
options.
-
CodeDemo.commands_callback(response)[source]¶ Handle user input to
get_commands().execute()the respective code snippet or allcommandsif response is a valid index or"a". Otherwise,retry()with the error message:"Invalid index. Please try again.".Parameters: response (str) – The user input to get_commands().Note
commands_callback()is decorated with:@options.register("commands", retry=True) def commands_callback(self, response): ...
For more information, refer to
options.register.
-
CodeDemo.commands_options()[source]¶ Provide options for
get_commands().Note
- The descriptions and options are the code snippets and their enumerations.
- An additional option is
"a", which is"Execute all of the above.".
-
CodeDemo.execute(commands, print_in=True)[source]¶ execeach command inlocalsandglobals.print_in()the command if print_in isTrue. Remove any comments, then compile the command if there are multiple lines or assignments.execthe code snippet, andprint_out()the result or catch and print any errors. If there are any assignments in the code snippet,execute()their assigned names.Parameters: - commands (list) – The code snippets to
exec. - print_in (bool) – Whether to
print_in()a command.
- commands (list) – The code snippets to
Print functions of a CodeDemo instance¶
-
CodeDemo.print_setup()[source]¶ Print
setup_code.Note
print_setup()is decorated with:@options.register("c", "Setup code.", retry=True, newline=True) def print_setup(self): ...
For more information, refer to
options.register.
SandboxDemo¶
-
class
cli_demo.sandbox.SandboxDemo[source]¶ Bases:
cli_demo.code.CodeDemoSandboxDemo extends CodeDemo by providing
sandbox(), a Python shell in which users can experiment with the context that has been set up.
commands process of a SandboxDemo instance¶
-
SandboxDemo.get_commands(*args, **kwargs)[source]¶ Prompt the user to select a command from
commands.Note
get_commands()is decorated with:@options("c", "o", "s", "r", "q", key="commands") def get_commands(self): ...
For more information, refer to
options."s", for"Sandbox mode.", has been added to the available options.
-
SandboxDemo.sandbox(key)[source]¶ Set up an interactive shell to experiment with.
Prompt the user for input,
execute()the entered command or code block, and then repeat. If the input is"quit()", print the previous options usingprint_options()and return.Parameters: key (str) – The key of the input function which triggered sandbox mode. Note
sandbox()is decorated with:@options.register("s", "Sandbox mode.", retry=True, lock=True) def sandbox(self, key): ...
For more information, refer to
options.register.
DemoOptions¶
-
class
cli_demo.options.DemoOptions[source]¶ Designates options for input functions and forwards their registered callbacks dynamically.
-
cache¶ dict – A cache of input function key ids and their options and keyword options that have been captured.
-
Designating options for an input function¶
-
DemoOptions.__call__(*opts, **kw_opts)[source]¶ Designate a set of options to an input function.
If a user input falls within the designated options, invoke the
callbackof the correspondingOptioninstance through itscall()method.Parameters: - retry (str, optional) – The text to print before the input function is called again when the user response is invalid. Defaults to
"Please try again". - key (str, optional) – The key of the input function.
- args (tuple, optional) – The arguments that should be passed into the
callbackof theOptioninstance registered under key. Defaults to(). - kwargs (dict, optional) – The keyword arguments that should be passed into
callbackof theOptioninstance registered under key. Defaults to{}. - *opts – The user responses that should be accepted.
- **kw_opts – The user responses that should be redirected.
Note
If key is provided:
- key will be used to store a record of opts and kw_opts in
cache. - To reference the options stored in
cachewhen callingprint_options(), you can pass in key as the key argument. - If a user input does not fall within the designated options, the response will be forwarded to the
callbackof theOptioninstance registered under key through itscall()method.
If key is not provided:
- The input function itself will be used to store a record of opts and kw_opts in
cache. - To reference the options stored in
cachewhen callingprint_options(), you need to pass in the input function itself as the key argument. - If a user input does not fall within the designated options,
retry()will be called and retry will be printed.
Returns: A decorator which takes a function (expected to be an input function) and returns a wrapped function. Return type: options_decorator()The following exceptions will only be raised when the wrapped function is called.
Raises: OptionNotFoundError– If an option does not exist inregistry, or if its value is not an instance ofOption.CallbackNotFoundError– If thecallbackof anOptioninstance has not been set.CallbackLockError– If thelockattribute of anOptioninstance isTruebut itscallbackdoes not accept a key argument.CallbackResponseError– If key is provided but thecallbackof theOptioninstance registered under key does not accept a response argument.
- retry (str, optional) – The text to print before the input function is called again when the user response is invalid. Defaults to
Getting the options of an input function¶
-
DemoOptions.get_options(key)[source]¶ Get the options that were set with key.
Parameters: key – A key for a set of options and keyword options. Returns: The options and keyword options set under key. Return type: list[list, dict] Raises: KeyNotFoundError– If the id of key does not exist incache.
Setting the options of an input function¶
-
DemoOptions.set_options(key, *opts, **kw_opts)[source]¶ Change the options that were set with key.
If opts or kw_opts are provided, override the options or keyword options that were recorded previously.
Parameters: - key – A key for a set of options and keyword options.
- *opts – Argument options for key.
- **kw_opts – Keyword options for key.
-
DemoOptions.insert(key, kw, opt, **kw_opts)[source]¶ Insert an option into the options that were set with key.
Insert opt into the argument options at index kw if it is an int or a digit. Otherwise, update the keyword options with kw and opt.
Parameters: - key – A key for a set of options and keyword options.
- kw – An index for argument options or a keyword option.
- opt (str) – The option to insert.
- **kw_opts – More kw and opt arguments.
Raises: KeyNotFoundError– If the id of key does not exist incache.
Registering an Option instance¶
-
DemoOptions.register(option, desc='', **kwargs)[source]¶ Register an option.
Create an
Optioninstance based on the arguments and keyword arguments provided and then store inregistry.Returns: A decorator which takes a function, sets the
callbackof theOptioninstance usingset_callback(), and returns the original function.Return type: register_decorator()Parameters: - option (str) – The name of the option.
- desc (str, optional) – The description of the option that should be printed in
print_options(). If not provided, it will be set to the name of the function passed intoset_callback(). - newline (bool, optional) – Whether an empty line should be printed before
callbackis called. Defaults toFalse. - retry (bool, optional) – Whether an input function should be called again once
callbackhas returned. Defaults toFalse. - lock (bool, optional) – Whether the key of a triggering input function should be received by
callback. Defaults toFalse. - args (tuple, optional) – The default arguments that should be used to call
callback. Defaults to(). - kwargs (dict, optional) – The default keyword arguments that should be used to call
callback. Defaults to{}.
Note
- option can be an expected user response or an input function key.
- If option is an input function key:
- The function passed into
register_decorator()must accept a response argument- the user’s response to that input function. - Any response to that input function which does not fall within its designated options will be forwarded to the function through the
call()method of theOptioninstance for further processing.
- The function passed into
- If lock is
True, the function passed intoregister_decorator()must accept a key argument- the key of the input function that triggered it.
-
class
cli_demo.options.Option(**kwargs)[source]¶ Holds information about a registered option.
-
name¶ str – The name of the option.
-
desc¶ str – The description of the option that should be printed in
print_options().
-
Invoking the callback of an Option instance¶
-
DemoOptions.call(option, *args, **kwargs)[source]¶ Invoke the
callbackof theOptioninstance through itscall()method.Parameters: Returns: The return value of
callback.Raises: DemoException– Ifdemois not set.OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.CallbackNotFoundError– If thecallbackof theOptioninstance has not been set.
Getting attributes of an Option instance¶
-
DemoOptions.__contains__(option)[source]¶ Check if an
Optioninstance is registered.Parameters: option (str) – The nameused to register theOptioninstance.Returns: Trueif option exists inregistryand its value is an instance ofOption,Falseotherwise.
-
DemoOptions.__getitem__(option)[source]¶ Get the registered
Optioninstance.Parameters: option (str) – The nameused to register theOptioninstance.Returns: The Optioninstance registered under option.Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.get_callback(option)[source]¶ Get the
call()method of theOptioninstance.Parameters: option (str) – The
nameused to register theOptioninstance.Returns: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.CallbackNotFoundError– If thecallbackof theOptioninstance has not been set.
-
DemoOptions.is_lock(option)[source]¶ Check if the key of a triggering input function will be received by the
callbackof theOptioninstance.Parameters: option (str) – The nameused to register theOptioninstance.Returns: Trueif thelockattribute of theOptioninstance isTrue,Falseotherwise.Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.will_retry(option)[source]¶ Check if an input function will be called again once the
callbackof theOptioninstance has returned.Parameters: option (str) – The nameused to register theOptioninstance.Returns: Trueif theretryattribute of theOptioninstance isTrue,Falseotherwise.Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.has_newline(option)[source]¶ Check if an empty line will be printed before the
callbackof theOptioninstance is called.Parameters: option (str) – The nameused to register theOptioninstance.Returns: Trueif thenewlineattribute of theOptioninstance isTrue,Falseotherwise.Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.get_desc(option)[source]¶ Get the description of the
Optioninstance.Parameters: option (str) – The nameused to register theOptioninstance.Returns: The descattribute of theOptioninstance.Return type: str Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.get_args(option)[source]¶ Get the default arguments that will be used to call the
callbackof theOptioninstance.Parameters: option (str) – The nameused to register theOptioninstance.Returns: The argsattribute of theOptioninstance.Return type: tuple Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.get_kwargs(option)[source]¶ Get the default keyword arguments that will be used to call the
callbackof theOptioninstance.Parameters: option (str) – The nameused to register theOptioninstance.Returns: The kwargsattribute of theOptioninstance.Return type: dict Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
Setting attributes of an Option instance¶
-
DemoOptions.set_callback(option, callback)[source]¶ Set the
callbackof theOptioninstance.If the
descof theOptioninstance is blank, use the name of callback to set it.Parameters: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.set_lock(option, lock)[source]¶ Set whether the key of a triggering input function should be received by the
callbackof theOptioninstance.Parameters: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.set_retry(option, retry)[source]¶ Set whether an input function should be called again once the
callbackof theOptioninstance has returned.Parameters: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.set_newline(option, newline)[source]¶ Set whether an empty line should be printed before the
callbackof theOptioninstance is called.Parameters: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
-
DemoOptions.set_desc(option, desc)[source]¶ Set the description of the
Optioninstance.Parameters: - option (str) – The
nameused to register theOptioninstance. - desc (str) – The description that should be printed in
print_options().
Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.- option (str) – The
-
DemoOptions.set_args(option, *args)[source]¶ Set the default arguments that should be used to call the
callbackof theOptioninstance.Parameters: Raises: OptionNotFoundError– If option does not exist inregistry, or if its value is not an instance ofOption.
Inheriting an instance of DemoOptions / Option¶
-
DemoOptions.copy()[source]¶ Initialize a new copy of
DemoOptions.Returns: An instance of DemoOptionswith a deep copy of thecacheandregistrybelonging toself.
exceptions¶
This module contains exceptions for Demo.
-
cli_demo.exceptions.catch_exc(*demo_exc)[source]¶ Catch instances of demo_exc raised while running a function.
Parameters: *demo_exc – One or a few subclasses of DemoException, and possibly a function to wrap.Returns: A decorator that takes a function and returns a wrapped function. As a shortcut, if a function was passed into demo_exc, the wrapped function is returned instead. Return type: catch_exc_decorator()Note
- Non-subclasses of
DemoExceptionare ignored, aside from a function or method. DemoExceptionis the default if no subclasses are provided.- Non-instances of demo_exc will not be caught. They should typically be handled by a higher level and more general kind of
catch_exc(). - If a
KeyboardInterruptis raised while running the function, it will be caught andDemoExitwill be re-raised.
- Non-subclasses of
-
exception
cli_demo.exceptions.DemoException(text=None)[source]¶ Bases:
exceptions.ExceptionBase exception for any error raised in a
Demo.-
text¶ str – The text to print when an instance of
DemoExceptionis caught incatch_exc().
-
-
exception
cli_demo.exceptions.DemoRestart(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when user wants to restarts a
Demo.
-
exception
cli_demo.exceptions.DemoExit(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when user wants to quit a
Demo.
-
exception
cli_demo.exceptions.DemoRetry(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when an input function in a
Demoshould be called again.
-
exception
cli_demo.exceptions.KeyNotFoundError(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when a key id could not be found in a
cache.
-
exception
cli_demo.exceptions.OptionNotFoundError(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when an
Optioninstance could not be found in aregistry.
-
exception
cli_demo.exceptions.CallbackNotFoundError(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when the
callbackof anOptioninstance has not been set.
-
exception
cli_demo.exceptions.CallbackLockError(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when the
lockattribute of anOptioninstance isTruebut itscallbackdoes not accept a key argument.
-
exception
cli_demo.exceptions.CallbackResponseError(text=None)[source]¶ Bases:
cli_demo.exceptions.DemoExceptionRaised when an
Optioninstance is registered under an input function key but itscallbackdoes not accept a response argument.