This is an automated email from the ASF dual-hosted git repository.
henry3260 pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new 62423e3e987 [v3-3-test] Add partition date filters to Dag run API
(#68682) (#70304)
62423e3e987 is described below
commit 62423e3e9870636bdec132f8b0ede515e9a8c2d7
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jul 24 01:18:00 2026 +0800
[v3-3-test] Add partition date filters to Dag run API (#68682) (#70304)
* Add partition date support to Dag run API
* Reject partition date filters on non-partitioned Dags in Dag run API
Runs of a non-partitioned Dag never carry a partition_date, so filtering
by partition_date_start/partition_date_end silently returned an empty
list, which reads as "no runs in that window" rather than "this Dag has
no partition dimension". Return 400 instead, mirroring how supplying a
partition_key for a non-partitioned Dag is rejected.
* Rename Dag run partition date filters to partition_date_gte/lte
The other range filters on the list Dag runs endpoint use the _gte/_lte
suffix convention (start_date_gte, logical_date_lte, ...), so the new
partition date bounds should follow it too. Also clarify in the query
parameter descriptions that the inclusive bounds cover the whole
calendar day, and fold the partition-date branches into a single
condition so the 400 paths and the filter path read in one place.
(cherry picked from commit 8e6f28fbd33b2e8ba55f2f8b0d775847b3244516)
Co-authored-by: Henry Chen <[email protected]>
---
.../core_api/openapi/v2-rest-api-generated.yaml | 38 ++++++++++--
.../api_fastapi/core_api/routes/public/dag_run.py | 58 ++++++++++++++++-
airflow-core/src/airflow/models/dagrun.py | 14 ++++-
.../src/airflow/ui/openapi-gen/queries/common.ts | 6 +-
.../ui/openapi-gen/queries/ensureQueryData.ts | 10 ++-
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 10 ++-
.../src/airflow/ui/openapi-gen/queries/queries.ts | 10 ++-
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 10 ++-
.../ui/openapi-gen/requests/services.gen.ts | 6 +-
.../airflow/ui/openapi-gen/requests/types.gen.ts | 10 ++-
.../core_api/routes/public/test_dag_run.py | 72 +++++++++++++++++++++-
11 files changed, 217 insertions(+), 27 deletions(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
index 75caaf4f033..1f73622f36a 100644
---
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
+++
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
@@ -2325,6 +2325,36 @@ paths:
schema:
type: string
title: Dag Id
+ - name: partition_date_gte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date
+ - type: 'null'
+ description: Inclusive lower bound of the partition_date window,
interpreted
+ as a local calendar day in the Dag's timetable timezone. Runs from
the
+ start of this day onwards match.
+ title: Partition Date Gte
+ description: Inclusive lower bound of the partition_date window,
interpreted
+ as a local calendar day in the Dag's timetable timezone. Runs from
the start
+ of this day onwards match.
+ - name: partition_date_lte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date
+ - type: 'null'
+ description: 'Inclusive upper bound of the partition_date window,
interpreted
+ as a local calendar day in the Dag''s timetable timezone. The
whole day
+ is included: runs up to the end of this day match.'
+ title: Partition Date Lte
+ description: 'Inclusive upper bound of the partition_date window,
interpreted
+ as a local calendar day in the Dag''s timetable timezone. The whole
day
+ is included: runs up to the end of this day match.'
- name: cursor
in: query
required: false
@@ -2614,15 +2644,15 @@ paths:
type: string
description: 'Attributes to order by, multi criteria sort is
supported.
Prefix with `-` for descending order. Supported attributes: `id,
state,
- dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at,
- conf, duration, dag_run_id`'
+ dag_id, run_id, logical_date, partition_date, run_after,
start_date, end_date,
+ updated_at, conf, duration, dag_run_id`'
default:
- id
title: Order By
description: 'Attributes to order by, multi criteria sort is
supported. Prefix
with `-` for descending order. Supported attributes: `id, state,
dag_id,
- run_id, logical_date, run_after, start_date, end_date, updated_at,
conf,
- duration, dag_run_id`'
+ run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at,
+ conf, duration, dag_run_id`'
- name: run_id_pattern
in: query
required: false
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
index 955c7aa34ce..84e2f77f8fa 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py
@@ -17,6 +17,7 @@
from __future__ import annotations
+import datetime
import textwrap
from typing import Annotated, Literal, cast
@@ -509,6 +510,7 @@ def get_dag_runs(
"dag_id",
"run_id",
"logical_date",
+ "partition_date",
"run_after",
"start_date",
"end_date",
@@ -547,6 +549,21 @@ def get_dag_runs(
partition_key_pattern: QueryDagRunPartitionKeySearch,
partition_key_prefix_pattern: QueryDagRunPartitionKeyPrefixSearch,
consuming_asset_pattern: QueryConsumingAssetPatternSearch,
+ partition_date_gte: datetime.date | None = Query(
+ None,
+ description=(
+ "Inclusive lower bound of the partition_date window, interpreted
as a local calendar "
+ "day in the Dag's timetable timezone. Runs from the start of this
day onwards match."
+ ),
+ ),
+ partition_date_lte: datetime.date | None = Query(
+ None,
+ description=(
+ "Inclusive upper bound of the partition_date window, interpreted
as a local calendar "
+ "day in the Dag's timetable timezone. The whole day is included:
runs up to the end "
+ "of this day match."
+ ),
+ ),
cursor: str | None = Query(
None,
description="Cursor for keyset-based pagination. "
@@ -571,9 +588,46 @@ def get_dag_runs(
use_cursor = cursor is not None
query = select(DagRun).options(*eager_load_dag_run_for_list())
- if dag_id != "~":
- get_latest_version_of_dag(dag_bag, dag_id, session) # Check if the
Dag exists.
+ has_partition_date_filter = partition_date_gte is not None or
partition_date_lte is not None
+
+ if dag_id == "~":
+ if has_partition_date_filter:
+ raise HTTPException(
+ status.HTTP_400_BAD_REQUEST,
+ "partition_date_gte and partition_date_lte require a specific
dag_id.",
+ )
+ else:
+ dag = get_latest_version_of_dag(dag_bag, dag_id, session) # Check if
the Dag exists.
query = query.filter(DagRun.dag_id == dag_id).options()
+ if has_partition_date_filter:
+ # Runs of a non-partitioned Dag never carry a partition_date (this
includes
+ # partitioned-at-runtime Dags, whose runs keep it NULL), so the
filter would
+ # silently match nothing; reject it instead.
+ if not dag.timetable.partitioned:
+ raise HTTPException(
+ status.HTTP_400_BAD_REQUEST,
+ f"Dag with dag_id: '{dag_id}' is not partitioned; "
+ "partition_date_gte and partition_date_lte are not
supported.",
+ )
+ # The bounds are calendar days, so the whole of partition_date_lte
belongs to the
+ # window: widen it to the following local midnight and exclude
that edge.
+ query = DagRun.apply_partition_date_window(
+ query,
+ timetable=dag.timetable,
+ start=(
+ datetime.datetime.combine(partition_date_gte,
datetime.time.min)
+ if partition_date_gte is not None
+ else None
+ ),
+ end=(
+ datetime.datetime.combine(
+ partition_date_lte + datetime.timedelta(days=1),
datetime.time.min
+ )
+ if partition_date_lte is not None
+ else None
+ ),
+ end_exclusive=True,
+ )
# Add join with DagVersion if dag_version filter is active
if dag_version.value:
diff --git a/airflow-core/src/airflow/models/dagrun.py
b/airflow-core/src/airflow/models/dagrun.py
index f5ae6a28d58..1ca2199252b 100644
--- a/airflow-core/src/airflow/models/dagrun.py
+++ b/airflow-core/src/airflow/models/dagrun.py
@@ -2225,14 +2225,24 @@ class DagRun(Base, LoggingMixin):
timetable: Timetable,
start: datetime | None,
end: datetime | None,
+ end_exclusive: bool = False,
) -> Select:
- """Filter stmt to the inclusive interval [lower, upper] on
partition_date."""
+ """
+ Filter stmt to a partition_date window bounded by *start* and *end*.
+
+ The lower bound is always inclusive. The upper bound is inclusive by
default;
+ pass ``end_exclusive=True`` when *end* is the open edge of the window,
as with
+ a date-only filter widened to the following local midnight.
+ """
if start is not None:
lower = timetable.localize_partition_datetime(start)
stmt = stmt.where(DagRun.partition_date >= lower)
if end is not None:
upper = timetable.localize_partition_datetime(end)
- stmt = stmt.where(DagRun.partition_date <= upper)
+ if end_exclusive:
+ stmt = stmt.where(DagRun.partition_date < upper)
+ else:
+ stmt = stmt.where(DagRun.partition_date <= upper)
return stmt
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
index 3d923f44e9a..d7baf71cf53 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -156,7 +156,7 @@ export const UseDagRunServiceGetDagRunKeyFn = ({ dagId,
dagRunId }: {
export type DagRunServiceGetDagRunsDefaultResponse = Awaited<ReturnType<typeof
DagRunService.getDagRuns>>;
export type DagRunServiceGetDagRunsQueryResult<TData =
DagRunServiceGetDagRunsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useDagRunServiceGetDagRunsKey = "DagRunServiceGetDagRuns";
-export const UseDagRunServiceGetDagRunsKeyFn = ({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdPattern, runIdPrefixPattern, runType, startD [...]
+export const UseDagRunServiceGetDagRunsKeyFn = ({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte,
partitionDateLte, partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runIdPattern, [...]
bundleVersion?: string;
confContains?: string;
consumingAssetPattern?: string;
@@ -180,6 +180,8 @@ export const UseDagRunServiceGetDagRunsKeyFn = ({
bundleVersion, confContains, c
logicalDateLte?: string;
offset?: number;
orderBy?: string[];
+ partitionDateGte?: string;
+ partitionDateLte?: string;
partitionKeyPattern?: string;
partitionKeyPrefixPattern?: string;
runAfterGt?: string;
@@ -200,7 +202,7 @@ export const UseDagRunServiceGetDagRunsKeyFn = ({
bundleVersion, confContains, c
updatedAtGte?: string;
updatedAtLt?: string;
updatedAtLte?: string;
-}, queryKey?: Array<unknown>) => [useDagRunServiceGetDagRunsKey, ...(queryKey
?? [{ bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, r [...]
+}, queryKey?: Array<unknown>) => [useDagRunServiceGetDagRunsKey, ...(queryKey
?? [{ bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionDateGte, partitionDateLte, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runA [...]
export type DagRunServiceGetUpstreamAssetEventsDefaultResponse =
Awaited<ReturnType<typeof DagRunService.getUpstreamAssetEvents>>;
export type DagRunServiceGetUpstreamAssetEventsQueryResult<TData =
DagRunServiceGetUpstreamAssetEventsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useDagRunServiceGetUpstreamAssetEventsKey =
"DagRunServiceGetUpstreamAssetEvents";
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
index c4a9f18e8d8..edcc8e6d4dd 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -307,6 +307,8 @@ export const ensureUseDagRunServiceGetDagRunData =
(queryClient: QueryClient, {
* on the first page.
* @param data The data for the request.
* @param data.dagId
+* @param data.partitionDateGte Inclusive lower bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
Runs from the start of this day onwards match.
+* @param data.partitionDateLte Inclusive upper bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
The whole day is included: runs up to the end of this day match.
* @param data.cursor Cursor for keyset-based pagination. Pass an empty string
for the first page, then use ``next_cursor`` from the response. When ``cursor``
is provided, ``offset`` is ignored.
* @param data.limit
* @param data.offset
@@ -339,7 +341,7 @@ export const ensureUseDagRunServiceGetDagRunData =
(queryClient: QueryClient, {
* @param data.state
* @param data.dagVersion
* @param data.bundleVersion
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at, conf, duration, dag_run_id`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at, conf, duration, dag_run_id`
* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g.
`%customer_%`). Use the pipe `|` operator for OR logic (e.g. `dag1 | dag2`).
Regular expressions are **not** supported.
*
* **Performance note:** this full-match pattern is evaluated as ``ILIKE
'%term%'`` and most of the time prevents the database from using B-tree
indexes, which can be very slow on large tables. Prefer the equivalent
``run_id_prefix_pattern`` parameter when possible.
@@ -360,7 +362,7 @@ export const ensureUseDagRunServiceGetDagRunData =
(queryClient: QueryClient, {
* @returns DAGRunCollectionResponse Successful Response
* @throws ApiError
*/
-export const ensureUseDagRunServiceGetDagRunsData = (queryClient: QueryClient,
{ bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runI [...]
+export const ensureUseDagRunServiceGetDagRunsData = (queryClient: QueryClient,
{ bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionDateGte, partitionDateLte, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runAfte [...]
bundleVersion?: string;
confContains?: string;
consumingAssetPattern?: string;
@@ -384,6 +386,8 @@ export const ensureUseDagRunServiceGetDagRunsData =
(queryClient: QueryClient, {
logicalDateLte?: string;
offset?: number;
orderBy?: string[];
+ partitionDateGte?: string;
+ partitionDateLte?: string;
partitionKeyPattern?: string;
partitionKeyPrefixPattern?: string;
runAfterGt?: string;
@@ -404,7 +408,7 @@ export const ensureUseDagRunServiceGetDagRunsData =
(queryClient: QueryClient, {
updatedAtGte?: string;
updatedAtLt?: string;
updatedAtLte?: string;
-}) => queryClient.ensureQueryData({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdPattern [...]
+}) => queryClient.ensureQueryData({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte,
partitionDateLte, partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt,
runAfterGte, r [...]
/**
* Get Upstream Asset Events
* If dag run is asset-triggered, return the asset events that triggered it.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
index ce348567d74..df3d75071d4 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -307,6 +307,8 @@ export const prefetchUseDagRunServiceGetDagRun =
(queryClient: QueryClient, { da
* on the first page.
* @param data The data for the request.
* @param data.dagId
+* @param data.partitionDateGte Inclusive lower bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
Runs from the start of this day onwards match.
+* @param data.partitionDateLte Inclusive upper bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
The whole day is included: runs up to the end of this day match.
* @param data.cursor Cursor for keyset-based pagination. Pass an empty string
for the first page, then use ``next_cursor`` from the response. When ``cursor``
is provided, ``offset`` is ignored.
* @param data.limit
* @param data.offset
@@ -339,7 +341,7 @@ export const prefetchUseDagRunServiceGetDagRun =
(queryClient: QueryClient, { da
* @param data.state
* @param data.dagVersion
* @param data.bundleVersion
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at, conf, duration, dag_run_id`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at, conf, duration, dag_run_id`
* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g.
`%customer_%`). Use the pipe `|` operator for OR logic (e.g. `dag1 | dag2`).
Regular expressions are **not** supported.
*
* **Performance note:** this full-match pattern is evaluated as ``ILIKE
'%term%'`` and most of the time prevents the database from using B-tree
indexes, which can be very slow on large tables. Prefer the equivalent
``run_id_prefix_pattern`` parameter when possible.
@@ -360,7 +362,7 @@ export const prefetchUseDagRunServiceGetDagRun =
(queryClient: QueryClient, { da
* @returns DAGRunCollectionResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseDagRunServiceGetDagRuns = (queryClient: QueryClient, {
bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdP [...]
+export const prefetchUseDagRunServiceGetDagRuns = (queryClient: QueryClient, {
bundleVersion, confContains, consumingAssetPattern, cursor, dagId,
dagIdPattern, dagIdPrefixPattern, dagVersion, durationGt, durationGte,
durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, limit,
logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, offset, orderBy,
partitionDateGte, partitionDateLte, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runAfterL [...]
bundleVersion?: string;
confContains?: string;
consumingAssetPattern?: string;
@@ -384,6 +386,8 @@ export const prefetchUseDagRunServiceGetDagRuns =
(queryClient: QueryClient, { b
logicalDateLte?: string;
offset?: number;
orderBy?: string[];
+ partitionDateGte?: string;
+ partitionDateLte?: string;
partitionKeyPattern?: string;
partitionKeyPrefixPattern?: string;
runAfterGt?: string;
@@ -404,7 +408,7 @@ export const prefetchUseDagRunServiceGetDagRuns =
(queryClient: QueryClient, { b
updatedAtGte?: string;
updatedAtLt?: string;
updatedAtLte?: string;
-}) => queryClient.prefetchQuery({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern,
partitionKeyPrefixPattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdPattern, [...]
+}) => queryClient.prefetchQuery({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte,
partitionDateLte, partitionKeyPattern, partitionKeyPrefixPattern, runAfterGt,
runAfterGte, run [...]
/**
* Get Upstream Asset Events
* If dag run is asset-triggered, return the asset events that triggered it.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
index 8bc74b305aa..ab04de50cb1 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -307,6 +307,8 @@ export const useDagRunServiceGetDagRun = <TData =
Common.DagRunServiceGetDagRunD
* on the first page.
* @param data The data for the request.
* @param data.dagId
+* @param data.partitionDateGte Inclusive lower bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
Runs from the start of this day onwards match.
+* @param data.partitionDateLte Inclusive upper bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
The whole day is included: runs up to the end of this day match.
* @param data.cursor Cursor for keyset-based pagination. Pass an empty string
for the first page, then use ``next_cursor`` from the response. When ``cursor``
is provided, ``offset`` is ignored.
* @param data.limit
* @param data.offset
@@ -339,7 +341,7 @@ export const useDagRunServiceGetDagRun = <TData =
Common.DagRunServiceGetDagRunD
* @param data.state
* @param data.dagVersion
* @param data.bundleVersion
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at, conf, duration, dag_run_id`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at, conf, duration, dag_run_id`
* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g.
`%customer_%`). Use the pipe `|` operator for OR logic (e.g. `dag1 | dag2`).
Regular expressions are **not** supported.
*
* **Performance note:** this full-match pattern is evaluated as ``ILIKE
'%term%'`` and most of the time prevents the database from using B-tree
indexes, which can be very slow on large tables. Prefer the equivalent
``run_id_prefix_pattern`` parameter when possible.
@@ -360,7 +362,7 @@ export const useDagRunServiceGetDagRun = <TData =
Common.DagRunServiceGetDagRunD
* @returns DAGRunCollectionResponse Successful Response
* @throws ApiError
*/
-export const useDagRunServiceGetDagRuns = <TData =
Common.DagRunServiceGetDagRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern,
partitionKey [...]
+export const useDagRunServiceGetDagRuns = <TData =
Common.DagRunServiceGetDagRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte,
partitionDateLt [...]
bundleVersion?: string;
confContains?: string;
consumingAssetPattern?: string;
@@ -384,6 +386,8 @@ export const useDagRunServiceGetDagRuns = <TData =
Common.DagRunServiceGetDagRun
logicalDateLte?: string;
offset?: number;
orderBy?: string[];
+ partitionDateGte?: string;
+ partitionDateLte?: string;
partitionKeyPattern?: string;
partitionKeyPrefixPattern?: string;
runAfterGt?: string;
@@ -404,7 +408,7 @@ export const useDagRunServiceGetDagRuns = <TData =
Common.DagRunServiceGetDagRun
updatedAtGte?: string;
updatedAtLt?: string;
updatedAtLte?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern, [...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte, pa [...]
/**
* Get Upstream Asset Events
* If dag run is asset-triggered, return the asset events that triggered it.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
index 5c22b3bf338..4fc85f3bc86 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -307,6 +307,8 @@ export const useDagRunServiceGetDagRunSuspense = <TData =
Common.DagRunServiceGe
* on the first page.
* @param data The data for the request.
* @param data.dagId
+* @param data.partitionDateGte Inclusive lower bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
Runs from the start of this day onwards match.
+* @param data.partitionDateLte Inclusive upper bound of the partition_date
window, interpreted as a local calendar day in the Dag's timetable timezone.
The whole day is included: runs up to the end of this day match.
* @param data.cursor Cursor for keyset-based pagination. Pass an empty string
for the first page, then use ``next_cursor`` from the response. When ``cursor``
is provided, ``offset`` is ignored.
* @param data.limit
* @param data.offset
@@ -339,7 +341,7 @@ export const useDagRunServiceGetDagRunSuspense = <TData =
Common.DagRunServiceGe
* @param data.state
* @param data.dagVersion
* @param data.bundleVersion
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at, conf, duration, dag_run_id`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at, conf, duration, dag_run_id`
* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g.
`%customer_%`). Use the pipe `|` operator for OR logic (e.g. `dag1 | dag2`).
Regular expressions are **not** supported.
*
* **Performance note:** this full-match pattern is evaluated as ``ILIKE
'%term%'`` and most of the time prevents the database from using B-tree
indexes, which can be very slow on large tables. Prefer the equivalent
``run_id_prefix_pattern`` parameter when possible.
@@ -360,7 +362,7 @@ export const useDagRunServiceGetDagRunSuspense = <TData =
Common.DagRunServiceGe
* @returns DAGRunCollectionResponse Successful Response
* @throws ApiError
*/
-export const useDagRunServiceGetDagRunsSuspense = <TData =
Common.DagRunServiceGetDagRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKeyPattern, part [...]
+export const useDagRunServiceGetDagRunsSuspense = <TData =
Common.DagRunServiceGetDagRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDateGte, partiti [...]
bundleVersion?: string;
confContains?: string;
consumingAssetPattern?: string;
@@ -384,6 +386,8 @@ export const useDagRunServiceGetDagRunsSuspense = <TData =
Common.DagRunServiceG
logicalDateLte?: string;
offset?: number;
orderBy?: string[];
+ partitionDateGte?: string;
+ partitionDateLte?: string;
partitionKeyPattern?: string;
partitionKeyPrefixPattern?: string;
runAfterGt?: string;
@@ -404,7 +408,7 @@ export const useDagRunServiceGetDagRunsSuspense = <TData =
Common.DagRunServiceG
updatedAtGte?: string;
updatedAtLt?: string;
updatedAtLte?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionKey [...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDagRunServiceGetDagRunsKeyFn({ bundleVersion, confContains,
consumingAssetPattern, cursor, dagId, dagIdPattern, dagIdPrefixPattern,
dagVersion, durationGt, durationGte, durationLt, durationLte, endDateGt,
endDateGte, endDateLt, endDateLte, limit, logicalDateGt, logicalDateGte,
logicalDateLt, logicalDateLte, offset, orderBy, partitionDat [...]
/**
* Get Upstream Asset Events
* If dag run is asset-triggered, return the asset events that triggered it.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index 69e12c4514c..8bbaed47da9 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -1059,6 +1059,8 @@ export class DagRunService {
* on the first page.
* @param data The data for the request.
* @param data.dagId
+ * @param data.partitionDateGte Inclusive lower bound of the
partition_date window, interpreted as a local calendar day in the Dag's
timetable timezone. Runs from the start of this day onwards match.
+ * @param data.partitionDateLte Inclusive upper bound of the
partition_date window, interpreted as a local calendar day in the Dag's
timetable timezone. The whole day is included: runs up to the end of this day
match.
* @param data.cursor Cursor for keyset-based pagination. Pass an empty
string for the first page, then use ``next_cursor`` from the response. When
``cursor`` is provided, ``offset`` is ignored.
* @param data.limit
* @param data.offset
@@ -1091,7 +1093,7 @@ export class DagRunService {
* @param data.state
* @param data.dagVersion
* @param data.bundleVersion
- * @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, run_after, start_date, end_date,
updated_at, conf, duration, dag_run_id`
+ * @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
state, dag_id, run_id, logical_date, partition_date, run_after, start_date,
end_date, updated_at, conf, duration, dag_run_id`
* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards
(e.g. `%customer_%`). Use the pipe `|` operator for OR logic (e.g. `dag1 |
dag2`). Regular expressions are **not** supported.
*
* **Performance note:** this full-match pattern is evaluated as ``ILIKE
'%term%'`` and most of the time prevents the database from using B-tree
indexes, which can be very slow on large tables. Prefer the equivalent
``run_id_prefix_pattern`` parameter when possible.
@@ -1120,6 +1122,8 @@ export class DagRunService {
dag_id: data.dagId
},
query: {
+ partition_date_gte: data.partitionDateGte,
+ partition_date_lte: data.partitionDateLte,
cursor: data.cursor,
limit: data.limit,
offset: data.offset,
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index ce406b5fcb6..1c6e5e073b7 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -3103,9 +3103,17 @@ export type GetDagRunsData = {
logicalDateLte?: string | null;
offset?: number;
/**
- * Attributes to order by, multi criteria sort is supported. Prefix with
`-` for descending order. Supported attributes: `id, state, dag_id, run_id,
logical_date, run_after, start_date, end_date, updated_at, conf, duration,
dag_run_id`
+ * Attributes to order by, multi criteria sort is supported. Prefix with
`-` for descending order. Supported attributes: `id, state, dag_id, run_id,
logical_date, partition_date, run_after, start_date, end_date, updated_at,
conf, duration, dag_run_id`
*/
orderBy?: Array<(string)>;
+ /**
+ * Inclusive lower bound of the partition_date window, interpreted as a
local calendar day in the Dag's timetable timezone. Runs from the start of this
day onwards match.
+ */
+ partitionDateGte?: string | null;
+ /**
+ * Inclusive upper bound of the partition_date window, interpreted as a
local calendar day in the Dag's timetable timezone. The whole day is included:
runs up to the end of this day match.
+ */
+ partitionDateLte?: string | null;
/**
* SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). The
pipe `|` is matched literally, not as an OR separator. Regular expressions are
**not** supported.
*
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
index 52ffc947eda..930ba978683 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py
@@ -128,6 +128,10 @@ RUN_AFTER2 = datetime(2024, 2, 20, 0, 0,
tzinfo=timezone.utc)
START_DATE2 = datetime(2024, 4, 15, 0, 0, tzinfo=timezone.utc)
LOGICAL_DATE3 = datetime(2024, 5, 16, 0, 0, tzinfo=timezone.utc)
LOGICAL_DATE4 = datetime(2024, 5, 25, 0, 0, tzinfo=timezone.utc)
+PARTITION_DATE1 = datetime(2024, 6, 1, 0, 0, tzinfo=timezone.utc)
+PARTITION_DATE2 = datetime(2024, 6, 2, 0, 0, tzinfo=timezone.utc)
+PARTITION_DATE3 = datetime(2024, 6, 3, 0, 0, tzinfo=timezone.utc)
+PARTITION_DATE4 = datetime(2024, 6, 4, 0, 0, tzinfo=timezone.utc)
DAG1_RUN1_NOTE = "test_note"
DAG2_PARAM = {"validated_number": Param(1, minimum=1, maximum=10)}
@@ -173,6 +177,7 @@ def setup(request, dag_maker, *, session=None):
dag_run1.end_date = dag_run1.start_date + timedelta(seconds=101)
# Set conf for testing conf_contains filter (values ordered for
predictable sorting)
dag_run1.conf = {"env": "development", "version": "1.0"}
+ dag_run1.partition_date = PARTITION_DATE1
for i, t in enumerate([task1, task2], start=1):
ti = dag_run1.get_task_instance(task_id=t.task_id)
@@ -203,6 +208,7 @@ def setup(request, dag_maker, *, session=None):
dag_run2.end_date = dag_run2.start_date + timedelta(seconds=201)
# Set conf for testing conf_contains filter
dag_run2.conf = {"env": "production", "debug": True}
+ dag_run2.partition_date = PARTITION_DATE2
ti1 = dag_run2.get_task_instance(task_id=task1.task_id)
ti1.task = task1
@@ -230,6 +236,7 @@ def setup(request, dag_maker, *, session=None):
dag_run3.end_date = dag_run3.start_date + timedelta(seconds=51)
# Set conf for testing conf_contains filter
dag_run3.conf = {"env": "staging", "test_mode": True}
+ dag_run3.partition_date = PARTITION_DATE3
dag_run4 = dag_maker.create_dagrun(
run_id=DAG2_RUN2_ID,
@@ -244,6 +251,7 @@ def setup(request, dag_maker, *, session=None):
dag_run4.end_date = dag_run4.start_date + timedelta(seconds=150)
# Set conf for testing conf_contains filter
dag_run4.conf = {"env": "testing", "mode": "ci"}
+ dag_run4.partition_date = PARTITION_DATE4
dag_maker.sync_dagbag_to_db()
dag_maker.dag_model.has_task_concurrency_limits = True
@@ -318,9 +326,9 @@ def get_dag_run_dict(run: DagRun):
"note": run.note,
"dag_versions": get_dag_versions_dict(run.dag_versions),
"partition_key": run.partition_key,
- "partition_date": from_datetime_to_zulu_without_ms(run.partition_date)
- if run.partition_date
- else None,
+ "partition_date": (
+ from_datetime_to_zulu_without_ms(run.partition_date) if
run.partition_date else None
+ ),
}
@@ -413,6 +421,21 @@ class TestGetDagRuns:
body = response.json()
assert body["detail"] == "The Dag with ID: `invalid` was not found"
+ def test_partition_date_day_filters_reject_all_dags_selector(self,
test_client):
+ response = test_client.get("/dags/~/dagRuns",
params={"partition_date_gte": "2025-01-01"})
+ assert response.status_code == 400
+ assert response.json()["detail"] == (
+ "partition_date_gte and partition_date_lte require a specific
dag_id."
+ )
+
+ def test_partition_date_day_filters_reject_non_partitioned_dag(self,
test_client):
+ response = test_client.get(f"/dags/{DAG1_ID}/dagRuns",
params={"partition_date_gte": "2025-01-01"})
+ assert response.status_code == 400
+ assert response.json()["detail"] == (
+ f"Dag with dag_id: '{DAG1_ID}' is not partitioned; "
+ "partition_date_gte and partition_date_lte are not supported."
+ )
+
def test_invalid_order_by_raises_400(self, test_client):
response = test_client.get("/dags/test_dag1/dagRuns?order_by=invalid")
assert response.status_code == 400
@@ -437,6 +460,7 @@ class TestGetDagRuns:
pytest.param("state", [DAG1_RUN2_ID, DAG1_RUN1_ID],
id="order_by_state"),
pytest.param("dag_id", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_dag_id"),
pytest.param("logical_date", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_logical_date"),
+ pytest.param("partition_date", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_partition_date"),
pytest.param("dag_run_id", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_dag_run_id"),
pytest.param("start_date", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_start_date"),
pytest.param("end_date", [DAG1_RUN1_ID, DAG1_RUN2_ID],
id="order_by_end_date"),
@@ -970,6 +994,48 @@ class TestGetDagRuns:
body = response.json()
assert [each["dag_run_id"] for each in body["dag_runs"]] ==
expected_dag_id_list
+ @pytest.mark.usefixtures("configure_git_connection_for_dag_bundle")
+ def test_partition_date_day_filters_use_timetable_timezone(self,
test_client, dag_maker, session):
+ dag_id = "test_partition_date_local_day"
+ with dag_maker(
+ dag_id=dag_id,
+ schedule=CronPartitionTimetable("0 0 * * *",
timezone="Asia/Taipei"),
+ start_date=START_DATE1,
+ session=session,
+ serialized=True,
+ ):
+ EmptyOperator(task_id="task")
+
+ for run_id, partition_date in [
+ ("before_local_day", datetime(2025, 1, 1, 15, 59, 59,
tzinfo=timezone.utc)),
+ ("start_local_day", datetime(2025, 1, 1, 16, 0, 0,
tzinfo=timezone.utc)),
+ ("end_local_day", datetime(2025, 1, 2, 15, 59, 59,
tzinfo=timezone.utc)),
+ ("after_local_day", datetime(2025, 1, 2, 16, 0, 0,
tzinfo=timezone.utc)),
+ ]:
+ dag_maker.create_dagrun(
+ run_id=run_id,
+ state=DagRunState.SUCCESS,
+ logical_date=None,
+ partition_date=partition_date,
+ partition_key=run_id,
+ )
+ dag_maker.sync_dagbag_to_db()
+ session.commit()
+
+ response = test_client.get(
+ f"/dags/{dag_id}/dagRuns",
+ params={
+ "partition_date_gte": "2025-01-02",
+ "partition_date_lte": "2025-01-02",
+ "order_by": "partition_date",
+ },
+ )
+ assert response.status_code == 200
+ assert [each["dag_run_id"] for each in response.json()["dag_runs"]] ==
[
+ "start_local_day",
+ "end_local_day",
+ ]
+
def test_bad_filters(self, test_client):
query_params = {
"logical_date_gte": "invalid",