pyrolab/manager.py:482-488:
class ProcessManager:
_instance = None
nameservers: Dict[str, NameServerProcessGroup] = {}
daemons: Dict[str, DaemonProcessGroup] = {}
GLOBAL_CONFIG: GlobalConfiguration
manager: multiprocessing.Manager
_timer: threading.Timer
nameservers and daemons are real class attributes holding mutable dicts, not annotations. instance() assigns instance attributes of the same names (pyrolab/manager.py:407-408), so the class-level dicts are shadowed and stay empty in normal use -- but any access through the class (ProcessManager.daemons[...]) or from a subclass touches shared state instead.
Note the inconsistency: GLOBAL_CONFIG, manager and _timer on the following lines are bare annotations with no value, which is the correct form. The two dicts look the same but behave differently.
Fix: drop the = {} so all six are annotations:
nameservers: Dict[str, NameServerProcessGroup]
daemons: Dict[str, DaemonProcessGroup]
The same pattern-with-a-value appears nowhere else in the codebase, so this looks unintentional.
Found in a full-codebase audit at v0.4.0 (commit 1ce3146).
pyrolab/manager.py:482-488:nameserversanddaemonsare real class attributes holding mutable dicts, not annotations.instance()assigns instance attributes of the same names (pyrolab/manager.py:407-408), so the class-level dicts are shadowed and stay empty in normal use -- but any access through the class (ProcessManager.daemons[...]) or from a subclass touches shared state instead.Note the inconsistency:
GLOBAL_CONFIG,managerand_timeron the following lines are bare annotations with no value, which is the correct form. The two dicts look the same but behave differently.Fix: drop the
= {}so all six are annotations:The same pattern-with-a-value appears nowhere else in the codebase, so this looks unintentional.
Found in a full-codebase audit at v0.4.0 (commit 1ce3146).