Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/airflow/providers/common/compat/sdk.py: 41%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

41 statements  

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""" 

18Airflow compatibility imports for seamless migration from Airflow 2 to Airflow 3. 

19 

20This module provides lazy imports that automatically try Airflow 3 paths first, 

21then fall back to Airflow 2 paths, enabling code to work across both versions. 

22""" 

23 

24from __future__ import annotations 

25 

26from typing import TYPE_CHECKING 

27 

28from airflow.providers.common.compat.version_compat import AIRFLOW_V_3_0_PLUS 

29 

30if TYPE_CHECKING: 

31 import airflow.sdk.io as io # noqa: F401 

32 import airflow.sdk.timezone as timezone # noqa: F401 

33 from airflow.models.xcom import XCOM_RETURN_KEY as XCOM_RETURN_KEY 

34 from airflow.sdk import ( 

35 DAG as DAG, 

36 Asset as Asset, 

37 AssetAlias as AssetAlias, 

38 AssetAll as AssetAll, 

39 AssetAny as AssetAny, 

40 BaseHook as BaseHook, 

41 BaseNotifier as BaseNotifier, 

42 BaseOperator as BaseOperator, 

43 BaseOperatorLink as BaseOperatorLink, 

44 BaseSensorOperator as BaseSensorOperator, 

45 Connection as Connection, 

46 Context as Context, 

47 DagRunState as DagRunState, 

48 EdgeModifier as EdgeModifier, 

49 Label as Label, 

50 Metadata as Metadata, 

51 ObjectStoragePath as ObjectStoragePath, 

52 Param as Param, 

53 PokeReturnValue as PokeReturnValue, 

54 TaskGroup as TaskGroup, 

55 TaskInstanceState as TaskInstanceState, 

56 TriggerRule as TriggerRule, 

57 Variable as Variable, 

58 WeightRule as WeightRule, 

59 XComArg as XComArg, 

60 chain as chain, 

61 chain_linear as chain_linear, 

62 cross_downstream as cross_downstream, 

63 dag as dag, 

64 get_current_context as get_current_context, 

65 get_parsing_context as get_parsing_context, 

66 setup as setup, 

67 task as task, 

68 task_group as task_group, 

69 teardown as teardown, 

70 ) 

71 from airflow.sdk._shared.listeners import hookimpl as hookimpl 

72 from airflow.sdk._shared.observability.metrics.stats import Stats as Stats 

73 from airflow.sdk.bases.decorator import ( 

74 DecoratedMappedOperator as DecoratedMappedOperator, 

75 DecoratedOperator as DecoratedOperator, 

76 TaskDecorator as TaskDecorator, 

77 get_unique_task_id as get_unique_task_id, 

78 task_decorator_factory as task_decorator_factory, 

79 ) 

80 from airflow.sdk.bases.sensor import poke_mode_only as poke_mode_only 

81 from airflow.sdk.configuration import conf as conf 

82 from airflow.sdk.definitions.context import context_merge as context_merge 

83 from airflow.sdk.definitions.mappedoperator import MappedOperator as MappedOperator 

84 from airflow.sdk.definitions.template import literal as literal 

85 from airflow.sdk.exceptions import ( 

86 AirflowConfigException as AirflowConfigException, 

87 AirflowException as AirflowException, 

88 AirflowFailException as AirflowFailException, 

89 AirflowNotFoundException as AirflowNotFoundException, 

90 AirflowOptionalProviderFeatureException as AirflowOptionalProviderFeatureException, 

91 AirflowSensorTimeout as AirflowSensorTimeout, 

92 AirflowSkipException as AirflowSkipException, 

93 AirflowTaskTimeout as AirflowTaskTimeout, 

94 ParamValidationError as ParamValidationError, 

95 TaskDeferred as TaskDeferred, 

96 XComNotFound as XComNotFound, 

97 ) 

98 from airflow.sdk.lineage import ( 

99 HookLineage as HookLineage, 

100 HookLineageCollector as HookLineageCollector, 

101 HookLineageReader as HookLineageReader, 

102 NoOpCollector as NoOpCollector, 

103 get_hook_lineage_collector as get_hook_lineage_collector, 

104 ) 

105 from airflow.sdk.listener import get_listener_manager as get_listener_manager 

106 from airflow.sdk.log import redact as redact 

107 from airflow.sdk.plugins_manager import AirflowPlugin as AirflowPlugin 

108 

109 # Airflow 3-only exceptions (conditionally imported) 

110 if AIRFLOW_V_3_0_PLUS: 

111 from airflow.sdk.exceptions import ( 

112 DagRunTriggerException as DagRunTriggerException, 

113 DownstreamTasksSkipped as DownstreamTasksSkipped, 

114 ) 

115 from airflow.sdk.execution_time.context import ( 

116 AIRFLOW_VAR_NAME_FORMAT_MAPPING as AIRFLOW_VAR_NAME_FORMAT_MAPPING, 

117 context_to_airflow_vars as context_to_airflow_vars, 

118 ) 

119 from airflow.sdk.execution_time.timeout import timeout as timeout 

120 from airflow.sdk.execution_time.xcom import XCom as XCom 

121 from airflow.sdk.types import TaskInstanceKey as TaskInstanceKey 

122 

123 

124from airflow.providers.common.compat._compat_utils import create_module_getattr 

125 

126# Rename map for classes that changed names between Airflow 2.x and 3.x 

127# Format: new_name -> (new_path, old_path, old_name) 

128_RENAME_MAP: dict[str, tuple[str, str, str]] = { 

129 # Assets: Dataset -> Asset rename in Airflow 3.0 

130 "Asset": ("airflow.sdk", "airflow.datasets", "Dataset"), 

131 "AssetAlias": ("airflow.sdk", "airflow.datasets", "DatasetAlias"), 

132 "AssetAll": ("airflow.sdk", "airflow.datasets", "DatasetAll"), 

133 "AssetAny": ("airflow.sdk", "airflow.datasets", "DatasetAny"), 

134} 

135 

136# Airflow 3-only renames (not available in Airflow 2) 

137_AIRFLOW_3_ONLY_RENAMES: dict[str, tuple[str, str, str]] = {} 

138 

139 

140# Import map for classes/functions/constants 

141# Format: class_name -> module_path(s) 

142# - str: single module path (no fallback) 

143# - tuple[str, ...]: multiple module paths (try in order, newest first) 

144_IMPORT_MAP: dict[str, str | tuple[str, ...]] = { 

145 # ============================================================================ 

146 # Hooks 

147 # ============================================================================ 

148 "BaseHook": ("airflow.sdk", "airflow.hooks.base"), 

149 # ============================================================================ 

150 # Sensors 

151 # ============================================================================ 

152 "BaseSensorOperator": ("airflow.sdk", "airflow.sensors.base"), 

153 "PokeReturnValue": ("airflow.sdk", "airflow.sensors.base"), 

154 "poke_mode_only": ("airflow.sdk.bases.sensor", "airflow.sensors.base"), 

155 # ============================================================================ 

156 # Operators 

157 # ============================================================================ 

158 "BaseOperator": ("airflow.sdk", "airflow.models.baseoperator"), 

159 # ============================================================================ 

160 # Decorators 

161 # ============================================================================ 

162 "task": ("airflow.sdk", "airflow.decorators"), 

163 "dag": ("airflow.sdk", "airflow.decorators"), 

164 "task_group": ("airflow.sdk", "airflow.decorators"), 

165 "setup": ("airflow.sdk", "airflow.decorators"), 

166 "teardown": ("airflow.sdk", "airflow.decorators"), 

167 "TaskDecorator": ("airflow.sdk.bases.decorator", "airflow.decorators"), 

168 "task_decorator_factory": ("airflow.sdk.bases.decorator", "airflow.decorators.base"), 

169 "get_unique_task_id": ("airflow.sdk.bases.decorator", "airflow.decorators.base"), 

170 # ============================================================================ 

171 # Models 

172 # ============================================================================ 

173 "Connection": ("airflow.sdk", "airflow.models.connection"), 

174 "Variable": ("airflow.sdk", "airflow.models.variable"), 

175 "XCom": ("airflow.sdk.execution_time.xcom", "airflow.models.xcom"), 

176 "DAG": ("airflow.sdk", "airflow.models.dag"), 

177 "Param": ("airflow.sdk", "airflow.models.param"), 

178 "XComArg": ("airflow.sdk", "airflow.models.xcom_arg"), 

179 "DecoratedOperator": ("airflow.sdk.bases.decorator", "airflow.decorators.base"), 

180 "DecoratedMappedOperator": ("airflow.sdk.bases.decorator", "airflow.decorators.base"), 

181 "MappedOperator": ("airflow.sdk.definitions.mappedoperator", "airflow.models.mappedoperator"), 

182 # ============================================================================ 

183 # Assets (Dataset → Asset rename in Airflow 3.0) 

184 # ============================================================================ 

185 # Note: Asset, AssetAlias, AssetAll, AssetAny are handled by _RENAME_MAP 

186 # Metadata moved from airflow.datasets.metadata (2.x) to airflow.sdk (3.x) 

187 "Metadata": ("airflow.sdk", "airflow.datasets.metadata"), 

188 # ============================================================================ 

189 # Notifiers 

190 # ============================================================================ 

191 "BaseNotifier": ("airflow.sdk", "airflow.notifications.basenotifier"), 

192 # ============================================================================ 

193 # Plugins 

194 # ============================================================================ 

195 "AirflowPlugin": ("airflow.sdk.plugins_manager", "airflow.plugins_manager"), 

196 # ============================================================================ 

197 # Operator Links & Task Groups 

198 # ============================================================================ 

199 "BaseOperatorLink": ("airflow.sdk", "airflow.models.baseoperatorlink"), 

200 "TaskInstanceKey": ("airflow.sdk.types", "airflow.models.taskinstancekey"), 

201 "TaskGroup": ("airflow.sdk", "airflow.utils.task_group"), 

202 # ============================================================================ 

203 # Operator Utilities (chain, cross_downstream, etc.) 

204 # ============================================================================ 

205 "chain": ("airflow.sdk", "airflow.models.baseoperator"), 

206 "chain_linear": ("airflow.sdk", "airflow.models.baseoperator"), 

207 "cross_downstream": ("airflow.sdk", "airflow.models.baseoperator"), 

208 # ============================================================================ 

209 # Edge Modifiers & Labels 

210 # ============================================================================ 

211 "EdgeModifier": ("airflow.sdk", "airflow.utils.edgemodifier"), 

212 "Label": ("airflow.sdk", "airflow.utils.edgemodifier"), 

213 # ============================================================================ 

214 # State Enums 

215 # ============================================================================ 

216 "DagRunState": ("airflow.sdk", "airflow.utils.state"), 

217 "TaskInstanceState": ("airflow.sdk", "airflow.utils.state"), 

218 "TriggerRule": ("airflow.sdk", "airflow.utils.trigger_rule"), 

219 "WeightRule": ("airflow.sdk", "airflow.utils.weight_rule"), 

220 # ============================================================================ 

221 # IO & Storage 

222 # ============================================================================ 

223 "ObjectStoragePath": ("airflow.sdk", "airflow.io.path"), 

224 # ============================================================================ 

225 # Template Utilities 

226 # ============================================================================ 

227 "literal": ("airflow.sdk.definitions.template", "airflow.utils.template"), 

228 # ============================================================================ 

229 # Context & Utilities 

230 # ============================================================================ 

231 "Context": ("airflow.sdk", "airflow.utils.context"), 

232 "context_merge": ("airflow.sdk.definitions.context", "airflow.utils.context"), 

233 "context_to_airflow_vars": ("airflow.sdk.execution_time.context", "airflow.utils.operator_helpers"), 

234 "AIRFLOW_VAR_NAME_FORMAT_MAPPING": ( 

235 "airflow.sdk.execution_time.context", 

236 "airflow.utils.operator_helpers", 

237 ), 

238 "get_current_context": ("airflow.sdk", "airflow.operators.python"), 

239 "get_parsing_context": ("airflow.sdk", "airflow.utils.dag_parsing_context"), 

240 # ============================================================================ 

241 # Timeout Utilities 

242 # ============================================================================ 

243 "timeout": ("airflow.sdk.execution_time.timeout", "airflow.utils.timeout"), 

244 # ============================================================================ 

245 # XCom & Task Communication 

246 # ============================================================================ 

247 "XCOM_RETURN_KEY": "airflow.models.xcom", 

248 # ============================================================================ 

249 # Lineage 

250 # ============================================================================ 

251 "HookLineageCollector": ("airflow.sdk.lineage", "airflow.lineage.hook"), 

252 "HookLineageReader": ("airflow.sdk.lineage", "airflow.lineage.hook"), 

253 "get_hook_lineage_collector": ("airflow.sdk.lineage", "airflow.lineage.hook"), 

254 "HookLineage": ("airflow.sdk.lineage", "airflow.lineage.hook"), 

255 # Note: AssetLineageInfo is handled by _RENAME_MAP (DatasetLineageInfo -> AssetLineageInfo) 

256 "NoOpCollector": ("airflow.sdk.lineage", "airflow.lineage.hook"), 

257 # ============================================================================ 

258 # Exceptions (deprecated in airflow.exceptions, prefer SDK) 

259 # ============================================================================ 

260 # Note: AirflowException and AirflowNotFoundException are not deprecated, but exposing them 

261 # here keeps provider imports consistent across Airflow 2 and 3. 

262 "AirflowException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

263 "AirflowFailException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

264 "AirflowNotFoundException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

265 "AirflowOptionalProviderFeatureException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

266 "AirflowSkipException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

267 "AirflowTaskTimeout": ("airflow.sdk.exceptions", "airflow.exceptions"), 

268 "AirflowSensorTimeout": ("airflow.sdk.exceptions", "airflow.exceptions"), 

269 "ParamValidationError": ("airflow.sdk.exceptions", "airflow.exceptions"), 

270 "TaskDeferred": ("airflow.sdk.exceptions", "airflow.exceptions"), 

271 "XComNotFound": ("airflow.sdk.exceptions", "airflow.exceptions"), 

272 # ============================================================================ 

273 # Observability 

274 # ============================================================================ 

275 "Stats": ("airflow.sdk._shared.observability.metrics.stats", "airflow.stats"), 

276 # ============================================================================ 

277 # Secrets Masking 

278 # ============================================================================ 

279 "redact": ( 

280 "airflow.sdk.log", 

281 "airflow.sdk._shared.secrets_masker", 

282 "airflow.sdk.execution_time.secrets_masker", 

283 "airflow.utils.log.secrets_masker", 

284 ), 

285 # ============================================================================ 

286 # Listeners 

287 # ============================================================================ 

288 "hookimpl": ("airflow.sdk._shared.listeners", "airflow.listeners"), 

289 "get_listener_manager": ("airflow.sdk.listener", "airflow.listeners.listener"), 

290 # Configuration 

291 # ============================================================================ 

292 "conf": ("airflow.sdk.configuration", "airflow.configuration"), 

293 "AirflowConfigException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

294} 

295 

296# Airflow 3-only exceptions (not available in Airflow 2) 

297_AIRFLOW_3_ONLY_EXCEPTIONS: dict[str, tuple[str, ...]] = { 

298 "DownstreamTasksSkipped": ("airflow.sdk.exceptions", "airflow.exceptions"), 

299 "DagRunTriggerException": ("airflow.sdk.exceptions", "airflow.exceptions"), 

300} 

301 

302# Add Airflow 3-only exceptions and renames to _IMPORT_MAP if running Airflow 3+ 

303if AIRFLOW_V_3_0_PLUS: 

304 _IMPORT_MAP.update(_AIRFLOW_3_ONLY_EXCEPTIONS) 

305 _RENAME_MAP.update(_AIRFLOW_3_ONLY_RENAMES) 

306 # AssetLineageInfo exists in 3.0+ but location changed in 3.2 

307 # 3.0-3.1: airflow.lineage.hook.AssetLineageInfo 

308 # 3.2+: airflow.sdk.lineage.AssetLineageInfo 

309 _IMPORT_MAP["AssetLineageInfo"] = ("airflow.sdk.lineage", "airflow.lineage.hook") 

310 

311# Module map: module_name -> module_path(s) 

312# For entire modules that have been moved (e.g., timezone) 

313# Usage: from airflow.providers.common.compat.lazy_compat import timezone 

314_MODULE_MAP: dict[str, str | tuple[str, ...]] = { 

315 "timezone": ("airflow.sdk.timezone", "airflow.utils.timezone"), 

316 "io": ("airflow.sdk.io", "airflow.io"), 

317} 

318 

319# Use the shared utility to create __getattr__ 

320__getattr__ = create_module_getattr( 

321 import_map=_IMPORT_MAP, 

322 module_map=_MODULE_MAP, 

323 rename_map=_RENAME_MAP, 

324) 

325 

326__all__ = list(_RENAME_MAP.keys()) + list(_IMPORT_MAP.keys()) + list(_MODULE_MAP.keys())