meta_package_manager.execution module¶
CLI-execution engine shared by every package manager.
Runs one manager’s CLI in one subprocess: the
meta_package_manager.execution.CLIExecutor mixin (which
meta_package_manager.manager.PackageManager inherits) locates the binary
and runs it, the meta_package_manager.execution.CLIError exception carries
a failed call’s result, and meta_package_manager.execution.highlight_cli_name()
themes a binary’s name.
Scheduling many managers at once is the next altitude up, and lives in
meta_package_manager.dispatch: the concurrent fan-out primitives, the
lock families and the shared ✓/✗ trail. The sudo machinery that cuts
across both altitudes (credential priming, the keepalive, the hidden-prompt stall
watchdog) lives in meta_package_manager.sudo: this module only consumes
it, to wrap escalated commands and diagnose their failures.
Note
The name and intent mirror click_extra.execution from the sibling
click-extra project, where the
generic layers now live: the concurrency primitives (run_jobs/run_lanes
driven by mpm --jobs), the single-subprocess engine
(click_extra.execution.run_cli(), which disclosed invocations and
streams output to the logs), and the Ctrl+C machinery
(click_extra.execution.install_interrupt_handler() terminating the
in-flight children registered by run_cli). This module keeps what is
package-manager policy: per-operation timeouts, sudo escalation, cooldown
enforcement and dry-run.
- meta_package_manager.execution.DIAGNOSIS_TAIL_LINES: Final = 10¶
Trailing lines of a failed command’s report relayed at
WARNING.CLIs conclude with their actual error, so the tail is where the diagnosis lives; the cap keeps a verbose failure (a source build’s compiler spew) from flooding the default view. The raw streams are always available in full, live, at
DEBUG.
- meta_package_manager.execution.WIN_DEFAULT_PATHEXT: Final = '.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC'¶
Executable suffixes to search on Windows when
%PATHEXT%is unset.A copy of CPython’s own
shutil._WIN_DEFAULT_PATHEXT, whichCLIExecutor.search_all_cli()reads to mirrorshutil.which()’s behaviour. That attribute is private, so it can be renamed or dropped by any release without notice, and reading it unguarded made every manager detection on Windows oneAttributeErroraway from failing. This constant is the fallback;test_windows_pathext_tracks_cpythoncompares the two on every platform and every interpreter the matrix covers, so a divergence surfaces as a named test failure rather than as a Windows-only crash.
- exception meta_package_manager.execution.CLIError(code, output, error)[source]¶
Bases:
ExceptionAn error occurred when running package manager CLI.
The exception internally keeps the result of CLI execution.
- property diagnosis: str¶
The command’s own account of its failure, capped for log relay.
Prefers
<stderr>, the conventional stream for error reporting, and falls back on<stdout>for the tools that report failures there (steamcmd); a command that died silently is reduced to its exit code. Only the lastDIAGNOSIS_TAIL_LINESlines are kept, behind a counter of the truncated ones: errors conclude streams.
- meta_package_manager.execution.VERSION_PROBE: Final = 'version'¶
Pseudo-operation stamped on
CLIExecutor._active_operationduring version detection.Not a member of
meta_package_manager.capabilities.Operations(no subcommand routes it), but it participates in the same per-operation machinery:OPERATION_TIMEOUTSbinds it to the short read-only cap, andCLIExecutor.run()demotes its command disclosure toDEBUGso the per-candidate probes cannot drown theINFOnarration.
- meta_package_manager.execution.format_plan_command(cmd_args, extra_env=None)[source]¶
Render a captured
mpm --plancommand as a copy-pasteable shell line.Unlike
click_extra.execution.format_cli_prompt()(styled, and prefixed with a$prompt sigil for logs and dry-runs), this returns a plain, unstyled, shell-quoted line: the forced environment assignments followed by the resolved binary and its arguments, ready to paste into a terminal or pipe into a shell. See the plan-mode branch ofCLIExecutor.run().- Return type:
- meta_package_manager.execution.PLAN_RECORDER: Final = <meta_package_manager.execution._PlanRecorder object>¶
Process-wide sink for
CLIExecutor.run()’s plan-mode captures.A module-level singleton because
runexecutes in the fan-out’s worker threads, where the click context is not reliably reachable. See_PlanRecorder.
- meta_package_manager.execution.highlight_cli_name(path, match_names)[source]¶
Highlight the binary name in the provided
path.The name is only highlighted when it matches one of the recognized
match_names, so an unrecognized binary stays plain. Matching is insensitive to case on Windows and case-sensitive on other platforms, thanks toos.path.normcase.The rendering is delegated to
click_extra.execution.highlight_bin_name(), the same helper behind the$-prompt and spawn-trace log lines, so thempm managerstable and the logs can never drift apart.
- meta_package_manager.execution.READ_ONLY_TIMEOUT: Final = 120¶
Default timeout (seconds) for read-only probes and queries.
These operations only inspect state, so a short cap lets a wedged binary fail fast instead of stalling the whole run. The value is generous enough for legitimately slow scans (a freshly-pulled
guix searchwalking every package’s metadata) while still being far belowMUTATING_TIMEOUT.
- meta_package_manager.execution.MUTATING_TIMEOUT: Final = 500¶
Default timeout (seconds) for operations that change system state.
Installs, upgrades, removals, channel syncs and cleanups routinely build from source, download large archives or pull entire channels, so they need a long cap. Kept identical to the historical global default so these operations behave exactly as before when no explicit
--timeoutis given.
- meta_package_manager.execution.DEFAULT_TIMEOUT: Final = 500¶
Fallback timeout (seconds) for a CLI call whose operation is unknown.
Defaults to the conservative
MUTATING_TIMEOUT: when in doubt, wait rather than risk killing a legitimate long-running command.
- meta_package_manager.execution.OPERATION_TIMEOUTS: Final[dict[str, int]] = {'cleanup': 500, 'doctor': 500, 'install': 500, 'installed': 120, 'orphans': 120, 'outdated': 120, 'remove': 500, 'search': 120, 'sync': 500, 'upgrade': 500, 'upgrade_all': 500, 'version': 120}¶
Per-operation timeout defaults, applied only when the user has set no explicit
--timeout(or per-managertimeoutoverride).Keyed by the
meta_package_manager.capabilities.Operationsmember name, plus the special"version"detection probe. The keys are validated against theOperationsenum by the test suite so the two never drift apart. An operation absent from this map resolves toDEFAULT_TIMEOUT.
- meta_package_manager.execution.SPINNER_DELAY: Final = 0.1¶
Seconds a CLI call must run before its progress spinner appears.
Kept short so the spinner surfaces almost immediately on any call that is not instant: prompt feedback makes
mpmfeel responsive from the start rather than stalled during the first second. Only the quickest calls (cached version probes, trivial metadata queries) finish within this delay and stay silent; anything slower (aguix search, a source build) shows the spinner right away.
- class meta_package_manager.execution.CLIExecutor[source]¶
Bases:
objectLocate a manager’s CLI on the system and run it.
Mixin inherited by
meta_package_manager.manager.PackageManager. Owns the CLI-invocation configuration (names, search paths, environment, arguments, timeout) and the engine that searches for the binary, executes it, captures and normalizes its output, accumulates errors, and parses its self-reported version.Initialize
cli_errorslist.- cli_names: tuple[str, ...]¶
List of CLI names the package manager is known as.
This list of recognized CLI names is ordered by priority. That way we can influence the search of the right binary.
- ..hint::
This was helpful in the case of the Python transition from 2.x to 3.x, where multiple versions of the same executable were named
pythonorpython3.
By default, this property’s value is derived from the manager’s ID (see the
MetaPackageManager.__init__method above).
- cli_search_path: tuple[str, ...] = ()¶
List of additional path to help mpm hunt down the package manager CLI.
Must be a list of strings whose order dictates the search sequence.
Most of the time unnecessary:
meta_package_manager.execution.CLIExecutor.cli_pathworks well on all platforms.
- extra_env: ClassVar[Mapping[str, str | None] | None] = None¶
Additional environment variables to add to the current context.
Automatically applied on each
meta_package_manager.execution.CLIExecutor.run_cli()calls.
- pre_cmds: tuple[str, ...] = ()¶
Global list of pre-commands to add before before invoked CLI.
Automatically added to each
meta_package_manager.execution.CLIExecutor.run_cli()call.Used to prepend sudo or other system utilities.
- post_args: tuple[str, ...] = ()¶
Global list of options used before and after the invoked package manager CLI.
Automatically added to each
meta_package_manager.execution.CLIExecutor.run_cli()call.Essentially used to force silencing, low verbosity or no-color output.
- version_cli_options: tuple[str, ...] = ('--version',)¶
CLI options used to produce the version of the package manager.
The raw output produced by the package manager CLI will be parsed with the
version_regexesbelow to extract the version number.
- version_cli: str | None = None¶
Alternate binary probed for the manager’s version, instead of the main CLI.
Some manager suites expose no version flag on any of their own binaries (OpenBSD’s
pkg_add/pkg_info, Solaris’pkgadd/pkginfo): they ship with the base system and are versioned with the OS itself. Naming aversion_cli(likeuname) makes the version probe run that binary withversion_cli_optionsand parse its output withversion_regexes, while every operation keeps using the manager’s owncli_path. The binary is resolved withwhich(); the version resolves toNone(manager notfresh) when it is not found.
- version_regexes: tuple[str, ...] = ('(?P<version>\\S+)',)¶
Regular expressions used to extract the version number.
This property must be a tuple of strings, each of which is a valid regular expression that must contain a group named
<version>.The first of these regexes producing a match and returning non-empty
<version>group will be used as the version string of the package manager.That version string will then be sanitized and normalized by
meta_package_manager.execution.CLIExecutor.version.By default match the first part that is space-separated.
Caution
These regexes are compiled with
re.MULTILINEonly. They are not compiled withre.VERBOSE, so literal whitespace in the pattern is significant and matches whitespace in the CLI output.
- plan: bool = False¶
Capture state-changing CLI calls for inspection instead of running them.
Set by
mpm --plan. Unlikedry_run(which simulates every call, read-only queries included), plan mode lets the read-only queries (installed,outdated,search) run for real so the resolved plan reflects actual system state, and records only the state-changing commands (see_MUTATING_OPERATIONS) intoPLAN_RECORDER.
- timeout: int | None = None¶
Maximum number of seconds to wait for a CLI call to complete.
Nonemeans the user expressed no explicit preference: the effective cap is then resolved per-operation by_resolve_timeout()fromOPERATION_TIMEOUTS. A non-Nonevalue (the--timeoutflag or a per-manager override) wins for every operation.
- progress: bool = False¶
Whether CLI calls may show a progress spinner while they block.
Set by the CLI to an interactive, human-facing run only (a TTY, no serialized output, not at DEBUG verbosity). Even when
Truethe spinner still self-suppresses off a TTY: see_make_spinner(). Defaults toFalseso programmatic use stays silent.
- cooldown: timedelta | None = None¶
Minimum age a release must have before it can be installed or upgraded.
When set, the manager refuses to bring in any package version published more recently than
cooldownago. This is a mitigation against supply-chain attacks: a malicious release is typically detected and pulled within days of publication, so a waiting period keeps freshly-published (and potentially compromised) versions out of the system.Nonedisables the gate.Only managers able to enforce a release-age limit honor this, natively through
cooldown_env_varor through the per-package release-date probe ofrelease_date(); seesupports_cooldown.
- cooldown_policy: CooldownPolicy | None = None¶
Per-manager enforcement posture of an active release-age
cooldown.None(the default) inherits the policy resolved from--cooldownand the[mpm.cooldown]configuration, which the pool’s selection applies to every manager per run. Pin it explicitly through a[mpm.managers.<id>]override, which keeps precedence over the global resolution:enforceholds the manager fail-closed even under a best-effort run,best-effortwaives the requirement and runs it without the safeguard, andoffexempts it from the gate entirely, suppressing the cutoff injection even where the manager could honor one.
- sudo: bool | None = None¶
User escalation policy: run this manager’s privileged commands with
sudo.None(the default) means the user expressed no preference, so the built-indefault_sudodecides.True/Falseforce escalation on or off for every operation this manager marks privileged (abuild_cli(..., sudo=True)call). Set globally bympm --sudo/mpm --no-sudoand per manager by the[mpm.managers.<id>] sudoconfig key, the latter winning (seemeta_package_manager.pool.ManagerPool._select_managers()).Only privileged operations on UNIX are ever escalated. A manager that escalates internally (
internal_sudo) has no such markers and is never wrapped insudobympm: its ownsudoreuses the credential cache whenprime_sudo()finds it already warm, and is otherwise covered by the silent-call notice inrun().
- default_sudo: bool = False¶
Built-in escalation default, used when
sudoisNone.Falseon the base: most managers install into user-writable trees and never need root. The system package managers whose privileged operations require root (apt,dnf,pacman,zypper, …) set this toTrueso theirbuild_cli(..., sudo=True)operations escalate out of the box, while staying switchable off throughsudo(--no-sudoor config) for rootless setups.
- internal_sudo: bool = False¶
Marks a manager whose CLI invokes
sudoitself mid-run.Homebrew
caskruns it from installer artifacts,finkre-execs its root commands through it, and the AUR helpers callsudo pacmanfor their install steps. mpm never wraps such a manager’s commands: either none of its operations carry abuild_cli(..., sudo=True)marker (cask,fink), or itsdefault_sudo = Falsepolicy leaves the markers it inherits unescalated (the AUR helpers). Running the tool undersudois often forbidden outright (brewrefuses root,makepkgrefuses to build). Consumed byprime_sudo(), whose opportunistic probe keeps an already-warm credential cache alive for these internal escalations, and by the silent-call notice inrun(), which flags a possibly-hidden password prompt on a cold cache.Forcing
sudo = trueon such a manager (config key or--sudo) still never wraps its commands, but does promote it into the up-front prompt path ofprime_sudo().
- cooldown_env_var: ClassVar[str | None] = None¶
Environment variable this manager reads to honor a
cooldown.None(the default) means the manager has no native release-age mechanism to feed through the environment; it may still honor a cooldown through the per-package release-date probe (see_probes_release_date()). A subclass that sets this string advertises native support (seesupports_cooldown); the value produced bycooldown_env_value()is then injected into the environment of every CLI call.
- windows_creation_flags: int = 0¶
Additional Windows process creation flags OR-ed with
CREATE_NO_WINDOW.Use this on individual managers to control how their subprocess is attached to the calling process’s console. For example, setting this to
subprocess.DETACHED_PROCESS(0x8) fully detaches the child from the parent’s console. Any grandchild process (like a COM server or installer EXE) that callsGenerateConsoleCtrlEvent(0)on exit will then fail silently because there is no console to broadcast to.No-op on non-Windows platforms (
getattrreturns0for Windows-only flags).
- windows_processes_to_cleanup: tuple[str, ...] = ()¶
Windows process image names to forcibly terminate after each CLI call.
When a package manager spawns grandchild processes that outlive the direct subprocess (like winget’s
WindowsPackageManagerServer.exeCOM server), those orphans can linger and consume resources. List the image names here so they are killed aftercommunicate()returns.No-op on non-Windows platforms.
- run_cache: dict[tuple, tuple[int, str, str]] | None = None¶
Optional cache that de-duplicates identical CLI runs across a lane’s managers.
Noneby default, which disables caching: everyrun()call spawns its own subprocess. Two callers install a shared dict, each for the duration of one lane:meta_package_manager.dispatch.dispatch(), on every multi-manager lock-family lane (seemeta_package_manager.dispatch.SHARED_LOCK_FAMILIES), sobrewandcaskboth runningbrew updatefor mpm sync spawn it once.meta_package_manager.dispatch.warm_availability(), on every version-probe lane (seemeta_package_manager.dispatch.merge_into_probe_lanes()), sobrewandcaskboth probingbrew --versionspawn it once too.
The replay still walks
run()’s logging and failure gate, so a failed shared command is attributed to every member. Keyed on the resolved command line and its environment, so only genuinely identical invocations collapse.Caution
Not thread-safe, and it does not need to be: both callers bind a cache to a lane, and
click_extra.execution.run_lanes()runs a lane’s items serially on a single worker. Handing one dict to managers that run concurrently would race two peers into spawning the same command anyway, losing the de-duplication rather than corrupting anything, so the lane is what makes the cache work at all.
- cli_errors: list[CLIError]¶
Accumulate all CLI errors encountered by the package manager.
Every
CLIErrorproduced byrun()lands here, whether or not it is also raised: a failure the caller goes on to swallow (installed_or_empty()and its peers) is still a failure this manager committed, and the end-of-run summary, the serializederrorspayload and the ✓/✗ trail all read this list to say so.Recording only the non-raising half made a manager’s visibility hinge on whether its query happened to pass
must_succeed: mpm list printed “Could not list installed packages.” and still scored the manager ✓, leaving it out of the closing count.
- property supports_cooldown: bool¶
Whether this manager can enforce a release-age
cooldown.Either natively, by injecting
cooldown_env_varinto every CLI call, or through the per-package release-date probe advertised by_probes_release_date().
- cooldown_env_value()[source]¶
Render
cooldownas the value ofcooldown_env_var.Defaults to the RFC 3339 timestamp of the most recent release date still allowed, i.e. now minus the cooldown. Managers whose environment variable expects another format (a number of minutes, a bare day count, …) override this.
- Return type:
- cooldown_rounded_up(unit_seconds)[source]¶
Render
cooldownas an integer count ofunit_seconds-long units, rounded up.Helper for the
cooldown_env_value()overrides of managers whose native release-age knob expects a unit count rather than the default RFC 3339 timestamp (npm’s day-basedmin-release-age, pnpm’s minute-basedminimumReleaseAge). Sub-unit cooldowns round up so the gate over-protects rather than silently collapsing to0(the “no cooldown” sentinel).- Return type:
- cooldown_env()[source]¶
Environment fragment enforcing the
cooldown, empty when inactive.Returns an empty mapping unless a
cooldownis set and the manager supports it and itscooldown_policyhas not exempted it (off). Merged into the environment of everyrun()call.
- search_all_cli(cli_names, env=None)[source]¶
Search for all binary files matching the CLI names, in all environment path.
This is like our own implementation of
shutil.which(), with the difference that it is capable of returning all the possible paths of the provided file names, in all environment path, not just the first one that match. And on Windows, prevents matching of CLI in the current directory, which takes precedence on other paths.Returns all files matching any
cli_names, by iterating over all folders in this order:folders provided by
cli_search_path,then in all the default places specified by the environment variable (i.e.
os.getenv("PATH")).
Only returns files that exists and are not empty.
Caution
Symlinks are not resolved, because some manager like Homebrew on Linux relies on some sort of symlink-based trickery to set environment variables.
- sibling_cli(name, *, same_dir=False)[source]¶
Resolve the path of a sibling binary of the manager’s main CLI.
Some managers ship as a suite of binaries (
xbps-install/xbps-query,pkg_add/pkg_info, emerge’sqlist): an operation then runs a sibling instead of the main CLI. By default the sibling is searched like the main CLI itself (which(), honoringcli_search_path), and a missing binary raisesFileNotFoundErrorrather than silently falling back to the wrong program.same_dir=Trueinstead takes the sibling from the directory ofcli_path, without an existence probe: suites installing all their binaries side by side (XBPS, Nix) guarantee the neighbor, and resolving it from the same directory can never mix two installations. A genuinely missing file then surfaces at spawn time.- Return type:
- property cli_path: Path | None[source]¶
Fully qualified path to the canonical package manager binary.
Try each CLI names provided by
cli_names, in each system path provided bycli_search_path. In that order. Then returns the first match.Executability of the CLI will be separately assessed later by the
meta_package_manager.execution.CLIExecutor.executableproperty below.
- property version: TokenizedString | None[source]¶
Invoke the manager and extract its own reported version string.
Returns a parsed and normalized version in the form of a
meta_package_manager.version.TokenizedStringinstance.Skipped on platforms where the manager is not supported, even if
cli_pathresolved to an executable: that binary almost certainly belongs to a different tool that happens to share the same name (e.g. GNUmakeon macOS getting matched by the FreeBSDportsmanager), so probing it would either misreport the version or surface confusing error output.
- acting_as(operation=None, *, stop_on_error=None)[source]¶
Temporarily adjust the manager’s execution state, restoring it on exit.
operationre-stamps_active_operation(the per-operation timeout and watchdog key) for the duration of the block;Noneleaves the current stamp untouched.stop_on_errorlikewise overrides the failure policy when set: the per-package state changers run their action understop_on_error=Trueso a botched operation raises and is recorded by the caller instead of being silently accumulated.The public seam for callers needing a scoped state override: the CLI layer must never poke
_active_operationorstop_on_errordirectly.
- run(*args, extra_env=None, must_succeed=False)[source]¶
Run a shell command, return the output and accumulate error messages.
argsis allowed to be a nested structure of iterables, in which case it will be recursively flatten, thenNonewill be discarded, and finally each item casted to strings.- Running commands with that method takes care of:
disclosing the invocation at
INFO(the reproducible$-prompt line with forced environment variables) and streaming the raw output live toDEBUG, prefixed with the manager ID, viaclick_extra.execution.run_cli()flagging, on a terminal, the mutating call of an internal escalator that goes silent on a cold credential cache and may be blocked on a hidden password prompt (see
_StallWatchdog)detaching every other call into its own POSIX session and process group, so a timeout or Ctrl+C reaps the whole process tree and a wedged grandchild cannot linger as an orphan; the flagged call above keeps the controlling terminal so its
sudoprompt stays answerableremoving ANSI escape codes from
subprocess.CompletedProcess.stdoutandsubprocess.CompletedProcess.stderrreturning ready-to-use normalized strings (dedented and stripped)
letting
mpm --dry-runandmpm --stop-on-errorhave expected effect on execution
- Parameters:
must_succeed (
bool) – ifTrue, raisemeta_package_manager.execution.CLIErrorwhen the command fails, regardless of the user-facingstop_on_errorpreference, rather than accumulating the error for an end-of-run summary. Use for calls whose output is parsed (JSON, XML, regex), where a swallowed failure would be indistinguishable from empty results. A non-zero exit that leaves<stderr>empty is tolerated as a benign status code (npmandpnpm outdatedexit1when updates exist); only the per-package state changers, which run under a patchedstop_on_error, treat every non-zero exit as a failure. See the failure gate below for details.- Return type:
- build_cli(*args, auto_pre_cmds=True, auto_pre_args=True, auto_post_args=True, override_pre_cmds=None, override_cli_path=None, override_pre_args=None, override_post_args=None, sudo=False)[source]¶
Build the package manager CLI by combining the custom
*argswith the package manager’s global parameters.Returns a tuple of strings.
Helps the construction of CLI’s repeating patterns and makes the code easier to read. Just pass the specific
*argsand the full CLI string will be composed out of the globals, following this schema:$ [<pre_cmds>|sudo --non-interactive] <cli_path> <pre_args> <*args> <post_args>
self.pre_cmdsis added before the CLI path.self.cli_pathis used as the main binary to execute.self.pre_argsandself.post_argsglobals are added before and after the provided*args.
Each additional set of elements can be disabled with their respective flag:
auto_pre_cmds=Falseto skip the automatic addition ofself.pre_cmdsauto_pre_args=Falseto skip the automatic addition ofself.pre_argsauto_post_args=Falseto skip the automatic addition ofself.post_args
Each global set of elements can be locally overridden with:
override_pre_cmds=tuple()override_cli_path=stroverride_pre_args=tuple()override_post_args=tuple()
On UNIX, an operation marked privileged (
sudo=True) is escalated only when the per-manager policy opts in (sudo, falling back todefault_sudo). It is then run through sudo with--non-interactive(it spends the credential cache warmed byprime_sudo()and fails fast rather than blocking on a password prompt). When escalation applies,override_pre_cmdsis not allowed to be set andauto_pre_cmdsis forced toFalse. A non-UNIX host never escalates.
- run_cli(*args, auto_extra_env=True, auto_pre_cmds=True, auto_pre_args=True, auto_post_args=True, override_extra_env=None, override_pre_cmds=None, override_cli_path=None, override_pre_args=None, override_post_args=None, force_exec=False, must_succeed=False, sudo=False)[source]¶
Build and run the package manager CLI by combining the custom
*argswith the package manager’s global parameters.After the CLI is built with the
meta_package_manager.execution.CLIExecutor.build_cli()method, it is executed with themeta_package_manager.execution.CLIExecutor.run()method, augmented with environment variables fromself.extra_env.All parameters are the same as
meta_package_manager.execution.CLIExecutor.build_cli(), plus:auto_extra_env=Falseto skip the automatic addition ofself.extra_envoverride_extra_env=dict()to locally overrides the laterforce_execignores thempm --dry-run,mpm --stop-on-errorandmpm --planoptions to force the execution and completion of the command. It is used for reads whose output is needed regardless (version detection,yarn global dir), which must run for real even when the user asked to simulate or to only plan mutations.must_succeedraises on non-zero exit regardless ofmpm --stop-on-error. Seerun()for details.
- Return type: