Automatically responding to program output¶
Command-line programs tend to be designed for interactive shells, which frequently manifests as waiting around for user input, or “prompts”. Well-designed programs offer options for pre-empting such prompts, resulting in an easily automated workflow – but with the rest, interactivity is unavoidable.
Runner class not only forwards your standard input to
the running program (allowing you to manually respond to prompts) but it can
also be configured to respond automatically on your behalf.
The mechanism for this automation is the
watchers kwarg to the
Runner.run method (and its wrappers elsewhere, such as
invoke.run), which is a list of
configured to watch for patterns & respond accordingly. The simplest of these
Responder, which just replies with its configured response every time its
pattern is seen; others can be found in the watchers module.
As with all other arguments to
run, you can also set the default set of
watchers globally via configuration files.
Take for example this program which expects a manual response to a yes/no prompt:
$ excitable-program When you give the OK, I'm going to do the things. All of them!! Are you ready? [Y/n] y OK! I just did all sorts of neat stuff. You're welcome! Bye!
You could call
run("excitable-program"), manually watch for the
prompt, and mash Y by hand. But if you instead supply a
Responder like so:
@task def always_ready(c): responder = Responder( pattern=r"Are you ready? \[Y/n\] ", response="y\n", ) c.run("excitable-program", watchers=[responder])
Runner passes the program’s
responder, which watches for
"Are you ready? [Y/n] " and automatically
\n to simulate hitting Enter/Return) to the program’s
The pattern argument to
Responder is treated as a
regular expression, requiring more care (note how we had to escape our square-brackets
in the above example) but providing more power as well.