Skip to content

Commit 1c36ffe

Browse files
authored
CLI option to force refresh results (#616)
* CLI option to force refresh results * address copilot comments
1 parent 849a6a4 commit 1c36ffe

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

metriq_gym/cli.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ def build_parser() -> argparse.ArgumentParser:
155155
default=argparse.SUPPRESS,
156156
help="Export results to JSON file (optional)",
157157
)
158+
suite_poll.add_argument(
159+
"--no-cache",
160+
action="store_true",
161+
help="Ignore locally cached results and refetch provider job data",
162+
)
158163

159164
suite_view = suite_subparsers.add_parser("view", help="View suite jobs")
160165
suite_view.add_argument(
@@ -210,6 +215,11 @@ def build_parser() -> argparse.ArgumentParser:
210215
default=argparse.SUPPRESS,
211216
help="Export results to JSON file (optional)",
212217
)
218+
job_poll.add_argument(
219+
"--no-cache",
220+
action="store_true",
221+
help="Ignore locally cached results and refetch provider job data",
222+
)
213223

214224
job_upload.add_argument(
215225
"--repo",

metriq_gym/run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,8 @@ def fetch_result(
565565
) -> Optional["BenchmarkResult"]:
566566
job_type: JobType = JobType(metriq_job.job_type)
567567
job_result_type = setup_benchmark_result_class(job_type)
568-
if metriq_job.result_data is not None:
568+
if metriq_job.result_data is not None and not getattr(args, "no_cache", False):
569+
print("[Cached result data]")
569570
return job_result_type.model_validate(metriq_job.result_data)
570571

571572
job_data: "BenchmarkData" = setup_job_data_class(job_type)(**metriq_job.data)

tests/unit/test_run.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
from dataclasses import dataclass
12
import logging
23
import pytest
34
from unittest.mock import MagicMock, patch
45

56
from qbraid import QbraidError
7+
from qbraid.runtime import JobStatus
8+
from metriq_gym.benchmarks.benchmark import BenchmarkData, BenchmarkResult
69
from metriq_gym.run import (
710
setup_device,
811
dispatch_job,
12+
fetch_result,
913
)
14+
from metriq_gym.job_manager import MetriqGymJob, JobManager
15+
from metriq_gym.constants import JobType
1016
from metriq_gym.exceptions import QBraidSetupError
1117

1218

@@ -113,3 +119,100 @@ def test_dispatch_missing_config_file(mock_exists, mock_args, mock_job_manager,
113119
# Verify output shows file not found errors
114120
captured = capsys.readouterr()
115121
assert "Configuration file not found" in captured.out
122+
123+
124+
class DummyResult(BenchmarkResult):
125+
value: int
126+
127+
128+
@dataclass
129+
class DummyJobData(BenchmarkData):
130+
provider_job_ids: list[str]
131+
132+
133+
class DummyQuantumJob:
134+
def __init__(self, job_id: str, value: int):
135+
self.id = job_id
136+
self._value = value
137+
138+
def status(self):
139+
return JobStatus.COMPLETED
140+
141+
def result(self):
142+
class _R:
143+
data = {"value": self._value}
144+
145+
return _R()
146+
147+
148+
class DummyBenchmark:
149+
def poll_handler(self, job_data, result_data, quantum_jobs):
150+
return DummyResult(value=result_data[0]["value"])
151+
152+
153+
def _make_cached_job(val: int) -> MetriqGymJob:
154+
return MetriqGymJob(
155+
id="job-1",
156+
job_type=JobType.WIT,
157+
params={"benchmark_name": JobType.WIT.name},
158+
data={"provider_job_ids": ["provider-job-1"]},
159+
provider_name="local",
160+
device_name="dummy_device",
161+
platform={},
162+
dispatch_time=None,
163+
result_data={"value": val},
164+
)
165+
166+
167+
def test_fetch_result_uses_cache_when_no_flag(monkeypatch):
168+
EXPECTED_CACHED_VALUE = 7
169+
job = _make_cached_job(EXPECTED_CACHED_VALUE)
170+
jm = JobManager()
171+
jm.jobs.append(job)
172+
args = MagicMock()
173+
args.no_cache = False
174+
175+
import metriq_gym.run as run_mod
176+
177+
monkeypatch.setattr(run_mod, "setup_benchmark_result_class", lambda *_: DummyResult)
178+
monkeypatch.setattr(run_mod, "setup_job_data_class", lambda *_: DummyJobData)
179+
monkeypatch.setattr(run_mod, "setup_benchmark", lambda *_, **__: DummyBenchmark())
180+
monkeypatch.setattr(
181+
run_mod,
182+
"load_job",
183+
lambda *_, **__: DummyQuantumJob("provider-job-1", EXPECTED_CACHED_VALUE),
184+
)
185+
monkeypatch.setattr(run_mod, "validate_and_create_model", lambda params: params)
186+
187+
result = fetch_result(job, args, jm)
188+
assert result.value == EXPECTED_CACHED_VALUE
189+
190+
191+
def test_fetch_result_bypasses_cache_with_flag(monkeypatch):
192+
EXPECTED_FRESH_VALUE = 42
193+
CACHED_VALUE = 7
194+
job = _make_cached_job(CACHED_VALUE)
195+
jm = JobManager()
196+
jm.jobs.append(job)
197+
args = MagicMock()
198+
args.no_cache = True
199+
200+
import metriq_gym.run as run_mod
201+
202+
monkeypatch.setattr(run_mod, "setup_benchmark_result_class", lambda *_: DummyResult)
203+
monkeypatch.setattr(run_mod, "setup_job_data_class", lambda *_: DummyJobData)
204+
monkeypatch.setattr(run_mod, "setup_benchmark", lambda *_, **__: DummyBenchmark())
205+
monkeypatch.setattr(
206+
run_mod,
207+
"load_job",
208+
lambda *_, **__: DummyQuantumJob("provider-job-1", EXPECTED_FRESH_VALUE),
209+
)
210+
monkeypatch.setattr(run_mod, "validate_and_create_model", lambda params: params)
211+
212+
result = fetch_result(job, args, jm)
213+
assert result.value == EXPECTED_FRESH_VALUE, (
214+
"Should fetch fresh value when --no-cache specified"
215+
)
216+
assert job.result_data == {"value": EXPECTED_FRESH_VALUE}, (
217+
"Cached result_data should be updated"
218+
)

0 commit comments

Comments
 (0)