"""pm: the hermes package system. Everything hermes depends on — tool binaries, the python venv, node_modules dirs, plugins — is a package in one dependency tree. Package definitions (pm/packages.py) say what a package IS. The lockfile (pm/lock.json, machine-written) says exactly which versions and hashes. The installed-state file (facts.json, per install) says what is actually on this machine. ensure(name) makes the installed state match the lockfile and returns a Runner with the composed environment. env_for(*names) composes already-installed packages' env without installing anything. The facade resolves lazily (PEP 562): ``pm.environments`` runs at process boot, before any dependency is importable, and must not drag the downloader/ensure machinery in with it. """ from __future__ import annotations import sys _EXPORTS = { "pm.install": ( "activate", "check", "drift", "enabled_extras", "env_for", "is_installed", "installed_package", "lazy_installs_allowed", "store_first_path", "uv_launcher", ), "pm.client": ( "ensure", "sync_venv", "build_environment", "lock_project", "stage_manager_runtime", "ensure_environment", "ensure_project_environment", "ensure_python_tool", "venv_is_current", "check_project_lock", "export_requirements", "build_requirements_environment", "prune_cache", "stage_tools", "prepare_tools", ), "pm.operations": ("environment_python", "python_tool"), "pm.extras": ("available", "ensure_import", "install_hint"), "pm.lock": ("Facts", "Lockfile"), "pm.package": ("InstallError", "Package", "Runner", "compose_env"), "pm.registry": ("all_packages", "get_package", "register", "walk"), "pm.store": ("Store", "current_target"), } _HOME = {name: module for module, names in _EXPORTS.items() for name in names} __all__ = list(_HOME) def __getattr__(name: str): module = _HOME.get(name) if module is None: raise AttributeError(f"module 'pm' has no attribute {name!r}") # Not importlib.import_module: tests patch that globally and the facade must keep resolving. __import__(module) value = getattr(sys.modules[module], name) globals()[name] = value return value def __dir__(): return sorted(set(globals()) | set(_HOME))