Python package for wrapping applications inside a tailored interactive shell
Full Changelog: https://github.com/fwkz/riposte/compare/v0.4.1...v0.5.0
Explicitly state support for Python 3.8
Riposte
with a file containing commandsThe input stream is an abstraction telling how you feed Riposte with commands.
From now on you can also pass text file containing commands as an argument to your application:
# demo.py
from riposte import Riposte
repl = Riposte()
@repl.command("hello")
def hello():
repl.print("Hello World!")
repl.run()
commands.rpst
text file containing commands to be executed:
hello
hello
hello
$ python demo.py commands.rpst
[+] Is it me you looking for?
[+] Is it me you looking for?
[+] Is it me you looking for?
If for some reason you need a custom way of feeding Riposte with commands you can always add your custom input stream. The input stream is a generator that yields function which after calling it returns a string (the command) Generator[Callable[[], str], None, None]
. Let's say you are an evil genius and want to make your interactive shell application less interactive by feeding it with some kind of messaging system.
import itertools
from typing import Callable, Generator
from riposte import Riposte
from some.messaging.system import Subscriber
def some_messaging_system_input_stream(
subscriber: Subscriber # you can parametrize your input streams
) -> Generator[Callable, None, None]:
# itertools.repeat() make sure that your input stream runs forever
yield from itertools.repeat(subscriber.poll) # calling poll() will return command
class CustomInputStreamRiposte(Riposte):
def setup_cli(self):
super().setup_cli() # preserve default Riposte CLI
self.parser.add_argument(
"-h", "--host", help="Some messaging system address"
)
def parse_cli_arguments(self) -> None:
super().parse_cli_arguments() # preserve default Riposte CLI
if self.arguments.host:
subscriber = Subscriber(self.arguments.host)
self.input_stream = some_messaging_system_input_stream(subscriber)
self.print_banner = False # I guess you don't want to print banner
If your application needs custom CLI arguments Riposte gives you a way to implement it by overwriting Riposte.setup_cli()
method. Let's say you want to introduce --verbose
flag into your application:
# custom_cli_args.py
from riposte import Riposte
class CustomArgsRiposte(Riposte):
def setup_cli(self):
super().setup_cli() # preserve default Riposte CLI
self.parser.add_argument(
"-v", "--verbose", action="store_true", help="Verbose mode"
)
repl = CustomArgsRiposte()
@repl.command("foo")
def foo(bar: str):
repl.success("Foobar executed.")
if repl.arguments.verbose:
repl.success("Argument passed as bar: ", bar)
repl.run()
$ python custom_cli_args.py -v
riposte:~ $ foo 123
[+] Foobar executed.
[+] Argument passed as bar: 123
riposte:~ $
Riposte.parser
is an instance of Python's builtin argparse.ArgumentParser
so for all further instructions regarding adding CLI arguments please follow argparse
documentation.
Passed arguments are being parsed in Riposte.run()
and stored in Riposte.arguments
so you can access it within your application. If you need to access them before entering the main evaluation loop you can overwrite
Riposte.parse_cli_arguments()
from riposte import Riposte
class CustomArgsRiposte(Riposte):
def setup_cli(self):
super().setup_cli() # preserve default Riposte CLI
self.parser.add_argument(
"-v", "--verbose", action="store_true", help="Verbose mode"
)
def parse_cli_arguments(self):
super().parse_cli_arguments() # preserve default Riposte CLI
if self.arguments.verbose:
do_something_specific()
Similarly to the bash
if you delimit commands with semicolon you can trigger
execution of multiple commands in one line.
riposte:~ $ hello; hello; hello
[+] Is it me you looking for?
[+] Is it me you looking for?
[+] Is it me you looking for?
Riposte
also exposes CLI for your applications which gives you the ability to
pass commands using -c
switch:
$ python app.py -c "hello; hello; hello;"
[+] Is it me you looking for?
[+] Is it me you looking for?
[+] Is it me you looking for?
$
Given all of this, you can also start to treat your application as something that could be turned into automated scripts.
# banner.py
from riposte import Riposte
BANNER = """ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | | | | | |
| |_| | ___| | | ___ | | | | ___ _ __| | __| | |
| _ |/ _ \ | |/ _ \ | |/\| |/ _ \| '__| |/ _` | |
| | | | __/ | | (_) | \ /\ / (_) | | | | (_| |_|
\_| |_/\___|_|_|\___/ \/ \/ \___/|_| |_|\__,_(_)
Welcome User Hello World v1.2.3
"""
repl = Riposte(banner=BANNER)
@repl.command("hello")
def hello():
repl.print("Hello World!")
repl.run()
$ python banner.py
_ _ _ _ _ _ _ _ _
| | | | | | | | | | | | | | | |
| |_| | ___| | | ___ | | | | ___ _ __| | __| | |
| _ |/ _ \ | |/ _ \ | |/\| |/ _ \| '__| |/ _` | |
| | | | __/ | | (_) | \ /\ / (_) | | | | (_| |_|
\_| |_/\___|_|_|\___/ \/ \/ \___/|_| |_|\__,_(_)
Welcome User Hello World v1.2.3
riposte:~ $
Check whether arguments provided by user via input()
match _func
signature.
Feeding already validated arguments list to _apply_guides
allow to simplify its code.
validators
to guides
str
guides.literal
is default guide for any type-hint except for str
Hue
to Palette
Hue
to Palette
BOLD
formatting optionInitial release