You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
run_support/config.py resolves a container engine at import time, so any module that imports it inherits a hard Docker dependency
src/clawbench/runner/run_support/config.py:90 runs engine detection as a side effect of import:
ENGINE=_detect_engine()
and _detect_engine (config.py:83-87) exits the process when neither engine is present:
forcmdin ("docker", "podman"):
ifshutil.which(cmd):
returncmdprint("ERROR: Neither 'podman' nor 'docker' found on PATH")
sys.exit(1)
Because this happens at module scope, import clawbench.runner.run_support.config — or anything that transitively imports it, including run_support.docker and run_support.metadata — terminates the interpreter on a host with no container runtime. Not an exception that a caller can catch and degrade on: a bare sys.exit.
Why this matters beyond tidiness
It has already forced workarounds in seven test files. Every one of these monkeypatches shutil.which for no reason other than getting past the probe:
runner/batch.py imports cleanly today with no engine present, and tests/test_batch_and_tui_helpers.py depends on that. Any constant or helper it wants from run_support.docker has to be duplicated or relocated instead of imported.
Both are avoidable. The engine is a runtime dependency of executing a container, not of importing the module that knows how.
Suggested fix
Make resolution lazy and cached:
@functools.lru_cache(maxsize=1)defengine() ->str:
... # current _detect_engine body
then replace the ENGINE constant at its use sites with engine(). The probe then happens on first actual use, where the caller has context to report a useful error, and importing the module stays free of side effects.
Scope looks small: 3 modules import ENGINE and there are 16 use sites, nearly all of the form [ENGINE, "wait", name] → [engine(), "wait", name]:
Module
Use sites
run_support/docker.py
13
runner/run.py
2
run_support/metadata.py
1
ENGINE could be kept as a deprecated module-level __getattr__ shim for one release if anything external reads it, though nothing in this repo does outside those three modules.
Follow-on cleanup this unlocks
The seven test files above drop their shutil.which monkeypatching.
run_support/config.py resolves a container engine at import time, so any module that imports it inherits a hard Docker dependency
src/clawbench/runner/run_support/config.py:90runs engine detection as a side effect of import:and
_detect_engine(config.py:83-87) exits the process when neither engine is present:Because this happens at module scope,
import clawbench.runner.run_support.config— or anything that transitively imports it, includingrun_support.dockerandrun_support.metadata— terminates the interpreter on a host with no container runtime. Not an exception that a caller can catch and degrade on: a baresys.exit.Why this matters beyond tidiness
It has already forced workarounds in seven test files. Every one of these monkeypatches
shutil.whichfor no reason other than getting past the probe:A typical instance, from
test_results_and_metadata.py:179:Tests that never touch a container still have to fake one into existence to import the module under test.
It shapes production code too. Two examples from the current tree:
eval/rescore.pyscores runs that have already finished and needs nothing from a container engine. It deliberately does not importrun_support.config, which is why it grew its ownyaml.safe_loadofmodels.yamlinstead of reusingload_model_config— the divergence reported in rescore: public reproducibility CLI defaults to a maintainer's home paths and silently no-ops elsewhere #296.runner/batch.pyimports cleanly today with no engine present, andtests/test_batch_and_tui_helpers.pydepends on that. Any constant or helper it wants fromrun_support.dockerhas to be duplicated or relocated instead of imported.Both are avoidable. The engine is a runtime dependency of executing a container, not of importing the module that knows how.
Suggested fix
Make resolution lazy and cached:
then replace the
ENGINEconstant at its use sites withengine(). The probe then happens on first actual use, where the caller has context to report a useful error, and importing the module stays free of side effects.Scope looks small: 3 modules import
ENGINEand there are 16 use sites, nearly all of the form[ENGINE, "wait", name]→[engine(), "wait", name]:run_support/docker.pyrunner/run.pyrun_support/metadata.pyENGINEcould be kept as a deprecated module-level__getattr__shim for one release if anything external reads it, though nothing in this repo does outside those three modules.Follow-on cleanup this unlocks
shutil.whichmonkeypatching.rescore.pycan reuseload_model_configdirectly rather than the workaround in rescore: public reproducibility CLI defaults to a maintainer's home paths and silently no-ops elsewhere #296.batch.pycan import shared helpers fromrun_support.dockerinstead of duplicating them.Ask
ENGINEconstant with a lazily-evaluated, cachedengine().shutil.whichmonkeypatching from the seven test files.Happy to send a PR for this if it's wanted — it is mechanical, but it touches enough call sites that it seemed worth agreeing on the shape first.