Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions foxglove/client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1297,9 +1297,15 @@ def get_dataset_episodes(
has_missing_recordings: Optional[bool] = None,
recording_id: Optional[str] = None,
include_recordings: bool = False,
metadata_query: Optional[str] = None,
):
"""Return a Page of the latest committed or initial editable membership.

``metadata_query`` filters top-level metadata; nested keys are not traversed.
Numeric, boolean and null values also match their JSON representations,
so ``attempts:3`` matches both the number 3 and the string "3".
See https://docs.foxglove.dev/api#tag/Episodes for the query syntax.

Supply ``start`` and ``end`` together to filter overlapping episode windows.
Use ``cursor`` to advance pages and ``limit`` to set the size of the page.
Use ``page.auto_paging_iter()`` to traverse all matching episodes.
Expand All @@ -1316,6 +1322,7 @@ def get_dataset_episodes(
has_missing_recordings=has_missing_recordings,
recording_id=recording_id,
include_recordings=include_recordings,
metadata_query=metadata_query,
)

def update_dataset_episodes(
Expand Down Expand Up @@ -1384,9 +1391,15 @@ def get_dataset_version_episodes(
has_missing_recordings: Optional[bool] = None,
recording_id: Optional[str] = None,
include_recordings: bool = False,
metadata_query: Optional[str] = None,
):
"""Return a Page of episode membership in a specific version.

``metadata_query`` filters top-level metadata; nested keys are not traversed.
Numeric, boolean and null values also match their JSON representations,
so ``attempts:3`` matches both the number 3 and the string "3".
See https://docs.foxglove.dev/api#tag/Episodes for the query syntax.

Supply ``start`` and ``end`` together to filter overlapping episode windows.
Use ``cursor`` to advance pages and ``limit`` to set the size of the page.
Use ``page.auto_paging_iter()`` to traverse all matching episodes.
Expand All @@ -1403,6 +1416,7 @@ def get_dataset_version_episodes(
has_missing_recordings=has_missing_recordings,
recording_id=recording_id,
include_recordings=include_recordings,
metadata_query=metadata_query,
)

def _get_dataset_episodes(
Expand All @@ -1419,6 +1433,7 @@ def _get_dataset_episodes(
has_missing_recordings: Optional[bool],
recording_id: Optional[str],
include_recordings: bool,
metadata_query: Optional[str],
):
_validate_episode_range(start, end)
path = f"/v1/datasets/{dataset_id}"
Expand All @@ -1443,6 +1458,7 @@ def _get_dataset_episodes(
else None
),
"recordingId": recording_id,
"metadataQuery": metadata_query,
"include": "recordings" if include_recordings else None,
}
),
Expand Down Expand Up @@ -1582,9 +1598,15 @@ def get_episodes(
limit: Optional[int] = None,
cursor: Optional[str] = None,
include_recordings: bool = False,
metadata_query: Optional[str] = None,
):
"""Return a Page of episodes, optionally with recording details.

``metadata_query`` filters top-level metadata; nested keys are not traversed.
Numeric, boolean and null values also match their JSON representations,
so ``attempts:3`` matches both the number 3 and the string "3".
See https://docs.foxglove.dev/api#tag/Episodes for the query syntax.

Supply ``start`` and ``end`` together to filter overlapping episode windows.
Use ``cursor`` to advance pages and ``limit`` to set the size of the page.
Use ``page.auto_paging_iter()`` to traverse all matching episodes.
Expand All @@ -1605,6 +1627,7 @@ def get_episodes(
else None
),
"recordingId": recording_id,
"metadataQuery": metadata_query,
"sortBy": camelize(sort_by),
"sortOrder": sort_order,
"limit": limit,
Expand Down
6 changes: 5 additions & 1 deletion tests/test_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"include_recordings": True,
"has_missing_recordings": False,
"recording_id": "rec_1",
"metadata_query": 'task:"fold towel" attempts:3',
"start": NOW,
"end": NOW + timedelta(minutes=1),
},
Expand All @@ -51,6 +52,7 @@
"end": NOW + timedelta(minutes=1),
"has_missing_recordings": False,
"recording_id": "rec_1",
"metadata_query": 'task:"fold towel" attempts:3',
"sort_by": "start_time",
},
),
Expand All @@ -60,7 +62,7 @@
"/v1/datasets/ds_1/versions/1/episodes",
"episodes",
_dataset_episode_json,
{"sort_by": "added_at"},
{"sort_by": "added_at", "metadata_query": "task:fold"},
),
(
"get_dataset_versions",
Expand Down Expand Up @@ -103,6 +105,8 @@ def test_pages_are_lazy_and_preserve_query(
assert len(responses.calls) == 2
first_params = responses.calls[0].request.params
assert responses.calls[1].request.params == {**first_params, "cursor": "forward"}
if "metadata_query" in filters:
assert first_params["metadataQuery"] == filters["metadata_query"]
if method == "get_datasets":
assert first_params["name"] == "runs"
assert first_params["sortBy"] == "episodeCount"
Expand Down
Loading