From b6e7977f6e0bb73a89fbeefe1723f3b9174af180 Mon Sep 17 00:00:00 2001 From: zilch Date: Sat, 12 Sep 2026 12:54:10 +0800 Subject: [PATCH 1/2] test: share numba kernel cache across manager tests instead of per-test recompile The autouse _isolated_numba_cache fixture cleared the in-process kernel caches and pointed NUMBA_CACHE_DIR at a fresh empty tmp directory for every test, so each of the 28 tests in test_numba_manager.py paid a full Numba recompilation (~26-31s total). Split it into two fixtures: - _shared_numba_cache_dir (autouse): sets a single hermetic on-disk cache directory per test run without clearing in-process caches, so each distinct plan compiles once; - _isolated_numba_cache (opt-in): the original cold-cache isolation, referenced explicitly only by tests that verify cache isolation behavior. 28 passed in ~11.5s (was ~26-31s); test count and coverage unchanged. Also add a pre-push check guideline (prek run --all-files) to AGENTS.md. Fixes #32 --- AGENTS.md | 10 +++++++++ motrix_env_core/tests/test_numba_manager.py | 23 +++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f01dc256..0900339e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -198,6 +198,16 @@ tensorboard --logdir runs/{env-name} python -m pytest ``` +### 提交前检查 + +push / 提交 PR 前,先在本地跑一次 pre-commit 钩子(ruff check、ruff format 等),确保 CI 不因 lint 失败空转: + +```bash +prek run --all-files +``` + +若 hook 自动修改了文件,将修改并入提交后再 push。 + ## 架构要点 - **Backend 无关 core**:`motrix_env_core` 不 import 任何 simulator;前端只通过 `motrix_env_core.sim.registry` 解析 backend。 diff --git a/motrix_env_core/tests/test_numba_manager.py b/motrix_env_core/tests/test_numba_manager.py index 9db0705c..655438f4 100644 --- a/motrix_env_core/tests/test_numba_manager.py +++ b/motrix_env_core/tests/test_numba_manager.py @@ -283,7 +283,18 @@ def _compile_manager(env: ManagerEnv): return NumbaKernelCompiler(env).build() +# Share a single on-disk cache directory across the whole test file (hermetic, +# never touches the user cache), but do not clear the in-process kernel caches: +# each distinct plan is compiled once instead of per-test full recompilation +# caused by cache-clearing autouse fixtures (issue #32). @pytest.fixture(autouse=True) +def _shared_numba_cache_dir(tmp_path_factory, monkeypatch): + monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path_factory.mktemp("numba-cache"))) + + +# Referenced explicitly only by tests that verify cache isolation behavior: +# additionally clear in-process caches and use a separate empty disk cache. +@pytest.fixture def _isolated_numba_cache(tmp_path, monkeypatch): monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path / "numba-cache")) compiler_module._KERNEL_CACHE.clear() @@ -432,7 +443,7 @@ def record_read() -> None: assert read_count == 1 -def test_reset_descriptor_is_part_of_numba_kernel_cache_key() -> None: +def test_reset_descriptor_is_part_of_numba_kernel_cache_key(_isolated_numba_cache) -> None: first = ManagerEnv( _ManagerEnvCfg(sim_reset=_DescriptorManagerResetCfg(term=_DescriptorResetTermCfg(tag="first"))), num_envs=1, @@ -738,7 +749,9 @@ def test_post_reset_observation_does_not_run_command_evaluation() -> None: np.testing.assert_allclose(state.obs.policy[:, 2], [0.5, 1.0, 1.5]) -def test_materialize_source_is_safe_for_concurrent_same_plan_writers(tmp_path, monkeypatch) -> None: +def test_materialize_source_is_safe_for_concurrent_same_plan_writers( + _isolated_numba_cache, tmp_path, monkeypatch +) -> None: monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path)) source = "generated = True\\n" @@ -753,7 +766,7 @@ def materialize(_: int) -> str: assert not list((tmp_path / "generated").glob("*.tmp")) -def test_build_rematerializes_source_after_cache_invalidation(monkeypatch, tmp_path) -> None: +def test_build_rematerializes_source_after_cache_invalidation(_isolated_numba_cache, monkeypatch, tmp_path) -> None: monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path)) compiler_module._KERNEL_CACHE.clear() env = _ManagerEnv(num_envs=1) @@ -774,7 +787,9 @@ def compile_kernels(source, filename): compiler_module._KERNEL_CACHE.pop(compiled.layout.plan_key, None) -def test_specialization_cache_failure_rebuilds_callable_dispatchers_before_retry(monkeypatch) -> None: +def test_specialization_cache_failure_rebuilds_callable_dispatchers_before_retry( + _isolated_numba_cache, monkeypatch +) -> None: env = _ManagerEnv(num_envs=1) invalidated = [] compile_attempts = [] From 872641647004123cefb30f96f99a2792788f8bc2 Mon Sep 17 00:00:00 2001 From: zilch Date: Sat, 12 Sep 2026 13:05:09 +0800 Subject: [PATCH 2/2] test: address review feedback on numba cache fixtures - Make _shared_numba_cache_dir module-scoped so the whole test module shares one on-disk cache directory instead of creating a fresh one per test; use a local MonkeyPatch since the monkeypatch fixture is function-scoped. - Make _isolated_numba_cache snapshot and restore the in-process caches so cache isolation is not order-dependent for later tests. --- motrix_env_core/tests/test_numba_manager.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/motrix_env_core/tests/test_numba_manager.py b/motrix_env_core/tests/test_numba_manager.py index 655438f4..a093da12 100644 --- a/motrix_env_core/tests/test_numba_manager.py +++ b/motrix_env_core/tests/test_numba_manager.py @@ -283,22 +283,33 @@ def _compile_manager(env: ManagerEnv): return NumbaKernelCompiler(env).build() -# Share a single on-disk cache directory across the whole test file (hermetic, +# Share a single on-disk cache directory across the whole test module (hermetic, # never touches the user cache), but do not clear the in-process kernel caches: # each distinct plan is compiled once instead of per-test full recompilation # caused by cache-clearing autouse fixtures (issue #32). -@pytest.fixture(autouse=True) -def _shared_numba_cache_dir(tmp_path_factory, monkeypatch): +@pytest.fixture(autouse=True, scope="module") +def _shared_numba_cache_dir(tmp_path_factory): + monkeypatch = pytest.MonkeyPatch() monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path_factory.mktemp("numba-cache"))) + yield + monkeypatch.undo() # Referenced explicitly only by tests that verify cache isolation behavior: -# additionally clear in-process caches and use a separate empty disk cache. +# clear in-process caches and use a separate empty disk cache, restoring the +# shared caches afterwards so later tests are not order-dependent. @pytest.fixture def _isolated_numba_cache(tmp_path, monkeypatch): monkeypatch.setenv("NUMBA_CACHE_DIR", str(tmp_path / "numba-cache")) + saved_kernel_cache = dict(compiler_module._KERNEL_CACHE) + saved_term_cache = dict(compiler_module._TERM_CACHE) compiler_module._KERNEL_CACHE.clear() compiler_module._TERM_CACHE.clear() + yield + compiler_module._KERNEL_CACHE.clear() + compiler_module._KERNEL_CACHE.update(saved_kernel_cache) + compiler_module._TERM_CACHE.clear() + compiler_module._TERM_CACHE.update(saved_term_cache) _GROUPS = _manager_groups()