1111import importlib .util
1212import re
1313import sys
14- from collections .abc import Callable , Iterable
14+ from collections .abc import Callable , Iterable , Iterator , Mapping
15+ from contextlib import contextmanager
16+ from contextvars import ContextVar
1517from dataclasses import dataclass
1618from functools import lru_cache
1719from importlib import metadata
@@ -52,6 +54,38 @@ class _ResolvedModule:
5254 is_package : bool
5355
5456
57+ @dataclass (slots = True )
58+ class _ManifestMeasurementBatch :
59+ source_modules : dict [
60+ tuple [tuple [str , ...], frozenset [str ]], tuple [CheckerSourceModule , ...]
61+ ]
62+ distributions : dict [str , CheckerPythonDistribution ]
63+ package_owners : Mapping [str , list [str ]] | None = None
64+ python_runtime : CheckerPythonRuntime | None = None
65+
66+
67+ _ACTIVE_MEASUREMENT_BATCH : ContextVar [_ManifestMeasurementBatch | None ] = ContextVar (
68+ "jacobian_checker_manifest_measurement_batch" , default = None
69+ )
70+
71+
72+ @contextmanager
73+ def batch_checker_manifest_measurement () -> Iterator [None ]:
74+ """Share immutable identity measurements across one installation operation."""
75+
76+ active = _ACTIVE_MEASUREMENT_BATCH .get ()
77+ if active is not None :
78+ yield
79+ return
80+ token = _ACTIVE_MEASUREMENT_BATCH .set (
81+ _ManifestMeasurementBatch (source_modules = {}, distributions = {})
82+ )
83+ try :
84+ yield
85+ finally :
86+ _ACTIVE_MEASUREMENT_BATCH .reset (token )
87+
88+
5589class _DeclaredSourceLoader (importlib .abc .Loader ):
5690 """Load one manifest-bound module from remeasured source only."""
5791
@@ -154,19 +188,19 @@ def build_checker_manifest(
154188 first_party_packages = frozenset (
155189 {_JACOBIAN_PACKAGE , entrypoint_module .split ("." , 1 )[0 ]}
156190 )
157- checker_source_modules = _collect_source_modules (
191+ checker_source_modules = _batched_source_modules (
158192 (entrypoint_module ,),
159193 first_party_packages = first_party_packages ,
160194 )
161- worker_source_modules = _collect_source_modules (
195+ worker_source_modules = _batched_source_modules (
162196 (_CHECKER_WORKER_MODULE , * extra_modules ),
163197 first_party_packages = first_party_packages ,
164198 )
165199 return CheckerManifest (
166200 entrypoint = entrypoint ,
167201 checker_source_modules = checker_source_modules ,
168202 worker_source_modules = worker_source_modules ,
169- python_runtime = _python_runtime (),
203+ python_runtime = _batched_python_runtime (),
170204 python_distributions = _collect_python_distributions (
171205 (* checker_source_modules , * worker_source_modules ),
172206 first_party_packages = first_party_packages ,
@@ -206,6 +240,31 @@ def require_manifest_unchanged(manifest: CheckerManifest) -> str:
206240 return checker_implementation_digest (measured )
207241
208242
243+ def require_manifest_material_unchanged (manifest : CheckerManifest ) -> str :
244+ """Reject changes to every execution artifact already bound by a manifest.
245+
246+ The worker performs full dependency discovery before loading the checker. Its
247+ post-execution check only needs to remeasure that closed set: the import guard
248+ prevents undeclared code from entering the process, while direct remeasurement
249+ avoids rebuilding and reparsing the complete import graph a second time.
250+ """
251+
252+ for expected in _manifest_source_modules (manifest ):
253+ resolved = _resolve_module (expected .module )
254+ measured = _source_digest (resolved .path .read_bytes ())
255+ if measured != expected .source_digest :
256+ raise CheckerManifestError (f"checker source changed: { expected .module } " )
257+ if _python_runtime () != manifest .python_runtime :
258+ raise CheckerManifestError ("checker Python runtime changed" )
259+ measured_distributions = tuple (
260+ _measure_python_distribution (item .distribution )
261+ for item in manifest .python_distributions
262+ )
263+ if measured_distributions != manifest .python_distributions :
264+ raise CheckerManifestError ("checker Python distribution changed" )
265+ return checker_implementation_digest (manifest )
266+
267+
209268def install_manifest_import_guard (manifest : CheckerManifest ) -> None :
210269 """Reload the checker through the manifest and reject undeclared code imports."""
211270
@@ -273,6 +332,24 @@ def _collect_source_modules(
273332 )
274333
275334
335+ def _batched_source_modules (
336+ roots : tuple [str , ...],
337+ * ,
338+ first_party_packages : frozenset [str ],
339+ ) -> tuple [CheckerSourceModule , ...]:
340+ batch = _ACTIVE_MEASUREMENT_BATCH .get ()
341+ if batch is None :
342+ return _collect_source_modules (roots , first_party_packages = first_party_packages )
343+ key = (roots , first_party_packages )
344+ measured = batch .source_modules .get (key )
345+ if measured is None :
346+ measured = _collect_source_modules (
347+ roots , first_party_packages = first_party_packages
348+ )
349+ batch .source_modules [key ] = measured
350+ return measured
351+
352+
276353def _manifest_source_modules (
277354 manifest : CheckerManifest ,
278355) -> tuple [CheckerSourceModule , ...]:
@@ -302,7 +379,13 @@ def _collect_python_distributions(
302379 for bound_source in source_modules :
303380 source = _resolve_module (bound_source .module )
304381 import_roots .update (_third_party_import_roots (source , first_party_packages ))
305- package_owners = metadata .packages_distributions ()
382+ batch = _ACTIVE_MEASUREMENT_BATCH .get ()
383+ if batch is not None and batch .package_owners is not None :
384+ package_owners = batch .package_owners
385+ else :
386+ package_owners = metadata .packages_distributions ()
387+ if batch is not None :
388+ batch .package_owners = package_owners
306389 distributions = set (_WORKER_DISTRIBUTIONS )
307390 for root in import_roots :
308391 owners = package_owners .get (root )
@@ -317,7 +400,7 @@ def _collect_python_distributions(
317400 distributions .add (owners [0 ])
318401 measured : dict [str , CheckerPythonDistribution ] = {}
319402 for distribution in sorted (distributions , key = _distribution_key ):
320- identity = _measure_python_distribution (distribution )
403+ identity = _batched_python_distribution (distribution )
321404 key = _distribution_key (identity .distribution )
322405 existing = measured .setdefault (key , identity )
323406 if existing != identity :
@@ -475,6 +558,29 @@ def _measure_python_distribution(distribution: str) -> CheckerPythonDistribution
475558 )
476559
477560
561+ def _batched_python_distribution (
562+ distribution : str ,
563+ ) -> CheckerPythonDistribution :
564+ batch = _ACTIVE_MEASUREMENT_BATCH .get ()
565+ if batch is None :
566+ return _measure_python_distribution (distribution )
567+ key = _distribution_key (distribution )
568+ measured = batch .distributions .get (key )
569+ if measured is None :
570+ measured = _measure_python_distribution (distribution )
571+ batch .distributions [key ] = measured
572+ return measured
573+
574+
575+ def _batched_python_runtime () -> CheckerPythonRuntime :
576+ batch = _ACTIVE_MEASUREMENT_BATCH .get ()
577+ if batch is None :
578+ return _python_runtime ()
579+ if batch .python_runtime is None :
580+ batch .python_runtime = _python_runtime ()
581+ return batch .python_runtime
582+
583+
478584def _distribution_file_closure (
479585 installed : metadata .Distribution ,
480586) -> tuple [int , str ]:
@@ -693,9 +799,11 @@ def _source_digest(source: bytes) -> str:
693799__all__ = [
694800 "CheckerManifestError" ,
695801 "UndeclaredCheckerImportError" ,
802+ "batch_checker_manifest_measurement" ,
696803 "build_checker_manifest" ,
697804 "checker_implementation_digest" ,
698805 "default_checker_sandbox_policy" ,
699806 "install_manifest_import_guard" ,
807+ "require_manifest_material_unchanged" ,
700808 "require_manifest_unchanged" ,
701809]
0 commit comments