-
[OPIK-6091] [BE] fix: resolve opik.* submodule imports in Python sandbox (#6396)
发布于
2026-04-21 13:42:33 +00:00 - [OPIK-6091] fix: resolve opik.* submodule imports in sandbox
The lightweight import patching in #6319 registers stub modules with
__path__ = []and a_FallbackModule.__getattr__that loads the real
opik on attribute access. That fallback fires forfrom opik import X
but not forfrom opik.evaluation.metrics.conversation import X—
submodule resolution goes through the import machinery (parent
__path__+ finders), which never consults__getattr__. Any user
metric importing fromopik.evaluation.metrics.{conversation,heuristics,llm_judges,aggregated_metric}(or other non-stubbed paths) fails with ModuleNotFoundError.Adds an
_OpikFallbackFinderonsys.meta_paththat intercepts
unresolvedopik.*submodule imports, triggers the same
_load_real_opik()used by the attribute fallback, and defers to the
standard PathFinder with the now-real__path__. Lightweight path
(BaseMetric/ScoreResultonly) stays unchanged.- refactor: unify opik import fallback into a single stub class
Address review feedback: the separate
_OpikFallbackFinderwas tacked
on alongside_FallbackModuleinstead of being part of it. Merge them
into_LazyOpikStubso one class owns both protocols:__getattr__for attribute access (from opik import Client)find_specfor submodule resolution (from opik.x.y import z)
The same instance is registered in both
sys.modules(as the parent
module stub) andsys.meta_path(as the finder). All cleanup — stub
eviction fromsys.modulesandsys.meta_path— lives inside
_load_real_opik, which is now idempotent via an early exit on empty
_stubs.-
Keep _FallbackModule name
-
test: cover the sys.meta_path submodule fallback
Adds two unit tests to TestLightweightOpikPackage that pin down the new
find_spec behavior:-
test_submodule_import_of_non_stubbed_opik_child_triggers_real_load:
sets up stubs + finder, imports from
opik.evaluation.metrics.conversation, asserts the stubs get evicted and
the real submodule resolves to the installed opik package. -
test_lightweight_path_stays_lightweight_with_finder_installed: same
setup, then a BaseMetric/ScoreResult-only flow, asserts no heavy opik
modules get loaded and the stubs remain in place.
Mirrors the subprocess pattern used by the existing tests in the class
so state stays isolated across test runs.下载附件