airflow-dbt-python 2.1.0__tar.gz → 2.2.0__tar.gz
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.
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/PKG-INFO +12 -18
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/README.md +2 -2
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/__version__.py +1 -1
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/dbt.py +1 -9
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/configs.py +45 -79
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/url.py +3 -3
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/version.py +5 -6
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/pyproject.toml +23 -23
- airflow_dbt_python-2.1.0/setup.py +0 -51
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/LICENSE +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/__init__.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/__init__.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/git.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/localfs.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/remote.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/hooks/s3.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/operators/__init__.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/operators/dbt.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/__init__.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/enums.py +0 -0
- {airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/utils/env.py +0 -0
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: airflow-dbt-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: A collection of Airflow operators, hooks, and utilities to execute dbt commands
|
|
5
|
-
Home-page: https://github.com/tomasfarias/airflow-dbt-python
|
|
6
5
|
License: MIT
|
|
7
6
|
Author: Tomás Farías Santana
|
|
8
7
|
Author-email: tomas@tomasfarias.dev
|
|
9
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.9,<3.13
|
|
10
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
10
|
Classifier: Intended Audience :: Developers
|
|
12
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
12
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
23
17
|
Provides-Extra: adapters
|
|
24
18
|
Provides-Extra: airflow-providers
|
|
25
19
|
Provides-Extra: bigquery
|
|
@@ -30,17 +24,17 @@ Provides-Extra: redshift
|
|
|
30
24
|
Provides-Extra: s3
|
|
31
25
|
Provides-Extra: snowflake
|
|
32
26
|
Provides-Extra: spark
|
|
33
|
-
Requires-Dist: apache-airflow (>=2.
|
|
27
|
+
Requires-Dist: apache-airflow (>=2.8)
|
|
34
28
|
Requires-Dist: apache-airflow-providers-amazon (>=3.0.0) ; extra == "airflow-providers" or extra == "s3"
|
|
35
29
|
Requires-Dist: apache-airflow-providers-ssh (>=3.0.0) ; extra == "airflow-providers" or extra == "git"
|
|
36
30
|
Requires-Dist: connexion (<3.0)
|
|
37
31
|
Requires-Dist: contextlib-chdir (==1.0.2) ; python_version < "3.11"
|
|
38
|
-
Requires-Dist: dbt-bigquery (>=1.
|
|
39
|
-
Requires-Dist: dbt-core (>=1.
|
|
40
|
-
Requires-Dist: dbt-postgres (>=1.
|
|
41
|
-
Requires-Dist: dbt-redshift (>=1.
|
|
42
|
-
Requires-Dist: dbt-snowflake (>=1.
|
|
43
|
-
Requires-Dist: dbt-spark (>=1.
|
|
32
|
+
Requires-Dist: dbt-bigquery (>=1.8.0,<2.0.0) ; extra == "adapters" or extra == "bigquery"
|
|
33
|
+
Requires-Dist: dbt-core (>=1.8.0,<2.0.0)
|
|
34
|
+
Requires-Dist: dbt-postgres (>=1.8.0,<2.0.0) ; extra == "adapters" or extra == "postgres"
|
|
35
|
+
Requires-Dist: dbt-redshift (>=1.8.0,<2.0.0) ; extra == "adapters" or extra == "redshift"
|
|
36
|
+
Requires-Dist: dbt-snowflake (>=1.8.0,<2.0.0) ; extra == "adapters" or extra == "snowflake"
|
|
37
|
+
Requires-Dist: dbt-spark (>=1.8.0,<2.0.0) ; extra == "adapters" or extra == "spark"
|
|
44
38
|
Requires-Dist: dulwich (>=0.21) ; extra == "git"
|
|
45
39
|
Project-URL: Repository, https://github.com/tomasfarias/airflow-dbt-python
|
|
46
40
|
Description-Content-Type: text/markdown
|
|
@@ -62,8 +56,8 @@ Read the [documentation](https://airflow-dbt-python.readthedocs.io) for examples
|
|
|
62
56
|
## Requirements
|
|
63
57
|
|
|
64
58
|
Before using *airflow-dbt-python*, ensure you meet the following requirements:
|
|
65
|
-
* A *dbt* project using [dbt-core](https://pypi.org/project/dbt-core/) version 1.
|
|
66
|
-
* An Airflow environment using version 2.
|
|
59
|
+
* A *dbt* project using [dbt-core](https://pypi.org/project/dbt-core/) version 1.8 or later.
|
|
60
|
+
* An Airflow environment using version 2.8 or later.
|
|
67
61
|
|
|
68
62
|
* If using any managed service, like AWS MWAA or GCP Cloud Composer 2/3, ensure your environment is created with a supported version of Airflow.
|
|
69
63
|
* If self-hosting, Airflow installation instructions can be found in their [official documentation](https://airflow.apache.org/docs/apache-airflow/stable/installation/index.html).
|
|
@@ -15,8 +15,8 @@ Read the [documentation](https://airflow-dbt-python.readthedocs.io) for examples
|
|
|
15
15
|
## Requirements
|
|
16
16
|
|
|
17
17
|
Before using *airflow-dbt-python*, ensure you meet the following requirements:
|
|
18
|
-
* A *dbt* project using [dbt-core](https://pypi.org/project/dbt-core/) version 1.
|
|
19
|
-
* An Airflow environment using version 2.
|
|
18
|
+
* A *dbt* project using [dbt-core](https://pypi.org/project/dbt-core/) version 1.8 or later.
|
|
19
|
+
* An Airflow environment using version 2.8 or later.
|
|
20
20
|
|
|
21
21
|
* If using any managed service, like AWS MWAA or GCP Cloud Composer 2/3, ensure your environment is created with a supported version of Airflow.
|
|
22
22
|
* If self-hosting, Airflow installation instructions can be found in their [official documentation](https://airflow.apache.org/docs/apache-airflow/stable/installation/index.html).
|
|
@@ -25,8 +25,6 @@ from airflow.exceptions import AirflowException
|
|
|
25
25
|
from airflow.hooks.base import BaseHook
|
|
26
26
|
from airflow.models.connection import Connection
|
|
27
27
|
|
|
28
|
-
from airflow_dbt_python.utils.version import DBT_INSTALLED_GTE_1_8
|
|
29
|
-
|
|
30
28
|
if sys.version_info >= (3, 11):
|
|
31
29
|
from contextlib import chdir as chdir_ctx
|
|
32
30
|
else:
|
|
@@ -400,13 +398,7 @@ class DbtHook(BaseHook):
|
|
|
400
398
|
default_stdout. As these are initialized by the CLI app, we need to
|
|
401
399
|
initialize them here.
|
|
402
400
|
"""
|
|
403
|
-
|
|
404
|
-
from dbt.events.logging import setup_event_logger
|
|
405
|
-
else:
|
|
406
|
-
from dbt.events.functions import ( # type: ignore[no-redef]
|
|
407
|
-
setup_event_logger,
|
|
408
|
-
)
|
|
409
|
-
|
|
401
|
+
from dbt.events.logging import setup_event_logger
|
|
410
402
|
from dbt.flags import get_flags
|
|
411
403
|
|
|
412
404
|
flags = get_flags()
|
|
@@ -11,7 +11,7 @@ from typing import Any, Optional, Type, Union
|
|
|
11
11
|
|
|
12
12
|
import dbt.flags as flags
|
|
13
13
|
import yaml
|
|
14
|
-
from dbt.
|
|
14
|
+
from dbt.cli.option_types import Package
|
|
15
15
|
from dbt.clients import yaml_helper # type: ignore
|
|
16
16
|
from dbt.config.profile import Profile, read_profile
|
|
17
17
|
from dbt.config.project import PartialProject, Project
|
|
@@ -20,13 +20,14 @@ from dbt.config.runtime import RuntimeConfig
|
|
|
20
20
|
from dbt.contracts.graph.manifest import Manifest
|
|
21
21
|
from dbt.exceptions import DbtProjectError
|
|
22
22
|
from dbt.graph.graph import Graph
|
|
23
|
-
from dbt.parser.manifest import
|
|
23
|
+
from dbt.parser.manifest import parse_manifest
|
|
24
24
|
from dbt.task.base import BaseTask, ConfiguredTask
|
|
25
25
|
from dbt.task.build import BuildTask
|
|
26
26
|
from dbt.task.clean import CleanTask
|
|
27
27
|
from dbt.task.compile import CompileTask
|
|
28
28
|
from dbt.task.debug import DebugTask
|
|
29
29
|
from dbt.task.deps import DepsTask
|
|
30
|
+
from dbt.task.docs.generate import GenerateTask
|
|
30
31
|
from dbt.task.freshness import FreshnessTask
|
|
31
32
|
from dbt.task.list import ListTask
|
|
32
33
|
from dbt.task.run import RunTask
|
|
@@ -38,15 +39,7 @@ from dbt.task.test import TestTask
|
|
|
38
39
|
from dbt.tracking import initialize_from_flags
|
|
39
40
|
|
|
40
41
|
from airflow_dbt_python.utils.enums import FromStrEnum, LogFormat, Output
|
|
41
|
-
from airflow_dbt_python.utils.version import
|
|
42
|
-
DBT_INSTALLED_GTE_1_7,
|
|
43
|
-
DBT_INSTALLED_GTE_1_8,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
if DBT_INSTALLED_GTE_1_8:
|
|
47
|
-
from dbt.task.docs.generate import GenerateTask
|
|
48
|
-
else:
|
|
49
|
-
from dbt.task.generate import GenerateTask # type: ignore[no-redef]
|
|
42
|
+
from airflow_dbt_python.utils.version import DBT_INSTALLED_GTE_1_9
|
|
50
43
|
|
|
51
44
|
|
|
52
45
|
def parse_yaml_args(args: Optional[Union[str, dict[str, Any]]]) -> dict[str, Any]:
|
|
@@ -139,34 +132,27 @@ class BaseConfig:
|
|
|
139
132
|
default=None, repr=False
|
|
140
133
|
)
|
|
141
134
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
from dbt.cli.option_types import Package
|
|
145
|
-
|
|
146
|
-
include_saved_query: Optional[bool] = None
|
|
147
|
-
no_include_saved_query: Optional[bool] = dataclasses.field(
|
|
148
|
-
default=None, repr=False
|
|
149
|
-
)
|
|
135
|
+
include_saved_query: Optional[bool] = None
|
|
136
|
+
no_include_saved_query: Optional[bool] = dataclasses.field(default=None, repr=False)
|
|
150
137
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
138
|
+
clean_project_files_only: Optional[bool] = None
|
|
139
|
+
no_clean_project_files_only: Optional[bool] = dataclasses.field(
|
|
140
|
+
default=None, repr=False
|
|
141
|
+
)
|
|
155
142
|
|
|
156
|
-
|
|
143
|
+
require_resource_names_without_spaces: bool = False
|
|
157
144
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
145
|
+
add_package: Optional[Package] = None
|
|
146
|
+
dry_run: bool = False
|
|
147
|
+
lock: bool = False
|
|
148
|
+
static: bool = False
|
|
149
|
+
upgrade: bool = False
|
|
163
150
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
)
|
|
151
|
+
require_model_names_without_spaces: bool = False
|
|
152
|
+
source_freshness_run_project_hooks: bool = False
|
|
153
|
+
exclude_resource_types: list[str] = dataclasses.field(
|
|
154
|
+
default_factory=list, repr=False
|
|
155
|
+
)
|
|
170
156
|
|
|
171
157
|
def __post_init__(self):
|
|
172
158
|
"""Post initialization actions for a dbt configuration."""
|
|
@@ -318,53 +304,33 @@ class BaseConfig:
|
|
|
318
304
|
flags.set_from_args(self, {}) # type: ignore
|
|
319
305
|
project, profile = self.create_dbt_project_and_profile(extra_targets)
|
|
320
306
|
|
|
321
|
-
|
|
307
|
+
if not DBT_INSTALLED_GTE_1_9:
|
|
308
|
+
self.cls.set_log_format() # type: ignore[attr-defined]
|
|
309
|
+
|
|
322
310
|
initialize_from_flags(self.send_anonymous_usage_stats, self.profiles_dir)
|
|
323
311
|
|
|
324
312
|
local_flags = flags.get_flags()
|
|
325
313
|
|
|
326
314
|
runtime_config = self.create_runtime_config(project, profile)
|
|
327
315
|
|
|
328
|
-
if
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
task = self.dbt_task(args=local_flags, config=project)
|
|
345
|
-
else:
|
|
346
|
-
task = self.dbt_task(args=local_flags)
|
|
316
|
+
if issubclass(self.dbt_task, ConfiguredTask) and runtime_config:
|
|
317
|
+
manifest = parse_manifest(
|
|
318
|
+
runtime_config,
|
|
319
|
+
write_perf_info=write_perf_info,
|
|
320
|
+
write=False,
|
|
321
|
+
write_json=False,
|
|
322
|
+
)
|
|
323
|
+
task: BaseTask = self.dbt_task(
|
|
324
|
+
args=local_flags, config=runtime_config, manifest=manifest
|
|
325
|
+
)
|
|
326
|
+
elif issubclass(self.dbt_task, DepsTask):
|
|
327
|
+
task = self.dbt_task(args=local_flags, project=project)
|
|
328
|
+
elif issubclass(self.dbt_task, DebugTask):
|
|
329
|
+
task = self.dbt_task(args=local_flags)
|
|
330
|
+
elif issubclass(self.dbt_task, CleanTask):
|
|
331
|
+
task = self.dbt_task(args=local_flags, config=project)
|
|
347
332
|
else:
|
|
348
|
-
|
|
349
|
-
register_adapter(runtime_config) # type: ignore[call-arg]
|
|
350
|
-
manifest = ManifestLoader.get_full_manifest(
|
|
351
|
-
runtime_config, write_perf_info=write_perf_info
|
|
352
|
-
)
|
|
353
|
-
task = self.dbt_task(
|
|
354
|
-
args=self, # type: ignore[arg-type]
|
|
355
|
-
config=runtime_config,
|
|
356
|
-
manifest=manifest,
|
|
357
|
-
)
|
|
358
|
-
elif issubclass(self.dbt_task, DepsTask):
|
|
359
|
-
task = self.dbt_task(args=self, project=project)
|
|
360
|
-
elif issubclass(self.dbt_task, DebugTask):
|
|
361
|
-
task = self.dbt_task(args=self, config=runtime_config) # type: ignore[arg-type,call-arg]
|
|
362
|
-
else:
|
|
363
|
-
task = self.dbt_task( # type: ignore[call-arg]
|
|
364
|
-
args=self, # type: ignore[arg-type]
|
|
365
|
-
config=runtime_config,
|
|
366
|
-
project=project,
|
|
367
|
-
)
|
|
333
|
+
task = self.dbt_task(args=local_flags)
|
|
368
334
|
|
|
369
335
|
if self.compiled_target is not None:
|
|
370
336
|
# Only supported by subclasses of dbt's GraphRunnableTask.
|
|
@@ -473,11 +439,10 @@ class BaseConfig:
|
|
|
473
439
|
Returns:
|
|
474
440
|
A dbt profile for the task represented by this configuration.
|
|
475
441
|
"""
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
from dbt_common.context import set_invocation_context
|
|
442
|
+
from dbt_common.clients.system import get_env
|
|
443
|
+
from dbt_common.context import set_invocation_context
|
|
479
444
|
|
|
480
|
-
|
|
445
|
+
set_invocation_context(get_env())
|
|
481
446
|
|
|
482
447
|
if self.profiles_dir is not None:
|
|
483
448
|
raw_profiles = read_profile(self.profiles_dir)
|
|
@@ -695,6 +660,7 @@ class TestTaskConfig(SelectionConfig):
|
|
|
695
660
|
singular: Optional[bool] = None
|
|
696
661
|
store_failures: Optional[bool] = None
|
|
697
662
|
which: str = dataclasses.field(default="test", init=False)
|
|
663
|
+
resource_types: Optional[list[str]] = None
|
|
698
664
|
|
|
699
665
|
def __post_init__(self):
|
|
700
666
|
"""Support for type casting arguments."""
|
|
@@ -465,7 +465,7 @@ def tar_dir_from_url(url: URL, tar_url: URL) -> None:
|
|
|
465
465
|
except IndexError:
|
|
466
466
|
compression = ""
|
|
467
467
|
|
|
468
|
-
with tarfile.open(tar_url, f"w:{compression}") as tf:
|
|
468
|
+
with tarfile.open(tar_url, f"w:{compression}") as tf: # type: ignore[call-overload]
|
|
469
469
|
for _file in url:
|
|
470
470
|
tf.add(_file)
|
|
471
471
|
|
|
@@ -473,6 +473,6 @@ def tar_dir_from_url(url: URL, tar_url: URL) -> None:
|
|
|
473
473
|
if __name__ == "__main__":
|
|
474
474
|
import doctest
|
|
475
475
|
|
|
476
|
-
import airflow_dbt_python.utils.url as
|
|
476
|
+
import airflow_dbt_python.utils.url as url_utils
|
|
477
477
|
|
|
478
|
-
doctest.testmod(
|
|
478
|
+
doctest.testmod(url_utils)
|
|
@@ -10,18 +10,17 @@ except ImportError:
|
|
|
10
10
|
|
|
11
11
|
from dbt.version import installed
|
|
12
12
|
|
|
13
|
-
DBT_1_7 = VersionSpecifier(
|
|
14
|
-
major="1", minor="7", patch="0", matcher=Matchers.GREATER_THAN_OR_EQUAL
|
|
15
|
-
)
|
|
16
13
|
DBT_1_8 = VersionSpecifier(
|
|
17
14
|
major="1", minor="8", patch="0", matcher=Matchers.GREATER_THAN_OR_EQUAL
|
|
18
15
|
)
|
|
19
16
|
DBT_1_9 = VersionSpecifier(
|
|
20
17
|
major="1", minor="9", patch="0", matcher=Matchers.GREATER_THAN_OR_EQUAL
|
|
21
18
|
)
|
|
19
|
+
DBT_2_0 = VersionSpecifier(
|
|
20
|
+
major="2", minor="0", patch="0", matcher=Matchers.GREATER_THAN_OR_EQUAL
|
|
21
|
+
)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
DBT_INSTALLED_GTE_1_8 = installed.compare(DBT_1_8) == 1
|
|
23
|
+
DBT_INSTALLED_GTE_1_9 = installed.compare(DBT_1_9) == 1
|
|
25
24
|
|
|
26
|
-
DBT_INSTALLED_1_7 = DBT_1_7 < installed < DBT_1_8
|
|
27
25
|
DBT_INSTALLED_1_8 = DBT_1_8 < installed < DBT_1_9
|
|
26
|
+
DBT_INSTALLED_1_9 = DBT_1_9 < installed < DBT_2_0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "airflow-dbt-python"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
4
4
|
description = "A collection of Airflow operators, hooks, and utilities to execute dbt commands"
|
|
5
5
|
authors = ["Tomás Farías Santana <tomas@tomasfarias.dev>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -13,29 +13,31 @@ classifiers = [
|
|
|
13
13
|
|
|
14
14
|
"License :: OSI Approved :: MIT License",
|
|
15
15
|
|
|
16
|
-
"Programming Language :: Python :: 3.8",
|
|
17
16
|
"Programming Language :: Python :: 3.9",
|
|
18
17
|
"Programming Language :: Python :: 3.10",
|
|
19
18
|
"Programming Language :: Python :: 3.11",
|
|
20
19
|
"Programming Language :: Python :: 3.12",
|
|
21
20
|
]
|
|
22
21
|
|
|
22
|
+
[tool.poetry.requires-plugins]
|
|
23
|
+
poetry-plugin-export = ">=1.8"
|
|
24
|
+
|
|
23
25
|
[tool.poetry.dependencies]
|
|
24
|
-
python = ">=3.
|
|
26
|
+
python = ">=3.9,<3.13" # Airflow providers require this upper boundary
|
|
25
27
|
|
|
26
|
-
apache-airflow = { version = ">=2.
|
|
28
|
+
apache-airflow = { version = ">=2.8" }
|
|
27
29
|
apache-airflow-providers-amazon = { version = ">=3.0.0", optional = true }
|
|
28
30
|
apache-airflow-providers-ssh = { version = ">=3.0.0", optional = true }
|
|
29
31
|
connexion = { version = "<3.0" } # https://github.com/apache/airflow/issues/35217
|
|
30
32
|
dulwich = { version = ">=0.21", optional = true }
|
|
31
33
|
contextlib-chdir = { version = "==1.0.2", python = "<3.11" }
|
|
32
34
|
|
|
33
|
-
dbt-core = { version = ">=1.
|
|
34
|
-
dbt-bigquery = { version = ">=1.
|
|
35
|
-
dbt-postgres = { version = ">=1.
|
|
36
|
-
dbt-redshift = { version = ">=1.
|
|
37
|
-
dbt-snowflake = { version = ">=1.
|
|
38
|
-
dbt-spark = { version = ">=1.
|
|
35
|
+
dbt-core = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
36
|
+
dbt-bigquery = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
37
|
+
dbt-postgres = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
38
|
+
dbt-redshift = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
39
|
+
dbt-snowflake = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
40
|
+
dbt-spark = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
39
41
|
|
|
40
42
|
[tool.poetry.group.dev]
|
|
41
43
|
optional = true
|
|
@@ -53,7 +55,6 @@ moto = ">=4.0.3"
|
|
|
53
55
|
mypy = ">=1"
|
|
54
56
|
freezegun = ">=1.1.0"
|
|
55
57
|
pre-commit = ">=2.18"
|
|
56
|
-
psycopg = ">=3.0"
|
|
57
58
|
pytest = ">=7.2"
|
|
58
59
|
pytest-postgresql = ">=5"
|
|
59
60
|
ruff = ">=0.0.254"
|
|
@@ -65,23 +66,22 @@ optional = true
|
|
|
65
66
|
|
|
66
67
|
[tool.poetry.group.docs.dependencies]
|
|
67
68
|
Sphinx = [
|
|
68
|
-
{ python = "
|
|
69
|
-
{ python = ">=3.8,<3.9", version = "<7.2" },
|
|
70
|
-
{ python = ">=3.9", version = ">=7.2" },
|
|
69
|
+
{ python = ">=3.9", version = "7.4.7" },
|
|
71
70
|
]
|
|
72
|
-
sphinx-rtd-theme = "
|
|
73
|
-
sphinx-copybutton = "
|
|
71
|
+
sphinx-rtd-theme = "3.0.2"
|
|
72
|
+
sphinx-copybutton = "0.5.2"
|
|
74
73
|
attrs = ">=22"
|
|
74
|
+
zipp = ">=3.19.1"
|
|
75
75
|
|
|
76
76
|
[tool.poetry.group.adapters]
|
|
77
77
|
optional = true
|
|
78
78
|
|
|
79
79
|
[tool.poetry.group.adapters.dependencies]
|
|
80
|
-
dbt-bigquery = { version = ">=1.
|
|
81
|
-
dbt-postgres = { version = ">=1.
|
|
82
|
-
dbt-redshift = { version = ">=1.
|
|
83
|
-
dbt-snowflake = { version = ">=1.
|
|
84
|
-
dbt-spark = { version = ">=1.
|
|
80
|
+
dbt-bigquery = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
81
|
+
dbt-postgres = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
82
|
+
dbt-redshift = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
83
|
+
dbt-snowflake = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
84
|
+
dbt-spark = { version = ">=1.8.0,<2.0.0", optional = true }
|
|
85
85
|
|
|
86
86
|
[tool.poetry.extras]
|
|
87
87
|
airflow-providers = ["apache-airflow-providers-amazon", "apache-airflow-providers-ssh"]
|
|
@@ -101,7 +101,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
101
101
|
|
|
102
102
|
[tool.black]
|
|
103
103
|
line-length = 88
|
|
104
|
-
target-version = ["
|
|
104
|
+
target-version = ["py39", "py310", "py311", "py312"]
|
|
105
105
|
include = '\.pyi?$'
|
|
106
106
|
exclude = '''
|
|
107
107
|
/(
|
|
@@ -151,7 +151,7 @@ markers = [
|
|
|
151
151
|
|
|
152
152
|
[tool.ruff]
|
|
153
153
|
line-length = 88
|
|
154
|
-
target-version = "
|
|
154
|
+
target-version = "py39"
|
|
155
155
|
exclude = [
|
|
156
156
|
".bzr",
|
|
157
157
|
".direnv",
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['airflow_dbt_python',
|
|
6
|
-
'airflow_dbt_python.hooks',
|
|
7
|
-
'airflow_dbt_python.operators',
|
|
8
|
-
'airflow_dbt_python.utils']
|
|
9
|
-
|
|
10
|
-
package_data = \
|
|
11
|
-
{'': ['*']}
|
|
12
|
-
|
|
13
|
-
install_requires = \
|
|
14
|
-
['apache-airflow>=2.7', 'connexion<3.0']
|
|
15
|
-
|
|
16
|
-
extras_require = \
|
|
17
|
-
{':python_version < "3.11"': ['contextlib-chdir==1.0.2'],
|
|
18
|
-
'adapters': ['dbt-bigquery>=1.7.0,<1.9.0',
|
|
19
|
-
'dbt-postgres>=1.7.0,<1.9.0',
|
|
20
|
-
'dbt-redshift>=1.7.0,<1.9.0',
|
|
21
|
-
'dbt-snowflake>=1.7.0,<1.9.0',
|
|
22
|
-
'dbt-spark>=1.7.0,<1.9.0'],
|
|
23
|
-
'airflow-providers': ['apache-airflow-providers-amazon>=3.0.0',
|
|
24
|
-
'apache-airflow-providers-ssh>=3.0.0'],
|
|
25
|
-
'bigquery': ['dbt-bigquery>=1.7.0,<1.9.0'],
|
|
26
|
-
'git': ['apache-airflow-providers-ssh>=3.0.0', 'dulwich>=0.21'],
|
|
27
|
-
'postgres': ['dbt-postgres>=1.7.0,<1.9.0'],
|
|
28
|
-
'redshift': ['dbt-redshift>=1.7.0,<1.9.0'],
|
|
29
|
-
's3': ['apache-airflow-providers-amazon>=3.0.0'],
|
|
30
|
-
'snowflake': ['dbt-snowflake>=1.7.0,<1.9.0'],
|
|
31
|
-
'spark': ['dbt-spark>=1.7.0,<1.9.0']}
|
|
32
|
-
|
|
33
|
-
setup_kwargs = {
|
|
34
|
-
'name': 'airflow-dbt-python',
|
|
35
|
-
'version': '2.1.0',
|
|
36
|
-
'description': 'A collection of Airflow operators, hooks, and utilities to execute dbt commands',
|
|
37
|
-
'long_description': '# airflow-dbt-python\n\n[](https://pypi.org/project/airflow-dbt-python/)\n[](https://github.com/tomasfarias/airflow-dbt-python/actions)\n[](https://github.com/psf/black)\n[](https://github.com/tomasfarias/airflow-dbt-python/actions)\n[](https://airflow-dbt-python.readthedocs.io/en/latest/?badge=latest)\n\nA collection of [Airflow](https://airflow.apache.org/) operators, hooks, and utilities to execute [`dbt`](https://pypi.org/project/dbt-core/) commands.\n\nRead the [documentation](https://airflow-dbt-python.readthedocs.io) for examples, installation instructions, and more details.\n\n# Installation\n\n## Requirements\n\nBefore using *airflow-dbt-python*, ensure you meet the following requirements:\n* A *dbt* project using [dbt-core](https://pypi.org/project/dbt-core/) version 1.7.5 or later.\n* An Airflow environment using version 2.7 or later.\n\n * If using any managed service, like AWS MWAA or GCP Cloud Composer 2/3, ensure your environment is created with a supported version of Airflow.\n * If self-hosting, Airflow installation instructions can be found in their [official documentation](https://airflow.apache.org/docs/apache-airflow/stable/installation/index.html).\n\n* Running Python 3.8 or later in your Airflow environment.\n\n> **Warning**\n>\n> Even though we don\'t impose any upper limits on versions of Airflow and *dbt*, it\'s possible that new versions are not supported immediately after release, particularly for *dbt*. We recommend testing the latest versions before upgrading and [reporting any issues](https://github.com/tomasfarias/airflow-dbt-python/issues/new/choose).\n\n> **Note**\n>\n> Older versions of Airflow and *dbt* may work with *airflow-dbt-python*, although we cannot guarantee this. Our testing pipeline runs the latest *dbt-core* with the latest Airflow release, and the latest version supported by [AWS MWAA](https://aws.amazon.com/managed-workflows-for-apache-airflow/) and [GCP Cloud Composer 2/3](https://aws.amazon.com/managed-workflows-for-apache-airflow/).\n\n## From PyPI\n\n*airflow-dbt-python* is available in [PyPI](https://pypi.org/project/airflow-dbt-python/) and can be installed with *pip*:\n\n``` shell\npip install airflow-dbt-python\n```\n\nAs a convenience, some *dbt* adapters can be installed by specifying extras. For example, if requiring the *dbt-redshift* adapter:\n\n``` shell\npip install airflow-dbt-python[redshift]\n```\n\n## From this repo\n\n*airflow-dbt-python* can also be built from source by cloning this GitHub repository:\n\n``` shell\ngit clone https://github.com/tomasfarias/airflow-dbt-python.git\ncd airflow-dbt-python\n```\n\nAnd installing with *Poetry*:\n\n``` shell\npoetry install\n```\n\n## In AWS MWAA\n\nAdd *airflow-dbt-python* to your `requirements.txt` file and edit your Airflow environment to use this new `requirements.txt` file, or upload it as a plugin.\n\nRead the [documentation](https://airflow-dbt-python.readthedocs.io/en/latest/getting_started.html#installing-in-mwaa) for more a more detailed AWS MWAA installation breakdown.\n\n## In GCP Cloud Composer\n\nAdd *airflow-dbt-python* to your PyPI packages list.\n\nRead the [documentation](https://cloud.google.com/composer/docs/composer-2/install-python-dependencies#install-pypi) for more a more detailed GCP Cloud Composer 2 installation breakdown.\n\n## In other managed services\n\n*airflow-dbt-python* should be compatible with most or all Airflow managed services. Consult the documentation specific to your provider.\n\nIf you notice an issue when installing *airflow-dbt-python* in a specific managed service, please open an [issue](https://github.com/tomasfarias/airflow-dbt-python/issues/new/choose).\n\n# Features\n\n*airflow-dbt-python* aims to make dbt a **first-class citizen** of Airflow by supporting additional features that integrate both tools. As you would expect, *airflow-dbt-python* can run all your dbt workflows in Airflow with the same interface you are used to from the CLI, but without being a mere wrapper: *airflow-dbt-python* directly communicates with internal *dbt-core* classes, bridging the gap between them and Airflow\'s operator interface. Essentially, we are attempting to use *dbt* **as a library**.\n\nAs this integration was completed, several features were developed to **extend the capabilities of dbt** to leverage Airflow as much as possible. Can you think of a way *dbt* could leverage Airflow that is not currently supported? Let us know in a [GitHub issue](https://github.com/tomasfarias/airflow-dbt-python/issues/new/choose)!\n\n## Independent task execution\n\nAirflow executes [Tasks](https://airflow.apache.org/docs/apache-airflow/stable/concepts/tasks.html) independent of one another: even though downstream and upstream dependencies between tasks exist, the execution of an individual task happens entirely independently of any other task execution (see: [Tasks Relationships](https://airflow.apache.org/docs/apache-airflow/stable/concepts/tasks.html#relationships)).\n\nIn order to work with this constraint, *airflow-dbt-python* runs each dbt command in a **temporary and isolated directory**. Before execution, all the relevant dbt files are copied from supported backends, and after executing the command any artifacts are exported. This ensures dbt can work with any Airflow deployment, including most production deployments as they are usually running [Remote Executors](https://airflow.apache.org/docs/apache-airflow/stable/executor/index.html#executor-types) and do not guarantee any files will be shared by default between tasks, since each task may run in a completely different environment.\n\n\n## Download dbt files from a remote storage\n\nThe dbt parameters `profiles_dir` and `project_dir` would normally point to a directory containing a `profiles.yml` file and a dbt project in the local environment respectively (defined by the presence of a *dbt_project.yml* file). *airflow-dbt-python* extends these parameters to also accept an URL pointing to a remote storage.\n\nCurrently, we support the following remote storages:\n\n* [AWS S3](https://aws.amazon.com/s3/) (identified by a *s3* scheme).\n* Remote git repositories, like those stored in GitHub (both *https* and *ssh* schemes are supported).\n\n* If a remote URL is used for `project_dir`, then this URL must point to a location in your remote storage containing a *dbt* project to run. A *dbt* project is identified by the prescence of a *dbt_project.yml*, and contains all your [resources](https://docs.getdbt.com/docs/build/projects). All of the contents of this remote location will be downloaded and made available for the operator. The URL may also point to an archived file containing all the files of a dbt project, which will be downloaded, uncompressed, and made available for the operator.\n* If a remote URL is used for `profiles_dir`, then this URL must point to a location in your remote storage that contains a *profiles.yml* file. The *profiles.yml* file will be downloaded and made available for the operator to use when running. The *profiles.yml* may be part of your *dbt* project, in which case this argument may be ommitted.\n\nThis feature is intended to work in line with Airflow\'s [description of the task concept](https://airflow.apache.org/docs/apache-airflow/stable/concepts/tasks.html#relationships):\n\n> Tasks don’t pass information to each other by default, and run entirely independently.\n\nWe interpret this as meaning a task should be responsible of fetching all the *dbt* related files it needs in order to run independently, as already described in [Independent Task Execution](#independent-task-execution).\n\n## Push dbt artifacts to XCom\n\nEach dbt execution produces one or more [JSON artifacts](https://docs.getdbt.com/reference/artifacts/dbt-artifacts/) that are valuable to produce meta-metrics, build conditional workflows, for reporting purposes, and other uses. *airflow-dbt-python* can push these artifacts to [XCom](https://airflow.apache.org/docs/apache-airflow/stable/concepts/xcoms.html) as requested via the `do_xcom_push_artifacts` parameter, which takes a list of artifacts to push.\n\n## Use Airflow connections as dbt targets (without a profiles.yml)\n\n[Airflow connections](https://airflow.apache.org/docs/apache-airflow/stable/howto/connection.html) allow users to manage and store connection information, such as hostname, port, username, and password, for operators to use when accessing certain applications, like databases. Similarly, a *dbt* `profiles.yml` file stores connection information under each target key. *airflow-dbt-python* bridges the gap between the two and allows you to use connection information stored as an Airflow connection by specifying the connection id as the `target` parameter of any of the *dbt* operators it provides. What\'s more, if using an Airflow connection, the `profiles.yml` file may be entirely omitted (although keep in mind a `profiles.yml` file contains a configuration block besides target connection information).\n\nSee an example DAG [here](examples/airflow_connection_target_dag.py).\n\n# Motivation\n\n## Airflow running in a managed environment\n\nAlthough [`dbt`](https://docs.getdbt.com/) is meant to be installed and used as a CLI, we may not have control of the environment where Airflow is running, disallowing us the option of using *dbt* as a CLI.\n\nThis is exactly what happens when using [Amazon\'s Managed Workflows for Apache Airflow](https://aws.amazon.com/managed-workflows-for-apache-airflow/) (aka MWAA): although a list of Python requirements can be passed, the CLI cannot be found in the worker\'s PATH.\n\nThere is a workaround which involves using Airflow\'s `BashOperator` and running Python from the command line:\n\n``` python\nfrom airflow.operators.bash import BashOperator\n\nBASH_COMMAND = "python -c \'from dbt.main import main; main()\' run"\noperator = BashOperator(\n task_id="dbt_run",\n bash_command=BASH_COMMAND,\n)\n```\n\nBut it can get cumbersome when appending all potential arguments a `dbt run` command (or other subcommand) can take.\n\nThat\'s where *airflow-dbt-python* comes in: it abstracts the complexity of interfacing with *dbt-core* and exposes one operator for each *dbt* subcommand that can be instantiated with all the corresponding arguments that the *dbt* CLI would take.\n\n## An alternative to *airflow-dbt* that works without the *dbt* CLI\n\nThe alternative [`airflow-dbt`](https://pypi.org/project/airflow-dbt/) package, by default, would not work if the *dbt* CLI is not in PATH, which means it would not be usable in MWAA. There is a workaround via the `dbt_bin` argument, which can be set to `"python -c \'from dbt.main import main; main()\' run"`, in similar fashion as the `BashOperator` example. Yet this approach is not without its limitations:\n* *airflow-dbt* works by wrapping the *dbt* CLI, which makes our code dependent on the environment in which it runs.\n* *airflow-dbt* does not support the full range of arguments a command can take. For example, `DbtRunOperator` does not have an attribute for `fail_fast`.\n* *airflow-dbt* does not offer access to *dbt* artifacts created during execution. *airflow-dbt-python* does so by pushing any artifacts to [XCom](https://airflow.apache.org/docs/apache-airflow/stable/concepts/xcoms.html).\n\n# Usage\n\nCurrently, the following *dbt* commands are supported:\n\n* `clean`\n* `compile`\n* `debug`\n* `deps`\n* `docs generate`\n* `ls`\n* `parse`\n* `run`\n* `run-operation`\n* `seed`\n* `snapshot`\n* `source`\n* `test`\n\n## Examples\n\nAll example DAGs are tested against the latest Airflow version. Some changes, like modifying `import` statements or changing types, may be required for them to work in other versions.\n\n``` python\nimport datetime as dt\n\nimport pendulum\nfrom airflow import DAG\n\nfrom airflow_dbt_python.operators.dbt import (\n DbtRunOperator,\n DbtSeedOperator,\n DbtTestOperator,\n)\n\nargs = {\n "owner": "airflow",\n}\n\nwith DAG(\n dag_id="example_dbt_operator",\n default_args=args,\n schedule="0 0 * * *",\n start_date=pendulum.today("UTC").add(days=-1),\n dagrun_timeout=dt.timedelta(minutes=60),\n tags=["example", "example2"],\n) as dag:\n dbt_test = DbtTestOperator(\n task_id="dbt_test",\n selector_name="pre-run-tests",\n )\n\n dbt_seed = DbtSeedOperator(\n task_id="dbt_seed",\n select=["/path/to/first.csv", "/path/to/second.csv"],\n full_refresh=True,\n )\n\n dbt_run = DbtRunOperator(\n task_id="dbt_run",\n select=["/path/to/models"],\n full_refresh=True,\n fail_fast=True,\n )\n\n dbt_test >> dbt_seed >> dbt_run\n```\n\nMore examples can be found in the [`examples/`](examples/) directory and the [documentation](https://airflow-dbt-python.readthedocs.io).\n\n# Development\n\nSee the [development documentation](https://airflow-dbt-python.readthedocs.io/en/latest/development.html) for a more in-depth dive into setting up a development environment, running the test-suite, and general commentary on working on *airflow-dbt-python*.\n\n## Testing\n\nTests are run with *pytest*, can be located in `tests/`. To run them locally, you may use *Poetry*:\n\n``` shell\npoetry run pytest tests/ -vv\n```\n\n# License\n\nThis project is licensed under the MIT license. See [LICENSE](LICENSE).\n',
|
|
38
|
-
'author': 'Tomás Farías Santana',
|
|
39
|
-
'author_email': 'tomas@tomasfarias.dev',
|
|
40
|
-
'maintainer': 'None',
|
|
41
|
-
'maintainer_email': 'None',
|
|
42
|
-
'url': 'https://github.com/tomasfarias/airflow-dbt-python',
|
|
43
|
-
'packages': packages,
|
|
44
|
-
'package_data': package_data,
|
|
45
|
-
'install_requires': install_requires,
|
|
46
|
-
'extras_require': extras_require,
|
|
47
|
-
'python_requires': '>=3.8,<3.13',
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
setup(**setup_kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airflow_dbt_python-2.1.0 → airflow_dbt_python-2.2.0}/airflow_dbt_python/operators/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|