Coverage for /home/airflow/.local/lib/python3.12/site-packages/airflow/api_fastapi/core_api/datamodels/ui/deadline.py: 70%

38 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 14:22 +0000

1# Licensed to the Apache Software Foundation (ASF) under one 

2# or more contributor license agreements. See the NOTICE file 

3# distributed with this work for additional information 

4# regarding copyright ownership. The ASF licenses this file 

5# to you under the Apache License, Version 2.0 (the 

6# "License"); you may not use this file except in compliance 

7# with the License. You may obtain a copy of the License at 

8# 

9# http://www.apache.org/licenses/LICENSE-2.0 

10# 

11# Unless required by applicable law or agreed to in writing, 

12# software distributed under the License is distributed on an 

13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 

14# KIND, either express or implied. See the License for the 

15# specific language governing permissions and limitations 

16# under the License. 

17 

18from __future__ import annotations 

19 

20from collections.abc import Iterable 

21from datetime import datetime 

22from typing import Any 

23from uuid import UUID 

24 

25from pydantic import AliasPath, Field, field_validator 

26 

27from airflow.api_fastapi.core_api.base import BaseModel 

28 

29 

30class DeadlineResponse(BaseModel): 

31 """Deadline serializer for responses.""" 

32 

33 id: UUID 

34 deadline_time: datetime 

35 missed: bool 

36 created_at: datetime 

37 dag_id: str = Field(validation_alias=AliasPath("dagrun", "dag_id")) 

38 dag_run_id: str = Field(validation_alias=AliasPath("dagrun", "run_id")) 

39 alert_id: UUID | None = Field(validation_alias="deadline_alert_id", default=None) 

40 alert_name: str | None = Field(validation_alias=AliasPath("deadline_alert", "name"), default=None) 

41 

42 

43class DeadlineCollectionResponse(BaseModel): 

44 """Deadline Collection serializer for responses.""" 

45 

46 deadlines: Iterable[DeadlineResponse] 

47 total_entries: int 

48 

49 

50class DeadlineAlertResponse(BaseModel): 

51 """DeadlineAlert serializer for responses.""" 

52 

53 id: UUID 

54 name: str | None = None 

55 reference_type: str = Field(validation_alias=AliasPath("reference", "reference_type")) 

56 interval: float | None = Field( 

57 default=None, 

58 description=( 

59 "Interval in seconds between the reference time and the deadline. " 

60 "Null for a dynamic interval (e.g. a VariableInterval) whose value is " 

61 "only resolved at scheduler evaluation time." 

62 ), 

63 ) 

64 created_at: datetime 

65 

66 @field_validator("interval", mode="before") 

67 @classmethod 

68 def coerce_interval_to_seconds(cls, value: Any) -> float | None: 

69 """ 

70 Coerce the stored ``interval`` into seconds. 

71 

72 ``interval`` is the Airflow-serialized SDK interval: a dict 

73 ``{"__classname__": ..., "__data__": <seconds|dict>}``, not a plain number. 

74 Return the seconds for a fixed ``timedelta``, or ``None`` for a dynamic 

75 interval (resolved later by the scheduler). Without this, Pydantic 500s on the dict. 

76 """ 

77 if value is None or isinstance(value, (int, float)): 

78 return value 

79 if isinstance(value, dict): 

80 data = value.get("__data__") 

81 if isinstance(data, (int, float)): 

82 return float(data) 

83 return None 

84 

85 

86class DeadlineAlertCollectionResponse(BaseModel): 

87 """DeadlineAlert Collection serializer for responses.""" 

88 

89 deadline_alerts: Iterable[DeadlineAlertResponse] 

90 total_entries: int