Skip to content

Commit 8d2d7e6

Browse files
authored
Merge pull request #62 from lsst-sqre/tickets/DM-48465
Add get_query_history
2 parents f9f9c57 + 93dc177 commit 8d2d7e6

File tree

7 files changed

+73
-25
lines changed

7 files changed

+73
-25
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!-- Delete the sections that don't apply -->
2+
3+
### New features
4+
5+
- added `get_query_history()` function
6+

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dependencies = [
2929
"httpx<0.28",
3030
"structlog", # Uses CalVer, not SemVer
3131
"symbolicmode<3",
32+
"xmltodict"
3233
]
3334
dynamic = ["version"]
3435

src/lsst/rsp/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .catalog import (
66
get_catalog,
77
get_obstap_service,
8+
get_query_history,
89
get_tap_service,
910
retrieve_query,
1011
)
@@ -41,6 +42,7 @@
4142
"get_datalink_result",
4243
"get_digest",
4344
"get_node",
45+
"get_query_history",
4446
"get_pod",
4547
"get_tap_service",
4648
"get_siav2_service",

src/lsst/rsp/catalog.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import warnings
44

55
import pyvo
6+
import xmltodict
67
from deprecated import deprecated
78

9+
from .client import RSPClient
810
from .utils import get_pyvo_auth, get_service_url
911

1012

@@ -66,3 +68,17 @@ def retrieve_query(query_url: str) -> pyvo.dal.AsyncTAPJob:
6668
with warnings.catch_warnings():
6769
warnings.simplefilter("ignore", category=UserWarning)
6870
return pyvo.dal.AsyncTAPJob(query_url, session=get_pyvo_auth())
71+
72+
73+
async def get_query_history(n: int | None = None) -> list[str]:
74+
"""Retrieve last n query jobref ids. If n is not specified, or n<1,
75+
retrieve all query jobref ids.
76+
"""
77+
client = RSPClient("/api/tap")
78+
params = {}
79+
if n and n > 0:
80+
params = {"last": f"{n}"}
81+
full_history_xml = await client.get("async", params=params)
82+
history_dict = xmltodict.parse(full_history_xml.text)
83+
joblist = history_dict["uws:jobs"]["uws:jobref"]
84+
return [job["@id"] for job in joblist if "@id" in job]

src/lsst/rsp/py.typed

Whitespace-only changes.

tests/catalog_test.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Test the RSPClient."""
2+
3+
import pytest
4+
from pytest_httpx import HTTPXMock
5+
6+
from lsst.rsp import get_query_history
7+
8+
9+
@pytest.mark.usefixtures("_rsp_env")
10+
@pytest.mark.asyncio
11+
async def test_get_query_history(httpx_mock: HTTPXMock) -> None:
12+
"""Ensure that get_query_history() works, which in turn will ensure
13+
that the RSPClient has the right headers and assembles its URL correctly.
14+
"""
15+
httpx_mock.add_response(
16+
url="https://rsp.example.com/api/tap/async",
17+
match_headers={
18+
"Authorization": "Bearer gf-dummytoken",
19+
"Content-Type": "application/json",
20+
},
21+
text=(
22+
"""<?xml version="1.0" encoding="UTF-8"?>
23+
<uws:jobs xmlns:uws="http://www.ivoa.net/xml/UWS/v1.0"
24+
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
25+
<uws:jobref id="phdl67i3tmklfdbz">
26+
<uws:phase>COMPLETED</uws:phase>
27+
<uws:runId>dp02_dc2_catalogs.Object - data-dev</uws:runId>
28+
<uws:ownerId>adam</uws:ownerId>
29+
<uws:creationTime>2025-01-15T23:36:17.931Z</uws:creationTime>
30+
</uws:jobref>
31+
<uws:jobref id="r4qyb04xesh7mbz3">
32+
<uws:phase>COMPLETED</uws:phase>
33+
<uws:ownerId>adam</uws:ownerId>
34+
<uws:creationTime>2024-12-05T17:49:27.518Z</uws:creationTime>
35+
</uws:jobref>
36+
<uws:jobref id="yk16agxjefl6gly6">
37+
<uws:phase>COMPLETED</uws:phase>
38+
<uws:runId>ivoa.ObsCore - data-dev</uws:runId>
39+
<uws:ownerId>adam</uws:ownerId>
40+
<uws:creationTime>2025-01-15T23:37:03.089Z</uws:creationTime>
41+
</uws:jobref>
42+
</uws:jobs>"""
43+
),
44+
)
45+
jobs = await get_query_history()
46+
assert jobs == ["phdl67i3tmklfdbz", "r4qyb04xesh7mbz3", "yk16agxjefl6gly6"]
47+
# The httpx mock will throw an error at teardown if we did not exercise
48+
# the mock, so we know the request matched both the URL and the headers.

tests/client_test.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)