Align Nix Python environment and add lazy CLI import
- Switch flake package and dev shell to Python 3.11 to match pyproject - Ensure the python-with-deps environment is preferred on PATH in nix develop - Introduce a lightweight pkgmgr __init__ with lazy loading of pkgmgr.cli - Avoid pulling in CLI/config dependencies on plain `import pkgmgr`, fixing unit test imports and PyYAML availability in the Nix test containers https://chatgpt.com/share/693a9723-27ac-800f-a6c2-c1bcc91b7dff
This commit is contained in:
14
flake.nix
14
flake.nix
@@ -27,9 +27,11 @@
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
|
||||
# Single source of truth: "python3" from this nixpkgs revision
|
||||
python = pkgs.python3;
|
||||
pyPkgs = python.pkgs;
|
||||
# Single source of truth for pkgmgr: Python 3.11
|
||||
# - Matches pyproject.toml: requires-python = ">=3.11"
|
||||
# - Uses python311Packages so that PyYAML etc. are available
|
||||
python = pkgs.python311;
|
||||
pyPkgs = pkgs.python311Packages;
|
||||
in
|
||||
rec {
|
||||
pkgmgr = pyPkgs.buildPythonApplication {
|
||||
@@ -74,7 +76,8 @@
|
||||
if pkgs ? ansible-core then pkgs.ansible-core
|
||||
else pkgs.ansible;
|
||||
|
||||
python = pkgs.python3;
|
||||
# Use the same Python version as the package (3.11)
|
||||
python = pkgs.python311;
|
||||
|
||||
pythonWithDeps = python.withPackages (ps: [
|
||||
ps.pip
|
||||
@@ -90,6 +93,9 @@
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
# Ensure our Python with dependencies is preferred on PATH
|
||||
export PATH=${pythonWithDeps}/bin:$PATH
|
||||
|
||||
# Ensure src/ layout is importable:
|
||||
# pkgmgr lives in ./src/pkgmgr
|
||||
export PYTHONPATH="$PWD/src:${PYTHONPATH:-}"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Top-level pkgmgr package.
|
||||
|
||||
We deliberately avoid importing heavy submodules (like the CLI)
|
||||
on import to keep unit tests fast and to not require optional
|
||||
dependencies (like PyYAML) unless they are actually used.
|
||||
|
||||
Accessing ``pkgmgr.cli`` will load the CLI module lazily via
|
||||
``__getattr__``. This keeps patterns like
|
||||
|
||||
from pkgmgr import cli
|
||||
|
||||
working as expected in tests and entry points.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from importlib import import_module
|
||||
from typing import Any
|
||||
|
||||
__all__ = ["cli"]
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""
|
||||
Lazily expose ``pkgmgr.cli`` as attribute on the top-level package.
|
||||
|
||||
This keeps ``import pkgmgr`` lightweight while still allowing
|
||||
``from pkgmgr import cli`` in tests and entry points.
|
||||
"""
|
||||
if name == "cli":
|
||||
return import_module("pkgmgr.cli")
|
||||
raise AttributeError(f"module 'pkgmgr' has no attribute {name!r}")
|
||||
|
||||
Reference in New Issue
Block a user