context¶
- class invoke.context.Context(config: Config | None = None)¶
Context-aware API wrapper & state-passing object.
Contextobjects are created during command-line parsing (or, if desired, by hand) and used to share parser and configuration state with executed tasks (see 旁白:这个 ‘context’ 的说法到底是什么?).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 itsconfigattribute - see that attribute’s documentation for details.Instances of
Contextmay 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).在 1.0 版本加入.
- cd(path: PathLike | str) Generator[None, None, None]¶
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
cdaffects all such invocations, any code making use of thecwdproperty will also be affected by use ofcd.Like the actual ‘cd’ shell builtin,
cdmay 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
runorsudo:c.run('cd /var/www') c.run('ls')
The above snippet will list the contents of the user’s
$HOMEinstead 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
备注
Space characters will be escaped automatically to make dealing with such directory names easier.
在 1.0 版本加入.
在 1.5 版本发生变更: Explicitly cast the
pathargument (the only argument) to a string; this allows any object defining__str__to be handed in (such as the variousPathobjects out there), and not just string literals.
- prefix(command: str) Generator[None, None, None]¶
Prefix all nested
run/sudocommands 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
workoncommand 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’tcdin itspostactivatescript, 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,
prefixmay 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.
在 1.0 版本加入.
- run(command: str, **kwargs: Any) Result | None¶
Execute a local shell command, honoring config options.
Specifically, this method instantiates a
Runnersubclass (according to therunnerconfig option; default isLocal) and calls its.runmethod withcommandandkwargs.See
Runner.runfor details oncommandand the available keyword arguments.在 1.0 版本加入.
- sudo(command: str, **kwargs: Any) Result | None¶
Execute a shell command via
sudowith password auto-response.Basics
This method is identical to
runbut adds a handful of convenient behaviors around invoking thesudoprogram. 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.备注
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
FailingResponderinto thewatcherskwarg (see 自动响应程序输出) which:searches for the configured
sudopassword prompt;responds with the configured sudo password (
sudo.passwordfrom 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
AuthFailureif so.
Builds a
sudocommand string using the suppliedcommandargument, prefixed by various flags (see below);Executes that command via a call to
run, returning the result.
Flags used
sudoflags used under the hood include:-Sto 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>ifuseris notNone, to execute the command as a user other thanroot;When
-uis present,-His also added, to ensure the subprocess has the requested user’s$HOMEset properly.
Configuring behavior
There are a couple of ways to change how this method behaves:
Because it wraps
run, it honors allrunconfig parameters and keyword arguments, in the same way thatrundoes.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.
sudohas 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.jsoncontaining{"sudo": {"user": "someuser"}}.
- 参数:
在 1.0 版本加入.
- class invoke.context.MockContext(config: Config | None = None, **kwargs: Any)¶
A
Contextwhose methods’ return values can be predetermined.Primarily useful for testing Invoke-using codebases.
备注
This class wraps its
run, etc methods inunittest.mock.Mockobjects. This allows you to easily assert that the methods (still returning the values you prepare them with) were actually called.备注
Methods not given
Resultsto yield will raiseNotImplementedErrorif called (since the alternative is to call the real underlying method - typically undesirable when mocking.)在 1.0 版本加入.
在 1.5 版本发生变更: Added
Mockwrapping ofrunandsudo.- __init__(config: Config | None = None, **kwargs: Any) None¶
Create a
Context-like object whose methods yieldResultobjects.- 参数:
config – A Configuration object to use. Identical in behavior to
Context.run –
A data structure indicating what
Resultobjects to return from calls to the instantiated object’srunmethod (instead of actually executing the requested shell command).Specifically, this kwarg accepts:
A single
Resultobject.A boolean; if True, yields a
Resultwhoseexitedis0, and if False,1.An iterable of the above values, which will be returned on each subsequent call to
.run(the first item on the first call, the second on the second call, etc).A dict mapping command strings or compiled regexen to the above values (including an iterable), allowing specific call-and-response semantics instead of assuming a call order.
sudo – Identical to
run, but whose values are yielded from calls tosudo.repeat (bool) –
A flag determining whether results yielded by this class’ methods repeat or are consumed.
For example, when a single result is indicated, it will normally only be returned once, causing
NotImplementedErrorafterwards. But whenrepeat=Trueis given, that result is returned on every call, forever.Similarly, iterable results are normally exhausted once, but when this setting is enabled, they are wrapped in
itertools.cycle.Default:
True.
- Raises:
TypeError, if the values given torunor other kwargs aren’t of the expected types.
在 1.5 版本发生变更: Added support for boolean and string result values.
在 1.5 版本发生变更: Added support for regex dict keys.
在 1.5 版本发生变更: Added the
repeatkeyword argument.在 2.0 版本发生变更: Changed
repeatdefault value fromFalsetoTrue.
- run(command: str, *args: Any, **kwargs: Any) Result¶
Execute a local shell command, honoring config options.
Specifically, this method instantiates a
Runnersubclass (according to therunnerconfig option; default isLocal) and calls its.runmethod withcommandandkwargs.See
Runner.runfor details oncommandand the available keyword arguments.在 1.0 版本加入.
- set_result_for(attname: str, command: str, result: Result) None¶
Modify the stored mock results for given
attname(e.g.run).This is similar to how one instantiates
MockContextwith arunorsudodict 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_foris mostly useful for modifying an already-instantiatedMockContext, such as one created by test setup or helper methods.在 1.0 版本加入.
- sudo(command: str, *args: Any, **kwargs: Any) Result¶
Execute a shell command via
sudowith password auto-response.Basics
This method is identical to
runbut adds a handful of convenient behaviors around invoking thesudoprogram. 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.备注
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
FailingResponderinto thewatcherskwarg (see 自动响应程序输出) which:searches for the configured
sudopassword prompt;responds with the configured sudo password (
sudo.passwordfrom 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
AuthFailureif so.
Builds a
sudocommand string using the suppliedcommandargument, prefixed by various flags (see below);Executes that command via a call to
run, returning the result.
Flags used
sudoflags used under the hood include:-Sto 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>ifuseris notNone, to execute the command as a user other thanroot;When
-uis present,-His also added, to ensure the subprocess has the requested user’s$HOMEset properly.
Configuring behavior
There are a couple of ways to change how this method behaves:
Because it wraps
run, it honors allrunconfig parameters and keyword arguments, in the same way thatrundoes.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.
sudohas 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.jsoncontaining{"sudo": {"user": "someuser"}}.
- 参数:
在 1.0 版本加入.