apache-airflow-providers-openlineage 1.9.1__py3-none-any.whl → 1.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of apache-airflow-providers-openlineage might be problematic. Click here for more details.

@@ -24,7 +24,7 @@ import re
24
24
  from contextlib import redirect_stdout, suppress
25
25
  from functools import wraps
26
26
  from io import StringIO
27
- from typing import TYPE_CHECKING, Any, Iterable
27
+ from typing import TYPE_CHECKING, Any, Callable, Iterable
28
28
 
29
29
  import attrs
30
30
  from deprecated import deprecated
@@ -32,15 +32,16 @@ from openlineage.client.utils import RedactMixin
32
32
  from packaging.version import Version
33
33
 
34
34
  from airflow import __version__ as AIRFLOW_VERSION
35
+ from airflow.datasets import Dataset
35
36
  from airflow.exceptions import AirflowProviderDeprecationWarning # TODO: move this maybe to Airflow's logic?
36
37
  from airflow.models import DAG, BaseOperator, MappedOperator
37
38
  from airflow.providers.openlineage import conf
38
39
  from airflow.providers.openlineage.plugins.facets import (
40
+ AirflowDagRunFacet,
39
41
  AirflowJobFacet,
40
42
  AirflowMappedTaskRunFacet,
41
43
  AirflowRunFacet,
42
44
  AirflowStateRunFacet,
43
- BaseFacet,
44
45
  UnknownOperatorAttributeRunFacet,
45
46
  UnknownOperatorInstance,
46
47
  )
@@ -54,12 +55,16 @@ from airflow.utils.log.secrets_masker import Redactable, Redacted, SecretsMasker
54
55
  from airflow.utils.module_loading import import_string
55
56
 
56
57
  if TYPE_CHECKING:
58
+ from openlineage.client.event_v2 import Dataset as OpenLineageDataset
59
+ from openlineage.client.facet_v2 import RunFacet
60
+
57
61
  from airflow.models import DagRun, TaskInstance
62
+ from airflow.utils.state import TaskInstanceState
58
63
 
59
64
 
60
65
  log = logging.getLogger(__name__)
61
66
  _NOMINAL_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
62
- _IS_AIRFLOW_2_10_OR_HIGHER = Version(Version(AIRFLOW_VERSION).base_version) >= Version("2.10.0")
67
+ IS_AIRFLOW_2_10_OR_HIGHER = Version(Version(AIRFLOW_VERSION).base_version) >= Version("2.10.0")
63
68
 
64
69
 
65
70
  def try_import_from_string(string: str) -> Any:
@@ -77,12 +82,52 @@ def get_job_name(task: TaskInstance) -> str:
77
82
  return f"{task.dag_id}.{task.task_id}"
78
83
 
79
84
 
80
- def get_custom_facets(task_instance: TaskInstance | None = None) -> dict[str, Any]:
81
- custom_facets = {}
85
+ def get_airflow_mapped_task_facet(task_instance: TaskInstance) -> dict[str, Any]:
82
86
  # check for -1 comes from SmartSensor compatibility with dynamic task mapping
83
87
  # this comes from Airflow code
84
88
  if hasattr(task_instance, "map_index") and getattr(task_instance, "map_index") != -1:
85
- custom_facets["airflow_mappedTask"] = AirflowMappedTaskRunFacet.from_task_instance(task_instance)
89
+ return {"airflow_mappedTask": AirflowMappedTaskRunFacet.from_task_instance(task_instance)}
90
+ return {}
91
+
92
+
93
+ def get_user_provided_run_facets(ti: TaskInstance, ti_state: TaskInstanceState) -> dict[str, RunFacet]:
94
+ custom_facets = {}
95
+
96
+ # Append custom run facets by executing the custom_run_facet functions.
97
+ for custom_facet_func in conf.custom_run_facets():
98
+ try:
99
+ func: Callable[[TaskInstance, TaskInstanceState], dict[str, RunFacet]] | None = (
100
+ try_import_from_string(custom_facet_func)
101
+ )
102
+ if not func:
103
+ log.warning(
104
+ "OpenLineage is unable to import custom facet function `%s`; will ignore it.",
105
+ custom_facet_func,
106
+ )
107
+ continue
108
+ facets: dict[str, RunFacet] | None = func(ti, ti_state)
109
+ if facets and isinstance(facets, dict):
110
+ duplicate_facet_keys = [facet_key for facet_key in facets if facet_key in custom_facets]
111
+ if duplicate_facet_keys:
112
+ log.warning(
113
+ "Duplicate OpenLineage custom facets key(s) found: `%s` from function `%s`; "
114
+ "this will overwrite the previous value.",
115
+ ", ".join(duplicate_facet_keys),
116
+ custom_facet_func,
117
+ )
118
+ log.debug(
119
+ "Adding OpenLineage custom facet with key(s): `%s` from function `%s`.",
120
+ tuple(facets),
121
+ custom_facet_func,
122
+ )
123
+ custom_facets.update(facets)
124
+ except Exception as exc:
125
+ log.warning(
126
+ "Error processing custom facet function `%s`; will ignore it. Error was: %s: %s",
127
+ custom_facet_func,
128
+ type(exc).__name__,
129
+ exc,
130
+ )
86
131
  return custom_facets
87
132
 
88
133
 
@@ -174,7 +219,19 @@ class InfoJsonEncodable(dict):
174
219
  setattr(self, field, getattr(self.obj, field))
175
220
  self._fields.append(field)
176
221
  else:
177
- for field, val in self.obj.__dict__.items():
222
+ if hasattr(self.obj, "__dict__"):
223
+ obj_fields = self.obj.__dict__
224
+ elif attrs.has(self.obj.__class__): # e.g. attrs.define class with slots=True has no __dict__
225
+ obj_fields = {
226
+ field.name: getattr(self.obj, field.name) for field in attrs.fields(self.obj.__class__)
227
+ }
228
+ else:
229
+ raise ValueError(
230
+ "Cannot iterate over fields: "
231
+ f"The object of type {type(self.obj).__name__} neither has a __dict__ attribute "
232
+ "nor is defined as an attrs class."
233
+ )
234
+ for field, val in obj_fields.items():
178
235
  if field not in self._fields and field not in self.excludes and field not in self.renames:
179
236
  setattr(self, field, val)
180
237
  self._fields.append(field)
@@ -206,7 +263,7 @@ class DagRunInfo(InfoJsonEncodable):
206
263
  class TaskInstanceInfo(InfoJsonEncodable):
207
264
  """Defines encoding TaskInstance object to JSON."""
208
265
 
209
- includes = ["duration", "try_number", "pool", "queued_dttm"]
266
+ includes = ["duration", "try_number", "pool", "queued_dttm", "log_url"]
210
267
  casts = {
211
268
  "map_index": lambda ti: (
212
269
  ti.map_index if hasattr(ti, "map_index") and getattr(ti, "map_index") != -1 else None
@@ -231,6 +288,7 @@ class TaskInfo(InfoJsonEncodable):
231
288
  "_is_teardown": "is_teardown",
232
289
  }
233
290
  includes = [
291
+ "deferrable",
234
292
  "depends_on_past",
235
293
  "downstream_task_ids",
236
294
  "execution_timeout",
@@ -259,16 +317,36 @@ class TaskInfo(InfoJsonEncodable):
259
317
  ]
260
318
  casts = {
261
319
  "operator_class": lambda task: task.task_type,
320
+ "operator_class_path": lambda task: get_fully_qualified_class_name(task),
262
321
  "task_group": lambda task: (
263
322
  TaskGroupInfo(task.task_group)
264
323
  if hasattr(task, "task_group") and getattr(task.task_group, "_group_id", None)
265
324
  else None
266
325
  ),
267
- "inlets": lambda task: [DatasetInfo(inlet) for inlet in task.inlets],
268
- "outlets": lambda task: [DatasetInfo(outlet) for outlet in task.outlets],
326
+ "inlets": lambda task: [DatasetInfo(i) for i in task.inlets if isinstance(i, Dataset)],
327
+ "outlets": lambda task: [DatasetInfo(o) for o in task.outlets if isinstance(o, Dataset)],
269
328
  }
270
329
 
271
330
 
331
+ class TaskInfoComplete(TaskInfo):
332
+ """Defines encoding BaseOperator/AbstractOperator object to JSON used when user enables full task info."""
333
+
334
+ includes = []
335
+ excludes = [
336
+ "_BaseOperator__instantiated",
337
+ "_dag",
338
+ "_hook",
339
+ "_log",
340
+ "_outlets",
341
+ "_inlets",
342
+ "_lock_for_execution",
343
+ "handler",
344
+ "params",
345
+ "python_callable",
346
+ "retry_delay",
347
+ ]
348
+
349
+
272
350
  class TaskGroupInfo(InfoJsonEncodable):
273
351
  """Defines encoding TaskGroup object to JSON."""
274
352
 
@@ -285,25 +363,36 @@ class TaskGroupInfo(InfoJsonEncodable):
285
363
  ]
286
364
 
287
365
 
366
+ def get_airflow_dag_run_facet(dag_run: DagRun) -> dict[str, RunFacet]:
367
+ if not dag_run.dag:
368
+ return {}
369
+ return {
370
+ "airflowDagRun": AirflowDagRunFacet(
371
+ dag=DagInfo(dag_run.dag),
372
+ dagRun=DagRunInfo(dag_run),
373
+ )
374
+ }
375
+
376
+
288
377
  def get_airflow_run_facet(
289
378
  dag_run: DagRun,
290
379
  dag: DAG,
291
380
  task_instance: TaskInstance,
292
381
  task: BaseOperator,
293
382
  task_uuid: str,
294
- ) -> dict[str, BaseFacet]:
383
+ ) -> dict[str, AirflowRunFacet]:
295
384
  return {
296
385
  "airflow": AirflowRunFacet(
297
386
  dag=DagInfo(dag),
298
387
  dagRun=DagRunInfo(dag_run),
299
388
  taskInstance=TaskInstanceInfo(task_instance),
300
- task=TaskInfo(task),
389
+ task=TaskInfoComplete(task) if conf.include_full_task_info() else TaskInfo(task),
301
390
  taskUuid=task_uuid,
302
391
  )
303
392
  }
304
393
 
305
394
 
306
- def get_airflow_job_facet(dag_run: DagRun) -> dict[str, BaseFacet]:
395
+ def get_airflow_job_facet(dag_run: DagRun) -> dict[str, AirflowJobFacet]:
307
396
  if not dag_run.dag:
308
397
  return {}
309
398
  return {
@@ -315,7 +404,7 @@ def get_airflow_job_facet(dag_run: DagRun) -> dict[str, BaseFacet]:
315
404
  }
316
405
 
317
406
 
318
- def get_airflow_state_run_facet(dag_run: DagRun) -> dict[str, BaseFacet]:
407
+ def get_airflow_state_run_facet(dag_run: DagRun) -> dict[str, AirflowStateRunFacet]:
319
408
  return {
320
409
  "airflowState": AirflowStateRunFacet(
321
410
  dagRunState=dag_run.get_state(),
@@ -574,6 +663,34 @@ def normalize_sql(sql: str | Iterable[str]):
574
663
 
575
664
  def should_use_external_connection(hook) -> bool:
576
665
  # If we're at Airflow 2.10, the execution is process-isolated, so we can safely run those again.
577
- if not _IS_AIRFLOW_2_10_OR_HIGHER:
666
+ if not IS_AIRFLOW_2_10_OR_HIGHER:
578
667
  return hook.__class__.__name__ not in ["SnowflakeHook", "SnowflakeSqlApiHook", "RedshiftSQLHook"]
579
668
  return True
669
+
670
+
671
+ def translate_airflow_dataset(dataset: Dataset, lineage_context) -> OpenLineageDataset | None:
672
+ """
673
+ Convert a Dataset with an AIP-60 compliant URI to an OpenLineageDataset.
674
+
675
+ This function returns None if no URI normalizer is defined, no dataset converter is found or
676
+ some core Airflow changes are missing and ImportError is raised.
677
+ """
678
+ try:
679
+ from airflow.datasets import _get_normalized_scheme
680
+ from airflow.providers_manager import ProvidersManager
681
+
682
+ ol_converters = ProvidersManager().dataset_to_openlineage_converters
683
+ normalized_uri = dataset.normalized_uri
684
+ except (ImportError, AttributeError):
685
+ return None
686
+
687
+ if normalized_uri is None:
688
+ return None
689
+
690
+ if not (normalized_scheme := _get_normalized_scheme(normalized_uri)):
691
+ return None
692
+
693
+ if (airflow_to_ol_converter := ol_converters.get(normalized_scheme)) is None:
694
+ return None
695
+
696
+ return airflow_to_ol_converter(Dataset(uri=normalized_uri, extra=dataset.extra), lineage_context)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apache-airflow-providers-openlineage
3
- Version: 1.9.1
3
+ Version: 1.10.0
4
4
  Summary: Provider package apache-airflow-providers-openlineage for Apache Airflow
5
5
  Keywords: airflow-provider,openlineage,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
@@ -28,8 +28,8 @@ Requires-Dist: openlineage-integration-common>=1.16.0
28
28
  Requires-Dist: openlineage-python>=1.16.0
29
29
  Requires-Dist: apache-airflow-providers-common-sql ; extra == "common.sql"
30
30
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
31
- Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.9.1/changelog.html
32
- Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.9.1
31
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.10.0/changelog.html
32
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.10.0
33
33
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
34
  Project-URL: Source Code, https://github.com/apache/airflow
35
35
  Project-URL: Twitter, https://twitter.com/ApacheAirflow
@@ -80,7 +80,7 @@ Provides-Extra: common.sql
80
80
 
81
81
  Package ``apache-airflow-providers-openlineage``
82
82
 
83
- Release: ``1.9.1``
83
+ Release: ``1.10.0``
84
84
 
85
85
 
86
86
  `OpenLineage <https://openlineage.io/>`__
@@ -93,7 +93,7 @@ This is a provider package for ``openlineage`` provider. All classes for this pr
93
93
  are in ``airflow.providers.openlineage`` python package.
94
94
 
95
95
  You can find package information and changelog for the provider
96
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.9.1/>`_.
96
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.10.0/>`_.
97
97
 
98
98
  Installation
99
99
  ------------
@@ -137,4 +137,4 @@ Dependent package
137
137
  ============================================================================================================ ==============
138
138
 
139
139
  The changelog for the provider package can be found in the
140
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.9.1/changelog.html>`_.
140
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-openlineage/1.10.0/changelog.html>`_.
@@ -0,0 +1,29 @@
1
+ airflow/providers/openlineage/LICENSE,sha256=FFb4jd2AXnOOf7XLP04pQW6jbdhG49TxlGY6fFpCV1Y,13609
2
+ airflow/providers/openlineage/__init__.py,sha256=Zzf-0tKDYGhUI6kWk87QwKPT5SyjtGXripKvR-lSAak,1499
3
+ airflow/providers/openlineage/conf.py,sha256=GcAY4poIXvFyhV3FywQFcgghl_XuMEIoVJOl3a_jKTU,5004
4
+ airflow/providers/openlineage/get_provider_info.py,sha256=o02ioktk-8rLrEvtLx6pD7VfKLOn89iY8Ue9FPt5CDs,8359
5
+ airflow/providers/openlineage/sqlparser.py,sha256=c7q3VVw41S87ZFozrkrEr2oZK79N12mC3KdDs9V1IuM,15581
6
+ airflow/providers/openlineage/extractors/__init__.py,sha256=I0X4f6zUniclyD9zT0DFHRImpCpJVP4MkPJT3cd7X5I,1081
7
+ airflow/providers/openlineage/extractors/base.py,sha256=W08Bg6FCSIzB9VLrm2fZ-zW0TLqfsIoY12hcD3qOzMw,6622
8
+ airflow/providers/openlineage/extractors/bash.py,sha256=3aR0PXs8fzRLibRxXN1R8wMZnGzyCur7mjpy8e5GC4A,2583
9
+ airflow/providers/openlineage/extractors/manager.py,sha256=uuSGLZgJHu0tu3RGzrc41uw6SahdgU3816T26FtnFEY,10539
10
+ airflow/providers/openlineage/extractors/python.py,sha256=hVWOplMlBimrpPKPeW6vm75a8OmAYMU1oJzqMz8Jh90,3171
11
+ airflow/providers/openlineage/facets/AirflowDagRunFacet.json,sha256=ie6c-J3-wGgk80WDTGWePz18o6DbW--TNM7BMF4WfcU,2251
12
+ airflow/providers/openlineage/facets/AirflowJobFacet.json,sha256=rS9PuPWOi1Jc5B4a5qLxS_Az7Q9Eb3jVYQnN41iXDC0,1187
13
+ airflow/providers/openlineage/facets/AirflowRunFacet.json,sha256=70mEaZShgSJp-2xr0bVvw3ljiGOPEaXD591fhuAQm_o,5953
14
+ airflow/providers/openlineage/facets/AirflowStateRunFacet.json,sha256=xhHQEKD9Jopw-oqbkCCrrwFjfXnxvuJAritsmegKjuQ,937
15
+ airflow/providers/openlineage/facets/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
16
+ airflow/providers/openlineage/plugins/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
17
+ airflow/providers/openlineage/plugins/adapter.py,sha256=4yKPGipMjn-E--RqGhTBzFCdBQjgmF0iBF1lSnw1p58,19430
18
+ airflow/providers/openlineage/plugins/facets.py,sha256=1xeP1CCVSrVM_b_ehwlJ6JvW-0iZjYnbA73iWlif-4E,4500
19
+ airflow/providers/openlineage/plugins/listener.py,sha256=MIXyHd-ITvNKVE7cij_v04MBtszJ-YQoRVM8s2DY3Fg,18435
20
+ airflow/providers/openlineage/plugins/macros.py,sha256=hgFA3ZdQibyn4KXIOsKYBm4WRKDLA5q6Asscx5rvNfM,3076
21
+ airflow/providers/openlineage/plugins/openlineage.py,sha256=rsRUW_zpXVAglzsgQRv5T9VWYY7CMQl0qRWm8-3oqDA,1678
22
+ airflow/providers/openlineage/utils/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
23
+ airflow/providers/openlineage/utils/selective_enable.py,sha256=dFJ7wK7J_-BFwcOKp9tqFOSrASV3lmLv7HtRkEuMk3Q,3087
24
+ airflow/providers/openlineage/utils/sql.py,sha256=bnuU9WvjVKcWVMN3cUp0jaHtU5_ZRM5I1OP1WhIdztg,9583
25
+ airflow/providers/openlineage/utils/utils.py,sha256=O-jknMrWjzVvguCpBZERDfYny5wE6g6OepA3w9Bi0EQ,24557
26
+ apache_airflow_providers_openlineage-1.10.0.dist-info/entry_points.txt,sha256=GAx0_i2OeZzqaiiiYuA-xchICDXiCT5kVqpKSxsOjt4,214
27
+ apache_airflow_providers_openlineage-1.10.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
28
+ apache_airflow_providers_openlineage-1.10.0.dist-info/METADATA,sha256=MhYQXkf5WMvmYd2aZi4QqnvpfRRbeD4JD2rSSYWbldQ,6374
29
+ apache_airflow_providers_openlineage-1.10.0.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- airflow/providers/openlineage/LICENSE,sha256=FFb4jd2AXnOOf7XLP04pQW6jbdhG49TxlGY6fFpCV1Y,13609
2
- airflow/providers/openlineage/__init__.py,sha256=bDqRpjqfCE-UNXjjy8Ph6IFG8z5fdRrKJ9pOcX_nVuU,1498
3
- airflow/providers/openlineage/conf.py,sha256=ZHUZF3wjFGupfFa40F1DjZSkOQJCUtWFyQM3nvz6Bq4,5099
4
- airflow/providers/openlineage/get_provider_info.py,sha256=diZ2iRGa-47G5qbtylQ6gIXnN8rHXhTFmSK_mnJoaeE,7493
5
- airflow/providers/openlineage/sqlparser.py,sha256=qX2ID75PH11-youFvRdRHqZbYzLdbm95H3STvbBzGb8,15667
6
- airflow/providers/openlineage/extractors/__init__.py,sha256=I0X4f6zUniclyD9zT0DFHRImpCpJVP4MkPJT3cd7X5I,1081
7
- airflow/providers/openlineage/extractors/base.py,sha256=D-ll2cz_WWv1XYh2_UfzmpCl8S5iC2aptFTy2sWZeHY,5499
8
- airflow/providers/openlineage/extractors/bash.py,sha256=m4hLvDV4-zX4gp8apRuhpAR3Uakr8UOUxf-thTWmOxw,2563
9
- airflow/providers/openlineage/extractors/manager.py,sha256=9TyszMLAsgPS9NETWq7fPJjxcbTFk47x4kd1NRGCvsw,10315
10
- airflow/providers/openlineage/extractors/python.py,sha256=EQXCj2aHr2XXw0pNxeX-ii8UQFCoqkdf40ozqmA5d58,3151
11
- airflow/providers/openlineage/facets/AirflowJobFacet.json,sha256=rS9PuPWOi1Jc5B4a5qLxS_Az7Q9Eb3jVYQnN41iXDC0,1187
12
- airflow/providers/openlineage/facets/AirflowRunFacet.json,sha256=Mk85_KKwBOEcn_ptiQuoo9ucP-coAHfkAnilws2XMl4,5867
13
- airflow/providers/openlineage/facets/AirflowStateRunFacet.json,sha256=xhHQEKD9Jopw-oqbkCCrrwFjfXnxvuJAritsmegKjuQ,937
14
- airflow/providers/openlineage/facets/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
15
- airflow/providers/openlineage/plugins/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
16
- airflow/providers/openlineage/plugins/adapter.py,sha256=s0-eQw7cqzlUbznHdnLWihmdLKczHjuDj1TYYmJSK04,18720
17
- airflow/providers/openlineage/plugins/facets.py,sha256=kNxxnibLurcv8SV0qXPkwXxpKWhByo745vcqzWGNMIs,4450
18
- airflow/providers/openlineage/plugins/listener.py,sha256=q6r63SS3ZKdZKyTlEhw8c12onHh7kQCQ-_G1kA67btw,17952
19
- airflow/providers/openlineage/plugins/macros.py,sha256=hgFA3ZdQibyn4KXIOsKYBm4WRKDLA5q6Asscx5rvNfM,3076
20
- airflow/providers/openlineage/plugins/openlineage.py,sha256=rsRUW_zpXVAglzsgQRv5T9VWYY7CMQl0qRWm8-3oqDA,1678
21
- airflow/providers/openlineage/utils/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
22
- airflow/providers/openlineage/utils/selective_enable.py,sha256=dFJ7wK7J_-BFwcOKp9tqFOSrASV3lmLv7HtRkEuMk3Q,3087
23
- airflow/providers/openlineage/utils/sql.py,sha256=5K3qFhevq-R4CDUZbq-XfFKPLWixIOtaypRem3jiHvw,9534
24
- airflow/providers/openlineage/utils/utils.py,sha256=cmPynb5QqZRV6Wzya-6cEcJUrCZjYm-4r4Z6NxwMzCc,19962
25
- apache_airflow_providers_openlineage-1.9.1.dist-info/entry_points.txt,sha256=GAx0_i2OeZzqaiiiYuA-xchICDXiCT5kVqpKSxsOjt4,214
26
- apache_airflow_providers_openlineage-1.9.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
27
- apache_airflow_providers_openlineage-1.9.1.dist-info/METADATA,sha256=naW8pSs4fWp5BmV8wo5dbJa3buwt3uWWObAVfB0NMMg,6368
28
- apache_airflow_providers_openlineage-1.9.1.dist-info/RECORD,,