Skip to content

Commit

Permalink
Add support for negative limit to query_dimension_records
Browse files Browse the repository at this point in the history
  • Loading branch information
timj committed Sep 6, 2024
1 parent 3d5e448 commit 3d4044e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
25 changes: 21 additions & 4 deletions python/lsst/daf/butler/_butler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1743,8 +1743,13 @@ def query_dimension_records(
Names of the columns/dimensions to use for ordering returned data
IDs. Column name can be prefixed with minus (``-``) to use
descending ordering.
limit : `int`, optional
Upper limit on the number of returned records.
limit : `int` or `None`, optional
Upper limit on the number of returned records. `None` can be used
if no limit is wanted. A limit of ``0`` means that the query will
be executed and validated but no results will be returned. In this
case there will be no exception even if ``explain`` is `True`.
If a negative value is given a warning will be issued if the number
of results is capped by that limit.
explain : `bool`, optional
If `True` (default) then `EmptyQueryResultError` exception is
raised when resulting list is empty. The exception contains
Expand Down Expand Up @@ -1781,15 +1786,27 @@ def query_dimension_records(
data_id = DataCoordinate.make_empty(self.dimensions)
if order_by is None:
order_by = []
query_limit = limit
warn_limit = False
if limit is not None and limit < 0:
query_limit = abs(limit) + 1
warn_limit = True
with self.query() as query:
result = (
query.where(data_id, where, bind=bind, **kwargs)
.dimension_records(element)
.order_by(*ensure_iterable(order_by))
.limit(limit)
.limit(query_limit)
)
dimension_records = list(result)
if explain and not dimension_records:
if warn_limit and len(dimension_records) == query_limit:
# We asked for one too many so must remove that from the list.
dimension_records.pop(-1)
assert limit is not None # For mypy.
_LOG.warning(
"More dimension records are available than the requested limit of %d.", abs(limit)
)
if explain and (limit is None or limit != 0) and not dimension_records:
raise EmptyQueryResultError(list(result.explain_no_results()))
return dimension_records

Expand Down
8 changes: 8 additions & 0 deletions python/lsst/daf/butler/tests/butler_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def test_simple_record_query(self) -> None:
results = query.dimension_records("detector")
self.check_detector_records(results)
self.check_detector_records_returned(butler.query_dimension_records("detector"))
self.assertEqual(len(butler.query_dimension_records("detector", limit=0)), 0)
self.check_detector_records(results.order_by("detector"), ordered=True)
self.check_detector_records_returned(
butler.query_dimension_records("detector", order_by="detector"), ordered=True
Expand All @@ -200,6 +201,13 @@ def test_simple_record_query(self) -> None:
ids=[1, 2],
ordered=True,
)
with self.assertLogs("lsst.daf.butler", level="WARNING") as wcm:
self.check_detector_records_returned(
butler.query_dimension_records("detector", limit=-2, order_by="-detector"),
ids=[4, 3],
ordered=True,
)
self.assertIn("More dimension records are available", wcm.output[0])
self.check_detector_records(results.where(_x.detector.raft == "B", instrument="Cam1"), [3, 4])
self.check_detector_records_returned(
butler.query_dimension_records(
Expand Down

0 comments on commit 3d4044e

Please sign in to comment.