143143from importlib import import_module
144144import sys
145145from pathlib import Path
146+ from importlib import invalidate_caches
146147from contextlib import contextmanager
147148
148149# Store project root for use in path calculations
149150_project_root = Path (__file__ ).parent .parent .resolve ()
150151
151-
152152@contextmanager
153153def isolated_import_context (benchmark_name : str , api : str ):
154154 """
@@ -204,6 +204,35 @@ def isolated_import_context(benchmark_name: str, api: str):
204204 # This ensures we don't leave the import system in a broken state
205205 sys .path = original_sys_path
206206
207+ """
208+ Alternate version of above, that should avoid the need for invalidate on cudaq, but doesn't.
209+ DEVNOTE: to be investigated.
210+
211+ @contextmanager
212+ def isolated_import_context(benchmark_name: str, api: str):
213+ original_sys_path = sys.path.copy()
214+
215+ project_root = str(_project_root) # e.g. .../QC-App-Oriented-Benchmarks-develop
216+ benchmark_dir = str(_project_root / benchmark_name) # e.g. .../bernstein_vazirani
217+ api_dir = str(_project_root / benchmark_name / api)
218+
219+ try:
220+ # Start from current sys.path but drop only the pieces that cause shadowing
221+ cleaned = [p for p in sys.path if p not in {'', '.', api_dir}]
222+ # (Optional) also drop the benchmark dir if you want to be extra safe:
223+ # cleaned = [p for p in cleaned if p != benchmark_dir]
224+
225+ # Critically: ensure the repo root is present and first,
226+ # so 'import bernstein_vazirani' always resolves like `python -m`.
227+ if project_root in cleaned:
228+ cleaned.remove(project_root)
229+ cleaned.insert(0, project_root)
230+
231+ sys.path = cleaned
232+ yield
233+ finally:
234+ sys.path = original_sys_path
235+ """
207236
208237def qedc_benchmarks_init (api : str , benchmark_name : str , module_names : list [str ] = None ) -> None :
209238 """
@@ -246,10 +275,16 @@ def qedc_benchmarks_init(api: str, benchmark_name: str, module_names: list[str]
246275 if module_names is None :
247276 module_names = []
248277
278+ #from importlib.util import find_spec
279+ #assert find_spec("bernstein_vazirani") is not None, "anchor package not importable"
280+
249281 # Use context manager to temporarily modify sys.path during imports
250282 # This prevents local qiskit/ and _common/ folders from shadowing real packages
251283 with isolated_import_context (benchmark_name , api ):
252-
284+
285+ if api == "cudaq" :
286+ reset_module_caches (api , benchmark_name , module_names )
287+
253288 # Dynamically load each requested kernel module
254289 for module_name in module_names :
255290 # Check if already loaded to avoid redundant imports
@@ -279,4 +314,34 @@ def qedc_benchmarks_init(api: str, benchmark_name: str, module_names: list[str]
279314 sys .modules ["execute" ] = module
280315
281316 # Context manager automatically restores sys.path here
282- # Subsequent imports in the benchmark program work normally
317+ # Subsequent imports in the benchmark program work normally
318+
319+
320+ def reset_module_caches (api : str , benchmark_name : str , module_names : list [str ] = None ) -> None :
321+ """
322+ Reset the module caches to normalize execution.
323+
324+ This unfortunate block of code seems to be required only for cudaq.
325+ If benchmark launched as benchmark_name/<bn>_benchmark.py, if fails to find the module.
326+ If launched using -m <benahmark_name>.<bn>_benchmark it would succeed.
327+ This code normalizes the sys.path stack so both work the same.
328+ """
329+ #assert find_spec("bernstein_vazirani") is not None, "anchor package not importable"
330+
331+ # 1) Normalize sys.path so top-level package import works like `-m`
332+ repo_root = str (Path (__file__ ).resolve ().parents [1 ]) # repo root
333+ pkg_dir = str (Path (repo_root ) / benchmark_name ) # e.g. .../bernstein_vazirani
334+ sys .path = [repo_root ] + [p for p in sys .path if p not in (repo_root , pkg_dir )]
335+
336+ # 2) Remove poisoned/partial module entries (this fixes __spec__ is None)
337+ to_clear = {benchmark_name ,
338+ f"{ benchmark_name } .{ api } " } | {
339+ f"{ benchmark_name } .{ api } .{ m } " for m in module_names }
340+ for name in to_clear :
341+ sys .modules .pop (name , None )
342+
343+ # 3) Refresh import caches
344+ invalidate_caches ()
345+
346+ #assert find_spec("bernstein_vazirani") is not None, "anchor package not importable"
347+
0 commit comments