fal 0.9.2__py3-none-any.whl → 0.9.4__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 fal might be problematic. Click here for more details.
- _fal_testing/utils.py +2 -2
- dbt/adapters/fal/__init__.py +21 -0
- dbt/adapters/fal/__version__.py +1 -0
- dbt/adapters/fal/connections.py +18 -0
- dbt/adapters/fal/impl.py +93 -0
- dbt/adapters/fal/load_db_profile.py +80 -0
- dbt/adapters/fal/wrappers.py +113 -0
- dbt/adapters/fal_experimental/__init__.py +11 -0
- dbt/adapters/fal_experimental/__version__.py +1 -0
- dbt/adapters/fal_experimental/adapter.py +149 -0
- dbt/adapters/fal_experimental/adapter_support.py +234 -0
- dbt/adapters/fal_experimental/connections.py +72 -0
- dbt/adapters/fal_experimental/impl.py +240 -0
- dbt/adapters/fal_experimental/support/athena.py +92 -0
- dbt/adapters/fal_experimental/support/bigquery.py +74 -0
- dbt/adapters/fal_experimental/support/duckdb.py +28 -0
- dbt/adapters/fal_experimental/support/postgres.py +88 -0
- dbt/adapters/fal_experimental/support/redshift.py +56 -0
- dbt/adapters/fal_experimental/support/snowflake.py +76 -0
- dbt/adapters/fal_experimental/support/trino.py +26 -0
- dbt/adapters/fal_experimental/telemetry/__init__.py +1 -0
- dbt/adapters/fal_experimental/telemetry/telemetry.py +411 -0
- dbt/adapters/fal_experimental/teleport.py +192 -0
- dbt/adapters/fal_experimental/teleport_adapter_support.py +23 -0
- dbt/adapters/fal_experimental/teleport_support/duckdb.py +122 -0
- dbt/adapters/fal_experimental/teleport_support/snowflake.py +72 -0
- dbt/adapters/fal_experimental/utils/__init__.py +50 -0
- dbt/adapters/fal_experimental/utils/environments.py +302 -0
- dbt/fal/adapters/python/__init__.py +3 -0
- dbt/fal/adapters/python/connections.py +319 -0
- dbt/fal/adapters/python/impl.py +291 -0
- dbt/fal/adapters/teleport/__init__.py +3 -0
- dbt/fal/adapters/teleport/impl.py +103 -0
- dbt/fal/adapters/teleport/info.py +73 -0
- dbt/include/fal/__init__.py +3 -0
- dbt/include/fal/dbt_project.yml +5 -0
- dbt/include/fal/macros/materializations/table.sql +46 -0
- dbt/include/fal/macros/teleport_duckdb.sql +8 -0
- dbt/include/fal/macros/teleport_snowflake.sql +31 -0
- dbt/include/fal_experimental/__init__.py +3 -0
- dbt/include/fal_experimental/dbt_project.yml +5 -0
- dbt/include/fal_experimental/macros/materializations/table.sql +36 -0
- fal/__init__.py +61 -11
- fal/dbt/__init__.py +11 -0
- fal/dbt/cli/__init__.py +1 -0
- fal/{cli → dbt/cli}/args.py +7 -2
- fal/{cli → dbt/cli}/cli.py +18 -3
- fal/{cli → dbt/cli}/dbt_runner.py +1 -1
- fal/{cli → dbt/cli}/fal_runner.py +6 -6
- fal/{cli → dbt/cli}/flow_runner.py +9 -9
- fal/{cli → dbt/cli}/model_generator/model_generator.py +5 -5
- fal/{cli → dbt/cli}/selectors.py +2 -2
- fal/{fal_script.py → dbt/fal_script.py} +4 -4
- {faldbt → fal/dbt/integration}/lib.py +2 -2
- {faldbt → fal/dbt/integration}/magics.py +2 -2
- {faldbt → fal/dbt/integration}/parse.py +7 -7
- {faldbt → fal/dbt/integration}/project.py +7 -7
- fal/dbt/integration/utils/yaml_helper.py +80 -0
- fal/dbt/new/project.py +43 -0
- fal/{node_graph.py → dbt/node_graph.py} +2 -2
- fal/{packages → dbt/packages}/dependency_analysis.py +32 -38
- fal/{packages → dbt/packages}/environments/__init__.py +3 -3
- fal/{packages → dbt/packages}/environments/base.py +2 -2
- fal/{packages → dbt/packages}/environments/conda.py +3 -3
- fal/{packages → dbt/packages}/environments/virtual_env.py +3 -3
- fal/{packages → dbt/packages}/isolated_runner.py +5 -5
- fal/{planner → dbt/planner}/executor.py +4 -4
- fal/{planner → dbt/planner}/plan.py +3 -3
- fal/{planner → dbt/planner}/schedule.py +5 -5
- fal/{planner → dbt/planner}/tasks.py +5 -5
- fal/{telemetry → dbt/telemetry}/telemetry.py +4 -4
- fal/{typing.py → dbt/typing.py} +2 -2
- fal/{utils.py → dbt/utils.py} +2 -2
- {fal-0.9.2.dist-info → fal-0.9.4.dist-info}/METADATA +98 -117
- fal-0.9.4.dist-info/RECORD +91 -0
- fal-0.9.4.dist-info/entry_points.txt +4 -0
- fal/cli/__init__.py +0 -1
- fal-0.9.2.dist-info/RECORD +0 -47
- fal-0.9.2.dist-info/entry_points.txt +0 -3
- {faldbt → dbt/adapters/fal_experimental}/utils/yaml_helper.py +0 -0
- /fal/{cli → dbt/cli}/model_generator/__init__.py +0 -0
- /fal/{cli → dbt/cli}/model_generator/module_check.py +0 -0
- /fal/{feature_store → dbt/feature_store}/__init__.py +0 -0
- /fal/{feature_store → dbt/feature_store}/feature.py +0 -0
- /fal/{packages → dbt/integration}/__init__.py +0 -0
- {faldbt → fal/dbt/integration}/logger.py +0 -0
- /fal/{planner → dbt/integration/utils}/__init__.py +0 -0
- {faldbt → fal/dbt/integration}/version.py +0 -0
- /fal/{telemetry → dbt/packages}/__init__.py +0 -0
- /fal/{packages → dbt/packages}/bridge.py +0 -0
- {faldbt → fal/dbt/planner}/__init__.py +0 -0
- {faldbt/utils → fal/dbt/telemetry}/__init__.py +0 -0
- {fal-0.9.2.dist-info → fal-0.9.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import List, Union
|
|
3
|
+
|
|
4
|
+
from dbt.exceptions import NotImplementedError
|
|
5
|
+
from dbt.adapters.base.relation import BaseRelation
|
|
6
|
+
from dbt.adapters.base.impl import BaseAdapter
|
|
7
|
+
|
|
8
|
+
from dbt.fal.adapters.teleport.info import TeleportInfo
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TeleportAdapter:
|
|
12
|
+
"""The TeleportAdapter provides an abstract class for adapters usable with Teleport.
|
|
13
|
+
|
|
14
|
+
Adapters must implement the following methods and macros. Some of the
|
|
15
|
+
methods can be safely overridden as a noop, where it makes sense. Those
|
|
16
|
+
methods are marked with a (passable) in their docstrings. Check docstrings
|
|
17
|
+
for type information, etc.
|
|
18
|
+
|
|
19
|
+
To implement a macro, implement "${adapter_type}__${macro_name}" in the
|
|
20
|
+
adapter's internal project.
|
|
21
|
+
|
|
22
|
+
To invoke a method in an adapter macro, call it on the 'adapter' Jinja
|
|
23
|
+
object using dot syntax.
|
|
24
|
+
|
|
25
|
+
To invoke a method in model code, add the @available decorator atop a method
|
|
26
|
+
declaration. Methods are invoked as macros.
|
|
27
|
+
|
|
28
|
+
Methods:
|
|
29
|
+
- storage_formats
|
|
30
|
+
# - teleport_backends
|
|
31
|
+
- teleport_from_external_storage
|
|
32
|
+
- teleport_to_external_storage
|
|
33
|
+
|
|
34
|
+
Macros:
|
|
35
|
+
-
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
@abc.abstractmethod
|
|
41
|
+
def storage_formats(cls) -> List[str]:
|
|
42
|
+
"""
|
|
43
|
+
List of formats this adapter handles. e.g. `['csv', 'parquet']`
|
|
44
|
+
"""
|
|
45
|
+
raise NotImplementedError(
|
|
46
|
+
"`storage_formats` is not implemented for this adapter!"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@abc.abstractmethod
|
|
50
|
+
def teleport_from_external_storage(
|
|
51
|
+
self, relation: BaseRelation, data_path: str, teleport_info: TeleportInfo
|
|
52
|
+
) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Localize data found in `data_path` into the a local table with the name given by `relation`.
|
|
55
|
+
Handle each possible format defined in `storage_formats` method.
|
|
56
|
+
"""
|
|
57
|
+
raise NotImplementedError(
|
|
58
|
+
"`teleport_from_external_storage` is not implemented for this adapter!"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
@abc.abstractmethod
|
|
62
|
+
def teleport_to_external_storage(
|
|
63
|
+
self, relation: BaseRelation, teleport_info: TeleportInfo
|
|
64
|
+
) -> str:
|
|
65
|
+
"""
|
|
66
|
+
Take local table `relation` and upload the data with Teleport. Return the `data_path` the data is uploaded to.
|
|
67
|
+
Handle each possible format defined in `storage_formats` method.
|
|
68
|
+
"""
|
|
69
|
+
raise NotImplementedError(
|
|
70
|
+
"`teleport_to_external_storage` is not implemented for this adapter!"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def is_teleport_adapter(
|
|
75
|
+
cls, adapter: Union[BaseAdapter, "TeleportAdapter"]
|
|
76
|
+
) -> bool:
|
|
77
|
+
methods = [
|
|
78
|
+
"storage_formats",
|
|
79
|
+
# "teleport_backends",
|
|
80
|
+
"teleport_from_external_storage",
|
|
81
|
+
"teleport_to_external_storage",
|
|
82
|
+
]
|
|
83
|
+
return isinstance(adapter, TeleportAdapter) or all(
|
|
84
|
+
map(lambda m: hasattr(adapter, m), methods)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def find_format(
|
|
89
|
+
cls, target_adapter: "TeleportAdapter", ref_adapter: "TeleportAdapter"
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
Find common format between target and ref adapter, giving priority to target list ordering.
|
|
93
|
+
"""
|
|
94
|
+
target_formats = target_adapter.storage_formats()
|
|
95
|
+
ref_formats = ref_adapter.storage_formats()
|
|
96
|
+
for format in target_formats:
|
|
97
|
+
if format in ref_formats:
|
|
98
|
+
return format
|
|
99
|
+
|
|
100
|
+
raise RuntimeError(
|
|
101
|
+
f"No common format between {target_adapter.type()} and {ref_adapter.type()} "
|
|
102
|
+
f"— {target_formats} | {ref_formats}"
|
|
103
|
+
)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Any, Union
|
|
4
|
+
|
|
5
|
+
from dbt.adapters.base.relation import BaseRelation
|
|
6
|
+
from dbt.contracts.relation import ComponentName
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class TeleportInfo:
|
|
10
|
+
format: str
|
|
11
|
+
credentials: Any
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def relation_name(cls, relation: Union[str, BaseRelation]):
|
|
15
|
+
if isinstance(relation, str):
|
|
16
|
+
# TODO: should we check for quoting?
|
|
17
|
+
return relation
|
|
18
|
+
else:
|
|
19
|
+
path = relation.path
|
|
20
|
+
db = path.get_lowered_part(ComponentName.Database)
|
|
21
|
+
sc = path.get_lowered_part(ComponentName.Schema)
|
|
22
|
+
tb = path.get_lowered_part(ComponentName.Identifier)
|
|
23
|
+
return f"{db}.{sc}.{tb}"
|
|
24
|
+
|
|
25
|
+
def build_relation_path(self, relation: Union[str, BaseRelation]):
|
|
26
|
+
rel_name = TeleportInfo.relation_name(relation)
|
|
27
|
+
return rel_name + "." + self.format
|
|
28
|
+
|
|
29
|
+
def build_url(self, path: str) -> str:
|
|
30
|
+
raise NotImplemented
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class LocalTeleportInfo(TeleportInfo):
|
|
34
|
+
base_dir: Path
|
|
35
|
+
|
|
36
|
+
def __init__(self, format: str, credentials: Any, base_dir: Union[str, Path]):
|
|
37
|
+
super().__init__(format, credentials)
|
|
38
|
+
|
|
39
|
+
self.base_dir = Path(base_dir)
|
|
40
|
+
self.base_dir.mkdir(exist_ok=True)
|
|
41
|
+
assert self.base_dir.is_dir(), "Local Teleport base_dir should be a directory"
|
|
42
|
+
|
|
43
|
+
def build_url(self, path: str):
|
|
44
|
+
return self.base_dir / path
|
|
45
|
+
|
|
46
|
+
# TODO: How to do Teleport Configuration
|
|
47
|
+
# Will each adapter have to implement a specific case for each teleport backend.
|
|
48
|
+
# And how will we generalize these configurations?
|
|
49
|
+
#
|
|
50
|
+
# Each adapter will have a specific `teleport` property.
|
|
51
|
+
# my_db:
|
|
52
|
+
# type: duckdb
|
|
53
|
+
# path: ./local_file.db
|
|
54
|
+
# teleport:
|
|
55
|
+
# type: s3
|
|
56
|
+
# bucket: my_bucket
|
|
57
|
+
# access_key_id: ...
|
|
58
|
+
# secret_access_key: ...
|
|
59
|
+
# my_py:
|
|
60
|
+
# type: fal
|
|
61
|
+
# teleport:
|
|
62
|
+
# type: s3
|
|
63
|
+
# s3_bucket: my_bucket
|
|
64
|
+
# s3_access_key_id: ...
|
|
65
|
+
# s3_access_key: ...
|
|
66
|
+
# Since all adapters could use different properties and methods to achieve this
|
|
67
|
+
@dataclass
|
|
68
|
+
class S3TeleportInfo(TeleportInfo):
|
|
69
|
+
bucket: str
|
|
70
|
+
inner_path: str
|
|
71
|
+
|
|
72
|
+
def build_url(self, path: str):
|
|
73
|
+
return f's3://{self.bucket}/{self.inner_path}/{path}'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% materialization table, adapter='fal', supported_languages=['python', 'sql'] -%}
|
|
2
|
+
|
|
3
|
+
{%- set language = model['language'] -%}
|
|
4
|
+
|
|
5
|
+
{%- if language == 'python' -%}
|
|
6
|
+
|
|
7
|
+
{%- if adapter.is_teleport() -%}
|
|
8
|
+
{%- for _ref in model.refs -%}
|
|
9
|
+
{% set _ref_args = [_ref.get('package'), _ref['name']] if _ref.get('package') else [_ref['name'],] %}
|
|
10
|
+
{%- set resolved = ref(*_ref_args, v=_ref.get('version')) -%}
|
|
11
|
+
{%- do adapter.sync_teleport_relation(resolved) -%}
|
|
12
|
+
{%- endfor -%}
|
|
13
|
+
{%- endif -%}
|
|
14
|
+
|
|
15
|
+
{%- set relation = this.incorporate(type='table') -%}
|
|
16
|
+
|
|
17
|
+
{%- call statement('main', language=language) -%}
|
|
18
|
+
|
|
19
|
+
{{- py_write(compiled_code, relation) }}
|
|
20
|
+
|
|
21
|
+
{%- endcall %}
|
|
22
|
+
|
|
23
|
+
{{- return({'relations': [relation]}) }}
|
|
24
|
+
|
|
25
|
+
{%- elif language == 'sql' -%}
|
|
26
|
+
|
|
27
|
+
{# HACK: proxy to the db adapter table materialization #}
|
|
28
|
+
{{- return(adapter.db_materialization(context, "table")) }}
|
|
29
|
+
|
|
30
|
+
{%- endif -%}
|
|
31
|
+
|
|
32
|
+
{% endmaterialization %}
|
|
33
|
+
|
|
34
|
+
{% macro py_write(code, relation) -%}
|
|
35
|
+
{{- compiled_code -}}
|
|
36
|
+
|
|
37
|
+
# Generated by dbt-fal
|
|
38
|
+
|
|
39
|
+
def main(read_df, write_df, fal_context=None):
|
|
40
|
+
dbt_context = dbtObj(read_df)
|
|
41
|
+
df = model(dbt_context, fal_context)
|
|
42
|
+
return write_df(
|
|
43
|
+
'{{ relation.quote(False, False, False) }}',
|
|
44
|
+
df
|
|
45
|
+
)
|
|
46
|
+
{%- endmacro %}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{% macro snowflake__create_table_from_parquet(relation, location) -%}
|
|
2
|
+
CREATE OR REPLACE TABLE {{ relation }} USING template (
|
|
3
|
+
SELECT array_agg(object_construct(*))
|
|
4
|
+
FROM table(
|
|
5
|
+
infer_schema(
|
|
6
|
+
LOCATION=>'{{ location }}',
|
|
7
|
+
FILE_FORMAT=>'falparquet',
|
|
8
|
+
IGNORE_CASE=>TRUE
|
|
9
|
+
)
|
|
10
|
+
)
|
|
11
|
+
);
|
|
12
|
+
{%- endmacro %}
|
|
13
|
+
|
|
14
|
+
{% macro snowflake__copy_from_parquet(relation, location) -%}
|
|
15
|
+
COPY INTO {{ relation }} FROM (
|
|
16
|
+
SELECT
|
|
17
|
+
{% for col in adapter.get_columns_in_relation(relation) %}
|
|
18
|
+
$1:{{col.column}}
|
|
19
|
+
{%- if not loop.last -%},{%- endif -%}
|
|
20
|
+
{% endfor %}
|
|
21
|
+
FROM {{ location }})
|
|
22
|
+
FILE_FORMAT = (FORMAT_NAME = 'falparquet');
|
|
23
|
+
{%- endmacro %}
|
|
24
|
+
|
|
25
|
+
{% macro snowflake__copy_to_parquet(relation, location) -%}
|
|
26
|
+
COPY INTO {{ location }} FROM {{ relation }}
|
|
27
|
+
FILE_FORMAT = (TYPE=parquet)
|
|
28
|
+
OVERWRITE = TRUE
|
|
29
|
+
SINGLE = TRUE
|
|
30
|
+
HEADER = TRUE;
|
|
31
|
+
{%- endmacro %}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- This file may be outdated because we actually use the `fal` materialization
|
|
2
|
+
{% materialization table, adapter='fal_experimental', supported_languages=['python'] -%}
|
|
3
|
+
|
|
4
|
+
-- TODO: change to sync_teleport() when available in dbt-core
|
|
5
|
+
{%- if adapter.is_teleport() -%}
|
|
6
|
+
{%- for _ref in model.refs -%}
|
|
7
|
+
{%- set resolved = ref(*_ref) -%}
|
|
8
|
+
{%- do adapter.sync_teleport_relation(ref(*_ref)) -%}
|
|
9
|
+
{%- endfor -%}
|
|
10
|
+
{%- endif -%}
|
|
11
|
+
|
|
12
|
+
{%- set relation = this.incorporate(type='table') -%}
|
|
13
|
+
|
|
14
|
+
{%- call statement('main', language='python') -%}
|
|
15
|
+
|
|
16
|
+
{{- py_write(compiled_code, relation) }}
|
|
17
|
+
|
|
18
|
+
{%- endcall %}
|
|
19
|
+
|
|
20
|
+
{{- return({'relations': [relation]}) }}
|
|
21
|
+
|
|
22
|
+
{% endmaterialization %}
|
|
23
|
+
|
|
24
|
+
{% macro py_write(code, relation) -%}
|
|
25
|
+
{{- compiled_code -}}
|
|
26
|
+
|
|
27
|
+
# Generated by dbt-fal
|
|
28
|
+
|
|
29
|
+
def main(read_df, write_df, fal_context=None):
|
|
30
|
+
dbt_context = dbtObj(read_df)
|
|
31
|
+
df = model(dbt_context, fal_context)
|
|
32
|
+
return write_df(
|
|
33
|
+
'{{ relation.quote(False, False, False) }}',
|
|
34
|
+
df
|
|
35
|
+
)
|
|
36
|
+
{%- endmacro %}
|
fal/__init__.py
CHANGED
|
@@ -1,11 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
# TODO: remove once `fal` is no longer a supported package
|
|
2
|
+
# The whole file
|
|
3
|
+
DBT_FAL_IMPORT_NOTICE = \
|
|
4
|
+
"""The dbt tool `fal` and `dbt-fal` adapter have been merged into a single tool.
|
|
5
|
+
Please import from the `fal.dbt` module instead.
|
|
6
|
+
Running `pip install dbt-fal` will install the new tool and the adapter alongside.
|
|
7
|
+
Then import from the `fal.dbt` module like
|
|
8
|
+
|
|
9
|
+
from fal.dbt import {name}
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
global DBT_FAL_IMPORT_NOTICE_SHOWN
|
|
13
|
+
DBT_FAL_IMPORT_NOTICE_SHOWN = {}
|
|
14
|
+
|
|
15
|
+
def _warn(name: str):
|
|
16
|
+
# Print once per deprecated import
|
|
17
|
+
global DBT_FAL_IMPORT_NOTICE_SHOWN
|
|
18
|
+
if not DBT_FAL_IMPORT_NOTICE_SHOWN.get(name, False):
|
|
19
|
+
print(DBT_FAL_IMPORT_NOTICE.format(name=name))
|
|
20
|
+
DBT_FAL_IMPORT_NOTICE_SHOWN[name] = True
|
|
21
|
+
|
|
22
|
+
# Avoid printing on non-direct imports
|
|
23
|
+
def __getattr__(name: str):
|
|
24
|
+
if name == "NodeStatus":
|
|
25
|
+
_warn(name)
|
|
26
|
+
from fal.dbt import NodeStatus
|
|
27
|
+
return NodeStatus
|
|
28
|
+
elif name == "FalDbt":
|
|
29
|
+
_warn(name)
|
|
30
|
+
from fal.dbt import FalDbt
|
|
31
|
+
return FalDbt
|
|
32
|
+
elif name == "DbtModel":
|
|
33
|
+
_warn(name)
|
|
34
|
+
from fal.dbt import DbtModel
|
|
35
|
+
return DbtModel
|
|
36
|
+
elif name == "DbtSource":
|
|
37
|
+
_warn(name)
|
|
38
|
+
from fal.dbt import DbtSource
|
|
39
|
+
return DbtSource
|
|
40
|
+
elif name == "DbtTest":
|
|
41
|
+
_warn(name)
|
|
42
|
+
from fal.dbt import DbtTest
|
|
43
|
+
return DbtTest
|
|
44
|
+
elif name == "DbtGenericTest":
|
|
45
|
+
_warn(name)
|
|
46
|
+
from fal.dbt import DbtGenericTest
|
|
47
|
+
return DbtGenericTest
|
|
48
|
+
elif name == "DbtSingularTest":
|
|
49
|
+
_warn(name)
|
|
50
|
+
from fal.dbt import DbtSingularTest
|
|
51
|
+
return DbtSingularTest
|
|
52
|
+
elif name == "Context":
|
|
53
|
+
_warn(name)
|
|
54
|
+
from fal.dbt import Context
|
|
55
|
+
return Context
|
|
56
|
+
elif name == "CurrentModel":
|
|
57
|
+
_warn(name)
|
|
58
|
+
from fal.dbt import CurrentModel
|
|
59
|
+
return CurrentModel
|
|
60
|
+
|
|
61
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
fal/dbt/__init__.py
ADDED
fal/dbt/cli/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .cli import cli, fal_cli
|
fal/{cli → dbt/cli}/args.py
RENAMED
|
@@ -204,11 +204,16 @@ def _build_flow_parser(sub: argparse.ArgumentParser):
|
|
|
204
204
|
|
|
205
205
|
def _build_cli_parser():
|
|
206
206
|
parser = argparse.ArgumentParser(
|
|
207
|
-
prog="fal",
|
|
207
|
+
prog="dbt-fal",
|
|
208
208
|
description="Run Python scripts on dbt models",
|
|
209
209
|
)
|
|
210
210
|
|
|
211
|
-
|
|
211
|
+
try:
|
|
212
|
+
version = pkg_resources.get_distribution("dbt-fal").version
|
|
213
|
+
except pkg_resources.DistributionNotFound:
|
|
214
|
+
# TODO: remove once `fal` is no longer a supported package
|
|
215
|
+
version = pkg_resources.get_distribution("fal").version
|
|
216
|
+
|
|
212
217
|
parser.add_argument(
|
|
213
218
|
"-v",
|
|
214
219
|
"--version",
|
fal/{cli → dbt/cli}/cli.py
RENAMED
|
@@ -3,14 +3,29 @@ import sys
|
|
|
3
3
|
|
|
4
4
|
from click.exceptions import ClickException
|
|
5
5
|
|
|
6
|
-
from fal.cli.flow_runner import fal_flow_run
|
|
6
|
+
from fal.dbt.cli.flow_runner import fal_flow_run
|
|
7
7
|
from .args import parse_args
|
|
8
8
|
from .fal_runner import fal_run
|
|
9
|
-
from fal.telemetry import telemetry
|
|
9
|
+
from fal.dbt.telemetry import telemetry
|
|
10
10
|
|
|
11
|
-
from
|
|
11
|
+
from fal.dbt.integration.logger import log_manager
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
# TODO: remove once `fal` is no longer a supported package
|
|
15
|
+
DBT_FAL_COMMAND_NOTICE = \
|
|
16
|
+
"""The dbt tool `fal` and `dbt-fal` adapter have been merged into a single tool.
|
|
17
|
+
Please use the new `dbt-fal` command line tool instead.
|
|
18
|
+
Running `pip install dbt-fal` will install the new tool and the adapter alongside.
|
|
19
|
+
Then run your command like
|
|
20
|
+
|
|
21
|
+
dbt-fal <command>
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# TODO: remove once `fal` is no longer a supported package
|
|
25
|
+
def fal_cli(argv: List[str] = sys.argv):
|
|
26
|
+
print(DBT_FAL_COMMAND_NOTICE)
|
|
27
|
+
cli(argv)
|
|
28
|
+
|
|
14
29
|
def cli(argv: List[str] = sys.argv):
|
|
15
30
|
# Wrapper to be able to shutdown telemetry afterwards
|
|
16
31
|
try:
|
|
@@ -2,12 +2,12 @@ import argparse
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Any, Dict, List
|
|
4
4
|
|
|
5
|
-
from fal.planner.executor import parallel_executor
|
|
6
|
-
from fal.planner.schedule import Scheduler
|
|
7
|
-
from fal.planner.tasks import FalLocalHookTask, Status, TaskGroup
|
|
5
|
+
from fal.dbt.planner.executor import parallel_executor
|
|
6
|
+
from fal.dbt.planner.schedule import Scheduler
|
|
7
|
+
from fal.dbt.planner.tasks import FalLocalHookTask, Status, TaskGroup
|
|
8
8
|
|
|
9
|
-
from fal.fal_script import FalScript, TimingType
|
|
10
|
-
from
|
|
9
|
+
from fal.dbt.fal_script import FalScript, TimingType
|
|
10
|
+
from fal.dbt.integration.project import FAL, DbtModel, FalDbt, FalGeneralException
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def create_fal_dbt(
|
|
@@ -151,7 +151,7 @@ def _get_filtered_models(faldbt: FalDbt, all, selected, before) -> List[DbtModel
|
|
|
151
151
|
and not before
|
|
152
152
|
and faldbt._run_results.native_run_result is None
|
|
153
153
|
):
|
|
154
|
-
from
|
|
154
|
+
from fal.dbt.integration.parse import FalParseError
|
|
155
155
|
|
|
156
156
|
raise FalParseError(
|
|
157
157
|
"Cannot define models to run without selection flags or dbt run_results artifact or --before flag"
|
|
@@ -3,12 +3,12 @@ import copy
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Any, Dict, Optional, cast, Union
|
|
5
5
|
|
|
6
|
-
from fal.cli.fal_runner import create_fal_dbt
|
|
7
|
-
from fal.cli.selectors import ExecutionPlan
|
|
8
|
-
from fal.cli.model_generator import generate_python_dbt_models
|
|
9
|
-
from fal.fal_script import FalScript
|
|
10
|
-
from fal.node_graph import DbtModelNode, FalFlowNode, NodeGraph, ScriptNode
|
|
11
|
-
from
|
|
6
|
+
from fal.dbt.cli.fal_runner import create_fal_dbt
|
|
7
|
+
from fal.dbt.cli.selectors import ExecutionPlan
|
|
8
|
+
from fal.dbt.cli.model_generator import generate_python_dbt_models
|
|
9
|
+
from fal.dbt.fal_script import FalScript
|
|
10
|
+
from fal.dbt.node_graph import DbtModelNode, FalFlowNode, NodeGraph, ScriptNode
|
|
11
|
+
from fal.dbt.integration.project import FalDbt, NodeStatus
|
|
12
12
|
import argparse
|
|
13
13
|
|
|
14
14
|
|
|
@@ -23,14 +23,14 @@ def run_threaded(
|
|
|
23
23
|
parsed: argparse.Namespace,
|
|
24
24
|
node_graph: NodeGraph,
|
|
25
25
|
) -> int:
|
|
26
|
-
from fal.planner.plan import (
|
|
26
|
+
from fal.dbt.planner.plan import (
|
|
27
27
|
OriginGraph,
|
|
28
28
|
FilteredGraph,
|
|
29
29
|
PlannedGraph,
|
|
30
30
|
ScriptConnectedGraph,
|
|
31
31
|
)
|
|
32
|
-
from fal.planner.schedule import schedule_graph
|
|
33
|
-
from fal.planner.executor import parallel_executor
|
|
32
|
+
from fal.dbt.planner.schedule import schedule_graph
|
|
33
|
+
from fal.dbt.planner.executor import parallel_executor
|
|
34
34
|
|
|
35
35
|
execution_plan = ExecutionPlan.create_plan_from_graph(parsed, node_graph, fal_dbt)
|
|
36
36
|
|
|
@@ -3,17 +3,17 @@ from functools import partial
|
|
|
3
3
|
import re
|
|
4
4
|
from typing import Callable, Iterable, List, TypeVar
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from fal.fal_script import python_from_file
|
|
6
|
+
from fal.dbt.fal_script import python_from_file
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from fal.cli.model_generator.module_check import (
|
|
8
|
+
from fal.dbt.integration.parse import get_fal_models_dirs, load_dbt_project_contract
|
|
9
|
+
from fal.dbt.cli.model_generator.module_check import (
|
|
10
10
|
generate_dbt_dependencies,
|
|
11
11
|
write_to_model_check,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
from
|
|
14
|
+
from fal.dbt.integration.logger import LOGGER
|
|
15
15
|
|
|
16
|
-
from fal.telemetry import telemetry
|
|
16
|
+
from fal.dbt.telemetry import telemetry
|
|
17
17
|
|
|
18
18
|
SQL_MODEL_TEMPLATE = """
|
|
19
19
|
{{ config(materialized='ephemeral') }}
|
fal/{cli → dbt/cli}/selectors.py
RENAMED
|
@@ -2,8 +2,8 @@ import itertools
|
|
|
2
2
|
import re
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import List, Optional, Union, Iterator
|
|
5
|
-
from fal.node_graph import NodeGraph
|
|
6
|
-
from
|
|
5
|
+
from fal.dbt.node_graph import NodeGraph
|
|
6
|
+
from fal.dbt.integration.project import CompileArgs, FalDbt, FalGeneralException
|
|
7
7
|
from dbt.task.compile import CompileTask
|
|
8
8
|
from enum import Enum
|
|
9
9
|
from functools import reduce
|
|
@@ -9,14 +9,14 @@ from deprecation import deprecated
|
|
|
9
9
|
|
|
10
10
|
import hashlib
|
|
11
11
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
12
|
+
from fal.dbt.integration.parse import normalize_path
|
|
13
|
+
from fal.dbt.integration.project import DbtModel, FalDbt, FAL
|
|
14
14
|
|
|
15
15
|
from dbt.contracts.results import RunStatus
|
|
16
16
|
from dbt.config.runtime import RuntimeConfig
|
|
17
|
-
from
|
|
17
|
+
from fal.dbt.integration.logger import LOGGER
|
|
18
18
|
|
|
19
|
-
from fal.telemetry import telemetry
|
|
19
|
+
from fal.dbt.telemetry import telemetry
|
|
20
20
|
|
|
21
21
|
from dbt.contracts.graph.nodes import ColumnInfo
|
|
22
22
|
|
|
@@ -29,8 +29,8 @@ from sqlalchemy.sql import Insert
|
|
|
29
29
|
from dbt.contracts.sql import RemoteRunResult
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
from
|
|
33
|
-
from
|
|
32
|
+
from fal.dbt.integration import parse
|
|
33
|
+
from fal.dbt.integration.logger import LOGGER
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class WriteModeEnum(Enum):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from IPython.core.magic import register_line_magic, needs_local_scope
|
|
2
2
|
from functools import partial
|
|
3
|
-
from fal import FalDbt
|
|
3
|
+
from fal.dbt import FalDbt
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
@register_line_magic
|
|
@@ -11,7 +11,7 @@ def init_fal(line="", local_ns={}):
|
|
|
11
11
|
|
|
12
12
|
Example:
|
|
13
13
|
"""
|
|
14
|
-
from
|
|
14
|
+
from fal.dbt.integration.magics import init_fal
|
|
15
15
|
|
|
16
16
|
%init_fal project_dir=/my_project_dir profiles_dir=/my_profiles_dir default_model_name=my_model
|
|
17
17
|
"""
|
|
@@ -14,14 +14,14 @@ from dbt.config.profile import read_user_config
|
|
|
14
14
|
|
|
15
15
|
from dbt.exceptions import IncompatibleSchemaError, DbtRuntimeError
|
|
16
16
|
|
|
17
|
-
from fal.utils import cache_static
|
|
17
|
+
from fal.dbt.utils import cache_static
|
|
18
18
|
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from fal.telemetry import telemetry
|
|
19
|
+
from fal.dbt.integration.logger import LOGGER
|
|
20
|
+
from fal.dbt.integration.utils.yaml_helper import load_yaml
|
|
21
|
+
from fal.dbt.telemetry import telemetry
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
|
-
from fal.packages.environments import BaseEnvironment
|
|
24
|
+
from fal.dbt.packages.environments import BaseEnvironment
|
|
25
25
|
|
|
26
26
|
FAL_SCRIPTS_PATH = "fal-scripts-path"
|
|
27
27
|
FAL_MODELS_PATHS = "fal-models-paths"
|
|
@@ -225,8 +225,8 @@ def _get_required_key(data: Dict[str, Any], name: str) -> Any:
|
|
|
225
225
|
|
|
226
226
|
|
|
227
227
|
def load_environments(base_dir: str) -> Dict[str, "BaseEnvironment"]:
|
|
228
|
-
from fal.packages.environments import create_environment
|
|
229
|
-
from fal.fal_script import _is_local_environment
|
|
228
|
+
from fal.dbt.packages.environments import create_environment
|
|
229
|
+
from fal.dbt.fal_script import _is_local_environment
|
|
230
230
|
|
|
231
231
|
try:
|
|
232
232
|
fal_project_path = os.path.join(base_dir, "fal_project.yml")
|