meta_package_manager.config module¶
Configuration utilities for mpm.
Hosts the schema of the [mpm] configuration section consumed by
click_extra and the runtime policy around the [mpm.managers.<id>]
sections of the same configuration file: applying attribute overrides to shipped
managers, gating manager definitions on the trust of their source, and registering
them into the pool.
The concerns stay separate across three modules:
meta_package_manager.pool.ManagerPool owns the live manager instances
and the per-manager overridden_fields tracking dict;
meta_package_manager.definitions owns the declarative schema (which
fields a section may set, how to coerce values) and the class factory; this module
owns the loading policy and mutates the pool through the
apply_manager_overrides() and register_config_managers() helpers.
- class meta_package_manager.config.MpmConfig(all_managers=False, ignore_auto_updates=True, stop_on_error=False, dry_run=False, plan=False, sudo=None, timeout=None, jobs='auto', cooldown=<factory>, description=False, sort_by=<factory>, summary=True, network=False, suggest_contribs=True, managers=<factory>)[source]¶
Bases:
objectSchema for
mpmconfiguration files.Defines the recognized options for the
[mpm](or[tool.mpm]) configuration section. Each field corresponds to a CLI option on the rootmpmgroup.Note
Dynamic manager selectors (
brew = true,pip = false, etc.), click-extra built-in options (verbosity,table_format) and one-shot utility flags (--bar-plugin-path,--xkcd) are handled by thedefault_mappipeline and do not appear here.Note
Multi-word fields pin their config path through
CONFIG_PATH_METADATA_KEY: mpm’s configuration convention is underscored keys (matching Click parameter names, the--validate-configchecks and every documented example), while click-extra would otherwise kebab-case field names in the renderedclick:configreference.- all_managers: bool = False¶
Force evaluation of all managers, including unsupported and unmaintained.
- sudo: bool | None = None¶
Force privileged manager operations with (
True) or without (False)sudo. Unset by default: system managers escalate, user-level managers do not. Overridden per manager by asudoentry in[mpm.managers.<id>].
- timeout: int | None = None¶
Maximum duration in seconds for each manager CLI call. When unset, a per-operation default applies:
120for read-only queries (installed,outdated,search) and500for state-changing operations. A set value overrides every operation.
- jobs: int | str = 'auto'¶
Maximum number of managers to run concurrently. Accepts an integer, or the keywords
auto(one fewer than the logical CPU count, the default) andmax(every logical CPU); set1to run sequentially.
- cooldown: dict[str, Any]¶
Release-age cooldown gate:
periodis the minimum age a package version must reach before it can be installed or upgraded,policythe posture for managers that cannot enforce it (enforceskips them,best-effortruns them without the safeguard).Typed as
dict[str, Any]so click-extra treats the[mpm.cooldown]sub-tree as opaque: it carries no CLI flag of its own (the--cooldownoption merges over it axis by axis at runtime instead) and its keys are validated byvalidate_cooldown_section(), registered as aclick_extra.ConfigValidator. The deprecated [mpm] cooldown = “<duration>” string spelling stays accepted as the period.
- summary: bool = True¶
Print an end-of-run summary on stderr: a count line of per-manager totals plus any subcommand-specific follow-up notes.
- network: bool = False¶
Opt into network calls during the run. Today this only affects
mpm sbom, which queries OSV.dev for vulnerability data.
- suggest_contribs: bool = True¶
Print a contribution invitation when a user override targets a field that likely indicates an upstream detection bug.
- managers: dict[str, dict]¶
Per-manager attribute overrides keyed by manager ID.
Typed as
dict[str, dict]so click-extra treats the sub-tree as opaque: its keys are manager IDs (data, not flag names) and its leaf entries are validated byvalidate_manager_overrides_section()registered as aclick_extra.ConfigValidator. The field carries no CLI flag — it only exists in the schema to declare opacity and to enable--validate-configcoverage of the override block.
- meta_package_manager.config.INVALIDATED_CACHED_PROPS: Final[tuple[str, ...]] = ('available', 'cli_path', 'executable', 'fresh', 'supported', 'version')¶
Cached properties on
meta_package_manager.manager.PackageManagerthat may have been computed from attributes covered byOVERRIDABLE_FIELDS.Any pre-computed values are popped from the manager instance’s
__dict__after an override is applied so the next access recomputes them against the new attribute values. Safe to pop even if nothing was cached.
- meta_package_manager.config.CONTRIBUTION_HINT_FIELDS: Final[frozenset[str]] = frozenset({'cli_names', 'cli_search_path', 'requirement', 'version_cli_options', 'version_regexes'})¶
Subset of
OVERRIDABLE_FIELDSwhose override probably reflects a real upstream detection bug rather than a personal preference.When the user overrides one of these, mpm did not find the binary, used the wrong binary name, rejected a valid version, or failed to parse one. The other overridable fields (
timeout,ignore_auto_updates,pre_args, etc.) are user preferences and do not warrant a contribution invitation.
- meta_package_manager.config.ISSUE_TRACKER_NEW_URL: Final[str] = 'https://github.com/kdeldycke/meta-package-manager/issues/new'¶
Base URL of the upstream GitHub issue tracker’s new-issue endpoint.
- meta_package_manager.config.MAX_ISSUE_URL_LENGTH: Final[int] = 8192¶
Practical upper bound on the length of a pre-filled GitHub new-issue URL.
GitHub silently truncates very long URLs, which yields a broken issue form when the user clicks the invitation. Anything past 8 KiB is treated as a bug in the URL builder rather than a configuration we should tolerate.
- class meta_package_manager.config.ContributionHint(manager_id, field, user_value, detected_cli_path)[source]¶
Bases:
objectA user override of a detection-related field, candidate for upstream contribution.
Captured at override time by
apply_manager_overrides()so the user can later be invited to file an upstream issue with a pre-filled bug-report URL.- field: str¶
Name of the overridden
PackageManagerattribute.
- meta_package_manager.config.format_contribution_hints(hints)[source]¶
Render a multi-line, human-readable batch message inviting the user to contribute their overrides back upstream.
Returns an empty string for an empty list so the caller can branch on truthiness without a length check.
- Return type:
- meta_package_manager.config.validate_cooldown_section(section)[source]¶
Strict validator for the
[mpm.cooldown]configuration sub-tree.Delegates the shape and value checks to
meta_package_manager.cooldown.parse_cooldown_section(), translating itsValueErrorinto aclick_extra.ValidationError. click-extra only hands dict sub-trees to extension validators, so the deprecated top-level string spelling never lands here: its migration warning is logged at runtime instead (see thempmgroup body).- Raises:
click_extra.ValidationError – when the section is malformed.
- Return type:
- meta_package_manager.config.build_cooldown_validator()[source]¶
Construct a
click_extra.ConfigValidatorfor the[mpm.cooldown]sub-tree.Used by the CLI bootstrap (
@groupdecorator) to register the validator alongside the manager-overrides one. Stateless: the cooldown section needs no pool binding, unlike the manager overrides.- Return type:
- meta_package_manager.config.cooldown_section(ctx)[source]¶
Return the raw
[mpm.cooldown]value from the loaded config, orNone.Reads the full parsed config
click_extraexposes underCONF_FULL, tolerating a missing or malformed layer at each step: resolution decides how to read the value, and an invalid one already failed the load-time validator. The deprecated top-level string spelling comes through here unchanged.- Return type:
- meta_package_manager.config.validate_manager_overrides_section(section, *, pool)[source]¶
Strict validator for the
[mpm.managers.<id>]configuration sub-tree.Pure function: inspects
sectionagainst the pool’s registered managers andOVERRIDABLE_FIELDS, raises the firstclick_extra.ValidationErrorit encounters, never mutates the pool. Suitable for registration as aclick_extra.ConfigValidatorand for direct invocation byapply_manager_overrides()so both the--validate-configpath and the runtime application path enforce the same rules.A section keyed by a built-in manager ID is validated as an override (its fields must be a subset of
OVERRIDABLE_FIELDS). A section keyed by any other ID is validated as a brand-new manager definition viaparse_manager_definition().- Raises:
click_extra.ValidationError – when
sectionis not a mapping, an override sets an unknown field or a wrong-typed value, or a definition is malformed. Thepathof the raised error is relative to the[mpm.managers]section root (e.g."winget.cli_searchpath"); click-extra prepends the app prefix when surfacing the error.- Return type:
- meta_package_manager.config.apply_manager_overrides(pool, overrides)[source]¶
Apply per-manager attribute overrides parsed from the user’s config file.
Expects
overridesto be a mapping of manager ID to a mapping of attribute name to its new value, as returned byconf["mpm"]["managers"].Noneand empty mappings are accepted as no-op shortcuts so callers can unconditionally forward whatever was parsed from the config file.Validation is delegated to
validate_manager_overrides_section(), which raisesclick_extra.ValidationErroron the first issue. Both the runtime config-loading path and the explicit--validate-configpath enforce the same rules through that single validator, so a config that survives one survives the other.After validation succeeds, every override is applied as an instance attribute (shadowing the class default for the lifetime of the process), recorded in
overridden_fieldssoManagerPool._select_managers()skips the matching global--<flag>defaults for that manager, and the cached properties derived from the affected attributes are evicted so the next access recomputes them. List-valued fields use replace semantics: the override fully supersedes the built-in default.Returns a list of
ContributionHintentries, one per accepted override that targets aCONTRIBUTION_HINT_FIELDSfield. Each hint captures the pre-overridecli_pathso the contribution invitation can show what mpm would have detected without the user’s intervention.- Return type:
- meta_package_manager.config.build_manager_overrides_validator(pool)[source]¶
Construct a
click_extra.ConfigValidatorfor the[mpm.managers]sub-tree, bound to a specificManagerPool.Used by the CLI bootstrap (
@groupdecorator) to register a validator against the live pool. Wrappingvalidate_manager_overrides_section()in a closure satisfies theclick_extra.ConfigValidator.validatorsignature (Callable[[dict], None]) while keeping the underlying validator pool-agnostic and testable in isolation.- Return type:
- meta_package_manager.config.dump_manager_overrides(manager)[source]¶
Return the current overridable attributes of
manageras a TOML-ready dict.Walks
OVERRIDABLE_FIELDSin alphabetical order, reads each attribute from the manager instance, and converts tuples to lists sotomli_wcan serialize the result without translation. Attributes whose value isNoneare skipped: TOML cannot expressNoneand the user cannot override a field toNoneeither, so emitting the key would be misleading.Every other overridable field is emitted, including ones still at the class default. The output is meant to be a canonical override template: paste, prune the rows that don’t apply, and customize the rest.
- meta_package_manager.config.CTX_HINTS_KEY: Final[str] = 'mpm.contribution_hints'¶
ctx.metakey under which collectedContributionHintentries are accumulated betweenapply_manager_overrides_from_context()andprint_contribution_hints().
- meta_package_manager.config.apply_manager_overrides_from_context(ctx, pool)[source]¶
Read the
[mpm.managers.<id>]sections from the loaded config and apply them topool.Reads the full parsed config that
click_extraexposes underCONF_FULLafter configuration discovery and forwards the["mpm"]["managers"]subtree toapply_manager_overrides(). Returns silently when no configuration file was loaded or when the section is absent.Any
ContributionHintreturned byapply_manager_overrides()is stashed underCTX_HINTS_KEYforprint_contribution_hints()to surface at the end of the run.- Return type:
- meta_package_manager.config.print_contribution_hints(ctx)[source]¶
Print the collected contribution hints to
<stderr>.Reads from
CTX_HINTS_KEYand writes viaclick_extra.echo()rather than the logging module, so the message survives--verbosity CRITICAL``and the``logging.disable()block that suppresses log output for serialization formats. Caller is expected to gate this on the user’ssuggest_contribspreference.- Return type:
- meta_package_manager.config.RISKY_OVERRIDE_FIELDS: Final[frozenset[str]] = frozenset({'cli_names', 'cli_search_path', 'pre_cmds', 'sudo'})¶
Override fields that can redirect mpm to run an arbitrary binary (or
sudo).When such an override is read from an untrusted config source,
apply_manager_overrides_from_context()logs a warning. Seedocs/security.md.
- meta_package_manager.config.config_file_is_trusted(path)[source]¶
Whether a config file is safe to load executable manager definitions from.
Trusted on POSIX when both the file and its parent directory are owned by the current user or root and are not group- or world-writable, mirroring how
ssh,gitandsudoreason about config-file trust: a writable file (or a writable directory that lets an attacker swap the file) could inject arbitrary commands.On platforms without
os.getuid(Windows), the POSIX ownership model does not apply and the check is skipped (returnsTrue); seedocs/security.mdfor the rationale and the residual risk.- Return type:
- meta_package_manager.config.register_config_managers(pool, definitions, *, source=None, source_is_url=False)[source]¶
Build and register config-defined managers into
pool, applying the trust gate.A definition is skipped (with a warning) when its ID collides with a built-in, when it comes from a remote URL config, or when its local config file fails
config_file_is_trusted(). Returns the IDs actually registered. Definitions whose ID is already in the pool (e.g. registered by the eager pre-load) are silently skipped so the eager and callback passes are idempotent.
- meta_package_manager.config.register_config_managers_from_context(ctx, pool)[source]¶
Register config-defined managers from the loaded config (authoritative pass).
Reads the parsed config under
CONF_FULL, parses the non-built-in[mpm.managers.<id>]sections, and registers them throughregister_config_managers(). This is the source of truth for availability: a manager defined in a config the eager pre-load could not reach (a URL, a custom path) still works from here, it just does not get a dedicated CLI flag.- Return type:
- meta_package_manager.config.discover_config_definitions(pool)[source]¶
Eagerly read new-manager definitions before the CLI group is built.
Best-effort and local-only: any error (no config, parse failure, missing reader) yields no definitions so CLI startup never breaks. URL configs are deferred to the authoritative
register_config_managers_from_context()pass. Supports both the standalone[mpm.managers]layout and[tool.mpm.managers]inpyproject.toml.
- meta_package_manager.config.register_eager_config_managers(pool)[source]¶
Register config-defined managers before the CLI group is constructed.
Called from
__main__.main()ahead of importing the Click group, so the dynamic--<id>/--no-<id>selectors enumerate the augmented pool and config-defined managers become first-class flags alongside the built-ins.- Return type: