From ed9ec6893adcada5db75b52ca904be7d7e0a2511 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Wed, 17 Jun 2026 09:51:47 +1000 Subject: [PATCH] Try to resolve circular imports --- enroll/harvest.py | 41 +++++++++++++++------ enroll/harvest_collectors/__init__.py | 53 ++++++++++++++++----------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/enroll/harvest.py b/enroll/harvest.py index 25146a2..43f3a90 100644 --- a/enroll/harvest.py +++ b/enroll/harvest.py @@ -2,6 +2,7 @@ from __future__ import annotations import glob import os +from importlib import import_module import re import shutil import shlex @@ -20,9 +21,30 @@ from .ignore import IgnorePolicy from .pathfilter import PathFilter from .version import get_enroll_version from .state import write_state +from .harvest_collectors.context import HarvestContext UnitQueryError = _systemd.UnitQueryError +_COLLECTOR_REEXPORTS = { + "CronLogrotateCollector": ".harvest_collectors.cron_logrotate", + "ExtraPathsCollector": ".harvest_collectors.paths", + "PackageManagerConfigCollector": ".harvest_collectors.package_manager", + "RuntimeStateCollector": ".harvest_collectors.runtime", + "ServicePackageCollector": ".harvest_collectors.services", + "UsersCollector": ".harvest_collectors.users", + "UsrLocalCustomCollector": ".harvest_collectors.paths", +} + + +def __getattr__(name: str) -> Any: + module_name = _COLLECTOR_REEXPORTS.get(name) + if module_name is None: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + module = import_module(module_name, __package__) + value = getattr(module, name) + globals()[name] = value + return value + def list_enabled_services() -> List[str]: return _systemd.list_enabled_services() @@ -1457,18 +1479,6 @@ def _collect_firewall_runtime_snapshot( ) -from .harvest_collectors import ( - CronLogrotateCollector, - ExtraPathsCollector, - HarvestContext, - PackageManagerConfigCollector, - RuntimeStateCollector, - ServicePackageCollector, - UsersCollector, - UsrLocalCustomCollector, -) - - def harvest( bundle_dir: str, policy: Optional[IgnorePolicy] = None, @@ -1491,6 +1501,13 @@ def harvest( # includes are harvested into an extra role. path_filter = PathFilter(include=include_paths or (), exclude=exclude_paths or ()) + from .harvest_collectors.cron_logrotate import CronLogrotateCollector + from .harvest_collectors.package_manager import PackageManagerConfigCollector + from .harvest_collectors.paths import ExtraPathsCollector, UsrLocalCustomCollector + from .harvest_collectors.runtime import RuntimeStateCollector + from .harvest_collectors.services import ServicePackageCollector + from .harvest_collectors.users import UsersCollector + if hasattr(os, "geteuid") and os.geteuid() != 0: print( "Warning: not running as root; harvest may miss files or metadata.", diff --git a/enroll/harvest_collectors/__init__.py b/enroll/harvest_collectors/__init__.py index 7512081..dc8925f 100644 --- a/enroll/harvest_collectors/__init__.py +++ b/enroll/harvest_collectors/__init__.py @@ -1,27 +1,38 @@ +"""Harvest collector package exports""" + +from __future__ import annotations + +from importlib import import_module + from .context import HarvestCollector, HarvestContext -from .cron_logrotate import CronLogrotateCollection, CronLogrotateCollector -from .package_manager import ( - PackageManagerConfigCollection, - PackageManagerConfigCollector, -) -from .paths import ExtraPathsCollector, UsrLocalCustomCollector -from .runtime import RuntimeStateCollection, RuntimeStateCollector -from .services import ServicePackageCollection, ServicePackageCollector -from .users import UsersCollection, UsersCollector + +_COLLECTOR_EXPORTS = { + "CronLogrotateCollection": ".cron_logrotate", + "CronLogrotateCollector": ".cron_logrotate", + "ExtraPathsCollector": ".paths", + "PackageManagerConfigCollection": ".package_manager", + "PackageManagerConfigCollector": ".package_manager", + "RuntimeStateCollection": ".runtime", + "RuntimeStateCollector": ".runtime", + "ServicePackageCollection": ".services", + "ServicePackageCollector": ".services", + "UsersCollection": ".users", + "UsersCollector": ".users", + "UsrLocalCustomCollector": ".paths", +} __all__ = [ - "CronLogrotateCollection", - "CronLogrotateCollector", - "ExtraPathsCollector", "HarvestCollector", "HarvestContext", - "PackageManagerConfigCollection", - "PackageManagerConfigCollector", - "RuntimeStateCollection", - "RuntimeStateCollector", - "ServicePackageCollection", - "ServicePackageCollector", - "UsersCollection", - "UsersCollector", - "UsrLocalCustomCollector", + *_COLLECTOR_EXPORTS, ] + + +def __getattr__(name: str): + module_name = _COLLECTOR_EXPORTS.get(name) + if module_name is None: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + module = import_module(module_name, __name__) + value = getattr(module, name) + globals()[name] = value + return value