simudyne-pulse 0.7.0.dev17__tar.gz → 0.7.0.dev18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simudyne_pulse-0.7.0.dev17/src/simudyne_pulse.egg-info → simudyne_pulse-0.7.0.dev18}/PKG-INFO +1 -1
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/pyproject.toml +1 -1
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/validation.py +52 -5
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18/src/simudyne_pulse.egg-info}/PKG-INFO +1 -1
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/tests/test_validation.py +22 -1
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/LICENSE +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/README.md +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/setup.cfg +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/__init__.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/client.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/exceptions.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/__init__.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/api_keys.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/data.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/fix.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/fm.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/profile.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/simulation.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/simulator_gym.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/SOURCES.txt +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/dependency_links.txt +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/requires.txt +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/top_level.txt +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/tests/test_new_resources.py +0 -0
- {simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/tests/test_simulator_gym.py +0 -0
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/validation.py
RENAMED
|
@@ -561,19 +561,57 @@ class ValidationResource:
|
|
|
561
561
|
job["plot_paths"] = _save_plots(job, plot_dir)
|
|
562
562
|
return job
|
|
563
563
|
|
|
564
|
-
def
|
|
564
|
+
def get_job_status(self, job_id: str) -> dict:
|
|
565
|
+
"""Where a validation job has got to, without its result.
|
|
566
|
+
|
|
567
|
+
The full result is large and tier-filtered, so a poll loop should ask
|
|
568
|
+
this instead of :meth:`get_job` and fetch the result once, when
|
|
569
|
+
``is_complete`` turns true.
|
|
570
|
+
|
|
571
|
+
Parameters
|
|
572
|
+
----------
|
|
573
|
+
job_id : str
|
|
574
|
+
A validation job handle from :meth:`run`.
|
|
575
|
+
|
|
576
|
+
Returns
|
|
577
|
+
-------
|
|
578
|
+
dict
|
|
579
|
+
``{job_id, status, message, is_complete, created_at, updated_at}``.
|
|
580
|
+
``status`` is one of pending / running / completed / failed, and
|
|
581
|
+
only the last two are terminal — which is what ``is_complete``
|
|
582
|
+
says, so a caller need not keep that list itself.
|
|
583
|
+
|
|
584
|
+
Raises
|
|
585
|
+
------
|
|
586
|
+
PulseAPIError
|
|
587
|
+
If the job does not exist or belongs to another key — status 404.
|
|
588
|
+
|
|
589
|
+
Examples
|
|
590
|
+
--------
|
|
591
|
+
>>> import time
|
|
592
|
+
>>> while not client.validation.get_job_status(job_id)["is_complete"]:
|
|
593
|
+
... time.sleep(30)
|
|
594
|
+
>>> result = client.validation.get_job(job_id, plot_dir="figures/")
|
|
595
|
+
"""
|
|
596
|
+
return self._client._request("GET", f"{JOBS_PATH}/{job_id}/status")
|
|
597
|
+
|
|
598
|
+
def list_jobs(self, limit: int = 50, offset: int = 0) -> dict:
|
|
565
599
|
"""List your validation jobs, newest first.
|
|
566
600
|
|
|
567
601
|
Parameters
|
|
568
602
|
----------
|
|
569
603
|
limit : int, default 50
|
|
570
|
-
Maximum number of jobs to return.
|
|
604
|
+
Maximum number of jobs to return. Capped at 200 by the API.
|
|
605
|
+
offset : int, default 0
|
|
606
|
+
Jobs to skip before this page, for paging through more than
|
|
607
|
+
``limit`` of them.
|
|
571
608
|
|
|
572
609
|
Returns
|
|
573
610
|
-------
|
|
574
611
|
dict
|
|
575
|
-
|
|
576
|
-
``total
|
|
612
|
+
``{total, limit, offset, jobs}``. ``jobs`` is the page, newest
|
|
613
|
+
first; ``total`` is your full job count rather than the page size,
|
|
614
|
+
so a caller can tell whether more pages exist.
|
|
577
615
|
|
|
578
616
|
Raises
|
|
579
617
|
------
|
|
@@ -591,5 +629,14 @@ class ValidationResource:
|
|
|
591
629
|
>>> done = [j for j in listing["jobs"] if j["status"] == "completed"]
|
|
592
630
|
>>> newest = done[0]
|
|
593
631
|
>>> result = client.validation.get_job(newest["job_id"])
|
|
632
|
+
|
|
633
|
+
Page through the rest:
|
|
634
|
+
|
|
635
|
+
>>> seen = len(listing["jobs"])
|
|
636
|
+
>>> while seen < listing["total"]:
|
|
637
|
+
... page = client.validation.list_jobs(limit=10, offset=seen)
|
|
638
|
+
... seen += len(page["jobs"])
|
|
594
639
|
"""
|
|
595
|
-
return self._client._request(
|
|
640
|
+
return self._client._request(
|
|
641
|
+
"GET", JOBS_PATH, params={"limit": limit, "offset": offset}
|
|
642
|
+
)
|
|
@@ -202,7 +202,7 @@ class TestOneEntryPoint:
|
|
|
202
202
|
res.get_job("v1")
|
|
203
203
|
res.list_jobs(limit=5)
|
|
204
204
|
assert client.calls[0][:2] == ("GET", "/validation/jobs/v1")
|
|
205
|
-
assert client.calls[1][2]["params"] == {"limit": 5}
|
|
205
|
+
assert client.calls[1][2]["params"] == {"limit": 5, "offset": 0}
|
|
206
206
|
|
|
207
207
|
|
|
208
208
|
class TestSimulatedFrameShapes:
|
|
@@ -406,3 +406,24 @@ class TestBothSourcesAtOnce:
|
|
|
406
406
|
sim_ids=["s"] * 13,
|
|
407
407
|
**IDENTITY,
|
|
408
408
|
)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class TestPagingAndStatus:
|
|
412
|
+
"""Matching pulse-api-pod 1.69.0: a paged list and a lightweight poll."""
|
|
413
|
+
|
|
414
|
+
def test_list_jobs_pages(self):
|
|
415
|
+
client = FakeClient([{"total": 60, "limit": 10, "offset": 10, "jobs": []}])
|
|
416
|
+
ValidationResource(client).list_jobs(limit=10, offset=10)
|
|
417
|
+
assert client.calls[0][2]["params"] == {"limit": 10, "offset": 10}
|
|
418
|
+
|
|
419
|
+
def test_list_jobs_starts_at_the_beginning(self):
|
|
420
|
+
client = FakeClient([{"total": 0, "limit": 50, "offset": 0, "jobs": []}])
|
|
421
|
+
ValidationResource(client).list_jobs()
|
|
422
|
+
assert client.calls[0][2]["params"] == {"limit": 50, "offset": 0}
|
|
423
|
+
|
|
424
|
+
def test_status_asks_the_cheap_endpoint(self):
|
|
425
|
+
"""Not get_job: the full result is large and tier-filtered."""
|
|
426
|
+
client = FakeClient([{"job_id": "v1", "status": "running", "is_complete": False}])
|
|
427
|
+
out = ValidationResource(client).get_job_status("v1")
|
|
428
|
+
assert client.calls[0][1] == "/validation/jobs/v1/status"
|
|
429
|
+
assert out["is_complete"] is False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/__init__.py
RENAMED
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/api_keys.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/simulation.py
RENAMED
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne/resources/simulator_gym.py
RENAMED
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/requires.txt
RENAMED
|
File without changes
|
{simudyne_pulse-0.7.0.dev17 → simudyne_pulse-0.7.0.dev18}/src/simudyne_pulse.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|