From 06c0a4856e80456d51fec7be21a913d7207217ec Mon Sep 17 00:00:00 2001 From: goodboy Date: Tue, 9 Jun 2026 17:21:04 -0400 Subject: [PATCH] Fix `pytest` config-dir isolation in subactors The old (commented-out) `get_app_dir()` override gated on `'pytest' in sys.modules` which can NEVER work in spawned subactors (fresh procs, no pytest import); as a result test `paperboi`/daemon actors were writing into the user's REAL `~/.config/piker/accounting/` files.. friggin yikes. Deats, - add `config._maybe_use_test_dir()` which lazily (at conf-path access time, NOT import time) reads the `piker_test_dir` entry from `tractor.runtime._state._runtime_vars['piker_vars']` as pre-loaded by `open_piker_runtime()` from the `tests.conftest._open_test_pikerd()` overrides. - hook it in `get_conf_dir()` and route `get_conf_path()` + `load()`'s mkdir through `get_conf_dir()`. - route `.accounting._ledger` / `._pos` dir derivation through `config.get_conf_dir()` (was reading the `_config_dir` global directly, bypassing the override); also `mkdir(parents=True, exist_ok=True)` for nested tmp-dir creation. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code Co-Authored-By: Claude Fable 5 --- piker/accounting/_ledger.py | 7 ++++-- piker/accounting/_pos.py | 11 ++++++-- piker/config.py | 50 ++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/piker/accounting/_ledger.py b/piker/accounting/_ledger.py index d2e56bf0..62e16028 100644 --- a/piker/accounting/_ledger.py +++ b/piker/accounting/_ledger.py @@ -324,10 +324,13 @@ def load_ledger( ldir: Path = ( dirpath or - config._config_dir / 'accounting' / 'ledgers' + config.get_conf_dir() / 'accounting' / 'ledgers' ) if not ldir.is_dir(): - ldir.mkdir() + ldir.mkdir( + parents=True, + exist_ok=True, + ) fname = f'trades_{brokername}_{acctid}.toml' fpath: Path = ldir / fname diff --git a/piker/accounting/_pos.py b/piker/accounting/_pos.py index e4577b47..d47c0369 100644 --- a/piker/accounting/_pos.py +++ b/piker/accounting/_pos.py @@ -785,9 +785,16 @@ def load_account( legacy_fn: str = f'pps.{brokername}.{acctid}.toml' fn: str = f'account.{brokername}.{acctid}.toml' - dirpath: Path = dirpath or (config._config_dir / 'accounting') + dirpath: Path = ( + dirpath + or + (config.get_conf_dir() / 'accounting') + ) if not dirpath.is_dir(): - dirpath.mkdir() + dirpath.mkdir( + parents=True, + exist_ok=True, + ) conf, path = config.load( path=dirpath / fn, diff --git a/piker/config.py b/piker/config.py index 4e286bd8..316ff28f 100644 --- a/piker/config.py +++ b/piker/config.py @@ -188,6 +188,48 @@ def _override_config_dir( _config_dir = path +def _maybe_use_test_dir() -> None: + ''' + When running under the `pytest` harness, override + the config dir to the per-test-tmp dir "passed down" + the actor tree via `tractor`'s runtime-vars + inheritance mechanism. + + See the `tractor_runtime_overrides` usage in our + `tests.conftest._open_test_pikerd()` as well as + `.service._actor_runtime.open_piker_runtime()` for + the root-actor's pre-loading of the var state. + + NOTE: this must be checked lazily at config-path + access time (NOT import time) since sub-actors only + receive runtime-vars once their `tractor` runtime + has fully booted. + + ''' + global _config_dir + import tractor + actor = tractor.current_actor( + err_on_no_runtime=False, + ) + if actor is None: + return + + rvs: dict = tractor.runtime._state._runtime_vars + pvars: dict|None = rvs.get('piker_vars') + if ( + pvars + and + (testdir := pvars.get('piker_test_dir')) + ): + testdirpath = Path(testdir) + assert testdirpath.exists(), ( + f'piker test harness might be borked!?\n' + f'testdirpath: {testdirpath!r}\n' + ) + if _config_dir != testdirpath: + _override_config_dir(testdirpath) + + def _conf_fn_w_ext( name: str, ) -> str: @@ -201,6 +243,7 @@ def get_conf_dir() -> Path: on the local filesystem. ''' + _maybe_use_test_dir() return _config_dir @@ -226,7 +269,7 @@ def get_conf_path( assert str(conf_name) in _conf_names fn = _conf_fn_w_ext(conf_name) - return _config_dir / Path(fn) + return get_conf_dir() / Path(fn) def repodir() -> Path: @@ -271,8 +314,9 @@ def load( ''' # create the $HOME/.config/piker dir if dne - if not _config_dir.is_dir(): - _config_dir.mkdir( + conf_dir: Path = get_conf_dir() + if not conf_dir.is_dir(): + conf_dir.mkdir( parents=True, exist_ok=True, )