dvt-core 0.52.2__cp310-cp310-macosx_10_9_x86_64.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 dvt-core might be problematic. Click here for more details.
- dbt/__init__.py +7 -0
- dbt/_pydantic_shim.py +26 -0
- dbt/artifacts/__init__.py +0 -0
- dbt/artifacts/exceptions/__init__.py +1 -0
- dbt/artifacts/exceptions/schemas.py +31 -0
- dbt/artifacts/resources/__init__.py +116 -0
- dbt/artifacts/resources/base.py +67 -0
- dbt/artifacts/resources/types.py +93 -0
- dbt/artifacts/resources/v1/analysis.py +10 -0
- dbt/artifacts/resources/v1/catalog.py +23 -0
- dbt/artifacts/resources/v1/components.py +274 -0
- dbt/artifacts/resources/v1/config.py +277 -0
- dbt/artifacts/resources/v1/documentation.py +11 -0
- dbt/artifacts/resources/v1/exposure.py +51 -0
- dbt/artifacts/resources/v1/function.py +52 -0
- dbt/artifacts/resources/v1/generic_test.py +31 -0
- dbt/artifacts/resources/v1/group.py +21 -0
- dbt/artifacts/resources/v1/hook.py +11 -0
- dbt/artifacts/resources/v1/macro.py +29 -0
- dbt/artifacts/resources/v1/metric.py +172 -0
- dbt/artifacts/resources/v1/model.py +145 -0
- dbt/artifacts/resources/v1/owner.py +10 -0
- dbt/artifacts/resources/v1/saved_query.py +111 -0
- dbt/artifacts/resources/v1/seed.py +41 -0
- dbt/artifacts/resources/v1/semantic_layer_components.py +72 -0
- dbt/artifacts/resources/v1/semantic_model.py +314 -0
- dbt/artifacts/resources/v1/singular_test.py +14 -0
- dbt/artifacts/resources/v1/snapshot.py +91 -0
- dbt/artifacts/resources/v1/source_definition.py +84 -0
- dbt/artifacts/resources/v1/sql_operation.py +10 -0
- dbt/artifacts/resources/v1/unit_test_definition.py +77 -0
- dbt/artifacts/schemas/__init__.py +0 -0
- dbt/artifacts/schemas/base.py +191 -0
- dbt/artifacts/schemas/batch_results.py +24 -0
- dbt/artifacts/schemas/catalog/__init__.py +11 -0
- dbt/artifacts/schemas/catalog/v1/__init__.py +0 -0
- dbt/artifacts/schemas/catalog/v1/catalog.py +59 -0
- dbt/artifacts/schemas/freshness/__init__.py +1 -0
- dbt/artifacts/schemas/freshness/v3/__init__.py +0 -0
- dbt/artifacts/schemas/freshness/v3/freshness.py +158 -0
- dbt/artifacts/schemas/manifest/__init__.py +2 -0
- dbt/artifacts/schemas/manifest/v12/__init__.py +0 -0
- dbt/artifacts/schemas/manifest/v12/manifest.py +211 -0
- dbt/artifacts/schemas/results.py +147 -0
- dbt/artifacts/schemas/run/__init__.py +2 -0
- dbt/artifacts/schemas/run/v5/__init__.py +0 -0
- dbt/artifacts/schemas/run/v5/run.py +184 -0
- dbt/artifacts/schemas/upgrades/__init__.py +4 -0
- dbt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
- dbt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
- dbt/artifacts/utils/validation.py +153 -0
- dbt/cli/__init__.py +1 -0
- dbt/cli/context.py +17 -0
- dbt/cli/exceptions.py +57 -0
- dbt/cli/flags.py +560 -0
- dbt/cli/main.py +2039 -0
- dbt/cli/option_types.py +121 -0
- dbt/cli/options.py +80 -0
- dbt/cli/params.py +804 -0
- dbt/cli/requires.py +490 -0
- dbt/cli/resolvers.py +50 -0
- dbt/cli/types.py +40 -0
- dbt/clients/__init__.py +0 -0
- dbt/clients/checked_load.py +83 -0
- dbt/clients/git.py +164 -0
- dbt/clients/jinja.py +206 -0
- dbt/clients/jinja_static.py +245 -0
- dbt/clients/registry.py +192 -0
- dbt/clients/yaml_helper.py +68 -0
- dbt/compilation.py +876 -0
- dbt/compute/__init__.py +14 -0
- dbt/compute/engines/__init__.py +12 -0
- dbt/compute/engines/spark_engine.py +624 -0
- dbt/compute/federated_executor.py +837 -0
- dbt/compute/filter_pushdown.cpython-310-darwin.so +0 -0
- dbt/compute/filter_pushdown.py +273 -0
- dbt/compute/jar_provisioning.cpython-310-darwin.so +0 -0
- dbt/compute/jar_provisioning.py +255 -0
- dbt/compute/java_compat.cpython-310-darwin.so +0 -0
- dbt/compute/java_compat.py +689 -0
- dbt/compute/jdbc_utils.cpython-310-darwin.so +0 -0
- dbt/compute/jdbc_utils.py +678 -0
- dbt/compute/smart_selector.cpython-310-darwin.so +0 -0
- dbt/compute/smart_selector.py +311 -0
- dbt/compute/strategies/__init__.py +54 -0
- dbt/compute/strategies/base.py +165 -0
- dbt/compute/strategies/dataproc.py +207 -0
- dbt/compute/strategies/emr.py +203 -0
- dbt/compute/strategies/local.py +364 -0
- dbt/compute/strategies/standalone.py +262 -0
- dbt/config/__init__.py +4 -0
- dbt/config/catalogs.py +94 -0
- dbt/config/compute.cpython-310-darwin.so +0 -0
- dbt/config/compute.py +547 -0
- dbt/config/dvt_profile.cpython-310-darwin.so +0 -0
- dbt/config/dvt_profile.py +342 -0
- dbt/config/profile.py +422 -0
- dbt/config/project.py +873 -0
- dbt/config/project_utils.py +28 -0
- dbt/config/renderer.py +231 -0
- dbt/config/runtime.py +553 -0
- dbt/config/selectors.py +208 -0
- dbt/config/utils.py +77 -0
- dbt/constants.py +28 -0
- dbt/context/__init__.py +0 -0
- dbt/context/base.py +745 -0
- dbt/context/configured.py +135 -0
- dbt/context/context_config.py +382 -0
- dbt/context/docs.py +82 -0
- dbt/context/exceptions_jinja.py +178 -0
- dbt/context/macro_resolver.py +195 -0
- dbt/context/macros.py +171 -0
- dbt/context/manifest.py +72 -0
- dbt/context/providers.py +2249 -0
- dbt/context/query_header.py +13 -0
- dbt/context/secret.py +58 -0
- dbt/context/target.py +74 -0
- dbt/contracts/__init__.py +0 -0
- dbt/contracts/files.py +413 -0
- dbt/contracts/graph/__init__.py +0 -0
- dbt/contracts/graph/manifest.py +1904 -0
- dbt/contracts/graph/metrics.py +97 -0
- dbt/contracts/graph/model_config.py +70 -0
- dbt/contracts/graph/node_args.py +42 -0
- dbt/contracts/graph/nodes.py +1806 -0
- dbt/contracts/graph/semantic_manifest.py +232 -0
- dbt/contracts/graph/unparsed.py +811 -0
- dbt/contracts/project.py +417 -0
- dbt/contracts/results.py +53 -0
- dbt/contracts/selection.py +23 -0
- dbt/contracts/sql.py +85 -0
- dbt/contracts/state.py +68 -0
- dbt/contracts/util.py +46 -0
- dbt/deprecations.py +346 -0
- dbt/deps/__init__.py +0 -0
- dbt/deps/base.py +152 -0
- dbt/deps/git.py +195 -0
- dbt/deps/local.py +79 -0
- dbt/deps/registry.py +130 -0
- dbt/deps/resolver.py +149 -0
- dbt/deps/tarball.py +120 -0
- dbt/docs/source/_ext/dbt_click.py +119 -0
- dbt/docs/source/conf.py +32 -0
- dbt/env_vars.py +64 -0
- dbt/event_time/event_time.py +40 -0
- dbt/event_time/sample_window.py +60 -0
- dbt/events/__init__.py +15 -0
- dbt/events/base_types.py +36 -0
- dbt/events/core_types_pb2.py +2 -0
- dbt/events/logging.py +108 -0
- dbt/events/types.py +2516 -0
- dbt/exceptions.py +1486 -0
- dbt/flags.py +89 -0
- dbt/graph/__init__.py +11 -0
- dbt/graph/cli.py +247 -0
- dbt/graph/graph.py +172 -0
- dbt/graph/queue.py +214 -0
- dbt/graph/selector.py +374 -0
- dbt/graph/selector_methods.py +975 -0
- dbt/graph/selector_spec.py +222 -0
- dbt/graph/thread_pool.py +18 -0
- dbt/hooks.py +21 -0
- dbt/include/README.md +49 -0
- dbt/include/__init__.py +3 -0
- dbt/include/starter_project/.gitignore +4 -0
- dbt/include/starter_project/README.md +15 -0
- dbt/include/starter_project/__init__.py +3 -0
- dbt/include/starter_project/analyses/.gitkeep +0 -0
- dbt/include/starter_project/dbt_project.yml +36 -0
- dbt/include/starter_project/macros/.gitkeep +0 -0
- dbt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
- dbt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
- dbt/include/starter_project/models/example/schema.yml +21 -0
- dbt/include/starter_project/seeds/.gitkeep +0 -0
- dbt/include/starter_project/snapshots/.gitkeep +0 -0
- dbt/include/starter_project/tests/.gitkeep +0 -0
- dbt/internal_deprecations.py +26 -0
- dbt/jsonschemas/__init__.py +3 -0
- dbt/jsonschemas/jsonschemas.py +309 -0
- dbt/jsonschemas/project/0.0.110.json +4717 -0
- dbt/jsonschemas/project/0.0.85.json +2015 -0
- dbt/jsonschemas/resources/0.0.110.json +2636 -0
- dbt/jsonschemas/resources/0.0.85.json +2536 -0
- dbt/jsonschemas/resources/latest.json +6773 -0
- dbt/links.py +4 -0
- dbt/materializations/__init__.py +0 -0
- dbt/materializations/incremental/__init__.py +0 -0
- dbt/materializations/incremental/microbatch.py +236 -0
- dbt/mp_context.py +8 -0
- dbt/node_types.py +37 -0
- dbt/parser/__init__.py +23 -0
- dbt/parser/analysis.py +21 -0
- dbt/parser/base.py +548 -0
- dbt/parser/common.py +266 -0
- dbt/parser/docs.py +52 -0
- dbt/parser/fixtures.py +51 -0
- dbt/parser/functions.py +30 -0
- dbt/parser/generic_test.py +100 -0
- dbt/parser/generic_test_builders.py +333 -0
- dbt/parser/hooks.py +118 -0
- dbt/parser/macros.py +137 -0
- dbt/parser/manifest.py +2204 -0
- dbt/parser/models.py +573 -0
- dbt/parser/partial.py +1178 -0
- dbt/parser/read_files.py +445 -0
- dbt/parser/schema_generic_tests.py +422 -0
- dbt/parser/schema_renderer.py +111 -0
- dbt/parser/schema_yaml_readers.py +935 -0
- dbt/parser/schemas.py +1466 -0
- dbt/parser/search.py +149 -0
- dbt/parser/seeds.py +28 -0
- dbt/parser/singular_test.py +20 -0
- dbt/parser/snapshots.py +44 -0
- dbt/parser/sources.py +558 -0
- dbt/parser/sql.py +62 -0
- dbt/parser/unit_tests.py +621 -0
- dbt/plugins/__init__.py +20 -0
- dbt/plugins/contracts.py +9 -0
- dbt/plugins/exceptions.py +2 -0
- dbt/plugins/manager.py +163 -0
- dbt/plugins/manifest.py +21 -0
- dbt/profiler.py +20 -0
- dbt/py.typed +1 -0
- dbt/query_analyzer.cpython-310-darwin.so +0 -0
- dbt/query_analyzer.py +410 -0
- dbt/runners/__init__.py +2 -0
- dbt/runners/exposure_runner.py +7 -0
- dbt/runners/no_op_runner.py +45 -0
- dbt/runners/saved_query_runner.py +7 -0
- dbt/selected_resources.py +8 -0
- dbt/task/__init__.py +0 -0
- dbt/task/base.py +503 -0
- dbt/task/build.py +197 -0
- dbt/task/clean.py +56 -0
- dbt/task/clone.py +161 -0
- dbt/task/compile.py +150 -0
- dbt/task/compute.py +454 -0
- dbt/task/debug.py +505 -0
- dbt/task/deps.py +280 -0
- dbt/task/docs/__init__.py +3 -0
- dbt/task/docs/generate.py +660 -0
- dbt/task/docs/index.html +250 -0
- dbt/task/docs/serve.py +29 -0
- dbt/task/freshness.py +322 -0
- dbt/task/function.py +121 -0
- dbt/task/group_lookup.py +46 -0
- dbt/task/init.py +553 -0
- dbt/task/java.py +316 -0
- dbt/task/list.py +236 -0
- dbt/task/printer.py +175 -0
- dbt/task/retry.py +175 -0
- dbt/task/run.py +1306 -0
- dbt/task/run_operation.py +141 -0
- dbt/task/runnable.py +758 -0
- dbt/task/seed.py +103 -0
- dbt/task/show.py +149 -0
- dbt/task/snapshot.py +56 -0
- dbt/task/spark.py +414 -0
- dbt/task/sql.py +110 -0
- dbt/task/target_sync.py +759 -0
- dbt/task/test.py +464 -0
- dbt/tests/fixtures/__init__.py +1 -0
- dbt/tests/fixtures/project.py +620 -0
- dbt/tests/util.py +651 -0
- dbt/tracking.py +529 -0
- dbt/utils/__init__.py +3 -0
- dbt/utils/artifact_upload.py +151 -0
- dbt/utils/utils.py +408 -0
- dbt/version.py +268 -0
- dvt_cli/__init__.py +72 -0
- dvt_core-0.52.2.dist-info/METADATA +286 -0
- dvt_core-0.52.2.dist-info/RECORD +275 -0
- dvt_core-0.52.2.dist-info/WHEEL +5 -0
- dvt_core-0.52.2.dist-info/entry_points.txt +2 -0
- dvt_core-0.52.2.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from typing import Any, Dict, Optional
|
|
2
|
+
|
|
3
|
+
from dbt.adapters.contracts.connection import AdapterRequiredConfig
|
|
4
|
+
from dbt.constants import DEFAULT_ENV_PLACEHOLDER
|
|
5
|
+
from dbt.context.base import Var, contextmember, contextproperty
|
|
6
|
+
from dbt.context.target import TargetContext
|
|
7
|
+
from dbt.exceptions import EnvVarMissingError, SecretEnvVarLocationError
|
|
8
|
+
from dbt.node_types import NodeType
|
|
9
|
+
from dbt.utils import MultiDict
|
|
10
|
+
from dbt_common.constants import SECRET_ENV_PREFIX
|
|
11
|
+
from dbt_common.context import get_invocation_context
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConfiguredContext(TargetContext):
|
|
15
|
+
# subclasses are SchemaYamlContext, MacroResolvingContext, ManifestContext
|
|
16
|
+
config: AdapterRequiredConfig
|
|
17
|
+
|
|
18
|
+
def __init__(self, config: AdapterRequiredConfig) -> None:
|
|
19
|
+
super().__init__(config.to_target_dict(), config.cli_vars)
|
|
20
|
+
self.config = config
|
|
21
|
+
|
|
22
|
+
@contextproperty()
|
|
23
|
+
def project_name(self) -> str:
|
|
24
|
+
return self.config.project_name
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FQNLookup:
|
|
28
|
+
def __init__(self, package_name: str):
|
|
29
|
+
self.package_name = package_name
|
|
30
|
+
self.fqn = [package_name]
|
|
31
|
+
self.resource_type = NodeType.Model
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ConfiguredVar(Var):
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
context: Dict[str, Any],
|
|
38
|
+
config: AdapterRequiredConfig,
|
|
39
|
+
project_name: str,
|
|
40
|
+
):
|
|
41
|
+
super().__init__(context, config.cli_vars)
|
|
42
|
+
self._config = config
|
|
43
|
+
self._project_name = project_name
|
|
44
|
+
|
|
45
|
+
def __call__(self, var_name, default=Var._VAR_NOTSET):
|
|
46
|
+
my_config = self._config.load_dependencies()[self._project_name]
|
|
47
|
+
|
|
48
|
+
# cli vars > active project > local project
|
|
49
|
+
if var_name in self._config.cli_vars:
|
|
50
|
+
return self._config.cli_vars[var_name]
|
|
51
|
+
|
|
52
|
+
adapter_type = self._config.credentials.type
|
|
53
|
+
lookup = FQNLookup(self._project_name)
|
|
54
|
+
active_vars = self._config.vars.vars_for(lookup, adapter_type)
|
|
55
|
+
|
|
56
|
+
all_vars = MultiDict()
|
|
57
|
+
if self._config.project_name != my_config.project_name:
|
|
58
|
+
all_vars.add(my_config.vars.vars_for(lookup, adapter_type))
|
|
59
|
+
all_vars.add(active_vars)
|
|
60
|
+
|
|
61
|
+
if var_name in all_vars:
|
|
62
|
+
return all_vars[var_name]
|
|
63
|
+
|
|
64
|
+
if default is not Var._VAR_NOTSET:
|
|
65
|
+
return default
|
|
66
|
+
|
|
67
|
+
return self.get_missing_var(var_name)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class SchemaYamlVars:
|
|
71
|
+
def __init__(self):
|
|
72
|
+
self.env_vars = {}
|
|
73
|
+
self.vars = {}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class SchemaYamlContext(ConfiguredContext):
|
|
77
|
+
# subclass is DocsRuntimeContext
|
|
78
|
+
def __init__(self, config, project_name: str, schema_yaml_vars: Optional[SchemaYamlVars]):
|
|
79
|
+
super().__init__(config)
|
|
80
|
+
self._project_name = project_name
|
|
81
|
+
self.schema_yaml_vars = schema_yaml_vars
|
|
82
|
+
|
|
83
|
+
@contextproperty()
|
|
84
|
+
def var(self) -> ConfiguredVar:
|
|
85
|
+
return ConfiguredVar(self._ctx, self.config, self._project_name)
|
|
86
|
+
|
|
87
|
+
@contextmember()
|
|
88
|
+
def env_var(self, var: str, default: Optional[str] = None) -> str:
|
|
89
|
+
return_value = None
|
|
90
|
+
if var.startswith(SECRET_ENV_PREFIX):
|
|
91
|
+
raise SecretEnvVarLocationError(var)
|
|
92
|
+
env = get_invocation_context().env
|
|
93
|
+
if var in env:
|
|
94
|
+
return_value = env[var]
|
|
95
|
+
elif default is not None:
|
|
96
|
+
return_value = default
|
|
97
|
+
|
|
98
|
+
if return_value is not None:
|
|
99
|
+
if self.schema_yaml_vars:
|
|
100
|
+
# If the environment variable is set from a default, store a string indicating
|
|
101
|
+
# that so we can skip partial parsing. Otherwise the file will be scheduled for
|
|
102
|
+
# reparsing. If the default changes, the file will have been updated and therefore
|
|
103
|
+
# will be scheduled for reparsing anyways.
|
|
104
|
+
self.schema_yaml_vars.env_vars[var] = (
|
|
105
|
+
return_value if var in env else DEFAULT_ENV_PLACEHOLDER
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return return_value
|
|
109
|
+
else:
|
|
110
|
+
raise EnvVarMissingError(var)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class MacroResolvingContext(ConfiguredContext):
|
|
114
|
+
def __init__(self, config):
|
|
115
|
+
super().__init__(config)
|
|
116
|
+
|
|
117
|
+
@contextproperty()
|
|
118
|
+
def var(self) -> ConfiguredVar:
|
|
119
|
+
return ConfiguredVar(self._ctx, self.config, self.config.project_name)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def generate_schema_yml_context(
|
|
123
|
+
config: AdapterRequiredConfig,
|
|
124
|
+
project_name: str,
|
|
125
|
+
schema_yaml_vars: Optional[SchemaYamlVars] = None,
|
|
126
|
+
) -> Dict[str, Any]:
|
|
127
|
+
ctx = SchemaYamlContext(config, project_name, schema_yaml_vars)
|
|
128
|
+
return ctx.to_dict()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def generate_macro_context(
|
|
132
|
+
config: AdapterRequiredConfig,
|
|
133
|
+
) -> Dict[str, Any]:
|
|
134
|
+
ctx = MacroResolvingContext(config)
|
|
135
|
+
return ctx.to_dict()
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from copy import deepcopy
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Dict, Generic, Iterator, List, Optional, TypeVar
|
|
5
|
+
|
|
6
|
+
from dbt.adapters.factory import get_config_class_by_name
|
|
7
|
+
from dbt.config import IsFQNResource, Project, RuntimeConfig
|
|
8
|
+
from dbt.contracts.graph.model_config import get_config_for
|
|
9
|
+
from dbt.exceptions import SchemaConfigError
|
|
10
|
+
from dbt.flags import get_flags
|
|
11
|
+
from dbt.node_types import NodeType
|
|
12
|
+
from dbt.utils import fqn_search
|
|
13
|
+
from dbt_common.contracts.config.base import BaseConfig, merge_config_dicts
|
|
14
|
+
from dbt_common.dataclass_schema import ValidationError
|
|
15
|
+
from dbt_common.exceptions import DbtInternalError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class ModelParts(IsFQNResource):
|
|
20
|
+
fqn: List[str]
|
|
21
|
+
resource_type: NodeType
|
|
22
|
+
package_name: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
T = TypeVar("T") # any old type
|
|
26
|
+
C = TypeVar("C", bound=BaseConfig)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ConfigSource:
|
|
30
|
+
def __init__(self, project):
|
|
31
|
+
self.project = project
|
|
32
|
+
|
|
33
|
+
def get_config_dict(self, resource_type: NodeType): ...
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class UnrenderedConfig(ConfigSource):
|
|
37
|
+
def __init__(self, project: Project):
|
|
38
|
+
self.project = project
|
|
39
|
+
|
|
40
|
+
def get_config_dict(self, resource_type: NodeType) -> Dict[str, Any]:
|
|
41
|
+
unrendered = self.project.unrendered.project_dict
|
|
42
|
+
if resource_type == NodeType.Seed:
|
|
43
|
+
model_configs = unrendered.get("seeds")
|
|
44
|
+
elif resource_type == NodeType.Snapshot:
|
|
45
|
+
model_configs = unrendered.get("snapshots")
|
|
46
|
+
elif resource_type == NodeType.Source:
|
|
47
|
+
model_configs = unrendered.get("sources")
|
|
48
|
+
elif resource_type == NodeType.Test:
|
|
49
|
+
model_configs = unrendered.get("data_tests")
|
|
50
|
+
elif resource_type == NodeType.Metric:
|
|
51
|
+
model_configs = unrendered.get("metrics")
|
|
52
|
+
elif resource_type == NodeType.SemanticModel:
|
|
53
|
+
model_configs = unrendered.get("semantic_models")
|
|
54
|
+
elif resource_type == NodeType.SavedQuery:
|
|
55
|
+
model_configs = unrendered.get("saved_queries")
|
|
56
|
+
elif resource_type == NodeType.Exposure:
|
|
57
|
+
model_configs = unrendered.get("exposures")
|
|
58
|
+
elif resource_type == NodeType.Unit:
|
|
59
|
+
model_configs = unrendered.get("unit_tests")
|
|
60
|
+
else:
|
|
61
|
+
model_configs = unrendered.get("models")
|
|
62
|
+
if model_configs is None:
|
|
63
|
+
return {}
|
|
64
|
+
else:
|
|
65
|
+
return model_configs
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class RenderedConfig(ConfigSource):
|
|
69
|
+
def __init__(self, project: Project):
|
|
70
|
+
self.project = project
|
|
71
|
+
|
|
72
|
+
def get_config_dict(self, resource_type: NodeType) -> Dict[str, Any]:
|
|
73
|
+
if resource_type == NodeType.Seed:
|
|
74
|
+
model_configs = self.project.seeds
|
|
75
|
+
elif resource_type == NodeType.Snapshot:
|
|
76
|
+
model_configs = self.project.snapshots
|
|
77
|
+
elif resource_type == NodeType.Source:
|
|
78
|
+
model_configs = self.project.sources
|
|
79
|
+
elif resource_type == NodeType.Test:
|
|
80
|
+
model_configs = self.project.data_tests
|
|
81
|
+
elif resource_type == NodeType.Metric:
|
|
82
|
+
model_configs = self.project.metrics
|
|
83
|
+
elif resource_type == NodeType.SemanticModel:
|
|
84
|
+
model_configs = self.project.semantic_models
|
|
85
|
+
elif resource_type == NodeType.SavedQuery:
|
|
86
|
+
model_configs = self.project.saved_queries
|
|
87
|
+
elif resource_type == NodeType.Exposure:
|
|
88
|
+
model_configs = self.project.exposures
|
|
89
|
+
elif resource_type == NodeType.Unit:
|
|
90
|
+
model_configs = self.project.unit_tests
|
|
91
|
+
elif resource_type == NodeType.Function:
|
|
92
|
+
model_configs = self.project.functions
|
|
93
|
+
else:
|
|
94
|
+
model_configs = self.project.models
|
|
95
|
+
return model_configs
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class BaseContextConfigGenerator(Generic[T]):
|
|
99
|
+
def __init__(self, active_project: RuntimeConfig):
|
|
100
|
+
self._active_project = active_project
|
|
101
|
+
|
|
102
|
+
def get_config_source(self, project: Project) -> ConfigSource:
|
|
103
|
+
return RenderedConfig(project)
|
|
104
|
+
|
|
105
|
+
def get_node_project(self, project_name: str):
|
|
106
|
+
if project_name == self._active_project.project_name:
|
|
107
|
+
return self._active_project
|
|
108
|
+
dependencies = self._active_project.load_dependencies()
|
|
109
|
+
if project_name not in dependencies:
|
|
110
|
+
raise DbtInternalError(
|
|
111
|
+
f"Project name {project_name} not found in dependencies "
|
|
112
|
+
f"(found {list(dependencies)})"
|
|
113
|
+
)
|
|
114
|
+
return dependencies[project_name]
|
|
115
|
+
|
|
116
|
+
def _project_configs(
|
|
117
|
+
self, project: Project, fqn: List[str], resource_type: NodeType
|
|
118
|
+
) -> Iterator[Dict[str, Any]]:
|
|
119
|
+
src = self.get_config_source(project)
|
|
120
|
+
model_configs = src.get_config_dict(resource_type)
|
|
121
|
+
for level_config in fqn_search(model_configs, fqn):
|
|
122
|
+
result = {}
|
|
123
|
+
for key, value in level_config.items():
|
|
124
|
+
if key.startswith("+"):
|
|
125
|
+
result[key[1:].strip()] = deepcopy(value)
|
|
126
|
+
elif not isinstance(value, dict):
|
|
127
|
+
result[key] = deepcopy(value)
|
|
128
|
+
|
|
129
|
+
yield result
|
|
130
|
+
|
|
131
|
+
def _active_project_configs(
|
|
132
|
+
self, fqn: List[str], resource_type: NodeType
|
|
133
|
+
) -> Iterator[Dict[str, Any]]:
|
|
134
|
+
return self._project_configs(self._active_project, fqn, resource_type)
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
def _update_from_config(
|
|
138
|
+
self, result: T, partial: Dict[str, Any], validate: bool = False
|
|
139
|
+
) -> T: ...
|
|
140
|
+
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def initial_result(self, resource_type: NodeType, base: bool) -> T: ...
|
|
143
|
+
|
|
144
|
+
def calculate_node_config(
|
|
145
|
+
self,
|
|
146
|
+
# this is the config from the sql file
|
|
147
|
+
config_call_dict: Dict[str, Any],
|
|
148
|
+
fqn: List[str],
|
|
149
|
+
resource_type: NodeType,
|
|
150
|
+
project_name: str,
|
|
151
|
+
base: bool,
|
|
152
|
+
# this is the config from the schema file
|
|
153
|
+
patch_config_dict: Optional[Dict[str, Any]] = None,
|
|
154
|
+
) -> BaseConfig:
|
|
155
|
+
own_config = self.get_node_project(project_name)
|
|
156
|
+
|
|
157
|
+
result = self.initial_result(resource_type=resource_type, base=base)
|
|
158
|
+
|
|
159
|
+
# builds the config from what was specified in the runtime_config, which generally
|
|
160
|
+
# comes from the project's dbt_project.yml file.
|
|
161
|
+
project_configs = self._project_configs(own_config, fqn, resource_type)
|
|
162
|
+
for fqn_config in project_configs:
|
|
163
|
+
result = self._update_from_config(result, fqn_config)
|
|
164
|
+
|
|
165
|
+
# When schema files patch config, it has lower precedence than
|
|
166
|
+
# config in the models (config_call_dict), so we add the patch_config_dict
|
|
167
|
+
# before the config_call_dict
|
|
168
|
+
if patch_config_dict:
|
|
169
|
+
result = self._update_from_config(result, patch_config_dict)
|
|
170
|
+
|
|
171
|
+
# config_calls are created in the 'experimental' model parser and
|
|
172
|
+
# the ParseConfigObject (via add_config_call)
|
|
173
|
+
result = self._update_from_config(result, config_call_dict)
|
|
174
|
+
|
|
175
|
+
if own_config.project_name != self._active_project.project_name:
|
|
176
|
+
for fqn_config in self._active_project_configs(fqn, resource_type):
|
|
177
|
+
result = self._update_from_config(result, fqn_config)
|
|
178
|
+
|
|
179
|
+
# this is mostly impactful in the snapshot config case
|
|
180
|
+
# TODO CT-211
|
|
181
|
+
return result # type: ignore[return-value]
|
|
182
|
+
|
|
183
|
+
@abstractmethod
|
|
184
|
+
def calculate_node_config_dict(
|
|
185
|
+
self,
|
|
186
|
+
config_call_dict: Dict[str, Any],
|
|
187
|
+
fqn: List[str],
|
|
188
|
+
resource_type: NodeType,
|
|
189
|
+
project_name: str,
|
|
190
|
+
base: bool,
|
|
191
|
+
patch_config_dict: Optional[Dict[str, Any]] = None,
|
|
192
|
+
) -> Dict[str, Any]: ...
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class ContextConfigGenerator(BaseContextConfigGenerator[C]):
|
|
196
|
+
def __init__(self, active_project: RuntimeConfig):
|
|
197
|
+
self._active_project = active_project
|
|
198
|
+
|
|
199
|
+
def get_config_source(self, project: Project) -> ConfigSource:
|
|
200
|
+
return RenderedConfig(project)
|
|
201
|
+
|
|
202
|
+
def initial_result(self, resource_type: NodeType, base: bool) -> C:
|
|
203
|
+
# defaults, own_config, config calls, active_config (if != own_config)
|
|
204
|
+
config_cls = get_config_for(resource_type, base=base)
|
|
205
|
+
# Calculate the defaults. We don't want to validate the defaults,
|
|
206
|
+
# because it might be invalid in the case of required config members
|
|
207
|
+
# (such as on snapshots!)
|
|
208
|
+
result = config_cls.from_dict({})
|
|
209
|
+
return result
|
|
210
|
+
|
|
211
|
+
def _get_target_adapter_type(self, config: Dict[str, Any]) -> str:
|
|
212
|
+
"""
|
|
213
|
+
Determine which adapter type to use for config merging.
|
|
214
|
+
|
|
215
|
+
If model specifies 'target' override, use that target's adapter type.
|
|
216
|
+
Otherwise, use the default target's adapter type.
|
|
217
|
+
|
|
218
|
+
This enables adapter-specific configs (like Redshift dist/sort,
|
|
219
|
+
BigQuery partition_by, Snowflake transient) to work correctly
|
|
220
|
+
when materializing to non-default targets in federated mode.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
config: Model configuration dictionary
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Adapter type name (e.g., 'postgres', 'snowflake', 'redshift')
|
|
227
|
+
"""
|
|
228
|
+
target_name = config.get('target')
|
|
229
|
+
|
|
230
|
+
if target_name:
|
|
231
|
+
# Model has target override - use that adapter's type
|
|
232
|
+
if hasattr(self._active_project, 'outputs'):
|
|
233
|
+
# DVTProfile with multiple outputs
|
|
234
|
+
target_creds = self._active_project.outputs.get(target_name)
|
|
235
|
+
if target_creds:
|
|
236
|
+
return target_creds.type
|
|
237
|
+
# Target name not found in outputs - fall back to default
|
|
238
|
+
# This maintains backward compatibility
|
|
239
|
+
|
|
240
|
+
# No target override, or target not found - use default
|
|
241
|
+
return self._active_project.credentials.type
|
|
242
|
+
|
|
243
|
+
def _update_from_config(self, result: C, partial: Dict[str, Any], validate: bool = False) -> C:
|
|
244
|
+
translated = self._active_project.credentials.translate_aliases(partial)
|
|
245
|
+
translated = self.translate_hook_names(translated)
|
|
246
|
+
|
|
247
|
+
# ENHANCEMENT (v0.2.3): Use target adapter type if specified
|
|
248
|
+
adapter_type = self._get_target_adapter_type(partial)
|
|
249
|
+
adapter_config_cls = get_config_class_by_name(adapter_type)
|
|
250
|
+
|
|
251
|
+
updated = result.update_from(translated, adapter_config_cls, validate=validate)
|
|
252
|
+
return updated
|
|
253
|
+
|
|
254
|
+
def translate_hook_names(self, project_dict):
|
|
255
|
+
# This is a kind of kludge because the fix for #6411 specifically allowed misspelling
|
|
256
|
+
# the hook field names in dbt_project.yml, which only ever worked because we didn't
|
|
257
|
+
# run validate on the dbt_project configs.
|
|
258
|
+
if "pre_hook" in project_dict:
|
|
259
|
+
project_dict["pre-hook"] = project_dict.pop("pre_hook")
|
|
260
|
+
if "post_hook" in project_dict:
|
|
261
|
+
project_dict["post-hook"] = project_dict.pop("post_hook")
|
|
262
|
+
return project_dict
|
|
263
|
+
|
|
264
|
+
def calculate_node_config_dict(
|
|
265
|
+
self,
|
|
266
|
+
config_call_dict: Dict[str, Any],
|
|
267
|
+
fqn: List[str],
|
|
268
|
+
resource_type: NodeType,
|
|
269
|
+
project_name: str,
|
|
270
|
+
base: bool,
|
|
271
|
+
patch_config_dict: Optional[dict] = None,
|
|
272
|
+
) -> Dict[str, Any]:
|
|
273
|
+
config = self.calculate_node_config(
|
|
274
|
+
config_call_dict=config_call_dict,
|
|
275
|
+
fqn=fqn,
|
|
276
|
+
resource_type=resource_type,
|
|
277
|
+
project_name=project_name,
|
|
278
|
+
base=base,
|
|
279
|
+
patch_config_dict=patch_config_dict,
|
|
280
|
+
)
|
|
281
|
+
try:
|
|
282
|
+
finalized = config.finalize_and_validate()
|
|
283
|
+
return finalized.to_dict(omit_none=True)
|
|
284
|
+
except ValidationError as exc:
|
|
285
|
+
# we got a ValidationError - probably bad types in config()
|
|
286
|
+
raise SchemaConfigError(exc, node=config) from exc
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class UnrenderedConfigGenerator(BaseContextConfigGenerator[Dict[str, Any]]):
|
|
290
|
+
def get_config_source(self, project: Project) -> ConfigSource:
|
|
291
|
+
return UnrenderedConfig(project)
|
|
292
|
+
|
|
293
|
+
def calculate_node_config_dict(
|
|
294
|
+
self,
|
|
295
|
+
config_call_dict: Dict[str, Any],
|
|
296
|
+
fqn: List[str],
|
|
297
|
+
resource_type: NodeType,
|
|
298
|
+
project_name: str,
|
|
299
|
+
base: bool,
|
|
300
|
+
patch_config_dict: Optional[dict] = None,
|
|
301
|
+
) -> Dict[str, Any]:
|
|
302
|
+
# TODO CT-211
|
|
303
|
+
return self.calculate_node_config(
|
|
304
|
+
config_call_dict=config_call_dict,
|
|
305
|
+
fqn=fqn,
|
|
306
|
+
resource_type=resource_type,
|
|
307
|
+
project_name=project_name,
|
|
308
|
+
base=base,
|
|
309
|
+
patch_config_dict=patch_config_dict,
|
|
310
|
+
) # type: ignore[return-value]
|
|
311
|
+
|
|
312
|
+
def initial_result(self, resource_type: NodeType, base: bool) -> Dict[str, Any]:
|
|
313
|
+
return {}
|
|
314
|
+
|
|
315
|
+
def _update_from_config(
|
|
316
|
+
self,
|
|
317
|
+
result: Dict[str, Any],
|
|
318
|
+
partial: Dict[str, Any],
|
|
319
|
+
validate: bool = False,
|
|
320
|
+
) -> Dict[str, Any]:
|
|
321
|
+
translated = self._active_project.credentials.translate_aliases(partial)
|
|
322
|
+
result.update(translated)
|
|
323
|
+
return result
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
class ContextConfig:
|
|
327
|
+
def __init__(
|
|
328
|
+
self,
|
|
329
|
+
active_project: RuntimeConfig,
|
|
330
|
+
fqn: List[str],
|
|
331
|
+
resource_type: NodeType,
|
|
332
|
+
project_name: str,
|
|
333
|
+
) -> None:
|
|
334
|
+
self._config_call_dict: Dict[str, Any] = {}
|
|
335
|
+
self._unrendered_config_call_dict: Dict[str, Any] = {}
|
|
336
|
+
self._active_project = active_project
|
|
337
|
+
self._fqn = fqn
|
|
338
|
+
self._resource_type = resource_type
|
|
339
|
+
self._project_name = project_name
|
|
340
|
+
|
|
341
|
+
def add_config_call(self, opts: Dict[str, Any]) -> None:
|
|
342
|
+
dct = self._config_call_dict
|
|
343
|
+
merge_config_dicts(dct, opts)
|
|
344
|
+
|
|
345
|
+
def add_unrendered_config_call(self, opts: Dict[str, Any]) -> None:
|
|
346
|
+
# Cannot perform complex merge behaviours on unrendered configs as they may not be appropriate types.
|
|
347
|
+
self._unrendered_config_call_dict.update(opts)
|
|
348
|
+
|
|
349
|
+
def build_config_dict(
|
|
350
|
+
self,
|
|
351
|
+
base: bool = False,
|
|
352
|
+
*,
|
|
353
|
+
rendered: bool = True,
|
|
354
|
+
patch_config_dict: Optional[dict] = None,
|
|
355
|
+
) -> Dict[str, Any]:
|
|
356
|
+
if rendered:
|
|
357
|
+
# TODO CT-211
|
|
358
|
+
src = ContextConfigGenerator(self._active_project) # type: ignore[var-annotated]
|
|
359
|
+
config_call_dict = self._config_call_dict
|
|
360
|
+
else:
|
|
361
|
+
# TODO CT-211
|
|
362
|
+
src = UnrenderedConfigGenerator(self._active_project) # type: ignore[assignment]
|
|
363
|
+
|
|
364
|
+
# preserve legacy behaviour - using unreliable (potentially rendered) _config_call_dict
|
|
365
|
+
if get_flags().state_modified_compare_more_unrendered_values is False:
|
|
366
|
+
config_call_dict = self._config_call_dict
|
|
367
|
+
else:
|
|
368
|
+
# Prefer _config_call_dict if it is available and _unrendered_config_call_dict is not,
|
|
369
|
+
# as _unrendered_config_call_dict is unreliable for non-sql nodes (e.g. no jinja config block rendered for python models, etc)
|
|
370
|
+
if self._config_call_dict and not self._unrendered_config_call_dict:
|
|
371
|
+
config_call_dict = self._config_call_dict
|
|
372
|
+
else:
|
|
373
|
+
config_call_dict = self._unrendered_config_call_dict
|
|
374
|
+
|
|
375
|
+
return src.calculate_node_config_dict(
|
|
376
|
+
config_call_dict=config_call_dict,
|
|
377
|
+
fqn=self._fqn,
|
|
378
|
+
resource_type=self._resource_type,
|
|
379
|
+
project_name=self._project_name,
|
|
380
|
+
base=base,
|
|
381
|
+
patch_config_dict=patch_config_dict,
|
|
382
|
+
)
|
dbt/context/docs.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from typing import Any, Dict, Union
|
|
2
|
+
|
|
3
|
+
from dbt.config.runtime import RuntimeConfig
|
|
4
|
+
from dbt.context.base import contextmember
|
|
5
|
+
from dbt.context.configured import SchemaYamlContext
|
|
6
|
+
from dbt.contracts.graph.manifest import Manifest
|
|
7
|
+
from dbt.contracts.graph.nodes import Macro, ResultNode
|
|
8
|
+
from dbt.exceptions import DocArgsError, DocTargetNotFoundError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DocsRuntimeContext(SchemaYamlContext):
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
config: RuntimeConfig,
|
|
15
|
+
node: Union[Macro, ResultNode],
|
|
16
|
+
manifest: Manifest,
|
|
17
|
+
current_project: str,
|
|
18
|
+
) -> None:
|
|
19
|
+
super().__init__(config, current_project, None)
|
|
20
|
+
self.node = node
|
|
21
|
+
self.manifest = manifest
|
|
22
|
+
|
|
23
|
+
@contextmember()
|
|
24
|
+
def doc(self, *args: str) -> str:
|
|
25
|
+
"""The `doc` function is used to reference docs blocks in schema.yml
|
|
26
|
+
files. It is analogous to the `ref` function. For more information,
|
|
27
|
+
consult the Documentation guide.
|
|
28
|
+
|
|
29
|
+
> orders.md:
|
|
30
|
+
|
|
31
|
+
{% docs orders %}
|
|
32
|
+
# docs
|
|
33
|
+
- go
|
|
34
|
+
- here
|
|
35
|
+
{% enddocs %}
|
|
36
|
+
|
|
37
|
+
> schema.yml
|
|
38
|
+
|
|
39
|
+
version: 2
|
|
40
|
+
models:
|
|
41
|
+
- name: orders
|
|
42
|
+
description: "{{ doc('orders') }}"
|
|
43
|
+
"""
|
|
44
|
+
# when you call doc(), this is what happens at runtime
|
|
45
|
+
if len(args) == 1:
|
|
46
|
+
doc_package_name = None
|
|
47
|
+
doc_name = args[0]
|
|
48
|
+
elif len(args) == 2:
|
|
49
|
+
doc_package_name, doc_name = args
|
|
50
|
+
else:
|
|
51
|
+
raise DocArgsError(self.node, args)
|
|
52
|
+
|
|
53
|
+
# Documentation
|
|
54
|
+
target_doc = self.manifest.resolve_doc(
|
|
55
|
+
doc_name,
|
|
56
|
+
doc_package_name,
|
|
57
|
+
self._project_name,
|
|
58
|
+
self.node.package_name,
|
|
59
|
+
)
|
|
60
|
+
if target_doc:
|
|
61
|
+
file_id = target_doc.file_id
|
|
62
|
+
if file_id in self.manifest.files:
|
|
63
|
+
source_file = self.manifest.files[file_id]
|
|
64
|
+
# TODO CT-211
|
|
65
|
+
source_file.add_node(self.node.unique_id) # type: ignore[union-attr]
|
|
66
|
+
else:
|
|
67
|
+
raise DocTargetNotFoundError(
|
|
68
|
+
node=self.node, target_doc_name=doc_name, target_doc_package=doc_package_name
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return target_doc.block_contents
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def generate_runtime_docs_context(
|
|
75
|
+
config: RuntimeConfig,
|
|
76
|
+
target: Any,
|
|
77
|
+
manifest: Manifest,
|
|
78
|
+
current_project: str,
|
|
79
|
+
) -> Dict[str, Any]:
|
|
80
|
+
ctx = DocsRuntimeContext(config, target, manifest, current_project)
|
|
81
|
+
# This is not a Mashumaro to_dict call
|
|
82
|
+
return ctx.to_dict()
|