context
¶
-
class
invoke.context.
Context
(config=None)¶ Context-aware API wrapper & state-passing object.
Context
objects are created during command-line parsing (or, if desired, by hand) and used to share parser and configuration state with executed tasks (see Aside: what exactly is this ‘context’ arg anyway?).Specifically, the class offers wrappers for core API calls (such as
run
) which take into account CLI parser flags, configuration files, and/or changes made at runtime. It also acts as a proxy for itsconfig
attribute - see that attribute’s documentation for details.Instances of
Context
may be shared between tasks when executing sub-tasks - either the same context the caller was given, or an altered copy thereof (or, theoretically, a brand new one).New in version 1.0.
-
__init__
(config=None)¶ Parameters: config – Config
object to use as the base configuration.Defaults to an anonymous/default
Config
instance.
-
cd
(*args, **kwds)¶ Context manager that keeps directory state when executing commands.
Any calls to
run
,sudo
, within the wrapped block will implicitly have a string similar to"cd <path> && "
prefixed in order to give the sense that there is actually statefulness involved.Because use of
cd
affects all such invocations, any code making use of thecwd
property will also be affected by use ofcd
.Like the actual ‘cd’ shell builtin,
cd
may be called with relative paths (keep in mind that your default starting directory is your user’s$HOME
) and may be nested as well.Below is a “normal” attempt at using the shell ‘cd’, which doesn’t work since all commands are executed in individual subprocesses – state is not kept between invocations of
run
orsudo
:c.run('cd /var/www') c.run('ls')
The above snippet will list the contents of the user’s
$HOME
instead of/var/www
. Withcd
, however, it will work as expected:with c.cd('/var/www'): c.run('ls') # Turns into "cd /var/www && ls"
Finally, a demonstration (see inline comments) of nesting:
with c.cd('/var/www'): c.run('ls') # cd /var/www && ls with c.cd('website1'): c.run('ls') # cd /var/www/website1 && ls
Note
Space characters will be escaped automatically to make dealing with such directory names easier.
New in version 1.0.
-
command_cwds
= None¶ A list of directories to ‘cd’ into before running commands with
run
orsudo
; intended for management viacd
, please see its docs for details.
-
command_prefixes
= None¶ A list of commands to run (via “&&”) before the main argument to any
run
orsudo
calls. Note that the primary API for manipulating this list isprefix
; see its docs for details.
-
config
¶ The fully merged
Config
object appropriate for this context.Config
settings (see their documentation for details) may be accessed like dictionary keys (c.config['foo']
) or object attributes (c.config.foo
).As a convenience shorthand, the
Context
object proxies to itsconfig
attribute in the same way - e.g.c['foo']
orc.foo
returns the same value asc.config['foo']
.
-
prefix
(*args, **kwds)¶ Prefix all nested
run
/sudo
commands with given command plus&&
.Most of the time, you’ll want to be using this alongside a shell script which alters shell state, such as ones which export or alter shell environment variables.
For example, one of the most common uses of this tool is with the
workon
command from virtualenvwrapper:with c.prefix('workon myvenv'): c.run('./manage.py migrate')
In the above snippet, the actual shell command run would be this:
$ workon myvenv && ./manage.py migrate
This context manager is compatible with
cd
, so if your virtualenv doesn’tcd
in itspostactivate
script, you could do the following:with c.cd('/path/to/app'): with c.prefix('workon myvenv'): c.run('./manage.py migrate') c.run('./manage.py loaddata fixture')
Which would result in executions like so:
$ cd /path/to/app && workon myvenv && ./manage.py migrate $ cd /path/to/app && workon myvenv && ./manage.py loaddata fixture
Finally, as alluded to above,
prefix
may be nested if desired, e.g.:with c.prefix('workon myenv'): c.run('ls') with c.prefix('source /some/script'): c.run('touch a_file')
The result:
$ workon myenv && ls $ workon myenv && source /some/script && touch a_file
Contrived, but hopefully illustrative.
New in version 1.0.
-
run
(command, **kwargs)¶ Execute a local shell command, honoring config options.
Specifically, this method instantiates a
Runner
subclass (according to therunner
config option; default isLocal
) and calls its.run
method withcommand
andkwargs
.See
Runner.run
for details oncommand
and the available keyword arguments.New in version 1.0.
-
sudo
(command, **kwargs)¶ Execute a shell command via
sudo
with password auto-response.Basics
This method is identical to
run
but adds a handful of convenient behaviors around invoking thesudo
program. It doesn’t do anything users could not do themselves by wrappingrun
, but the use case is too common to make users reinvent these wheels themselves.Note
If you intend to respond to sudo’s password prompt by hand, just use
run("sudo command")
instead! The autoresponding features in this method will just get in your way.Specifically,
sudo
:Places a
FailingResponder
into thewatchers
kwarg (see Automatically responding to program output) which:- searches for the configured
sudo
password prompt; - responds with the configured sudo password (
sudo.password
from the configuration); - can tell when that response causes an authentication failure
(e.g. if the system requires a password and one was not
configured), and raises
AuthFailure
if so.
- searches for the configured
Builds a
sudo
command string using the suppliedcommand
argument, prefixed by various flags (see below);Executes that command via a call to
run
, returning the result.
Flags used
sudo
flags used under the hood include:-S
to allow auto-responding of password via stdin;-p <prompt>
to explicitly state the prompt to use, so we can be sure our auto-responder knows what to look for;-u <user>
ifuser
is notNone
, to execute the command as a user other thanroot
;- When
-u
is present,-H
is also added, to ensure the subprocess has the requested user’s$HOME
set properly.
Configuring behavior
There are a couple of ways to change how this method behaves:
Because it wraps
run
, it honors allrun
config parameters and keyword arguments, in the same way thatrun
does.- Thus, invocations such as
c.sudo('command', echo=True)
are possible, and if a config layer (such as a config file or env var) specifies that e.g.run.warn = True
, that too will take effect undersudo
.
- Thus, invocations such as
sudo
has its own set of keyword arguments (see below) and they are also all controllable via the configuration system, under thesudo.*
tree.- Thus you could, for example, pre-set a sudo user in a config
file; such as an
invoke.json
containing{"sudo": {"user": "someuser"}}
.
- Thus you could, for example, pre-set a sudo user in a config
file; such as an
Parameters: New in version 1.0.
-
-
class
invoke.context.
MockContext
(config=None, **kwargs)¶ A
Context
whose methods’ return values can be predetermined.Primarily useful for testing Invoke-using codebases.
Note
Methods not given
Results
to yield will raiseNotImplementedError
if called (since the alternative is to call the real underlying method - typically undesirable when mocking.)New in version 1.0.
-
__init__
(config=None, **kwargs)¶ Create a
Context
-like object whose methods yieldResult
objects.Parameters: - config – A Configuration object to use. Identical in behavior to
Context
. - run –
A data structure of
Results
, to return from calls to the instantiated object’srun
method (instead of actually executing the requested shell command).Specifically, this kwarg accepts:
- sudo – Identical to
run
, but whose values are yielded from calls tosudo
.
Raises: TypeError
, if the values given torun
or other kwargs aren’t individualResult
objects or iterables.- config – A Configuration object to use. Identical in behavior to
-
set_result_for
(attname, command, result)¶ Modify the stored mock results for given
attname
(e.g.run
).This is similar to how one instantiates
MockContext
with arun
orsudo
dict kwarg. For example, this:mc = MockContext(run={'mycommand': Result("mystdout")}) assert mc.run('mycommand').stdout == "mystdout"
is functionally equivalent to this:
mc = MockContext() mc.set_result_for('run', 'mycommand', Result("mystdout")) assert mc.run('mycommand').stdout == "mystdout"
set_result_for
is mostly useful for modifying an already-instantiatedMockContext
, such as one created by test setup or helper methods.New in version 1.0.
-