Skip to content

Commit 4bede65

Browse files
authored
[Feature] Enable cross project dbt ref support, dbt mesh, multi porject dbt setup (#49)
* Enable multi project references and settings Revert "Enable multi project references and settings" This reverts commit 2686a19. * Enable multi project references and settings * Enable multi project references and settings
1 parent 7e91e6b commit 4bede65

File tree

12 files changed

+158
-1
lines changed

12 files changed

+158
-1
lines changed

opendbt/dbt/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ def patch_dbt():
99
# ================================================================================================================
1010
dbt_version = Version(version.get_installed_version().to_version_string(skip_matcher=True))
1111
if Version("1.6.0") <= dbt_version < Version("1.8.0"):
12+
from opendbt.dbt.v17.config.runtime import OpenDbtRuntimeConfig
13+
dbt.config.RuntimeConfig = OpenDbtRuntimeConfig
1214
from opendbt.dbt.v17.task.docs.generate import OpenDbtGenerateTask
1315
dbt.task.generate.GenerateTask = OpenDbtGenerateTask
1416
from opendbt.dbt.v17.adapters.factory import OpenDbtAdapterContainer
1517
dbt.adapters.factory.FACTORY = OpenDbtAdapterContainer()
1618
from opendbt.dbt.v17.task.run import ModelRunner
1719
dbt.task.run.ModelRunner = ModelRunner
1820
elif Version("1.8.0") <= dbt_version < Version("1.10.0"):
21+
from opendbt.dbt.v18.config.runtime import OpenDbtRuntimeConfig
22+
dbt.config.RuntimeConfig = OpenDbtRuntimeConfig
1923
from opendbt.dbt.v18.task.docs.generate import OpenDbtGenerateTask
2024
dbt.task.docs.generate.GenerateTask = OpenDbtGenerateTask
2125
from opendbt.dbt.v18.adapters.factory import OpenDbtAdapterContainer

opendbt/dbt/v17/config/__init__.py

Whitespace-only changes.

opendbt/dbt/v17/config/runtime.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from dataclasses import dataclass
2+
from pathlib import Path
3+
from typing import Mapping
4+
5+
from dbt.config import RuntimeConfig
6+
from dbt.config.project import path_exists, _load_yaml
7+
from dbt.constants import DEPENDENCIES_FILE_NAME
8+
from dbt.exceptions import (
9+
DbtProjectError, NonUniquePackageNameError,
10+
)
11+
from typing_extensions import override
12+
13+
14+
def load_yml_dict(file_path):
15+
ret = {}
16+
if path_exists(file_path):
17+
ret = _load_yaml(file_path) or {}
18+
return ret
19+
20+
# pylint: disable=too-many-ancestors
21+
@dataclass
22+
class OpenDbtRuntimeConfig(RuntimeConfig):
23+
def load_dependence_projects(self):
24+
dependencies_yml_dict = load_yml_dict(f"{self.project_root}/{DEPENDENCIES_FILE_NAME}")
25+
26+
if "projects" not in dependencies_yml_dict:
27+
return
28+
29+
projects = dependencies_yml_dict["projects"]
30+
project_root_parent = Path(self.project_root).parent
31+
for project in projects:
32+
path = project_root_parent.joinpath(project['name'])
33+
try:
34+
project = self.new_project(str(path.as_posix()))
35+
except DbtProjectError as e:
36+
raise DbtProjectError(
37+
f"Failed to read depending project: {e} \n project path:{path.as_posix()}",
38+
result_type="invalid_project",
39+
path=path,
40+
) from e
41+
42+
yield project.project_name, project
43+
44+
@override
45+
def load_dependencies(self, base_only=False) -> Mapping[str, "RuntimeConfig"]:
46+
# if self.dependencies is None:
47+
48+
if self.dependencies is None:
49+
# this sets self.dependencies variable!
50+
self.dependencies = super().load_dependencies(base_only=base_only)
51+
52+
# additionally load `projects` defined in `dependencies.yml`
53+
for project_name, project in self.load_dependence_projects():
54+
if project_name in self.dependencies:
55+
raise NonUniquePackageNameError(project_name)
56+
self.dependencies[project_name] = project
57+
58+
return self.dependencies

opendbt/dbt/v18/config/__init__.py

Whitespace-only changes.

opendbt/dbt/v18/config/runtime.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from dataclasses import dataclass
2+
from pathlib import Path
3+
from typing import Mapping
4+
5+
from dbt.config import RuntimeConfig
6+
from dbt.config.project import load_yml_dict
7+
from dbt.constants import DEPENDENCIES_FILE_NAME
8+
from dbt.exceptions import (
9+
DbtProjectError, NonUniquePackageNameError,
10+
)
11+
from typing_extensions import override
12+
13+
14+
# pylint: disable=too-many-ancestors
15+
@dataclass
16+
class OpenDbtRuntimeConfig(RuntimeConfig):
17+
def load_dependence_projects(self):
18+
dependencies_yml_dict = load_yml_dict(f"{self.project_root}/{DEPENDENCIES_FILE_NAME}")
19+
20+
if "projects" not in dependencies_yml_dict:
21+
return
22+
23+
projects = dependencies_yml_dict["projects"]
24+
project_root_parent = Path(self.project_root).parent
25+
for project in projects:
26+
path = project_root_parent.joinpath(project['name'])
27+
try:
28+
project = self.new_project(str(path.as_posix()))
29+
except DbtProjectError as e:
30+
raise DbtProjectError(
31+
f"Failed to read depending project: {e} \n project path:{path.as_posix()}",
32+
result_type="invalid_project",
33+
path=path,
34+
) from e
35+
36+
yield project.project_name, project
37+
38+
@override
39+
def load_dependencies(self, base_only=False) -> Mapping[str, "RuntimeConfig"]:
40+
# if self.dependencies is None:
41+
42+
if self.dependencies is None:
43+
# this sets self.dependencies variable!
44+
self.dependencies = super().load_dependencies(base_only=base_only)
45+
46+
# additionally load `projects` defined in `dependencies.yml`
47+
for project_name, project in self.load_dependence_projects():
48+
if project_name in self.dependencies:
49+
raise NonUniquePackageNameError(project_name)
50+
self.dependencies[project_name] = project
51+
52+
return self.dependencies

tests/resources/dbtcore/profiles.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ dbtcore:
33
dev:
44
type: duckdb
55
adapter: my.dbt.custom.OpenAdapterXXX
6-
path: dev.duckdb
6+
path: ./../dev.duckdb
77
threads: 1
88

99
prod:

tests/resources/dbtfinance/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target/
3+
dbt_packages/
4+
logs/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: 'dbtfinance'
2+
version: '1.0.0'
3+
4+
profile: 'dbtfinance'
5+
6+
# directories to be removed by `dbt clean`
7+
clean-targets:
8+
- "target"
9+
- "dbt_packages"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#packages:
2+
# - package: dbt-labs/dbt_utils
3+
# version: 1.1.1
4+
5+
# case-sensitive and matches the 'name' in the 'dbt_project.yml'
6+
projects:
7+
- name: dbtcore
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
select * from {{ ref('dbtcore', 'my_core_table1') }}

0 commit comments

Comments
 (0)