mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-19 17:31:28 +00:00
Compare commits
1 Commits
jerco/unit
...
adding-sem
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2da925aa25 |
6
.changes/unreleased/Features-20230118-134804.yaml
Normal file
6
.changes/unreleased/Features-20230118-134804.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
kind: Features
|
||||||
|
body: Adding the entity node
|
||||||
|
time: 2023-01-18T13:48:04.487817-06:00
|
||||||
|
custom:
|
||||||
|
Author: callum-mcdata
|
||||||
|
Issue: "6627"
|
||||||
@@ -48,6 +48,7 @@ def print_compile_stats(stats):
|
|||||||
NodeType.Source: "source",
|
NodeType.Source: "source",
|
||||||
NodeType.Exposure: "exposure",
|
NodeType.Exposure: "exposure",
|
||||||
NodeType.Metric: "metric",
|
NodeType.Metric: "metric",
|
||||||
|
NodeType.Entity: "entity",
|
||||||
}
|
}
|
||||||
|
|
||||||
results = {k: 0 for k in names.keys()}
|
results = {k: 0 for k in names.keys()}
|
||||||
@@ -83,6 +84,8 @@ def _generate_stats(manifest: Manifest):
|
|||||||
stats[exposure.resource_type] += 1
|
stats[exposure.resource_type] += 1
|
||||||
for metric in manifest.metrics.values():
|
for metric in manifest.metrics.values():
|
||||||
stats[metric.resource_type] += 1
|
stats[metric.resource_type] += 1
|
||||||
|
for entity in manifest.entities.values():
|
||||||
|
stats[entity.resource_type] += 1
|
||||||
for macro in manifest.macros.values():
|
for macro in manifest.macros.values():
|
||||||
stats[macro.resource_type] += 1
|
stats[macro.resource_type] += 1
|
||||||
return stats
|
return stats
|
||||||
@@ -398,6 +401,8 @@ class Compiler:
|
|||||||
linker.dependency(node.unique_id, (manifest.sources[dependency].unique_id))
|
linker.dependency(node.unique_id, (manifest.sources[dependency].unique_id))
|
||||||
elif dependency in manifest.metrics:
|
elif dependency in manifest.metrics:
|
||||||
linker.dependency(node.unique_id, (manifest.metrics[dependency].unique_id))
|
linker.dependency(node.unique_id, (manifest.metrics[dependency].unique_id))
|
||||||
|
elif dependency in manifest.entities:
|
||||||
|
linker.dependency(node.unique_id, (manifest.entities[dependency].unique_id))
|
||||||
else:
|
else:
|
||||||
raise GraphDependencyNotFoundError(node, dependency)
|
raise GraphDependencyNotFoundError(node, dependency)
|
||||||
|
|
||||||
@@ -410,6 +415,8 @@ class Compiler:
|
|||||||
self.link_node(linker, exposure, manifest)
|
self.link_node(linker, exposure, manifest)
|
||||||
for metric in manifest.metrics.values():
|
for metric in manifest.metrics.values():
|
||||||
self.link_node(linker, metric, manifest)
|
self.link_node(linker, metric, manifest)
|
||||||
|
for entity in manifest.entities.values():
|
||||||
|
self.link_node(linker, entity, manifest)
|
||||||
|
|
||||||
cycle = linker.find_cycles()
|
cycle = linker.find_cycles()
|
||||||
|
|
||||||
|
|||||||
@@ -381,6 +381,7 @@ class PartialProject(RenderComponents):
|
|||||||
sources: Dict[str, Any]
|
sources: Dict[str, Any]
|
||||||
tests: Dict[str, Any]
|
tests: Dict[str, Any]
|
||||||
metrics: Dict[str, Any]
|
metrics: Dict[str, Any]
|
||||||
|
entities: Dict[str, Any]
|
||||||
exposures: Dict[str, Any]
|
exposures: Dict[str, Any]
|
||||||
vars_value: VarProvider
|
vars_value: VarProvider
|
||||||
|
|
||||||
@@ -391,6 +392,7 @@ class PartialProject(RenderComponents):
|
|||||||
sources = cfg.sources
|
sources = cfg.sources
|
||||||
tests = cfg.tests
|
tests = cfg.tests
|
||||||
metrics = cfg.metrics
|
metrics = cfg.metrics
|
||||||
|
entities = cfg.entities
|
||||||
exposures = cfg.exposures
|
exposures = cfg.exposures
|
||||||
if cfg.vars is None:
|
if cfg.vars is None:
|
||||||
vars_dict: Dict[str, Any] = {}
|
vars_dict: Dict[str, Any] = {}
|
||||||
@@ -446,6 +448,7 @@ class PartialProject(RenderComponents):
|
|||||||
sources=sources,
|
sources=sources,
|
||||||
tests=tests,
|
tests=tests,
|
||||||
metrics=metrics,
|
metrics=metrics,
|
||||||
|
entities=entities,
|
||||||
exposures=exposures,
|
exposures=exposures,
|
||||||
vars=vars_value,
|
vars=vars_value,
|
||||||
config_version=cfg.config_version,
|
config_version=cfg.config_version,
|
||||||
@@ -550,6 +553,7 @@ class Project:
|
|||||||
sources: Dict[str, Any]
|
sources: Dict[str, Any]
|
||||||
tests: Dict[str, Any]
|
tests: Dict[str, Any]
|
||||||
metrics: Dict[str, Any]
|
metrics: Dict[str, Any]
|
||||||
|
entities: Dict[str, Any]
|
||||||
exposures: Dict[str, Any]
|
exposures: Dict[str, Any]
|
||||||
vars: VarProvider
|
vars: VarProvider
|
||||||
dbt_version: List[VersionSpecifier]
|
dbt_version: List[VersionSpecifier]
|
||||||
@@ -624,6 +628,7 @@ class Project:
|
|||||||
"sources": self.sources,
|
"sources": self.sources,
|
||||||
"tests": self.tests,
|
"tests": self.tests,
|
||||||
"metrics": self.metrics,
|
"metrics": self.metrics,
|
||||||
|
"entities": self.entities,
|
||||||
"exposures": self.exposures,
|
"exposures": self.exposures,
|
||||||
"vars": self.vars.to_dict(),
|
"vars": self.vars.to_dict(),
|
||||||
"require-dbt-version": [v.to_version_string() for v in self.dbt_version],
|
"require-dbt-version": [v.to_version_string() for v in self.dbt_version],
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class RuntimeConfig(Project, Profile, AdapterRequiredConfig):
|
|||||||
sources=project.sources,
|
sources=project.sources,
|
||||||
tests=project.tests,
|
tests=project.tests,
|
||||||
metrics=project.metrics,
|
metrics=project.metrics,
|
||||||
|
entities=project.entities,
|
||||||
exposures=project.exposures,
|
exposures=project.exposures,
|
||||||
vars=project.vars,
|
vars=project.vars,
|
||||||
config_version=project.config_version,
|
config_version=project.config_version,
|
||||||
@@ -312,6 +313,7 @@ class RuntimeConfig(Project, Profile, AdapterRequiredConfig):
|
|||||||
"sources": self._get_config_paths(self.sources),
|
"sources": self._get_config_paths(self.sources),
|
||||||
"tests": self._get_config_paths(self.tests),
|
"tests": self._get_config_paths(self.tests),
|
||||||
"metrics": self._get_config_paths(self.metrics),
|
"metrics": self._get_config_paths(self.metrics),
|
||||||
|
"entities": self._get_config_paths(self.entities),
|
||||||
"exposures": self._get_config_paths(self.exposures),
|
"exposures": self._get_config_paths(self.exposures),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,6 +502,7 @@ class UnsetProfileConfig(RuntimeConfig):
|
|||||||
"sources": self.sources,
|
"sources": self.sources,
|
||||||
"tests": self.tests,
|
"tests": self.tests,
|
||||||
"metrics": self.metrics,
|
"metrics": self.metrics,
|
||||||
|
"entities": self.entities,
|
||||||
"exposures": self.exposures,
|
"exposures": self.exposures,
|
||||||
"vars": self.vars.to_dict(),
|
"vars": self.vars.to_dict(),
|
||||||
"require-dbt-version": [v.to_version_string() for v in self.dbt_version],
|
"require-dbt-version": [v.to_version_string() for v in self.dbt_version],
|
||||||
@@ -562,6 +565,7 @@ class UnsetProfileConfig(RuntimeConfig):
|
|||||||
sources=project.sources,
|
sources=project.sources,
|
||||||
tests=project.tests,
|
tests=project.tests,
|
||||||
metrics=project.metrics,
|
metrics=project.metrics,
|
||||||
|
entities=project.entities,
|
||||||
exposures=project.exposures,
|
exposures=project.exposures,
|
||||||
vars=project.vars,
|
vars=project.vars,
|
||||||
config_version=project.config_version,
|
config_version=project.config_version,
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ class UnrenderedConfig(ConfigSource):
|
|||||||
model_configs = unrendered.get("tests")
|
model_configs = unrendered.get("tests")
|
||||||
elif resource_type == NodeType.Metric:
|
elif resource_type == NodeType.Metric:
|
||||||
model_configs = unrendered.get("metrics")
|
model_configs = unrendered.get("metrics")
|
||||||
|
elif resource_type == NodeType.Entity:
|
||||||
|
model_configs = unrendered.get("entities")
|
||||||
elif resource_type == NodeType.Exposure:
|
elif resource_type == NodeType.Exposure:
|
||||||
model_configs = unrendered.get("exposures")
|
model_configs = unrendered.get("exposures")
|
||||||
else:
|
else:
|
||||||
@@ -70,6 +72,8 @@ class RenderedConfig(ConfigSource):
|
|||||||
model_configs = self.project.tests
|
model_configs = self.project.tests
|
||||||
elif resource_type == NodeType.Metric:
|
elif resource_type == NodeType.Metric:
|
||||||
model_configs = self.project.metrics
|
model_configs = self.project.metrics
|
||||||
|
elif resource_type == NodeType.Entity:
|
||||||
|
model_configs = self.project.entities
|
||||||
elif resource_type == NodeType.Exposure:
|
elif resource_type == NodeType.Exposure:
|
||||||
model_configs = self.project.exposures
|
model_configs = self.project.exposures
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
Macro,
|
Macro,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
SeedNode,
|
SeedNode,
|
||||||
SourceDefinition,
|
SourceDefinition,
|
||||||
Resource,
|
Resource,
|
||||||
@@ -1504,6 +1505,44 @@ def generate_parse_metrics(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class EntityRefResolver(BaseResolver):
|
||||||
|
def __call__(self, *args) -> str:
|
||||||
|
package = None
|
||||||
|
if len(args) == 1:
|
||||||
|
name = args[0]
|
||||||
|
elif len(args) == 2:
|
||||||
|
package, name = args
|
||||||
|
else:
|
||||||
|
raise RefArgsError(node=self.model, args=args)
|
||||||
|
self.validate_args(name, package)
|
||||||
|
self.model.refs.append(list(args))
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def validate_args(self, name, package):
|
||||||
|
if not isinstance(name, str):
|
||||||
|
raise ParsingError(
|
||||||
|
f"In the entity associated with {self.model.original_file_path} "
|
||||||
|
"the name argument to ref() must be a string"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_parse_entities(
|
||||||
|
entity: Entity,
|
||||||
|
config: RuntimeConfig,
|
||||||
|
manifest: Manifest,
|
||||||
|
package_name: str,
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
project = config.load_dependencies()[package_name]
|
||||||
|
return {
|
||||||
|
"ref": EntityRefResolver(
|
||||||
|
None,
|
||||||
|
entity,
|
||||||
|
project,
|
||||||
|
manifest,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# This class is currently used by the schema parser in order
|
# This class is currently used by the schema parser in order
|
||||||
# to limit the number of macros in the context by using
|
# to limit the number of macros in the context by using
|
||||||
# the TestMacroNamespace
|
# the TestMacroNamespace
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ class SchemaSourceFile(BaseSourceFile):
|
|||||||
sources: List[str] = field(default_factory=list)
|
sources: List[str] = field(default_factory=list)
|
||||||
exposures: List[str] = field(default_factory=list)
|
exposures: List[str] = field(default_factory=list)
|
||||||
metrics: List[str] = field(default_factory=list)
|
metrics: List[str] = field(default_factory=list)
|
||||||
|
entities: List[str] = field(default_factory=list)
|
||||||
# node patches contain models, seeds, snapshots, analyses
|
# node patches contain models, seeds, snapshots, analyses
|
||||||
ndp: List[str] = field(default_factory=list)
|
ndp: List[str] = field(default_factory=list)
|
||||||
# any macro patches in this file by macro unique_id.
|
# any macro patches in this file by macro unique_id.
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
GenericTestNode,
|
GenericTestNode,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
UnpatchedSourceDefinition,
|
UnpatchedSourceDefinition,
|
||||||
ManifestNode,
|
ManifestNode,
|
||||||
GraphMemberNode,
|
GraphMemberNode,
|
||||||
@@ -212,6 +213,39 @@ class MetricLookup(dbtClassMixin):
|
|||||||
return manifest.metrics[unique_id]
|
return manifest.metrics[unique_id]
|
||||||
|
|
||||||
|
|
||||||
|
class EntityLookup(dbtClassMixin):
|
||||||
|
def __init__(self, manifest: "Manifest"):
|
||||||
|
self.storage: Dict[str, Dict[PackageName, UniqueID]] = {}
|
||||||
|
self.populate(manifest)
|
||||||
|
|
||||||
|
def get_unique_id(self, search_name, package: Optional[PackageName]):
|
||||||
|
return find_unique_id_for_package(self.storage, search_name, package)
|
||||||
|
|
||||||
|
def find(self, search_name, package: Optional[PackageName], manifest: "Manifest"):
|
||||||
|
unique_id = self.get_unique_id(search_name, package)
|
||||||
|
if unique_id is not None:
|
||||||
|
return self.perform_lookup(unique_id, manifest)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_entity(self, entity: Entity):
|
||||||
|
if entity.search_name not in self.storage:
|
||||||
|
self.storage[entity.search_name] = {}
|
||||||
|
|
||||||
|
self.storage[entity.search_name][entity.package_name] = entity.unique_id
|
||||||
|
|
||||||
|
def populate(self, manifest):
|
||||||
|
for entity in manifest.entities.values():
|
||||||
|
if hasattr(entity, "name"):
|
||||||
|
self.add_entity(entity)
|
||||||
|
|
||||||
|
def perform_lookup(self, unique_id: UniqueID, manifest: "Manifest") -> Entity:
|
||||||
|
if unique_id not in manifest.entities:
|
||||||
|
raise dbt.exceptions.DbtInternalError(
|
||||||
|
f"Entity {unique_id} found in cache but not found in manifest"
|
||||||
|
)
|
||||||
|
return manifest.entities[unique_id]
|
||||||
|
|
||||||
|
|
||||||
# This handles both models/seeds/snapshots and sources/metrics/exposures
|
# This handles both models/seeds/snapshots and sources/metrics/exposures
|
||||||
class DisabledLookup(dbtClassMixin):
|
class DisabledLookup(dbtClassMixin):
|
||||||
def __init__(self, manifest: "Manifest"):
|
def __init__(self, manifest: "Manifest"):
|
||||||
@@ -456,6 +490,9 @@ class Disabled(Generic[D]):
|
|||||||
MaybeMetricNode = Optional[Union[Metric, Disabled[Metric]]]
|
MaybeMetricNode = Optional[Union[Metric, Disabled[Metric]]]
|
||||||
|
|
||||||
|
|
||||||
|
MaybeEntityNode = Optional[Union[Entity, Disabled[Entity]]]
|
||||||
|
|
||||||
|
|
||||||
MaybeDocumentation = Optional[Documentation]
|
MaybeDocumentation = Optional[Documentation]
|
||||||
|
|
||||||
|
|
||||||
@@ -599,6 +636,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
docs: MutableMapping[str, Documentation] = field(default_factory=dict)
|
docs: MutableMapping[str, Documentation] = field(default_factory=dict)
|
||||||
exposures: MutableMapping[str, Exposure] = field(default_factory=dict)
|
exposures: MutableMapping[str, Exposure] = field(default_factory=dict)
|
||||||
metrics: MutableMapping[str, Metric] = field(default_factory=dict)
|
metrics: MutableMapping[str, Metric] = field(default_factory=dict)
|
||||||
|
entities: MutableMapping[str, Entity] = field(default_factory=dict)
|
||||||
selectors: MutableMapping[str, Any] = field(default_factory=dict)
|
selectors: MutableMapping[str, Any] = field(default_factory=dict)
|
||||||
files: MutableMapping[str, AnySourceFile] = field(default_factory=dict)
|
files: MutableMapping[str, AnySourceFile] = field(default_factory=dict)
|
||||||
metadata: ManifestMetadata = field(default_factory=ManifestMetadata)
|
metadata: ManifestMetadata = field(default_factory=ManifestMetadata)
|
||||||
@@ -620,6 +658,9 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
_metric_lookup: Optional[MetricLookup] = field(
|
_metric_lookup: Optional[MetricLookup] = field(
|
||||||
default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None}
|
default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None}
|
||||||
)
|
)
|
||||||
|
_entity_lookup: Optional[EntityLookup] = field(
|
||||||
|
default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None}
|
||||||
|
)
|
||||||
_disabled_lookup: Optional[DisabledLookup] = field(
|
_disabled_lookup: Optional[DisabledLookup] = field(
|
||||||
default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None}
|
default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None}
|
||||||
)
|
)
|
||||||
@@ -670,6 +711,9 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
def update_metric(self, new_metric: Metric):
|
def update_metric(self, new_metric: Metric):
|
||||||
_update_into(self.metrics, new_metric)
|
_update_into(self.metrics, new_metric)
|
||||||
|
|
||||||
|
def update_entity(self, new_entity: Entity):
|
||||||
|
_update_into(self.entities, new_entity)
|
||||||
|
|
||||||
def update_node(self, new_node: ManifestNode):
|
def update_node(self, new_node: ManifestNode):
|
||||||
_update_into(self.nodes, new_node)
|
_update_into(self.nodes, new_node)
|
||||||
|
|
||||||
@@ -685,6 +729,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self.flat_graph = {
|
self.flat_graph = {
|
||||||
"exposures": {k: v.to_dict(omit_none=False) for k, v in self.exposures.items()},
|
"exposures": {k: v.to_dict(omit_none=False) for k, v in self.exposures.items()},
|
||||||
"metrics": {k: v.to_dict(omit_none=False) for k, v in self.metrics.items()},
|
"metrics": {k: v.to_dict(omit_none=False) for k, v in self.metrics.items()},
|
||||||
|
"entities": {k: v.to_dict(omit_none=False) for k, v in self.entities.items()},
|
||||||
"nodes": {k: v.to_dict(omit_none=False) for k, v in self.nodes.items()},
|
"nodes": {k: v.to_dict(omit_none=False) for k, v in self.nodes.items()},
|
||||||
"sources": {k: v.to_dict(omit_none=False) for k, v in self.sources.items()},
|
"sources": {k: v.to_dict(omit_none=False) for k, v in self.sources.items()},
|
||||||
}
|
}
|
||||||
@@ -747,6 +792,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self.nodes.values(),
|
self.nodes.values(),
|
||||||
self.sources.values(),
|
self.sources.values(),
|
||||||
self.metrics.values(),
|
self.metrics.values(),
|
||||||
|
self.entities.values(),
|
||||||
)
|
)
|
||||||
for resource in all_resources:
|
for resource in all_resources:
|
||||||
resource_type_plural = resource.resource_type.pluralize()
|
resource_type_plural = resource.resource_type.pluralize()
|
||||||
@@ -775,6 +821,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
docs={k: _deepcopy(v) for k, v in self.docs.items()},
|
docs={k: _deepcopy(v) for k, v in self.docs.items()},
|
||||||
exposures={k: _deepcopy(v) for k, v in self.exposures.items()},
|
exposures={k: _deepcopy(v) for k, v in self.exposures.items()},
|
||||||
metrics={k: _deepcopy(v) for k, v in self.metrics.items()},
|
metrics={k: _deepcopy(v) for k, v in self.metrics.items()},
|
||||||
|
entities={k: _deepcopy(v) for k, v in self.entities.items()},
|
||||||
selectors={k: _deepcopy(v) for k, v in self.selectors.items()},
|
selectors={k: _deepcopy(v) for k, v in self.selectors.items()},
|
||||||
metadata=self.metadata,
|
metadata=self.metadata,
|
||||||
disabled={k: _deepcopy(v) for k, v in self.disabled.items()},
|
disabled={k: _deepcopy(v) for k, v in self.disabled.items()},
|
||||||
@@ -791,6 +838,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self.sources.values(),
|
self.sources.values(),
|
||||||
self.exposures.values(),
|
self.exposures.values(),
|
||||||
self.metrics.values(),
|
self.metrics.values(),
|
||||||
|
self.entities.values(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
forward_edges, backward_edges = build_node_edges(edge_members)
|
forward_edges, backward_edges = build_node_edges(edge_members)
|
||||||
@@ -816,6 +864,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
docs=self.docs,
|
docs=self.docs,
|
||||||
exposures=self.exposures,
|
exposures=self.exposures,
|
||||||
metrics=self.metrics,
|
metrics=self.metrics,
|
||||||
|
entities=self.entities,
|
||||||
selectors=self.selectors,
|
selectors=self.selectors,
|
||||||
metadata=self.metadata,
|
metadata=self.metadata,
|
||||||
disabled=self.disabled,
|
disabled=self.disabled,
|
||||||
@@ -837,6 +886,8 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
return self.exposures[unique_id]
|
return self.exposures[unique_id]
|
||||||
elif unique_id in self.metrics:
|
elif unique_id in self.metrics:
|
||||||
return self.metrics[unique_id]
|
return self.metrics[unique_id]
|
||||||
|
elif unique_id in self.entities:
|
||||||
|
return self.entities[unique_id]
|
||||||
else:
|
else:
|
||||||
# something terrible has happened
|
# something terrible has happened
|
||||||
raise dbt.exceptions.DbtInternalError(
|
raise dbt.exceptions.DbtInternalError(
|
||||||
@@ -873,6 +924,12 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self._metric_lookup = MetricLookup(self)
|
self._metric_lookup = MetricLookup(self)
|
||||||
return self._metric_lookup
|
return self._metric_lookup
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_lookup(self) -> EntityLookup:
|
||||||
|
if self._entity_lookup is None:
|
||||||
|
self._entity_lookup = EntityLookup(self)
|
||||||
|
return self._entity_lookup
|
||||||
|
|
||||||
def rebuild_ref_lookup(self):
|
def rebuild_ref_lookup(self):
|
||||||
self._ref_lookup = RefableLookup(self)
|
self._ref_lookup = RefableLookup(self)
|
||||||
|
|
||||||
@@ -973,6 +1030,31 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
return Disabled(disabled[0])
|
return Disabled(disabled[0])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def resolve_entity(
|
||||||
|
self,
|
||||||
|
target_entity_name: str,
|
||||||
|
target_entity_package: Optional[str],
|
||||||
|
current_project: str,
|
||||||
|
node_package: str,
|
||||||
|
) -> MaybeEntityNode:
|
||||||
|
|
||||||
|
entity: Optional[Entity] = None
|
||||||
|
disabled: Optional[List[Entity]] = None
|
||||||
|
|
||||||
|
candidates = _search_packages(current_project, node_package, target_entity_package)
|
||||||
|
for pkg in candidates:
|
||||||
|
entity = self.entity_lookup.find(target_entity_name, pkg, self)
|
||||||
|
|
||||||
|
if entity is not None and entity.config.enabled:
|
||||||
|
return entity
|
||||||
|
|
||||||
|
# it's possible that the node is disabled
|
||||||
|
if disabled is None:
|
||||||
|
disabled = self.disabled_lookup.find(f"{target_entity_name}", pkg)
|
||||||
|
if disabled:
|
||||||
|
return Disabled(disabled[0])
|
||||||
|
return None
|
||||||
|
|
||||||
# Called by DocsRuntimeContext.doc
|
# Called by DocsRuntimeContext.doc
|
||||||
def resolve_doc(
|
def resolve_doc(
|
||||||
self,
|
self,
|
||||||
@@ -1083,6 +1165,11 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self.metrics[metric.unique_id] = metric
|
self.metrics[metric.unique_id] = metric
|
||||||
source_file.metrics.append(metric.unique_id)
|
source_file.metrics.append(metric.unique_id)
|
||||||
|
|
||||||
|
def add_entity(self, source_file: SchemaSourceFile, entity: Entity):
|
||||||
|
_check_duplicates(entity, self.entities)
|
||||||
|
self.entities[entity.unique_id] = entity
|
||||||
|
source_file.entities.append(entity.unique_id)
|
||||||
|
|
||||||
def add_disabled_nofile(self, node: GraphMemberNode):
|
def add_disabled_nofile(self, node: GraphMemberNode):
|
||||||
# There can be multiple disabled nodes for the same unique_id
|
# There can be multiple disabled nodes for the same unique_id
|
||||||
if node.unique_id in self.disabled:
|
if node.unique_id in self.disabled:
|
||||||
@@ -1098,6 +1185,8 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
source_file.add_test(node.unique_id, test_from)
|
source_file.add_test(node.unique_id, test_from)
|
||||||
if isinstance(node, Metric):
|
if isinstance(node, Metric):
|
||||||
source_file.metrics.append(node.unique_id)
|
source_file.metrics.append(node.unique_id)
|
||||||
|
if isinstance(node, Entity):
|
||||||
|
source_file.entities.append(node.unique_id)
|
||||||
if isinstance(node, Exposure):
|
if isinstance(node, Exposure):
|
||||||
source_file.exposures.append(node.unique_id)
|
source_file.exposures.append(node.unique_id)
|
||||||
else:
|
else:
|
||||||
@@ -1125,6 +1214,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self.docs,
|
self.docs,
|
||||||
self.exposures,
|
self.exposures,
|
||||||
self.metrics,
|
self.metrics,
|
||||||
|
self.entities,
|
||||||
self.selectors,
|
self.selectors,
|
||||||
self.files,
|
self.files,
|
||||||
self.metadata,
|
self.metadata,
|
||||||
@@ -1137,6 +1227,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
|||||||
self._source_lookup,
|
self._source_lookup,
|
||||||
self._ref_lookup,
|
self._ref_lookup,
|
||||||
self._metric_lookup,
|
self._metric_lookup,
|
||||||
|
self._entity_lookup,
|
||||||
self._disabled_lookup,
|
self._disabled_lookup,
|
||||||
self._analysis_lookup,
|
self._analysis_lookup,
|
||||||
)
|
)
|
||||||
@@ -1178,6 +1269,9 @@ class WritableManifest(ArtifactMixin):
|
|||||||
metrics: Mapping[UniqueID, Metric] = field(
|
metrics: Mapping[UniqueID, Metric] = field(
|
||||||
metadata=dict(description=("The metrics defined in the dbt project and its dependencies"))
|
metadata=dict(description=("The metrics defined in the dbt project and its dependencies"))
|
||||||
)
|
)
|
||||||
|
entities: Mapping[UniqueID, Entity] = field(
|
||||||
|
metadata=dict(description=("The entities defined in the dbt project and its dependencies"))
|
||||||
|
)
|
||||||
selectors: Mapping[UniqueID, Any] = field(
|
selectors: Mapping[UniqueID, Any] = field(
|
||||||
metadata=dict(description=("The selectors defined in selectors.yml"))
|
metadata=dict(description=("The selectors defined in selectors.yml"))
|
||||||
)
|
)
|
||||||
@@ -1202,7 +1296,8 @@ class WritableManifest(ArtifactMixin):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def compatible_previous_versions(self):
|
def compatible_previous_versions(self):
|
||||||
return [("manifest", 4), ("manifest", 5), ("manifest", 6), ("manifest", 7)]
|
# return [("manifest", 4), ("manifest", 5), ("manifest", 6), ("manifest", 7)]
|
||||||
|
return []
|
||||||
|
|
||||||
def __post_serialize__(self, dct):
|
def __post_serialize__(self, dct):
|
||||||
for unique_id, node in dct["nodes"].items():
|
for unique_id, node in dct["nodes"].items():
|
||||||
|
|||||||
@@ -368,6 +368,11 @@ class MetricConfig(BaseConfig):
|
|||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EntityConfig(BaseConfig):
|
||||||
|
enabled: bool = True
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExposureConfig(BaseConfig):
|
class ExposureConfig(BaseConfig):
|
||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
@@ -604,6 +609,7 @@ class SnapshotConfig(EmptySnapshotConfig):
|
|||||||
|
|
||||||
RESOURCE_TYPES: Dict[NodeType, Type[BaseConfig]] = {
|
RESOURCE_TYPES: Dict[NodeType, Type[BaseConfig]] = {
|
||||||
NodeType.Metric: MetricConfig,
|
NodeType.Metric: MetricConfig,
|
||||||
|
NodeType.Entity: EntityConfig,
|
||||||
NodeType.Exposure: ExposureConfig,
|
NodeType.Exposure: ExposureConfig,
|
||||||
NodeType.Source: SourceConfig,
|
NodeType.Source: SourceConfig,
|
||||||
NodeType.Seed: SeedConfig,
|
NodeType.Seed: SeedConfig,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ from .model_config import (
|
|||||||
TestConfig,
|
TestConfig,
|
||||||
SourceConfig,
|
SourceConfig,
|
||||||
MetricConfig,
|
MetricConfig,
|
||||||
|
EntityConfig,
|
||||||
ExposureConfig,
|
ExposureConfig,
|
||||||
EmptySnapshotConfig,
|
EmptySnapshotConfig,
|
||||||
SnapshotConfig,
|
SnapshotConfig,
|
||||||
@@ -272,7 +273,7 @@ class ParsedNode(NodeInfoMixin, ParsedNodeMandatory, SerializableType):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def _deserialize(cls, dct: Dict[str, int]):
|
def _deserialize(cls, dct: Dict[str, int]):
|
||||||
# The serialized ParsedNodes do not differ from each other
|
# The serialized ParsedNodes do not differ from each other
|
||||||
# in fields that would allow 'from_dict' to distinguis
|
# in fields that would allow 'from_dict' to distinguish
|
||||||
# between them.
|
# between them.
|
||||||
resource_type = dct["resource_type"]
|
resource_type = dct["resource_type"]
|
||||||
if resource_type == "model":
|
if resource_type == "model":
|
||||||
@@ -392,6 +393,7 @@ class CompiledNode(ParsedNode):
|
|||||||
refs: List[List[str]] = field(default_factory=list)
|
refs: List[List[str]] = field(default_factory=list)
|
||||||
sources: List[List[str]] = field(default_factory=list)
|
sources: List[List[str]] = field(default_factory=list)
|
||||||
metrics: List[List[str]] = field(default_factory=list)
|
metrics: List[List[str]] = field(default_factory=list)
|
||||||
|
entities: List[List[str]] = field(default_factory=list)
|
||||||
depends_on: DependsOn = field(default_factory=DependsOn)
|
depends_on: DependsOn = field(default_factory=DependsOn)
|
||||||
compiled_path: Optional[str] = None
|
compiled_path: Optional[str] = None
|
||||||
compiled: bool = False
|
compiled: bool = False
|
||||||
@@ -906,6 +908,7 @@ class Exposure(GraphNode):
|
|||||||
refs: List[List[str]] = field(default_factory=list)
|
refs: List[List[str]] = field(default_factory=list)
|
||||||
sources: List[List[str]] = field(default_factory=list)
|
sources: List[List[str]] = field(default_factory=list)
|
||||||
metrics: List[List[str]] = field(default_factory=list)
|
metrics: List[List[str]] = field(default_factory=list)
|
||||||
|
entities: List[List[str]] = field(default_factory=list)
|
||||||
created_at: float = field(default_factory=lambda: time.time())
|
created_at: float = field(default_factory=lambda: time.time())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -997,6 +1000,7 @@ class Metric(GraphNode):
|
|||||||
depends_on: DependsOn = field(default_factory=DependsOn)
|
depends_on: DependsOn = field(default_factory=DependsOn)
|
||||||
refs: List[List[str]] = field(default_factory=list)
|
refs: List[List[str]] = field(default_factory=list)
|
||||||
metrics: List[List[str]] = field(default_factory=list)
|
metrics: List[List[str]] = field(default_factory=list)
|
||||||
|
entities: List[List[str]] = field(default_factory=list)
|
||||||
created_at: float = field(default_factory=lambda: time.time())
|
created_at: float = field(default_factory=lambda: time.time())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -1065,6 +1069,63 @@ class Metric(GraphNode):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Entity(GraphNode):
|
||||||
|
name: str
|
||||||
|
model: str
|
||||||
|
description: str
|
||||||
|
dimensions: List[str]
|
||||||
|
resource_type: NodeType = field(metadata={"restrict": [NodeType.Entity]})
|
||||||
|
model_unique_id: Optional[str] = None
|
||||||
|
meta: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
tags: List[str] = field(default_factory=list)
|
||||||
|
config: EntityConfig = field(default_factory=EntityConfig)
|
||||||
|
unrendered_config: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
sources: List[List[str]] = field(default_factory=list)
|
||||||
|
depends_on: DependsOn = field(default_factory=DependsOn)
|
||||||
|
refs: List[List[str]] = field(default_factory=list)
|
||||||
|
entities: List[List[str]] = field(default_factory=list)
|
||||||
|
metrics: List[List[str]] = field(default_factory=list)
|
||||||
|
created_at: float = field(default_factory=lambda: time.time())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def depends_on_nodes(self):
|
||||||
|
return self.depends_on.nodes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def search_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def same_model(self, old: "Entity") -> bool:
|
||||||
|
return self.model == old.model
|
||||||
|
|
||||||
|
def same_dimensions(self, old: "Entity") -> bool:
|
||||||
|
return self.dimensions == old.dimensions
|
||||||
|
|
||||||
|
def same_description(self, old: "Entity") -> bool:
|
||||||
|
return self.description == old.description
|
||||||
|
|
||||||
|
def same_config(self, old: "Entity") -> bool:
|
||||||
|
return self.config.same_contents(
|
||||||
|
self.unrendered_config,
|
||||||
|
old.unrendered_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
def same_contents(self, old: Optional["Entity"]) -> bool:
|
||||||
|
# existing when it didn't before is a change!
|
||||||
|
# metadata/tags changes are not "changes"
|
||||||
|
if old is None:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return (
|
||||||
|
self.same_model(old)
|
||||||
|
and self.same_dimensions(old)
|
||||||
|
and self.same_description(old)
|
||||||
|
and self.same_config(old)
|
||||||
|
and True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ====================================
|
# ====================================
|
||||||
# Patches
|
# Patches
|
||||||
# ====================================
|
# ====================================
|
||||||
@@ -1126,6 +1187,7 @@ GraphMemberNode = Union[
|
|||||||
ResultNode,
|
ResultNode,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
]
|
]
|
||||||
|
|
||||||
# All "nodes" (or node-like objects) in this file
|
# All "nodes" (or node-like objects) in this file
|
||||||
|
|||||||
@@ -533,3 +533,21 @@ class UnparsedMetric(dbtClassMixin, Replaceable):
|
|||||||
|
|
||||||
if data.get("model") is not None and data.get("calculation_method") == "derived":
|
if data.get("model") is not None and data.get("calculation_method") == "derived":
|
||||||
raise ValidationError("Derived metrics cannot have a 'model' property")
|
raise ValidationError("Derived metrics cannot have a 'model' property")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class UnparsedEntity(dbtClassMixin, Replaceable):
|
||||||
|
"""This class is used for entity information"""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
model: str
|
||||||
|
description: str = ""
|
||||||
|
dimensions: List[str] = field(default_factory=list)
|
||||||
|
meta: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
tags: List[str] = field(default_factory=list)
|
||||||
|
config: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, data):
|
||||||
|
super(UnparsedEntity, cls).validate(data)
|
||||||
|
# TODO: Add validation here around include/exclude and others
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ class Project(HyphenatedDbtClassMixin, Replaceable):
|
|||||||
sources: Dict[str, Any] = field(default_factory=dict)
|
sources: Dict[str, Any] = field(default_factory=dict)
|
||||||
tests: Dict[str, Any] = field(default_factory=dict)
|
tests: Dict[str, Any] = field(default_factory=dict)
|
||||||
metrics: Dict[str, Any] = field(default_factory=dict)
|
metrics: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
entities: Dict[str, Any] = field(default_factory=dict)
|
||||||
exposures: Dict[str, Any] = field(default_factory=dict)
|
exposures: Dict[str, Any] = field(default_factory=dict)
|
||||||
vars: Optional[Dict[str, Any]] = field(
|
vars: Optional[Dict[str, Any]] = field(
|
||||||
default=None,
|
default=None,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from .selector_spec import (
|
|||||||
|
|
||||||
INTERSECTION_DELIMITER = ","
|
INTERSECTION_DELIMITER = ","
|
||||||
|
|
||||||
DEFAULT_INCLUDES: List[str] = ["fqn:*", "source:*", "exposure:*", "metric:*"]
|
DEFAULT_INCLUDES: List[str] = ["fqn:*", "source:*", "exposure:*", "metric:*", "entity:*"]
|
||||||
DEFAULT_EXCLUDES: List[str] = []
|
DEFAULT_EXCLUDES: List[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
SourceDefinition,
|
SourceDefinition,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
GraphMemberNode,
|
GraphMemberNode,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.manifest import Manifest
|
from dbt.contracts.graph.manifest import Manifest
|
||||||
@@ -51,8 +52,8 @@ class GraphQueue:
|
|||||||
node = self.manifest.expect(node_id)
|
node = self.manifest.expect(node_id)
|
||||||
if node.resource_type != NodeType.Model:
|
if node.resource_type != NodeType.Model:
|
||||||
return False
|
return False
|
||||||
# must be a Model - tell mypy this won't be a Source or Exposure or Metric
|
# must be a Model - tell mypy this won't be a Source or Exposure or Metric or Entity
|
||||||
assert not isinstance(node, (SourceDefinition, Exposure, Metric))
|
assert not isinstance(node, (SourceDefinition, Exposure, Metric, Entity))
|
||||||
if node.is_ephemeral:
|
if node.is_ephemeral:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -163,6 +163,9 @@ class NodeSelector(MethodManager):
|
|||||||
elif unique_id in self.manifest.metrics:
|
elif unique_id in self.manifest.metrics:
|
||||||
metric = self.manifest.metrics[unique_id]
|
metric = self.manifest.metrics[unique_id]
|
||||||
return metric.config.enabled
|
return metric.config.enabled
|
||||||
|
elif unique_id in self.manifest.entities:
|
||||||
|
entity = self.manifest.entities[unique_id]
|
||||||
|
return entity.config.enabled
|
||||||
node = self.manifest.nodes[unique_id]
|
node = self.manifest.nodes[unique_id]
|
||||||
return not node.empty and node.config.enabled
|
return not node.empty and node.config.enabled
|
||||||
|
|
||||||
@@ -182,6 +185,8 @@ class NodeSelector(MethodManager):
|
|||||||
node = self.manifest.exposures[unique_id]
|
node = self.manifest.exposures[unique_id]
|
||||||
elif unique_id in self.manifest.metrics:
|
elif unique_id in self.manifest.metrics:
|
||||||
node = self.manifest.metrics[unique_id]
|
node = self.manifest.metrics[unique_id]
|
||||||
|
elif unique_id in self.manifest.entities:
|
||||||
|
node = self.manifest.entities[unique_id]
|
||||||
else:
|
else:
|
||||||
raise DbtInternalError(f"Node {unique_id} not found in the manifest!")
|
raise DbtInternalError(f"Node {unique_id} not found in the manifest!")
|
||||||
return self.node_is_match(node)
|
return self.node_is_match(node)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
SingularTestNode,
|
SingularTestNode,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
GenericTestNode,
|
GenericTestNode,
|
||||||
SourceDefinition,
|
SourceDefinition,
|
||||||
ResultNode,
|
ResultNode,
|
||||||
@@ -43,6 +44,7 @@ class MethodName(StrEnum):
|
|||||||
State = "state"
|
State = "state"
|
||||||
Exposure = "exposure"
|
Exposure = "exposure"
|
||||||
Metric = "metric"
|
Metric = "metric"
|
||||||
|
Entity = "entity"
|
||||||
Result = "result"
|
Result = "result"
|
||||||
SourceStatus = "source_status"
|
SourceStatus = "source_status"
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ def is_selected_node(fqn: List[str], node_selector: str):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
SelectorTarget = Union[SourceDefinition, ManifestNode, Exposure, Metric]
|
SelectorTarget = Union[SourceDefinition, ManifestNode, Exposure, Metric, Entity]
|
||||||
|
|
||||||
|
|
||||||
class SelectorMethod(metaclass=abc.ABCMeta):
|
class SelectorMethod(metaclass=abc.ABCMeta):
|
||||||
@@ -118,6 +120,14 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
|||||||
continue
|
continue
|
||||||
yield unique_id, metric
|
yield unique_id, metric
|
||||||
|
|
||||||
|
def entity_nodes(self, included_nodes: Set[UniqueId]) -> Iterator[Tuple[UniqueId, Entity]]:
|
||||||
|
|
||||||
|
for key, metric in self.manifest.entities.items():
|
||||||
|
unique_id = UniqueId(key)
|
||||||
|
if unique_id not in included_nodes:
|
||||||
|
continue
|
||||||
|
yield unique_id, metric
|
||||||
|
|
||||||
def all_nodes(
|
def all_nodes(
|
||||||
self, included_nodes: Set[UniqueId]
|
self, included_nodes: Set[UniqueId]
|
||||||
) -> Iterator[Tuple[UniqueId, SelectorTarget]]:
|
) -> Iterator[Tuple[UniqueId, SelectorTarget]]:
|
||||||
@@ -126,6 +136,7 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
|||||||
self.source_nodes(included_nodes),
|
self.source_nodes(included_nodes),
|
||||||
self.exposure_nodes(included_nodes),
|
self.exposure_nodes(included_nodes),
|
||||||
self.metric_nodes(included_nodes),
|
self.metric_nodes(included_nodes),
|
||||||
|
self.entity_nodes(included_nodes),
|
||||||
)
|
)
|
||||||
|
|
||||||
def configurable_nodes(
|
def configurable_nodes(
|
||||||
@@ -136,11 +147,12 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
|||||||
def non_source_nodes(
|
def non_source_nodes(
|
||||||
self,
|
self,
|
||||||
included_nodes: Set[UniqueId],
|
included_nodes: Set[UniqueId],
|
||||||
) -> Iterator[Tuple[UniqueId, Union[Exposure, ManifestNode, Metric]]]:
|
) -> Iterator[Tuple[UniqueId, Union[Exposure, ManifestNode, Metric, Entity]]]:
|
||||||
yield from chain(
|
yield from chain(
|
||||||
self.parsed_nodes(included_nodes),
|
self.parsed_nodes(included_nodes),
|
||||||
self.exposure_nodes(included_nodes),
|
self.exposure_nodes(included_nodes),
|
||||||
self.metric_nodes(included_nodes),
|
self.metric_nodes(included_nodes),
|
||||||
|
self.entity_nodes(included_nodes),
|
||||||
)
|
)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@@ -270,6 +282,33 @@ class MetricSelectorMethod(SelectorMethod):
|
|||||||
yield node
|
yield node
|
||||||
|
|
||||||
|
|
||||||
|
class EntitySelectorMethod(SelectorMethod):
|
||||||
|
"""TODO: Add a description of what this selector method is doing"""
|
||||||
|
|
||||||
|
def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]:
|
||||||
|
parts = selector.split(".")
|
||||||
|
target_package = SELECTOR_GLOB
|
||||||
|
if len(parts) == 1:
|
||||||
|
target_name = parts[0]
|
||||||
|
elif len(parts) == 2:
|
||||||
|
target_package, target_name = parts
|
||||||
|
else:
|
||||||
|
msg = (
|
||||||
|
'Invalid entity selector value "{}". Entities must be of '
|
||||||
|
"the form ${{entity_name}} or "
|
||||||
|
"${{entity_package.entity_name}}"
|
||||||
|
).format(selector)
|
||||||
|
raise DbtRuntimeError(msg)
|
||||||
|
|
||||||
|
for node, real_node in self.entity_nodes(included_nodes):
|
||||||
|
if target_package not in (real_node.package_name, SELECTOR_GLOB):
|
||||||
|
continue
|
||||||
|
if target_name not in (real_node.name, SELECTOR_GLOB):
|
||||||
|
continue
|
||||||
|
|
||||||
|
yield node
|
||||||
|
|
||||||
|
|
||||||
class PathSelectorMethod(SelectorMethod):
|
class PathSelectorMethod(SelectorMethod):
|
||||||
def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]:
|
def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]:
|
||||||
"""Yields nodes from included that match the given path."""
|
"""Yields nodes from included that match the given path."""
|
||||||
@@ -530,6 +569,8 @@ class StateSelectorMethod(SelectorMethod):
|
|||||||
previous_node = manifest.exposures[node]
|
previous_node = manifest.exposures[node]
|
||||||
elif node in manifest.metrics:
|
elif node in manifest.metrics:
|
||||||
previous_node = manifest.metrics[node]
|
previous_node = manifest.metrics[node]
|
||||||
|
elif node in manifest.entities:
|
||||||
|
previous_node = manifest.entities[node]
|
||||||
|
|
||||||
if checker(previous_node, real_node):
|
if checker(previous_node, real_node):
|
||||||
yield node
|
yield node
|
||||||
@@ -616,6 +657,7 @@ class MethodManager:
|
|||||||
MethodName.State: StateSelectorMethod,
|
MethodName.State: StateSelectorMethod,
|
||||||
MethodName.Exposure: ExposureSelectorMethod,
|
MethodName.Exposure: ExposureSelectorMethod,
|
||||||
MethodName.Metric: MetricSelectorMethod,
|
MethodName.Metric: MetricSelectorMethod,
|
||||||
|
MethodName.Entity: EntitySelectorMethod,
|
||||||
MethodName.Result: ResultSelectorMethod,
|
MethodName.Result: ResultSelectorMethod,
|
||||||
MethodName.SourceStatus: SourceStatusSelectorMethod,
|
MethodName.SourceStatus: SourceStatusSelectorMethod,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class NodeType(StrEnum):
|
|||||||
Macro = "macro"
|
Macro = "macro"
|
||||||
Exposure = "exposure"
|
Exposure = "exposure"
|
||||||
Metric = "metric"
|
Metric = "metric"
|
||||||
|
Entity = "entity"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def executable(cls) -> List["NodeType"]:
|
def executable(cls) -> List["NodeType"]:
|
||||||
@@ -52,11 +53,14 @@ class NodeType(StrEnum):
|
|||||||
cls.Analysis,
|
cls.Analysis,
|
||||||
cls.Exposure,
|
cls.Exposure,
|
||||||
cls.Metric,
|
cls.Metric,
|
||||||
|
cls.Entity,
|
||||||
]
|
]
|
||||||
|
|
||||||
def pluralize(self) -> str:
|
def pluralize(self) -> str:
|
||||||
if self is self.Analysis:
|
if self is self.Analysis:
|
||||||
return "analyses"
|
return "analyses"
|
||||||
|
if self is self.Entity:
|
||||||
|
return "entities"
|
||||||
return f"{self}s"
|
return f"{self}s"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
ColumnInfo,
|
ColumnInfo,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
SeedNode,
|
SeedNode,
|
||||||
ManifestNode,
|
ManifestNode,
|
||||||
ResultNode,
|
ResultNode,
|
||||||
@@ -340,7 +341,7 @@ class ManifestLoader:
|
|||||||
project, project_parser_files[project.project_name], parser_types
|
project, project_parser_files[project.project_name], parser_types
|
||||||
)
|
)
|
||||||
|
|
||||||
# Now that we've loaded most of the nodes (except for schema tests, sources, metrics)
|
# Now that we've loaded most of the nodes (except for schema tests, sources, metrics, entities)
|
||||||
# load up the Lookup objects to resolve them by name, so the SourceFiles store
|
# load up the Lookup objects to resolve them by name, so the SourceFiles store
|
||||||
# the unique_id instead of the name. Sources are loaded from yaml files, so
|
# the unique_id instead of the name. Sources are loaded from yaml files, so
|
||||||
# aren't in place yet
|
# aren't in place yet
|
||||||
@@ -376,7 +377,7 @@ class ManifestLoader:
|
|||||||
# copy the selectors from the root_project to the manifest
|
# copy the selectors from the root_project to the manifest
|
||||||
self.manifest.selectors = self.root_project.manifest_selectors
|
self.manifest.selectors = self.root_project.manifest_selectors
|
||||||
|
|
||||||
# update the refs, sources, docs and metrics depends_on.nodes
|
# update the refs, sources, docs, entities and metrics depends_on.nodes
|
||||||
# These check the created_at time on the nodes to
|
# These check the created_at time on the nodes to
|
||||||
# determine whether they need processing.
|
# determine whether they need processing.
|
||||||
start_process = time.perf_counter()
|
start_process = time.perf_counter()
|
||||||
@@ -384,6 +385,7 @@ class ManifestLoader:
|
|||||||
self.process_refs(self.root_project.project_name)
|
self.process_refs(self.root_project.project_name)
|
||||||
self.process_docs(self.root_project)
|
self.process_docs(self.root_project)
|
||||||
self.process_metrics(self.root_project)
|
self.process_metrics(self.root_project)
|
||||||
|
self.process_entities(self.root_project)
|
||||||
|
|
||||||
# update tracking data
|
# update tracking data
|
||||||
self._perf_info.process_manifest_elapsed = time.perf_counter() - start_process
|
self._perf_info.process_manifest_elapsed = time.perf_counter() - start_process
|
||||||
@@ -838,6 +840,10 @@ class ManifestLoader:
|
|||||||
if metric.created_at < self.started_at:
|
if metric.created_at < self.started_at:
|
||||||
continue
|
continue
|
||||||
_process_refs_for_metric(self.manifest, current_project, metric)
|
_process_refs_for_metric(self.manifest, current_project, metric)
|
||||||
|
for entity in self.manifest.entities.values():
|
||||||
|
if entity.created_at < self.started_at:
|
||||||
|
continue
|
||||||
|
_process_refs_for_entity(self.manifest, current_project, entity)
|
||||||
|
|
||||||
# Takes references in 'metrics' array of nodes and exposures, finds the target
|
# Takes references in 'metrics' array of nodes and exposures, finds the target
|
||||||
# node, and updates 'depends_on.nodes' with the unique id
|
# node, and updates 'depends_on.nodes' with the unique id
|
||||||
@@ -858,6 +864,23 @@ class ManifestLoader:
|
|||||||
continue
|
continue
|
||||||
_process_metrics_for_node(self.manifest, current_project, exposure)
|
_process_metrics_for_node(self.manifest, current_project, exposure)
|
||||||
|
|
||||||
|
# Takes references in 'entities' array of nodes and exposures, finds the target
|
||||||
|
# node, and updates 'depends_on.nodes' with the unique id
|
||||||
|
def process_entities(self, config: RuntimeConfig):
|
||||||
|
current_project = config.project_name
|
||||||
|
for node in self.manifest.nodes.values():
|
||||||
|
if node.created_at < self.started_at:
|
||||||
|
continue
|
||||||
|
_process_entities_for_node(self.manifest, current_project, node)
|
||||||
|
for entity in self.manifest.entities.values():
|
||||||
|
if entity.created_at < self.started_at:
|
||||||
|
continue
|
||||||
|
_process_entities_for_node(self.manifest, current_project, entity)
|
||||||
|
for exposure in self.manifest.exposures.values():
|
||||||
|
if exposure.created_at < self.started_at:
|
||||||
|
continue
|
||||||
|
_process_entities_for_node(self.manifest, current_project, exposure)
|
||||||
|
|
||||||
# nodes: node and column descriptions
|
# nodes: node and column descriptions
|
||||||
# sources: source and table descriptions, column descriptions
|
# sources: source and table descriptions, column descriptions
|
||||||
# macros: macro argument descriptions
|
# macros: macro argument descriptions
|
||||||
@@ -913,6 +936,16 @@ class ManifestLoader:
|
|||||||
config.project_name,
|
config.project_name,
|
||||||
)
|
)
|
||||||
_process_docs_for_metrics(ctx, metric)
|
_process_docs_for_metrics(ctx, metric)
|
||||||
|
for entity in self.manifest.entities.values():
|
||||||
|
if entity.created_at < self.started_at:
|
||||||
|
continue
|
||||||
|
ctx = generate_runtime_docs_context(
|
||||||
|
config,
|
||||||
|
entity,
|
||||||
|
self.manifest,
|
||||||
|
config.project_name,
|
||||||
|
)
|
||||||
|
_process_docs_for_entities(ctx, entity)
|
||||||
|
|
||||||
# Loops through all nodes and exposures, for each element in
|
# Loops through all nodes and exposures, for each element in
|
||||||
# 'sources' array finds the source node and updates the
|
# 'sources' array finds the source node and updates the
|
||||||
@@ -1103,6 +1136,10 @@ def _process_docs_for_metrics(context: Dict[str, Any], metric: Metric) -> None:
|
|||||||
metric.description = get_rendered(metric.description, context)
|
metric.description = get_rendered(metric.description, context)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_docs_for_entities(context: Dict[str, Any], entity: Entity) -> None:
|
||||||
|
entity.description = get_rendered(entity.description, context)
|
||||||
|
|
||||||
|
|
||||||
def _process_refs_for_exposure(manifest: Manifest, current_project: str, exposure: Exposure):
|
def _process_refs_for_exposure(manifest: Manifest, current_project: str, exposure: Exposure):
|
||||||
"""Given a manifest and exposure in that manifest, process its refs"""
|
"""Given a manifest and exposure in that manifest, process its refs"""
|
||||||
for ref in exposure.refs:
|
for ref in exposure.refs:
|
||||||
@@ -1190,6 +1227,48 @@ def _process_refs_for_metric(manifest: Manifest, current_project: str, metric: M
|
|||||||
manifest.update_metric(metric)
|
manifest.update_metric(metric)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_refs_for_entity(manifest: Manifest, current_project: str, entity: Entity):
|
||||||
|
"""Given a manifest and an entity in that manifest, process its refs"""
|
||||||
|
for ref in entity.refs:
|
||||||
|
target_model: Optional[Union[Disabled, ManifestNode]] = None
|
||||||
|
target_model_name: str
|
||||||
|
target_model_package: Optional[str] = None
|
||||||
|
|
||||||
|
if len(ref) == 1:
|
||||||
|
target_model_name = ref[0]
|
||||||
|
elif len(ref) == 2:
|
||||||
|
target_model_package, target_model_name = ref
|
||||||
|
else:
|
||||||
|
raise dbt.exceptions.DbtInternalError(
|
||||||
|
f"Refs should always be 1 or 2 arguments - got {len(ref)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_model = manifest.resolve_ref(
|
||||||
|
target_model_name,
|
||||||
|
target_model_package,
|
||||||
|
current_project,
|
||||||
|
entity.package_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if target_model is None or isinstance(target_model, Disabled):
|
||||||
|
# This may raise. Even if it doesn't, we don't want to add
|
||||||
|
# this entity to the graph b/c there is no destination entity
|
||||||
|
entity.config.enabled = False
|
||||||
|
invalid_target_fail_unless_test(
|
||||||
|
node=entity,
|
||||||
|
target_name=target_model_name,
|
||||||
|
target_kind="node",
|
||||||
|
target_package=target_model_package,
|
||||||
|
disabled=(isinstance(target_model, Disabled)),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
target_model_id = target_model.unique_id
|
||||||
|
|
||||||
|
entity.depends_on.nodes.append(target_model_id)
|
||||||
|
manifest.update_entity(entity)
|
||||||
|
|
||||||
|
|
||||||
def _process_metrics_for_node(
|
def _process_metrics_for_node(
|
||||||
manifest: Manifest,
|
manifest: Manifest,
|
||||||
current_project: str,
|
current_project: str,
|
||||||
@@ -1239,6 +1318,55 @@ def _process_metrics_for_node(
|
|||||||
node.depends_on.nodes.append(target_metric_id)
|
node.depends_on.nodes.append(target_metric_id)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_entities_for_node(
|
||||||
|
manifest: Manifest,
|
||||||
|
current_project: str,
|
||||||
|
node: Union[ManifestNode, Entity, Exposure],
|
||||||
|
):
|
||||||
|
"""Given a manifest and a node in that manifest, process its entities"""
|
||||||
|
|
||||||
|
if isinstance(node, SeedNode):
|
||||||
|
return
|
||||||
|
|
||||||
|
for entity in node.entities:
|
||||||
|
target_entity: Optional[Union[Disabled, Entity]] = None
|
||||||
|
target_entity_name: str
|
||||||
|
target_entity_package: Optional[str] = None
|
||||||
|
|
||||||
|
if len(entity) == 1:
|
||||||
|
target_entity_name = entity[0]
|
||||||
|
elif len(entity) == 2:
|
||||||
|
target_entity_package, target_entity_name = entity
|
||||||
|
else:
|
||||||
|
raise dbt.exceptions.DbtInternalError(
|
||||||
|
f"Entity references should always be 1 or 2 arguments - got {len(entity)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_entity = manifest.resolve_entity(
|
||||||
|
target_entity_name,
|
||||||
|
target_entity_package,
|
||||||
|
current_project,
|
||||||
|
node.package_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if target_entity is None or isinstance(target_entity, Disabled):
|
||||||
|
# This may raise. Even if it doesn't, we don't want to add
|
||||||
|
# this node to the graph b/c there is no destination node
|
||||||
|
node.config.enabled = False
|
||||||
|
invalid_target_fail_unless_test(
|
||||||
|
node=node,
|
||||||
|
target_name=target_entity_name,
|
||||||
|
target_kind="source",
|
||||||
|
target_package=target_entity_package,
|
||||||
|
disabled=(isinstance(target_entity, Disabled)),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
target_entity_id = target_entity.unique_id
|
||||||
|
|
||||||
|
node.depends_on.nodes.append(target_entity_id)
|
||||||
|
|
||||||
|
|
||||||
def _process_refs_for_node(manifest: Manifest, current_project: str, node: ManifestNode):
|
def _process_refs_for_node(manifest: Manifest, current_project: str, node: ManifestNode):
|
||||||
"""Given a manifest and a node in that manifest, process its refs"""
|
"""Given a manifest and a node in that manifest, process its refs"""
|
||||||
|
|
||||||
@@ -1313,6 +1441,7 @@ def _process_sources_for_exposure(manifest: Manifest, current_project: str, expo
|
|||||||
manifest.update_exposure(exposure)
|
manifest.update_exposure(exposure)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Remove this code because metrics can't be based on sources
|
||||||
def _process_sources_for_metric(manifest: Manifest, current_project: str, metric: Metric):
|
def _process_sources_for_metric(manifest: Manifest, current_project: str, metric: Metric):
|
||||||
target_source: Optional[Union[Disabled, SourceDefinition]] = None
|
target_source: Optional[Union[Disabled, SourceDefinition]] = None
|
||||||
for source_name, table_name in metric.sources:
|
for source_name, table_name in metric.sources:
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ class PartialParsing:
|
|||||||
self.remove_source_override_target(source)
|
self.remove_source_override_target(source)
|
||||||
|
|
||||||
def delete_disabled(self, unique_id, file_id):
|
def delete_disabled(self, unique_id, file_id):
|
||||||
# This node/metric/exposure is disabled. Find it and remove it from disabled dictionary.
|
# This node/metric/entity/exposure is disabled. Find it and remove it from disabled dictionary.
|
||||||
for dis_index, dis_node in enumerate(self.saved_manifest.disabled[unique_id]):
|
for dis_index, dis_node in enumerate(self.saved_manifest.disabled[unique_id]):
|
||||||
if dis_node.file_id == file_id:
|
if dis_node.file_id == file_id:
|
||||||
node = dis_node
|
node = dis_node
|
||||||
@@ -441,6 +441,18 @@ class PartialParsing:
|
|||||||
if metric_element:
|
if metric_element:
|
||||||
self.delete_schema_metric(schema_file, metric_element)
|
self.delete_schema_metric(schema_file, metric_element)
|
||||||
self.merge_patch(schema_file, "metrics", metric_element)
|
self.merge_patch(schema_file, "metrics", metric_element)
|
||||||
|
elif unique_id in self.saved_manifest.entities:
|
||||||
|
entity = self.saved_manifest.entities[unique_id]
|
||||||
|
file_id = entity.file_id
|
||||||
|
if file_id in self.saved_files and file_id not in self.file_diff["deleted"]:
|
||||||
|
schema_file = self.saved_files[file_id]
|
||||||
|
entities = []
|
||||||
|
if "entities" in schema_file.dict_from_yaml:
|
||||||
|
entities = schema_file.dict_from_yaml["entities"]
|
||||||
|
entity_element = self.get_schema_element(entities, entity.name)
|
||||||
|
if entity_element:
|
||||||
|
self.delete_schema_entity(schema_file, entity_element)
|
||||||
|
self.merge_patch(schema_file, "entities", entity_element)
|
||||||
elif unique_id in self.saved_manifest.macros:
|
elif unique_id in self.saved_manifest.macros:
|
||||||
macro = self.saved_manifest.macros[unique_id]
|
macro = self.saved_manifest.macros[unique_id]
|
||||||
file_id = macro.file_id
|
file_id = macro.file_id
|
||||||
@@ -746,6 +758,29 @@ class PartialParsing:
|
|||||||
self.delete_schema_metric(schema_file, elem)
|
self.delete_schema_metric(schema_file, elem)
|
||||||
self.merge_patch(schema_file, dict_key, elem)
|
self.merge_patch(schema_file, dict_key, elem)
|
||||||
|
|
||||||
|
# entities
|
||||||
|
dict_key = "entities"
|
||||||
|
entity_diff = self.get_diff_for("entities", saved_yaml_dict, new_yaml_dict)
|
||||||
|
if entity_diff["changed"]:
|
||||||
|
for entity in entity_diff["changed"]:
|
||||||
|
self.delete_schema_entity(schema_file, entity)
|
||||||
|
self.merge_patch(schema_file, dict_key, entity)
|
||||||
|
if entity_diff["deleted"]:
|
||||||
|
for entity in entity_diff["deleted"]:
|
||||||
|
self.delete_schema_entity(schema_file, entity)
|
||||||
|
if entity_diff["added"]:
|
||||||
|
for entity in entity_diff["added"]:
|
||||||
|
self.merge_patch(schema_file, dict_key, entity)
|
||||||
|
# Handle schema file updates due to env_var changes
|
||||||
|
if dict_key in env_var_changes and dict_key in new_yaml_dict:
|
||||||
|
for name in env_var_changes[dict_key]:
|
||||||
|
if name in entity_diff["changed_or_deleted_names"]:
|
||||||
|
continue
|
||||||
|
elem = self.get_schema_element(new_yaml_dict[dict_key], name)
|
||||||
|
if elem:
|
||||||
|
self.delete_schema_entity(schema_file, elem)
|
||||||
|
self.merge_patch(schema_file, dict_key, elem)
|
||||||
|
|
||||||
# Take a "section" of the schema file yaml dictionary from saved and new schema files
|
# Take a "section" of the schema file yaml dictionary from saved and new schema files
|
||||||
# and determine which parts have changed
|
# and determine which parts have changed
|
||||||
def get_diff_for(self, key, saved_yaml_dict, new_yaml_dict):
|
def get_diff_for(self, key, saved_yaml_dict, new_yaml_dict):
|
||||||
@@ -921,6 +956,24 @@ class PartialParsing:
|
|||||||
elif unique_id in self.saved_manifest.disabled:
|
elif unique_id in self.saved_manifest.disabled:
|
||||||
self.delete_disabled(unique_id, schema_file.file_id)
|
self.delete_disabled(unique_id, schema_file.file_id)
|
||||||
|
|
||||||
|
# entities are created only from schema files, but also can be referred to by other nodes
|
||||||
|
def delete_schema_entity(self, schema_file, entity_dict):
|
||||||
|
entity_name = entity_dict["name"]
|
||||||
|
entities = schema_file.entities.copy()
|
||||||
|
for unique_id in entities:
|
||||||
|
if unique_id in self.saved_manifest.entities:
|
||||||
|
entity = self.saved_manifest.entities[unique_id]
|
||||||
|
if entity.name == entity_name:
|
||||||
|
# Need to find everything that referenced this entity and schedule for parsing
|
||||||
|
if unique_id in self.saved_manifest.child_map:
|
||||||
|
self.schedule_nodes_for_parsing(self.saved_manifest.child_map[unique_id])
|
||||||
|
self.deleted_manifest.entities[unique_id] = self.saved_manifest.entities.pop(
|
||||||
|
unique_id
|
||||||
|
)
|
||||||
|
schema_file.entities.remove(unique_id)
|
||||||
|
elif unique_id in self.saved_manifest.disabled:
|
||||||
|
self.delete_disabled(unique_id, schema_file.file_id)
|
||||||
|
|
||||||
def get_schema_element(self, elem_list, elem_name):
|
def get_schema_element(self, elem_list, elem_name):
|
||||||
for element in elem_list:
|
for element in elem_list:
|
||||||
if "name" in element and element["name"] == elem_name:
|
if "name" in element and element["name"] == elem_name:
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ from dbt.context.configured import generate_schema_yml_context, SchemaYamlVars
|
|||||||
from dbt.context.providers import (
|
from dbt.context.providers import (
|
||||||
generate_parse_exposure,
|
generate_parse_exposure,
|
||||||
generate_parse_metrics,
|
generate_parse_metrics,
|
||||||
|
generate_parse_entities,
|
||||||
generate_test_context,
|
generate_test_context,
|
||||||
)
|
)
|
||||||
from dbt.context.macro_resolver import MacroResolver
|
from dbt.context.macro_resolver import MacroResolver
|
||||||
from dbt.contracts.files import FileHash, SchemaSourceFile
|
from dbt.contracts.files import FileHash, SchemaSourceFile
|
||||||
from dbt.contracts.graph.model_config import MetricConfig, ExposureConfig
|
from dbt.contracts.graph.model_config import MetricConfig, ExposureConfig, EntityConfig
|
||||||
from dbt.contracts.graph.nodes import (
|
from dbt.contracts.graph.nodes import (
|
||||||
ParsedNodePatch,
|
ParsedNodePatch,
|
||||||
ColumnInfo,
|
ColumnInfo,
|
||||||
@@ -35,6 +36,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
UnpatchedSourceDefinition,
|
UnpatchedSourceDefinition,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.unparsed import (
|
from dbt.contracts.graph.unparsed import (
|
||||||
HasColumnDocs,
|
HasColumnDocs,
|
||||||
@@ -47,6 +49,7 @@ from dbt.contracts.graph.unparsed import (
|
|||||||
UnparsedNodeUpdate,
|
UnparsedNodeUpdate,
|
||||||
UnparsedExposure,
|
UnparsedExposure,
|
||||||
UnparsedMetric,
|
UnparsedMetric,
|
||||||
|
UnparsedEntity,
|
||||||
UnparsedSourceDefinition,
|
UnparsedSourceDefinition,
|
||||||
)
|
)
|
||||||
from dbt.exceptions import (
|
from dbt.exceptions import (
|
||||||
@@ -94,6 +97,7 @@ schema_file_keys = (
|
|||||||
"analyses",
|
"analyses",
|
||||||
"exposures",
|
"exposures",
|
||||||
"metrics",
|
"metrics",
|
||||||
|
"entities",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -114,6 +118,7 @@ class ParserRef:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.column_info: Dict[str, ColumnInfo] = {}
|
self.column_info: Dict[str, ColumnInfo] = {}
|
||||||
|
|
||||||
|
# TODO: Mimic this for dimension information at the entity level
|
||||||
def add(
|
def add(
|
||||||
self,
|
self,
|
||||||
column: Union[HasDocs, UnparsedColumn],
|
column: Union[HasDocs, UnparsedColumn],
|
||||||
@@ -536,6 +541,11 @@ class SchemaParser(SimpleParser[GenericTestBlock, GenericTestNode]):
|
|||||||
metric_parser = MetricParser(self, yaml_block)
|
metric_parser = MetricParser(self, yaml_block)
|
||||||
metric_parser.parse()
|
metric_parser.parse()
|
||||||
|
|
||||||
|
# parse entities
|
||||||
|
if "entities" in dct:
|
||||||
|
entity_parser = EntityParser(self, yaml_block)
|
||||||
|
entity_parser.parse()
|
||||||
|
|
||||||
|
|
||||||
def check_format_version(file_path, yaml_dct) -> None:
|
def check_format_version(file_path, yaml_dct) -> None:
|
||||||
if "version" not in yaml_dct:
|
if "version" not in yaml_dct:
|
||||||
@@ -1183,3 +1193,107 @@ class MetricParser(YamlReader):
|
|||||||
except (ValidationError, JSONValidationError) as exc:
|
except (ValidationError, JSONValidationError) as exc:
|
||||||
raise YamlParseDictError(self.yaml.path, self.key, data, exc)
|
raise YamlParseDictError(self.yaml.path, self.key, data, exc)
|
||||||
self.parse_metric(unparsed)
|
self.parse_metric(unparsed)
|
||||||
|
|
||||||
|
|
||||||
|
class EntityParser(YamlReader):
|
||||||
|
def __init__(self, schema_parser: SchemaParser, yaml: YamlBlock):
|
||||||
|
super().__init__(schema_parser, yaml, NodeType.Entity.pluralize())
|
||||||
|
self.schema_parser = schema_parser
|
||||||
|
self.yaml = yaml
|
||||||
|
|
||||||
|
def parse_entity(self, unparsed: UnparsedEntity):
|
||||||
|
package_name = self.project.project_name
|
||||||
|
unique_id = f"{NodeType.Entity}.{package_name}.{unparsed.name}"
|
||||||
|
path = self.yaml.path.relative_path
|
||||||
|
|
||||||
|
fqn = self.schema_parser.get_fqn_prefix(path)
|
||||||
|
fqn.append(unparsed.name)
|
||||||
|
|
||||||
|
config = self._generate_entity_config(
|
||||||
|
target=unparsed,
|
||||||
|
fqn=fqn,
|
||||||
|
package_name=package_name,
|
||||||
|
rendered=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
config = config.finalize_and_validate()
|
||||||
|
|
||||||
|
unrendered_config = self._generate_entity_config(
|
||||||
|
target=unparsed,
|
||||||
|
fqn=fqn,
|
||||||
|
package_name=package_name,
|
||||||
|
rendered=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not isinstance(config, EntityConfig):
|
||||||
|
raise DbtInternalError(
|
||||||
|
f"Calculated a {type(config)} for an entity, but expected a EntityConfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
parsed = Entity(
|
||||||
|
resource_type=NodeType.Entity,
|
||||||
|
package_name=package_name,
|
||||||
|
path=path,
|
||||||
|
original_file_path=self.yaml.path.original_file_path,
|
||||||
|
unique_id=unique_id,
|
||||||
|
fqn=fqn,
|
||||||
|
model=unparsed.model,
|
||||||
|
name=unparsed.name,
|
||||||
|
description=unparsed.description,
|
||||||
|
dimensions=unparsed.dimensions,
|
||||||
|
meta=unparsed.meta,
|
||||||
|
tags=unparsed.tags,
|
||||||
|
config=config,
|
||||||
|
unrendered_config=unrendered_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx = generate_parse_entities(
|
||||||
|
parsed,
|
||||||
|
self.root_project,
|
||||||
|
self.schema_parser.manifest,
|
||||||
|
package_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if parsed.model is not None:
|
||||||
|
model_ref = "{{ " + parsed.model + " }}"
|
||||||
|
get_rendered(model_ref, ctx, parsed)
|
||||||
|
|
||||||
|
# if the metric is disabled we do not want it included in the manifest, only in the disabled dict
|
||||||
|
if parsed.config.enabled:
|
||||||
|
# self.manifest.add_metric(self.yaml.file, parsed)
|
||||||
|
self.manifest.add_entity(self.yaml.file, parsed)
|
||||||
|
else:
|
||||||
|
self.manifest.add_disabled(self.yaml.file, parsed)
|
||||||
|
|
||||||
|
def _generate_entity_config(
|
||||||
|
self, target: UnparsedEntity, fqn: List[str], package_name: str, rendered: bool
|
||||||
|
):
|
||||||
|
generator: BaseContextConfigGenerator
|
||||||
|
if rendered:
|
||||||
|
generator = ContextConfigGenerator(self.root_project)
|
||||||
|
else:
|
||||||
|
generator = UnrenderedConfigGenerator(self.root_project)
|
||||||
|
|
||||||
|
# configs with precendence set
|
||||||
|
precedence_configs = dict()
|
||||||
|
# first apply metric configs
|
||||||
|
precedence_configs.update(target.config)
|
||||||
|
|
||||||
|
return generator.calculate_node_config(
|
||||||
|
config_call_dict={},
|
||||||
|
fqn=fqn,
|
||||||
|
resource_type=NodeType.Entity,
|
||||||
|
project_name=package_name,
|
||||||
|
base=False,
|
||||||
|
patch_config_dict=precedence_configs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
for data in self.get_key_dicts():
|
||||||
|
try:
|
||||||
|
UnparsedEntity.validate(data)
|
||||||
|
unparsed = UnparsedEntity.from_dict(data)
|
||||||
|
|
||||||
|
except (ValidationError, JSONValidationError) as exc:
|
||||||
|
raise YamlParseDictError(self.yaml.path, self.key, data, exc)
|
||||||
|
self.parse_entity(unparsed)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from dbt.contracts.graph.nodes import Exposure, SourceDefinition, Metric
|
from dbt.contracts.graph.nodes import Exposure, SourceDefinition, Metric, Entity
|
||||||
from dbt.graph import ResourceTypeSelector
|
from dbt.graph import ResourceTypeSelector
|
||||||
from dbt.task.runnable import GraphRunnableTask, ManifestTask
|
from dbt.task.runnable import GraphRunnableTask, ManifestTask
|
||||||
from dbt.task.test import TestSelector
|
from dbt.task.test import TestSelector
|
||||||
@@ -22,6 +22,7 @@ class ListTask(GraphRunnableTask):
|
|||||||
NodeType.Source,
|
NodeType.Source,
|
||||||
NodeType.Exposure,
|
NodeType.Exposure,
|
||||||
NodeType.Metric,
|
NodeType.Metric,
|
||||||
|
NodeType.Entity,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
ALL_RESOURCE_VALUES = DEFAULT_RESOURCE_VALUES | frozenset((NodeType.Analysis,))
|
ALL_RESOURCE_VALUES = DEFAULT_RESOURCE_VALUES | frozenset((NodeType.Analysis,))
|
||||||
@@ -82,6 +83,8 @@ class ListTask(GraphRunnableTask):
|
|||||||
yield self.manifest.exposures[node]
|
yield self.manifest.exposures[node]
|
||||||
elif node in self.manifest.metrics:
|
elif node in self.manifest.metrics:
|
||||||
yield self.manifest.metrics[node]
|
yield self.manifest.metrics[node]
|
||||||
|
elif node in self.manifest.entities:
|
||||||
|
yield self.manifest.entities[node]
|
||||||
else:
|
else:
|
||||||
raise DbtRuntimeError(
|
raise DbtRuntimeError(
|
||||||
f'Got an unexpected result from node selection: "{node}"'
|
f'Got an unexpected result from node selection: "{node}"'
|
||||||
@@ -105,6 +108,11 @@ class ListTask(GraphRunnableTask):
|
|||||||
# metrics are searched for by pkg.metric_name
|
# metrics are searched for by pkg.metric_name
|
||||||
metric_selector = ".".join([node.package_name, node.name])
|
metric_selector = ".".join([node.package_name, node.name])
|
||||||
yield f"metric:{metric_selector}"
|
yield f"metric:{metric_selector}"
|
||||||
|
elif node.resource_type == NodeType.Entity:
|
||||||
|
assert isinstance(node, Entity)
|
||||||
|
# entities are searched for by pkg.entity_name
|
||||||
|
entity_selector = ".".join([node.package_name, node.name])
|
||||||
|
yield f"entity:{entity_selector}"
|
||||||
else:
|
else:
|
||||||
# everything else is from `fqn`
|
# everything else is from `fqn`
|
||||||
yield ".".join(node.fqn)
|
yield ".".join(node.fqn)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "CatalogArtifact(metadata: dbt.contracts.results.CatalogMetadata, nodes: Dict[str, dbt.contracts.results.CatalogTable], sources: Dict[str, dbt.contracts.results.CatalogTable], errors: Union[List[str], NoneType] = None, _compile_results: Union[Any, NoneType] = None)",
|
"description": "CatalogArtifact(metadata: dbt.contracts.results.CatalogMetadata, nodes: Dict[str, dbt.contracts.results.CatalogTable], sources: Dict[str, dbt.contracts.results.CatalogTable], errors: Optional[List[str]] = None, _compile_results: Optional[Any] = None)",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"CatalogMetadata": {
|
"CatalogMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -48,12 +48,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.2.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-04-15T20:38:22.701177Z"
|
"default": "2023-01-23T21:56:17.789289Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "CatalogMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.2.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Union[str, NoneType] = <factory>, env: Dict[str, str] = <factory>)"
|
"description": "CatalogMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.5.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
||||||
},
|
},
|
||||||
"CatalogTable": {
|
"CatalogTable": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "CatalogTable(metadata: dbt.contracts.results.TableMetadata, columns: Dict[str, dbt.contracts.results.ColumnMetadata], stats: Dict[str, dbt.contracts.results.StatsItem], unique_id: Union[str, NoneType] = None)"
|
"description": "CatalogTable(metadata: dbt.contracts.results.TableMetadata, columns: Dict[str, dbt.contracts.results.ColumnMetadata], stats: Dict[str, dbt.contracts.results.StatsItem], unique_id: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"TableMetadata": {
|
"TableMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "TableMetadata(type: str, schema: str, name: str, database: Union[str, NoneType] = None, comment: Union[str, NoneType] = None, owner: Union[str, NoneType] = None)"
|
"description": "TableMetadata(type: str, schema: str, name: str, database: Optional[str] = None, comment: Optional[str] = None, owner: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"ColumnMetadata": {
|
"ColumnMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "ColumnMetadata(type: str, index: int, name: str, comment: Union[str, NoneType] = None)"
|
"description": "ColumnMetadata(type: str, index: int, name: str, comment: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"StatsItem": {
|
"StatsItem": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "StatsItem(id: str, label: str, value: Union[bool, str, float, NoneType], include: bool, description: Union[str, NoneType] = None)"
|
"description": "StatsItem(id: str, label: str, value: Union[bool, str, float, NoneType], include: bool, description: Optional[str] = None)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
|||||||
"docs",
|
"docs",
|
||||||
"exposures",
|
"exposures",
|
||||||
"metrics",
|
"metrics",
|
||||||
|
"entities",
|
||||||
"selectors"
|
"selectors"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -85,6 +86,13 @@
|
|||||||
},
|
},
|
||||||
"description": "The metrics defined in the dbt project and its dependencies"
|
"description": "The metrics defined in the dbt project and its dependencies"
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/definitions/Entity"
|
||||||
|
},
|
||||||
|
"description": "The entities defined in the dbt project and its dependencies"
|
||||||
|
},
|
||||||
"selectors": {
|
"selectors": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The selectors defined in selectors.yml"
|
"description": "The selectors defined in selectors.yml"
|
||||||
@@ -173,7 +181,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "WritableManifest(metadata: dbt.contracts.graph.manifest.ManifestMetadata, nodes: Mapping[str, Union[dbt.contracts.graph.nodes.AnalysisNode, dbt.contracts.graph.nodes.SingularTestNode, dbt.contracts.graph.nodes.HookNode, dbt.contracts.graph.nodes.ModelNode, dbt.contracts.graph.nodes.RPCNode, dbt.contracts.graph.nodes.SqlNode, dbt.contracts.graph.nodes.GenericTestNode, dbt.contracts.graph.nodes.SnapshotNode, dbt.contracts.graph.nodes.SeedNode]], sources: Mapping[str, dbt.contracts.graph.nodes.SourceDefinition], macros: Mapping[str, dbt.contracts.graph.nodes.Macro], docs: Mapping[str, dbt.contracts.graph.nodes.Documentation], exposures: Mapping[str, dbt.contracts.graph.nodes.Exposure], metrics: Mapping[str, dbt.contracts.graph.nodes.Metric], selectors: Mapping[str, Any], disabled: Optional[Mapping[str, List[Union[dbt.contracts.graph.nodes.AnalysisNode, dbt.contracts.graph.nodes.SingularTestNode, dbt.contracts.graph.nodes.HookNode, dbt.contracts.graph.nodes.ModelNode, dbt.contracts.graph.nodes.RPCNode, dbt.contracts.graph.nodes.SqlNode, dbt.contracts.graph.nodes.GenericTestNode, dbt.contracts.graph.nodes.SnapshotNode, dbt.contracts.graph.nodes.SeedNode, dbt.contracts.graph.nodes.SourceDefinition]]]], parent_map: Optional[Dict[str, List[str]]], child_map: Optional[Dict[str, List[str]]])",
|
"description": "WritableManifest(metadata: dbt.contracts.graph.manifest.ManifestMetadata, nodes: Mapping[str, Union[dbt.contracts.graph.nodes.AnalysisNode, dbt.contracts.graph.nodes.SingularTestNode, dbt.contracts.graph.nodes.HookNode, dbt.contracts.graph.nodes.ModelNode, dbt.contracts.graph.nodes.RPCNode, dbt.contracts.graph.nodes.SqlNode, dbt.contracts.graph.nodes.GenericTestNode, dbt.contracts.graph.nodes.SnapshotNode, dbt.contracts.graph.nodes.SeedNode]], sources: Mapping[str, dbt.contracts.graph.nodes.SourceDefinition], macros: Mapping[str, dbt.contracts.graph.nodes.Macro], docs: Mapping[str, dbt.contracts.graph.nodes.Documentation], exposures: Mapping[str, dbt.contracts.graph.nodes.Exposure], metrics: Mapping[str, dbt.contracts.graph.nodes.Metric], entities: Mapping[str, dbt.contracts.graph.nodes.Entity], selectors: Mapping[str, Any], disabled: Optional[Mapping[str, List[Union[dbt.contracts.graph.nodes.AnalysisNode, dbt.contracts.graph.nodes.SingularTestNode, dbt.contracts.graph.nodes.HookNode, dbt.contracts.graph.nodes.ModelNode, dbt.contracts.graph.nodes.RPCNode, dbt.contracts.graph.nodes.SqlNode, dbt.contracts.graph.nodes.GenericTestNode, dbt.contracts.graph.nodes.SnapshotNode, dbt.contracts.graph.nodes.SeedNode, dbt.contracts.graph.nodes.SourceDefinition]]]], parent_map: Optional[Dict[str, List[str]]], child_map: Optional[Dict[str, List[str]]])",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"ManifestMetadata": {
|
"ManifestMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -185,12 +193,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.4.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-12-13T03:30:15.966964Z"
|
"default": "2023-01-23T21:56:17.790304Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -201,7 +209,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "4f2b967b-7e02-46de-a7ea-268a05e3fab1"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -262,7 +270,6 @@
|
|||||||
"AnalysisNode": {
|
"AnalysisNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -276,7 +283,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -400,7 +414,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.970579
|
"default": 1674510977.792257
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -454,6 +468,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -498,7 +522,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "AnalysisNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "AnalysisNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"FileHash": {
|
"FileHash": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -811,7 +835,6 @@
|
|||||||
"SingularTestNode": {
|
"SingularTestNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -825,7 +848,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -941,7 +971,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.973521
|
"default": 1674510977.79368
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -995,6 +1025,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -1039,7 +1079,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "SingularTestNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.TestConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "SingularTestNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.TestConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"TestConfig": {
|
"TestConfig": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -1156,7 +1196,6 @@
|
|||||||
"HookNode": {
|
"HookNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -1170,7 +1209,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -1294,7 +1340,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.975156
|
"default": 1674510977.795094
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -1348,6 +1394,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -1402,12 +1458,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "HookNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None, index: Optional[int] = None)"
|
"description": "HookNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None, index: Optional[int] = None)"
|
||||||
},
|
},
|
||||||
"ModelNode": {
|
"ModelNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -1421,7 +1476,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -1545,7 +1607,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.976732
|
"default": 1674510977.7959611
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -1599,6 +1661,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -1643,12 +1715,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "ModelNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "ModelNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"RPCNode": {
|
"RPCNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -1662,7 +1733,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -1786,7 +1864,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.978195
|
"default": 1674510977.796774
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -1840,6 +1918,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -1884,12 +1972,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "RPCNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "RPCNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"SqlNode": {
|
"SqlNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -1903,7 +1990,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2027,7 +2121,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.979718
|
"default": 1674510977.797567
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2081,6 +2175,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -2125,13 +2229,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "SqlNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "SqlNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.NodeConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"GenericTestNode": {
|
"GenericTestNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"test_metadata",
|
"test_metadata",
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -2148,7 +2251,14 @@
|
|||||||
"$ref": "#/definitions/TestMetadata"
|
"$ref": "#/definitions/TestMetadata"
|
||||||
},
|
},
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2264,7 +2374,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.981434
|
"default": 1674510977.79852
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2318,6 +2428,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -2382,7 +2502,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "GenericTestNode(test_metadata: dbt.contracts.graph.nodes.TestMetadata, database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.TestConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None, column_name: Optional[str] = None, file_key_name: Optional[str] = None)"
|
"description": "GenericTestNode(test_metadata: dbt.contracts.graph.nodes.TestMetadata, database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.TestConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None, column_name: Optional[str] = None, file_key_name: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"TestMetadata": {
|
"TestMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2414,7 +2534,6 @@
|
|||||||
"SnapshotNode": {
|
"SnapshotNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -2429,7 +2548,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2529,7 +2655,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.984685
|
"default": 1674510977.79998
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2583,6 +2709,16 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"depends_on": {
|
"depends_on": {
|
||||||
"$ref": "#/definitions/DependsOn",
|
"$ref": "#/definitions/DependsOn",
|
||||||
"default": {
|
"default": {
|
||||||
@@ -2627,7 +2763,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "SnapshotNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.SnapshotConfig, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
"description": "SnapshotNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.SnapshotConfig, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', language: str = 'sql', refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, compiled_path: Optional[str] = None, compiled: bool = False, compiled_code: Optional[str] = None, extra_ctes_injected: bool = False, extra_ctes: List[dbt.contracts.graph.nodes.InjectedCTE] = <factory>, _pre_injected_sql: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"SnapshotConfig": {
|
"SnapshotConfig": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -2837,7 +2973,6 @@
|
|||||||
"SeedNode": {
|
"SeedNode": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -2851,7 +2986,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -2976,7 +3118,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.987447
|
"default": 1674510977.801306
|
||||||
},
|
},
|
||||||
"config_call_dict": {
|
"config_call_dict": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3008,7 +3150,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "SeedNode(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.SeedConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', root_path: Optional[str] = None)"
|
"description": "SeedNode(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], alias: str, checksum: dbt.contracts.files.FileHash, config: dbt.contracts.graph.model_config.SeedConfig = <factory>, _event_status: Dict[str, Any] = <factory>, tags: List[str] = <factory>, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, docs: dbt.contracts.graph.unparsed.Docs = <factory>, patch_path: Optional[str] = None, build_path: Optional[str] = None, deferred: bool = False, unrendered_config: Dict[str, Any] = <factory>, created_at: float = <factory>, config_call_dict: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, raw_code: str = '', root_path: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"SeedConfig": {
|
"SeedConfig": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3178,7 +3320,6 @@
|
|||||||
"SourceDefinition": {
|
"SourceDefinition": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
|
||||||
"schema",
|
"schema",
|
||||||
"name",
|
"name",
|
||||||
"resource_type",
|
"resource_type",
|
||||||
@@ -3194,7 +3335,14 @@
|
|||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string"
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -3335,11 +3483,11 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.989922
|
"default": 1674510977.802621
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "SourceDefinition(database: str, schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], source_name: str, source_description: str, loader: str, identifier: str, _event_status: Dict[str, Any] = <factory>, quoting: dbt.contracts.graph.unparsed.Quoting = <factory>, loaded_at_field: Optional[str] = None, freshness: Optional[dbt.contracts.graph.unparsed.FreshnessThreshold] = None, external: Optional[dbt.contracts.graph.unparsed.ExternalTable] = None, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, source_meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.SourceConfig = <factory>, patch_path: Optional[str] = None, unrendered_config: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, created_at: float = <factory>)"
|
"description": "SourceDefinition(database: Optional[str], schema: str, name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], source_name: str, source_description: str, loader: str, identifier: str, _event_status: Dict[str, Any] = <factory>, quoting: dbt.contracts.graph.unparsed.Quoting = <factory>, loaded_at_field: Optional[str] = None, freshness: Optional[dbt.contracts.graph.unparsed.FreshnessThreshold] = None, external: Optional[dbt.contracts.graph.unparsed.ExternalTable] = None, description: str = '', columns: Dict[str, dbt.contracts.graph.nodes.ColumnInfo] = <factory>, meta: Dict[str, Any] = <factory>, source_meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.SourceConfig = <factory>, patch_path: Optional[str] = None, unrendered_config: Dict[str, Any] = <factory>, relation_name: Optional[str] = None, created_at: float = <factory>)"
|
||||||
},
|
},
|
||||||
"Quoting": {
|
"Quoting": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3445,12 +3593,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.4.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-12-13T03:30:15.961825Z"
|
"default": "2023-01-23T21:56:17.787436Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -3461,7 +3609,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "4f2b967b-7e02-46de-a7ea-268a05e3fab1"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3472,7 +3620,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.4.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.5.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
||||||
},
|
},
|
||||||
"SourceFreshnessRuntimeError": {
|
"SourceFreshnessRuntimeError": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -3814,7 +3962,7 @@
|
|||||||
},
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.990816
|
"default": 1674510977.8031092
|
||||||
},
|
},
|
||||||
"supported_languages": {
|
"supported_languages": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -4070,13 +4218,23 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.993354
|
"default": 1674510977.8040562
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "Exposure(name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], type: dbt.contracts.graph.unparsed.ExposureType, owner: dbt.contracts.graph.unparsed.ExposureOwner, description: str = '', label: Optional[str] = None, maturity: Optional[dbt.contracts.graph.unparsed.MaturityType] = None, meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.ExposureConfig = <factory>, unrendered_config: Dict[str, Any] = <factory>, url: Optional[str] = None, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, created_at: float = <factory>)"
|
"description": "Exposure(name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], type: dbt.contracts.graph.unparsed.ExposureType, owner: dbt.contracts.graph.unparsed.ExposureOwner, description: str = '', label: Optional[str] = None, maturity: Optional[dbt.contracts.graph.unparsed.MaturityType] = None, meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.ExposureConfig = <factory>, unrendered_config: Dict[str, Any] = <factory>, url: Optional[str] = None, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, refs: List[List[str]] = <factory>, sources: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, created_at: float = <factory>)"
|
||||||
},
|
},
|
||||||
"ExposureOwner": {
|
"ExposureOwner": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -4126,7 +4284,6 @@
|
|||||||
"description",
|
"description",
|
||||||
"label",
|
"label",
|
||||||
"calculation_method",
|
"calculation_method",
|
||||||
"timestamp",
|
|
||||||
"expression",
|
"expression",
|
||||||
"filters",
|
"filters",
|
||||||
"time_grains",
|
"time_grains",
|
||||||
@@ -4169,9 +4326,6 @@
|
|||||||
"calculation_method": {
|
"calculation_method": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"timestamp": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"expression": {
|
"expression": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -4193,6 +4347,16 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"timestamp": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"window": {
|
"window": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
@@ -4281,13 +4445,23 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 1670902215.995033
|
"default": 1674510977.804972
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "Metric(name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], description: str, label: str, calculation_method: str, timestamp: str, expression: str, filters: List[dbt.contracts.graph.unparsed.MetricFilter], time_grains: List[str], dimensions: List[str], window: Optional[dbt.contracts.graph.unparsed.MetricTime] = None, model: Optional[str] = None, model_unique_id: Optional[str] = None, meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.MetricConfig = <factory>, unrendered_config: Dict[str, Any] = <factory>, sources: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, refs: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, created_at: float = <factory>)"
|
"description": "Metric(name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], description: str, label: str, calculation_method: str, expression: str, filters: List[dbt.contracts.graph.unparsed.MetricFilter], time_grains: List[str], dimensions: List[str], timestamp: Optional[str] = None, window: Optional[dbt.contracts.graph.unparsed.MetricTime] = None, model: Optional[str] = None, model_unique_id: Optional[str] = None, meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.MetricConfig = <factory>, unrendered_config: Dict[str, Any] = <factory>, sources: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, refs: List[List[str]] = <factory>, metrics: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, created_at: float = <factory>)"
|
||||||
},
|
},
|
||||||
"MetricFilter": {
|
"MetricFilter": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -4355,6 +4529,148 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": true,
|
"additionalProperties": true,
|
||||||
"description": "MetricConfig(_extra: Dict[str, Any] = <factory>, enabled: bool = True)"
|
"description": "MetricConfig(_extra: Dict[str, Any] = <factory>, enabled: bool = True)"
|
||||||
|
},
|
||||||
|
"Entity": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"resource_type",
|
||||||
|
"package_name",
|
||||||
|
"path",
|
||||||
|
"original_file_path",
|
||||||
|
"unique_id",
|
||||||
|
"fqn",
|
||||||
|
"model",
|
||||||
|
"description",
|
||||||
|
"dimensions"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"resource_type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"entity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"package_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"original_file_path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"unique_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"fqn": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"dimensions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"model_unique_id": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"type": "object",
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"$ref": "#/definitions/EntityConfig",
|
||||||
|
"default": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unrendered_config": {
|
||||||
|
"type": "object",
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"depends_on": {
|
||||||
|
"$ref": "#/definitions/DependsOn",
|
||||||
|
"default": {
|
||||||
|
"macros": [],
|
||||||
|
"nodes": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"entities": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "number",
|
||||||
|
"default": 1674510977.805523
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Entity(name: str, resource_type: dbt.node_types.NodeType, package_name: str, path: str, original_file_path: str, unique_id: str, fqn: List[str], model: str, description: str, dimensions: List[str], model_unique_id: Optional[str] = None, meta: Dict[str, Any] = <factory>, tags: List[str] = <factory>, config: dbt.contracts.graph.model_config.EntityConfig = <factory>, unrendered_config: Dict[str, Any] = <factory>, sources: List[List[str]] = <factory>, depends_on: dbt.contracts.graph.nodes.DependsOn = <factory>, refs: List[List[str]] = <factory>, entities: List[List[str]] = <factory>, created_at: float = <factory>)"
|
||||||
|
},
|
||||||
|
"EntityConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [],
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": true,
|
||||||
|
"description": "EntityConfig(_extra: Dict[str, Any] = <factory>, enabled: bool = True)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
|||||||
@@ -37,12 +37,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.2.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-04-15T20:38:22.700175Z"
|
"default": "2023-01-23T21:56:17.788708Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "BaseArtifactMetadata(dbt_schema_version: str, dbt_version: str = '1.2.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Union[str, NoneType] = <factory>, env: Dict[str, str] = <factory>)"
|
"description": "BaseArtifactMetadata(dbt_schema_version: str, dbt_version: str = '1.5.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
||||||
},
|
},
|
||||||
"RunResultOutput": {
|
"RunResultOutput": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "RunResultOutput(status: Union[dbt.contracts.results.RunStatus, dbt.contracts.results.TestStatus, dbt.contracts.results.FreshnessStatus], timing: List[dbt.contracts.results.TimingInfo], thread_id: str, execution_time: float, adapter_response: Dict[str, Any], message: Union[str, NoneType], failures: Union[int, NoneType], unique_id: str)"
|
"description": "RunResultOutput(status: Union[dbt.contracts.results.RunStatus, dbt.contracts.results.TestStatus, dbt.contracts.results.FreshnessStatus], timing: List[dbt.contracts.results.TimingInfo], thread_id: str, execution_time: float, adapter_response: Dict[str, Any], message: Optional[str], failures: Optional[int], unique_id: str)"
|
||||||
},
|
},
|
||||||
"TimingInfo": {
|
"TimingInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "TimingInfo(name: str, started_at: Union[datetime.datetime, NoneType] = None, completed_at: Union[datetime.datetime, NoneType] = None)"
|
"description": "TimingInfo(name: str, started_at: Optional[datetime.datetime] = None, completed_at: Optional[datetime.datetime] = None)"
|
||||||
},
|
},
|
||||||
"FreshnessMetadata": {
|
"FreshnessMetadata": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -195,12 +195,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.2.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-04-15T20:38:22.697740Z"
|
"default": "2023-01-23T21:56:17.787436Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -222,7 +222,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.2.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Union[str, NoneType] = <factory>, env: Dict[str, str] = <factory>)"
|
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.5.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
||||||
},
|
},
|
||||||
"SourceFreshnessRuntimeError": {
|
"SourceFreshnessRuntimeError": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -361,7 +361,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "FreshnessThreshold(warn_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, error_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, filter: Union[str, NoneType] = None)"
|
"description": "FreshnessThreshold(warn_after: Optional[dbt.contracts.graph.unparsed.Time] = <factory>, error_after: Optional[dbt.contracts.graph.unparsed.Time] = <factory>, filter: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"Time": {
|
"Time": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -394,7 +394,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "Time(count: Union[int, NoneType] = None, period: Union[dbt.contracts.graph.unparsed.TimePeriod, NoneType] = None)"
|
"description": "Time(count: Optional[int] = None, period: Optional[dbt.contracts.graph.unparsed.TimePeriod] = None)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
|||||||
@@ -39,12 +39,12 @@
|
|||||||
},
|
},
|
||||||
"dbt_version": {
|
"dbt_version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "1.2.0a1"
|
"default": "1.5.0a1"
|
||||||
},
|
},
|
||||||
"generated_at": {
|
"generated_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"default": "2022-04-15T20:38:22.697740Z"
|
"default": "2023-01-23T21:56:17.787436Z"
|
||||||
},
|
},
|
||||||
"invocation_id": {
|
"invocation_id": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.2.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Union[str, NoneType] = <factory>, env: Dict[str, str] = <factory>)"
|
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.5.0a1', generated_at: datetime.datetime = <factory>, invocation_id: Optional[str] = <factory>, env: Dict[str, str] = <factory>)"
|
||||||
},
|
},
|
||||||
"SourceFreshnessRuntimeError": {
|
"SourceFreshnessRuntimeError": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "FreshnessThreshold(warn_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, error_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, filter: Union[str, NoneType] = None)"
|
"description": "FreshnessThreshold(warn_after: Optional[dbt.contracts.graph.unparsed.Time] = <factory>, error_after: Optional[dbt.contracts.graph.unparsed.Time] = <factory>, filter: Optional[str] = None)"
|
||||||
},
|
},
|
||||||
"Time": {
|
"Time": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "Time(count: Union[int, NoneType] = None, period: Union[dbt.contracts.graph.unparsed.TimePeriod, NoneType] = None)"
|
"description": "Time(count: Optional[int] = None, period: Optional[dbt.contracts.graph.unparsed.TimePeriod] = None)"
|
||||||
},
|
},
|
||||||
"TimingInfo": {
|
"TimingInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"description": "TimingInfo(name: str, started_at: Union[datetime.datetime, NoneType] = None, completed_at: Union[datetime.datetime, NoneType] = None)"
|
"description": "TimingInfo(name: str, started_at: Optional[datetime.datetime] = None, completed_at: Optional[datetime.datetime] = None)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ def basic_uncompiled_model():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
deferred=False,
|
deferred=False,
|
||||||
description='',
|
description='',
|
||||||
@@ -67,6 +68,7 @@ def basic_compiled_model():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
deferred=True,
|
deferred=True,
|
||||||
description='',
|
description='',
|
||||||
@@ -123,6 +125,7 @@ def basic_uncompiled_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities':[],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
@@ -172,6 +175,7 @@ def basic_compiled_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities':[],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': True,
|
'deferred': True,
|
||||||
@@ -359,6 +363,7 @@ def basic_uncompiled_schema_test_node():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
deferred=False,
|
deferred=False,
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
@@ -392,6 +397,7 @@ def basic_compiled_schema_test_node():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
deferred=False,
|
deferred=False,
|
||||||
description='',
|
description='',
|
||||||
@@ -430,6 +436,7 @@ def basic_uncompiled_schema_test_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities':[],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'description': '',
|
'description': '',
|
||||||
@@ -480,6 +487,7 @@ def basic_compiled_schema_test_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from dbt.contracts.graph.model_config import (
|
|||||||
SnapshotConfig,
|
SnapshotConfig,
|
||||||
SourceConfig,
|
SourceConfig,
|
||||||
ExposureConfig,
|
ExposureConfig,
|
||||||
|
MetricConfig,
|
||||||
|
EntityConfig,
|
||||||
EmptySnapshotConfig,
|
EmptySnapshotConfig,
|
||||||
Hook,
|
Hook,
|
||||||
)
|
)
|
||||||
@@ -24,6 +26,7 @@ from dbt.contracts.graph.nodes import (
|
|||||||
Macro,
|
Macro,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric,
|
Metric,
|
||||||
|
Entity,
|
||||||
SeedNode,
|
SeedNode,
|
||||||
Docs,
|
Docs,
|
||||||
MacroDependsOn,
|
MacroDependsOn,
|
||||||
@@ -139,6 +142,7 @@ def base_parsed_model_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'description': '',
|
'description': '',
|
||||||
@@ -185,6 +189,7 @@ def basic_parsed_model_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -235,6 +240,7 @@ def complex_parsed_model_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': True,
|
'deferred': True,
|
||||||
@@ -292,6 +298,7 @@ def complex_parsed_model_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||||
deferred=True,
|
deferred=True,
|
||||||
description='My parsed node',
|
description='My parsed node',
|
||||||
@@ -714,6 +721,7 @@ def patched_model_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='The foo model',
|
description='The foo model',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -773,6 +781,7 @@ def base_parsed_hook_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
@@ -819,6 +828,7 @@ def base_parsed_hook_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
deferred=False,
|
deferred=False,
|
||||||
@@ -849,6 +859,7 @@ def complex_parsed_hook_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
@@ -906,6 +917,7 @@ def complex_parsed_hook_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||||
description='My parsed node',
|
description='My parsed node',
|
||||||
deferred=False,
|
deferred=False,
|
||||||
@@ -1000,6 +1012,7 @@ def basic_parsed_schema_test_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
@@ -1046,6 +1059,7 @@ def basic_parsed_schema_test_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -1075,6 +1089,7 @@ def complex_parsed_schema_test_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
@@ -1138,6 +1153,7 @@ def complex_parsed_schema_test_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||||
description='My parsed node',
|
description='My parsed node',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -1432,6 +1448,7 @@ def basic_timestamp_snapshot_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
@@ -1489,6 +1506,7 @@ def basic_timestamp_snapshot_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -1537,6 +1555,7 @@ def basic_intermediate_timestamp_snapshot_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -1572,6 +1591,7 @@ def basic_check_snapshot_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'depends_on': {'macros': [], 'nodes': []},
|
'depends_on': {'macros': [], 'nodes': []},
|
||||||
'database': 'test_db',
|
'database': 'test_db',
|
||||||
'deferred': False,
|
'deferred': False,
|
||||||
@@ -1629,6 +1649,7 @@ def basic_check_snapshot_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -1677,6 +1698,7 @@ def basic_intermediate_check_snapshot_object():
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
description='',
|
description='',
|
||||||
database='test_db',
|
database='test_db',
|
||||||
@@ -2115,6 +2137,7 @@ def basic_parsed_exposure_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'fqn': ['test', 'exposures', 'my_exposure'],
|
'fqn': ['test', 'exposures', 'my_exposure'],
|
||||||
'unique_id': 'exposure.test.my_exposure',
|
'unique_id': 'exposure.test.my_exposure',
|
||||||
'package_name': 'test',
|
'package_name': 'test',
|
||||||
@@ -2177,6 +2200,7 @@ def complex_parsed_exposure_dict():
|
|||||||
'refs': [],
|
'refs': [],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'fqn': ['test', 'exposures', 'my_exposure'],
|
'fqn': ['test', 'exposures', 'my_exposure'],
|
||||||
'unique_id': 'exposure.test.my_exposure',
|
'unique_id': 'exposure.test.my_exposure',
|
||||||
'package_name': 'test',
|
'package_name': 'test',
|
||||||
@@ -2251,47 +2275,24 @@ def test_compare_changed_exposure(func, basic_parsed_exposure_object):
|
|||||||
|
|
||||||
|
|
||||||
# METRICS
|
# METRICS
|
||||||
@pytest.fixture
|
|
||||||
def minimal_parsed_metric_dict():
|
|
||||||
return {
|
|
||||||
'name': 'my_metric',
|
|
||||||
'type': 'count',
|
|
||||||
'timestamp': 'created_at',
|
|
||||||
'time_grains': ['day'],
|
|
||||||
'fqn': ['test', 'metrics', 'my_metric'],
|
|
||||||
'unique_id': 'metric.test.my_metric',
|
|
||||||
'package_name': 'test',
|
|
||||||
'meta': {},
|
|
||||||
'tags': [],
|
|
||||||
'path': 'models/something.yml',
|
|
||||||
'original_file_path': 'models/something.yml',
|
|
||||||
'description': '',
|
|
||||||
'created_at': 1.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def basic_parsed_metric_dict():
|
def basic_parsed_metric_dict():
|
||||||
return {
|
return {
|
||||||
'name': 'new_customers',
|
'name': 'new_customers',
|
||||||
'label': 'New Customers',
|
'label': 'New Customers',
|
||||||
'model': 'ref("dim_customers")',
|
'model': "ref('dim_customers')",
|
||||||
'calculation_method': 'count',
|
'calculation_method': 'count',
|
||||||
'expression': 'user_id',
|
'expression': 'user_id',
|
||||||
'timestamp': 'signup_date',
|
'timestamp': 'signup_date',
|
||||||
'time_grains': ['day', 'week', 'month'],
|
'time_grains': ['day', 'week', 'month'],
|
||||||
'dimensions': ['plan', 'country'],
|
'dimensions': ['plan', 'country'],
|
||||||
'filters': [
|
'filters': [],
|
||||||
{
|
|
||||||
"field": "is_paying",
|
|
||||||
"value": "true",
|
|
||||||
"operator": "=",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'resource_type': 'metric',
|
'resource_type': 'metric',
|
||||||
'refs': [['dim_customers']],
|
'refs': [['dim_customers']],
|
||||||
'sources': [],
|
'sources': [],
|
||||||
'metrics': [],
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
'fqn': ['test', 'metrics', 'my_metric'],
|
'fqn': ['test', 'metrics', 'my_metric'],
|
||||||
'unique_id': 'metric.test.my_metric',
|
'unique_id': 'metric.test.my_metric',
|
||||||
'package_name': 'test',
|
'package_name': 'test',
|
||||||
@@ -2300,26 +2301,98 @@ def basic_parsed_metric_dict():
|
|||||||
'description': '',
|
'description': '',
|
||||||
'meta': {},
|
'meta': {},
|
||||||
'tags': [],
|
'tags': [],
|
||||||
|
'created_at': 1,
|
||||||
|
'depends_on': {
|
||||||
|
'nodes': [],
|
||||||
|
'macros': [],
|
||||||
|
},
|
||||||
|
'config': {
|
||||||
|
'enabled': True,
|
||||||
|
},
|
||||||
|
'unrendered_config': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def basic_parsed_metric_object():
|
||||||
|
return Metric(
|
||||||
|
name='new_customers',
|
||||||
|
resource_type=NodeType.Metric,
|
||||||
|
model="ref('dim_customers')",
|
||||||
|
label='New Customers',
|
||||||
|
calculation_method='count',
|
||||||
|
expression="user_id",
|
||||||
|
timestamp='signup_date',
|
||||||
|
time_grains=['day','week','month'],
|
||||||
|
dimensions=['plan','country'],
|
||||||
|
filters=[],
|
||||||
|
refs=[['dim_customers']],
|
||||||
|
fqn=['test', 'metrics', 'my_metric'],
|
||||||
|
unique_id='metric.test.my_metric',
|
||||||
|
package_name='test',
|
||||||
|
path='models/something.yml',
|
||||||
|
original_file_path='models/something.yml',
|
||||||
|
description='',
|
||||||
|
meta={},
|
||||||
|
tags=[],
|
||||||
|
config=MetricConfig(),
|
||||||
|
unrendered_config={},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_simple_parsed_metric(basic_parsed_metric_dict, basic_parsed_metric_object):
|
||||||
|
assert_symmetric(basic_parsed_metric_object, basic_parsed_metric_dict, Metric)
|
||||||
|
|
||||||
|
# ENTITIES
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def basic_parsed_entity_dict():
|
||||||
|
return {
|
||||||
|
'name': 'my_entity',
|
||||||
|
'model': "ref('my_model')",
|
||||||
|
'dimensions': [],
|
||||||
|
'resource_type': 'entity',
|
||||||
|
'refs': [['my_model']],
|
||||||
|
'sources': [],
|
||||||
|
'metrics': [],
|
||||||
|
'entities': [],
|
||||||
|
'fqn': ['test', 'entities', 'my_entity'],
|
||||||
|
'unique_id': 'entity.test.my_entity',
|
||||||
|
'package_name': 'test',
|
||||||
|
'path': 'models/something.yml',
|
||||||
|
'original_file_path': 'models/something.yml',
|
||||||
|
'description': '',
|
||||||
|
'meta': {},
|
||||||
|
'tags': [],
|
||||||
'created_at': 1.0,
|
'created_at': 1.0,
|
||||||
'depends_on': {
|
'depends_on': {
|
||||||
'nodes': [],
|
'nodes': [],
|
||||||
'macros': [],
|
'macros': [],
|
||||||
},
|
},
|
||||||
|
'config': {
|
||||||
|
'enabled': True,
|
||||||
|
},
|
||||||
|
'unrendered_config': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def basic_parsed_metric_object():
|
def basic_parsed_entity_object():
|
||||||
return Metric(
|
return Entity(
|
||||||
name='my_metric',
|
name='my_entity',
|
||||||
resource_type=NodeType.Metric,
|
model="ref('my_model')",
|
||||||
calculation_method='count',
|
dimensions=[],
|
||||||
fqn=['test', 'metrics', 'my_metric'],
|
resource_type=NodeType.Entity,
|
||||||
unique_id='metric.test.my_metric',
|
fqn=['test', 'entities', 'my_entity'],
|
||||||
|
refs=[['my_model']],
|
||||||
|
unique_id='entity.test.my_entity',
|
||||||
package_name='test',
|
package_name='test',
|
||||||
path='models/something.yml',
|
path='models/something.yml',
|
||||||
original_file_path='models/something.yml',
|
original_file_path='models/something.yml',
|
||||||
description='',
|
description='',
|
||||||
meta={},
|
meta={},
|
||||||
tags=[]
|
tags=[],
|
||||||
|
config=EntityConfig(),
|
||||||
|
unrendered_config={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_simple_parsed_entity(basic_parsed_entity_dict, basic_parsed_entity_object):
|
||||||
|
assert_symmetric(basic_parsed_entity_object, basic_parsed_entity_dict, Entity)
|
||||||
@@ -7,7 +7,8 @@ from dbt.contracts.graph.unparsed import (
|
|||||||
FreshnessThreshold, Quoting, UnparsedSourceDefinition,
|
FreshnessThreshold, Quoting, UnparsedSourceDefinition,
|
||||||
UnparsedSourceTableDefinition, UnparsedDocumentationFile, UnparsedColumn,
|
UnparsedSourceTableDefinition, UnparsedDocumentationFile, UnparsedColumn,
|
||||||
UnparsedNodeUpdate, Docs, UnparsedExposure, MaturityType, ExposureOwner,
|
UnparsedNodeUpdate, Docs, UnparsedExposure, MaturityType, ExposureOwner,
|
||||||
ExposureType, UnparsedMetric, MetricFilter, MetricTime, MetricTimePeriod
|
ExposureType, UnparsedMetric, UnparsedEntity, MetricFilter, MetricTime,
|
||||||
|
MetricTimePeriod
|
||||||
)
|
)
|
||||||
from dbt.contracts.results import FreshnessStatus
|
from dbt.contracts.results import FreshnessStatus
|
||||||
from dbt.node_types import NodeType
|
from dbt.node_types import NodeType
|
||||||
@@ -783,3 +784,49 @@ class TestUnparsedMetric(ContractTestCase):
|
|||||||
tst = self.get_ok_dict()
|
tst = self.get_ok_dict()
|
||||||
tst['tags'] = [123]
|
tst['tags'] = [123]
|
||||||
self.assert_fails_validation(tst)
|
self.assert_fails_validation(tst)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestUnparsedEntity(ContractTestCase):
|
||||||
|
ContractType = UnparsedEntity
|
||||||
|
|
||||||
|
def get_ok_dict(self):
|
||||||
|
return {
|
||||||
|
'name': 'my_entity',
|
||||||
|
'model': "ref('my_model')",
|
||||||
|
'description': 'my model',
|
||||||
|
'dimensions': ['plan', 'country'],
|
||||||
|
'config': {},
|
||||||
|
'tags': [],
|
||||||
|
'meta': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_ok(self):
|
||||||
|
metric = self.ContractType(
|
||||||
|
name='my_entity',
|
||||||
|
model="ref('my_model')",
|
||||||
|
description="my model",
|
||||||
|
dimensions=['plan', 'country'],
|
||||||
|
config={},
|
||||||
|
tags=[],
|
||||||
|
meta={},
|
||||||
|
)
|
||||||
|
dct = self.get_ok_dict()
|
||||||
|
self.assert_symmetric(metric, dct)
|
||||||
|
pickle.loads(pickle.dumps(metric))
|
||||||
|
|
||||||
|
def test_bad_entity_no_name(self):
|
||||||
|
tst = self.get_ok_dict()
|
||||||
|
del tst['name']
|
||||||
|
self.assert_fails_validation(tst)
|
||||||
|
|
||||||
|
def test_bad_entity_no_model(self):
|
||||||
|
tst = self.get_ok_dict()
|
||||||
|
del tst['model']
|
||||||
|
self.assert_fails_validation(tst)
|
||||||
|
|
||||||
|
def test_bad_tags(self):
|
||||||
|
tst = self.get_ok_dict()
|
||||||
|
tst['tags'] = [123]
|
||||||
|
self.assert_fails_validation(tst)
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ from dbt.contracts.graph.nodes import (
|
|||||||
SeedNode,
|
SeedNode,
|
||||||
SourceDefinition,
|
SourceDefinition,
|
||||||
Exposure,
|
Exposure,
|
||||||
Metric
|
Metric,
|
||||||
|
Entity
|
||||||
)
|
)
|
||||||
|
|
||||||
from dbt.contracts.graph.unparsed import (
|
from dbt.contracts.graph.unparsed import (
|
||||||
@@ -42,7 +43,7 @@ from .utils import MockMacro, MockDocumentation, MockSource, MockNode, MockMater
|
|||||||
|
|
||||||
|
|
||||||
REQUIRED_PARSED_NODE_KEYS = frozenset({
|
REQUIRED_PARSED_NODE_KEYS = frozenset({
|
||||||
'alias', 'tags', 'config', 'unique_id', 'refs', 'sources', 'metrics', 'meta',
|
'alias', 'tags', 'config', 'unique_id', 'refs', 'sources', 'metrics', 'entities', 'meta',
|
||||||
'depends_on', 'database', 'schema', 'name', 'resource_type',
|
'depends_on', 'database', 'schema', 'name', 'resource_type',
|
||||||
'package_name', 'path', 'original_file_path', 'raw_code', 'language',
|
'package_name', 'path', 'original_file_path', 'raw_code', 'language',
|
||||||
'description', 'columns', 'fqn', 'build_path', 'compiled_path', 'patch_path', 'docs',
|
'description', 'columns', 'fqn', 'build_path', 'compiled_path', 'patch_path', 'docs',
|
||||||
@@ -123,6 +124,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[['multi']],
|
refs=[['multi']],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
fqn=['root', 'my_metric'],
|
fqn=['root', 'my_metric'],
|
||||||
unique_id='metric.root.my_metric',
|
unique_id='metric.root.my_metric',
|
||||||
package_name='root',
|
package_name='root',
|
||||||
@@ -131,6 +133,28 @@ class ManifestTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.entities = {
|
||||||
|
'entity.root.my_entity': Entity(
|
||||||
|
name='my_entity',
|
||||||
|
model='ref("multi")',
|
||||||
|
description="my entity",
|
||||||
|
dimensions=['plan', 'country'],
|
||||||
|
resource_type=NodeType.Entity,
|
||||||
|
meta={'is_okr': True},
|
||||||
|
tags=['okrs'],
|
||||||
|
depends_on=DependsOn(nodes=['model.root.multi']),
|
||||||
|
refs=[['multi']],
|
||||||
|
sources=[],
|
||||||
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
|
fqn=['root', 'my_entity'],
|
||||||
|
unique_id='entity.root.my_entity',
|
||||||
|
package_name='root',
|
||||||
|
path='my_entity.yml',
|
||||||
|
original_file_path='my_entity.yml'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
self.nested_nodes = {
|
self.nested_nodes = {
|
||||||
'model.snowplow.events': ModelNode(
|
'model.snowplow.events': ModelNode(
|
||||||
name='events',
|
name='events',
|
||||||
@@ -144,6 +168,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -166,6 +191,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -188,6 +214,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[['events']],
|
refs=[['events']],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.root.events']),
|
depends_on=DependsOn(nodes=['model.root.events']),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -210,6 +237,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[['events']],
|
refs=[['events']],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.root.dep']),
|
depends_on=DependsOn(nodes=['model.root.dep']),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -232,6 +260,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[['events']],
|
refs=[['events']],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.root.events']),
|
depends_on=DependsOn(nodes=['model.root.events']),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -254,6 +283,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[['events']],
|
refs=[['events']],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(nodes=['model.root.nested', 'model.root.sibling']),
|
depends_on=DependsOn(nodes=['model.root.nested', 'model.root.sibling']),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -288,6 +318,8 @@ class ManifestTest(unittest.TestCase):
|
|||||||
exposure.validate(exposure.to_dict(omit_none=True))
|
exposure.validate(exposure.to_dict(omit_none=True))
|
||||||
for metric in self.metrics.values():
|
for metric in self.metrics.values():
|
||||||
metric.validate(metric.to_dict(omit_none=True))
|
metric.validate(metric.to_dict(omit_none=True))
|
||||||
|
for entity in self.entities.values():
|
||||||
|
entity.validate(entity.to_dict(omit_none=True))
|
||||||
for node in self.nested_nodes.values():
|
for node in self.nested_nodes.values():
|
||||||
node.validate(node.to_dict(omit_none=True))
|
node.validate(node.to_dict(omit_none=True))
|
||||||
for source in self.sources.values():
|
for source in self.sources.values():
|
||||||
@@ -303,7 +335,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
def test__no_nodes(self):
|
def test__no_nodes(self):
|
||||||
manifest = Manifest(
|
manifest = Manifest(
|
||||||
nodes={}, sources={}, macros={}, docs={}, disabled={}, files={},
|
nodes={}, sources={}, macros={}, docs={}, disabled={}, files={},
|
||||||
exposures={}, metrics={}, selectors={},
|
exposures={}, metrics={}, selectors={}, entities={},
|
||||||
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -316,6 +348,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
'macros': {},
|
'macros': {},
|
||||||
'exposures': {},
|
'exposures': {},
|
||||||
'metrics': {},
|
'metrics': {},
|
||||||
|
'entities': {},
|
||||||
'selectors': {},
|
'selectors': {},
|
||||||
'parent_map': {},
|
'parent_map': {},
|
||||||
'child_map': {},
|
'child_map': {},
|
||||||
@@ -336,7 +369,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
nodes = copy.copy(self.nested_nodes)
|
nodes = copy.copy(self.nested_nodes)
|
||||||
manifest = Manifest(
|
manifest = Manifest(
|
||||||
nodes=nodes, sources={}, macros={}, docs={}, disabled={}, files={},
|
nodes=nodes, sources={}, macros={}, docs={}, disabled={}, files={},
|
||||||
exposures={}, metrics={}, selectors={},
|
exposures={}, metrics={}, entities={}, selectors={},
|
||||||
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
||||||
)
|
)
|
||||||
serialized = manifest.writable_manifest().to_dict(omit_none=True)
|
serialized = manifest.writable_manifest().to_dict(omit_none=True)
|
||||||
@@ -402,20 +435,23 @@ class ManifestTest(unittest.TestCase):
|
|||||||
def test__build_flat_graph(self):
|
def test__build_flat_graph(self):
|
||||||
exposures = copy.copy(self.exposures)
|
exposures = copy.copy(self.exposures)
|
||||||
metrics = copy.copy(self.metrics)
|
metrics = copy.copy(self.metrics)
|
||||||
|
entities = copy.copy(self.entities)
|
||||||
nodes = copy.copy(self.nested_nodes)
|
nodes = copy.copy(self.nested_nodes)
|
||||||
sources = copy.copy(self.sources)
|
sources = copy.copy(self.sources)
|
||||||
manifest = Manifest(nodes=nodes, sources=sources, macros={}, docs={},
|
manifest = Manifest(nodes=nodes, sources=sources, macros={}, docs={},
|
||||||
disabled={}, files={}, exposures=exposures,
|
disabled={}, files={}, exposures=exposures,
|
||||||
metrics=metrics, selectors={})
|
metrics=metrics, entities=entities, selectors={})
|
||||||
manifest.build_flat_graph()
|
manifest.build_flat_graph()
|
||||||
flat_graph = manifest.flat_graph
|
flat_graph = manifest.flat_graph
|
||||||
flat_exposures = flat_graph['exposures']
|
flat_exposures = flat_graph['exposures']
|
||||||
flat_metrics = flat_graph['metrics']
|
flat_metrics = flat_graph['metrics']
|
||||||
|
flat_entities = flat_graph['entities']
|
||||||
flat_nodes = flat_graph['nodes']
|
flat_nodes = flat_graph['nodes']
|
||||||
flat_sources = flat_graph['sources']
|
flat_sources = flat_graph['sources']
|
||||||
self.assertEqual(set(flat_graph), set(['exposures', 'nodes', 'sources', 'metrics']))
|
self.assertEqual(set(flat_graph), set(['exposures', 'nodes', 'sources', 'metrics', 'entities']))
|
||||||
self.assertEqual(set(flat_exposures), set(self.exposures))
|
self.assertEqual(set(flat_exposures), set(self.exposures))
|
||||||
self.assertEqual(set(flat_metrics), set(self.metrics))
|
self.assertEqual(set(flat_metrics), set(self.metrics))
|
||||||
|
self.assertEqual(set(flat_entities), set(self.entities))
|
||||||
self.assertEqual(set(flat_nodes), set(self.nested_nodes))
|
self.assertEqual(set(flat_nodes), set(self.nested_nodes))
|
||||||
self.assertEqual(set(flat_sources), set(self.sources))
|
self.assertEqual(set(flat_sources), set(self.sources))
|
||||||
for node in flat_nodes.values():
|
for node in flat_nodes.values():
|
||||||
@@ -466,6 +502,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
'macros': {},
|
'macros': {},
|
||||||
'exposures': {},
|
'exposures': {},
|
||||||
'metrics': {},
|
'metrics': {},
|
||||||
|
'entities': {},
|
||||||
'selectors': {},
|
'selectors': {},
|
||||||
'parent_map': {},
|
'parent_map': {},
|
||||||
'child_map': {},
|
'child_map': {},
|
||||||
@@ -509,11 +546,14 @@ class ManifestTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
manifest = Manifest(nodes=nodes, sources=self.sources, macros={}, docs={},
|
manifest = Manifest(nodes=nodes, sources=self.sources, macros={}, docs={},
|
||||||
disabled={}, files={}, exposures=self.exposures,
|
disabled={}, files={}, exposures=self.exposures,
|
||||||
metrics=self.metrics, selectors={})
|
metrics=self.metrics, entities=self.entities, selectors={})
|
||||||
expect = {
|
expect = {
|
||||||
'metrics': frozenset([
|
'metrics': frozenset([
|
||||||
('root', 'my_metric')
|
('root', 'my_metric')
|
||||||
]),
|
]),
|
||||||
|
'entities': frozenset([
|
||||||
|
('root', 'my_entity')
|
||||||
|
]),
|
||||||
'exposures': frozenset([
|
'exposures': frozenset([
|
||||||
('root', 'my_exposure')
|
('root', 'my_exposure')
|
||||||
]),
|
]),
|
||||||
@@ -548,6 +588,7 @@ class ManifestTest(unittest.TestCase):
|
|||||||
refs=[],
|
refs=[],
|
||||||
sources=[],
|
sources=[],
|
||||||
metrics=[],
|
metrics=[],
|
||||||
|
entities=[],
|
||||||
depends_on=DependsOn(),
|
depends_on=DependsOn(),
|
||||||
config=self.model_config,
|
config=self.model_config,
|
||||||
tags=[],
|
tags=[],
|
||||||
@@ -735,6 +776,7 @@ class MixedManifestTest(unittest.TestCase):
|
|||||||
'sources': {},
|
'sources': {},
|
||||||
'exposures': {},
|
'exposures': {},
|
||||||
'metrics': {},
|
'metrics': {},
|
||||||
|
'entities': {},
|
||||||
'selectors': {},
|
'selectors': {},
|
||||||
'parent_map': {},
|
'parent_map': {},
|
||||||
'child_map': {},
|
'child_map': {},
|
||||||
@@ -824,7 +866,7 @@ class MixedManifestTest(unittest.TestCase):
|
|||||||
manifest.build_flat_graph()
|
manifest.build_flat_graph()
|
||||||
flat_graph = manifest.flat_graph
|
flat_graph = manifest.flat_graph
|
||||||
flat_nodes = flat_graph['nodes']
|
flat_nodes = flat_graph['nodes']
|
||||||
self.assertEqual(set(flat_graph), set(['exposures', 'metrics', 'nodes', 'sources']))
|
self.assertEqual(set(flat_graph), set(['exposures', 'metrics', 'entities', 'nodes', 'sources']))
|
||||||
self.assertEqual(set(flat_nodes), set(self.nested_nodes))
|
self.assertEqual(set(flat_nodes), set(self.nested_nodes))
|
||||||
compiled_count = 0
|
compiled_count = 0
|
||||||
for node in flat_nodes.values():
|
for node in flat_nodes.values():
|
||||||
@@ -870,6 +912,7 @@ class TestManifestSearch(unittest.TestCase):
|
|||||||
files={},
|
files={},
|
||||||
exposures={},
|
exposures={},
|
||||||
metrics={},
|
metrics={},
|
||||||
|
entities={},
|
||||||
selectors={},
|
selectors={},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -892,6 +935,7 @@ def make_manifest(nodes=[], sources=[], macros=[], docs=[]):
|
|||||||
files={},
|
files={},
|
||||||
exposures={},
|
exposures={},
|
||||||
metrics={},
|
metrics={},
|
||||||
|
entities={},
|
||||||
selectors={},
|
selectors={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ node_type_pluralizations = {
|
|||||||
NodeType.Macro: "macros",
|
NodeType.Macro: "macros",
|
||||||
NodeType.Exposure: "exposures",
|
NodeType.Exposure: "exposures",
|
||||||
NodeType.Metric: "metrics",
|
NodeType.Metric: "metrics",
|
||||||
|
NodeType.Entity: "entities",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
testing-project/postgres/.gitignore
vendored
Normal file
4
testing-project/postgres/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
target/
|
||||||
|
dbt_packages/
|
||||||
|
logs/
|
||||||
34
testing-project/postgres/dbt_project.yml
Normal file
34
testing-project/postgres/dbt_project.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Name your project! Project names should contain only lowercase characters
|
||||||
|
# and underscores. A good package name should reflect your organization's
|
||||||
|
# name or the intended use of these models
|
||||||
|
name: 'postgres'
|
||||||
|
version: '1.0.0'
|
||||||
|
config-version: 2
|
||||||
|
|
||||||
|
# This setting configures which "profile" dbt uses for this project.
|
||||||
|
profile: 'postgres'
|
||||||
|
|
||||||
|
# These configurations specify where dbt should look for different types of files.
|
||||||
|
# The `model-paths` config, for example, states that models in this project can be
|
||||||
|
# found in the "models/" directory. You probably won't need to change these!
|
||||||
|
model-paths: ["models"]
|
||||||
|
analysis-paths: ["analyses"]
|
||||||
|
test-paths: ["tests"]
|
||||||
|
seed-paths: ["seeds"]
|
||||||
|
macro-paths: ["macros"]
|
||||||
|
snapshot-paths: ["snapshots"]
|
||||||
|
|
||||||
|
target-path: "target" # directory which will store compiled SQL files
|
||||||
|
clean-targets: # directories to be removed by `dbt clean`
|
||||||
|
- "target"
|
||||||
|
- "dbt_packages"
|
||||||
|
|
||||||
|
|
||||||
|
# Configuring models
|
||||||
|
# Full documentation: https://docs.getdbt.com/docs/configuring-models
|
||||||
|
|
||||||
|
# In this example config, we tell dbt to build all models in the example/
|
||||||
|
# directory as views. These settings can be overridden in the individual model
|
||||||
|
# files using the `{{ config(...) }}` macro.
|
||||||
|
models:
|
||||||
|
postgres:
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
with orders as (
|
||||||
|
|
||||||
|
select * from {{ ref('fact_orders') }}
|
||||||
|
|
||||||
|
)
|
||||||
|
,
|
||||||
|
customers as (
|
||||||
|
|
||||||
|
select * from {{ ref('dim_customers') }}
|
||||||
|
|
||||||
|
)
|
||||||
|
,
|
||||||
|
final as (
|
||||||
|
|
||||||
|
select *
|
||||||
|
from orders
|
||||||
|
left join customers using (customer_id)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
select * from final
|
||||||
1
testing-project/postgres/models/dim_customers.sql
Normal file
1
testing-project/postgres/models/dim_customers.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
select * from {{ref('dim_customers_source')}}
|
||||||
21
testing-project/postgres/models/dim_customers.yml
Normal file
21
testing-project/postgres/models/dim_customers.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
version: 2
|
||||||
|
models:
|
||||||
|
- name: dim_customers
|
||||||
|
columns:
|
||||||
|
- name: customer_id
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: first_name
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: last_name
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: email
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: gender
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: is_new_customer
|
||||||
|
description: TBD
|
||||||
17
testing-project/postgres/models/entities/customers.yml
Normal file
17
testing-project/postgres/models/entities/customers.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# version: 2
|
||||||
|
# entities:
|
||||||
|
|
||||||
|
# - name: customers
|
||||||
|
# model: ref('dim_customers')
|
||||||
|
# description: "Our customers entity"
|
||||||
|
|
||||||
|
# dimensions:
|
||||||
|
# - dimension_1
|
||||||
|
|
||||||
|
# - name: first_name_v3_testing
|
||||||
|
# description: string
|
||||||
|
# column_name: first_name
|
||||||
|
# date_type: string
|
||||||
|
# default_timestamp: true
|
||||||
|
# primary_key: true
|
||||||
|
# time_grains: [day, week, month]
|
||||||
8
testing-project/postgres/models/entities/orders.yml
Normal file
8
testing-project/postgres/models/entities/orders.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: 2
|
||||||
|
entities:
|
||||||
|
|
||||||
|
- name: orders
|
||||||
|
model: ref('fact_orders')
|
||||||
|
description: "Our orders entity"
|
||||||
|
dimensions:
|
||||||
|
- dimension_1
|
||||||
4
testing-project/postgres/models/fact_orders.sql
Normal file
4
testing-project/postgres/models/fact_orders.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
select
|
||||||
|
*
|
||||||
|
,round(order_total - (order_total/2)) as discount_total
|
||||||
|
from {{ref('fact_orders_source')}}
|
||||||
21
testing-project/postgres/models/fact_orders.yml
Normal file
21
testing-project/postgres/models/fact_orders.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
version: 2
|
||||||
|
models:
|
||||||
|
- name: fact_orders
|
||||||
|
columns:
|
||||||
|
- name: order_id
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: order_country
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: order_total
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: had_discount
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: customer_id
|
||||||
|
description: TBD
|
||||||
|
|
||||||
|
- name: order_date
|
||||||
|
description: TBD
|
||||||
8
testing-project/postgres/models/metrics/revenue.yml
Normal file
8
testing-project/postgres/models/metrics/revenue.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: 2
|
||||||
|
metrics:
|
||||||
|
- name: revenue
|
||||||
|
label: Revenue
|
||||||
|
model: ref('fact_orders')
|
||||||
|
|
||||||
|
calculation_method: sum
|
||||||
|
expression: order_total
|
||||||
6
testing-project/postgres/seeds/dim_customers_source.csv
Normal file
6
testing-project/postgres/seeds/dim_customers_source.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
customer_id,first_name,last_name,email,gender,is_new_customer,date_added
|
||||||
|
1,Geodude,Pokemon,rocks@pokemon.org,Male,FALSE,2022-01-01
|
||||||
|
2,Mew,Pokemon,mew.is.the.best@pokemon.com,Genderfluid,TRUE,2022-01-06
|
||||||
|
3,Mewtwo,Pokemon,no.mewtwo.is.better@pokemon.com,Genderqueer,FALSE,2022-01-13
|
||||||
|
4,Charizard,Pokemon,firebreathbaby@pokemon.com,Female,TRUE,2022-02-01
|
||||||
|
5,Snorlax,Pokemon,sleep@pokemon.com,Male,TRUE,2022-02-03
|
||||||
|
11
testing-project/postgres/seeds/fact_orders_source.csv
Normal file
11
testing-project/postgres/seeds/fact_orders_source.csv
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
order_id,order_country,order_total,had_discount,customer_id,order_date
|
||||||
|
1,Unovo,2,false,1,01/28/2022
|
||||||
|
2,Kalos,1,false,2,01/20/2022
|
||||||
|
3,Kalos,1,false,1,01/13/2022
|
||||||
|
4,Alola,1,true,3,01/06/2022
|
||||||
|
5,Alola,1,false,4,01/08/2022
|
||||||
|
6,Kanto,1,false,5,01/21/2022
|
||||||
|
7,Alola,1,true,2,01/22/2022
|
||||||
|
8,Kanto,0,true,1,02/15/2022
|
||||||
|
9,Unovo,1,false,2,02/03/2022
|
||||||
|
10,Kanto,1,false,3,02/13/2022
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -258,6 +258,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"unique_id": "model.test.model",
|
"unique_id": "model.test.model",
|
||||||
"fqn": ["test", "model"],
|
"fqn": ["test", "model"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"meta": {},
|
"meta": {},
|
||||||
"config": model_config,
|
"config": model_config,
|
||||||
@@ -339,6 +340,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"unique_id": "model.test.second_model",
|
"unique_id": "model.test.second_model",
|
||||||
"fqn": ["test", "second_model"],
|
"fqn": ["test", "second_model"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"meta": {},
|
"meta": {},
|
||||||
"config": second_config,
|
"config": second_config,
|
||||||
@@ -488,6 +490,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"file_key_name": "models.model",
|
"file_key_name": "models.model",
|
||||||
"fqn": ["test", "not_null_model_id"],
|
"fqn": ["test", "not_null_model_id"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "not_null_model_id",
|
"name": "not_null_model_id",
|
||||||
"original_file_path": model_schema_yml_path,
|
"original_file_path": model_schema_yml_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -541,6 +544,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"extra_ctes_injected": True,
|
"extra_ctes_injected": True,
|
||||||
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"meta": {},
|
"meta": {},
|
||||||
"name": "snapshot_seed",
|
"name": "snapshot_seed",
|
||||||
"original_file_path": snapshot_path,
|
"original_file_path": snapshot_path,
|
||||||
@@ -584,6 +588,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"file_key_name": "models.model",
|
"file_key_name": "models.model",
|
||||||
"fqn": ["test", "test_nothing_model_"],
|
"fqn": ["test", "test_nothing_model_"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "test_nothing_model_",
|
"name": "test_nothing_model_",
|
||||||
"original_file_path": model_schema_yml_path,
|
"original_file_path": model_schema_yml_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -634,6 +639,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"file_key_name": "models.model",
|
"file_key_name": "models.model",
|
||||||
"fqn": ["test", "unique_model_id"],
|
"fqn": ["test", "unique_model_id"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "unique_model_id",
|
"name": "unique_model_id",
|
||||||
"original_file_path": model_schema_yml_path,
|
"original_file_path": model_schema_yml_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -735,6 +741,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
"maturity": "medium",
|
"maturity": "medium",
|
||||||
"meta": {"tool": "my_tool", "languages": ["python"]},
|
"meta": {"tool": "my_tool", "languages": ["python"]},
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"tags": ["my_department"],
|
"tags": ["my_department"],
|
||||||
"name": "notebook_exposure",
|
"name": "notebook_exposure",
|
||||||
"original_file_path": os.path.join("models", "schema.yml"),
|
"original_file_path": os.path.join("models", "schema.yml"),
|
||||||
@@ -762,6 +769,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
},
|
},
|
||||||
"fqn": ["test", "simple_exposure"],
|
"fqn": ["test", "simple_exposure"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "simple_exposure",
|
"name": "simple_exposure",
|
||||||
"original_file_path": os.path.join("models", "schema.yml"),
|
"original_file_path": os.path.join("models", "schema.yml"),
|
||||||
"owner": {
|
"owner": {
|
||||||
@@ -783,6 +791,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"metrics": {},
|
"metrics": {},
|
||||||
|
"entities": {},
|
||||||
"selectors": {},
|
"selectors": {},
|
||||||
"parent_map": {
|
"parent_map": {
|
||||||
"model.test.model": ["seed.test.seed"],
|
"model.test.model": ["seed.test.seed"],
|
||||||
@@ -865,6 +874,7 @@ def expected_references_manifest(project):
|
|||||||
"docs": {"node_color": None, "show": True},
|
"docs": {"node_color": None, "show": True},
|
||||||
"fqn": ["test", "ephemeral_copy"],
|
"fqn": ["test", "ephemeral_copy"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "ephemeral_copy",
|
"name": "ephemeral_copy",
|
||||||
"original_file_path": ephemeral_copy_path,
|
"original_file_path": ephemeral_copy_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -918,6 +928,7 @@ def expected_references_manifest(project):
|
|||||||
"docs": {"node_color": None, "show": True},
|
"docs": {"node_color": None, "show": True},
|
||||||
"fqn": ["test", "ephemeral_summary"],
|
"fqn": ["test", "ephemeral_summary"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "ephemeral_summary",
|
"name": "ephemeral_summary",
|
||||||
"original_file_path": ephemeral_summary_path,
|
"original_file_path": ephemeral_summary_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -973,6 +984,7 @@ def expected_references_manifest(project):
|
|||||||
"docs": {"node_color": None, "show": True},
|
"docs": {"node_color": None, "show": True},
|
||||||
"fqn": ["test", "view_summary"],
|
"fqn": ["test", "view_summary"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"name": "view_summary",
|
"name": "view_summary",
|
||||||
"original_file_path": view_summary_path,
|
"original_file_path": view_summary_path,
|
||||||
"package_name": "test",
|
"package_name": "test",
|
||||||
@@ -1082,6 +1094,7 @@ def expected_references_manifest(project):
|
|||||||
"extra_ctes_injected": True,
|
"extra_ctes_injected": True,
|
||||||
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"meta": {},
|
"meta": {},
|
||||||
"name": "snapshot_seed",
|
"name": "snapshot_seed",
|
||||||
"original_file_path": snapshot_path,
|
"original_file_path": snapshot_path,
|
||||||
@@ -1168,6 +1181,7 @@ def expected_references_manifest(project):
|
|||||||
"maturity": "medium",
|
"maturity": "medium",
|
||||||
"meta": {"tool": "my_tool", "languages": ["python"]},
|
"meta": {"tool": "my_tool", "languages": ["python"]},
|
||||||
"metrics": [],
|
"metrics": [],
|
||||||
|
"entities": [],
|
||||||
"tags": ["my_department"],
|
"tags": ["my_department"],
|
||||||
"name": "notebook_exposure",
|
"name": "notebook_exposure",
|
||||||
"original_file_path": os.path.join("models", "schema.yml"),
|
"original_file_path": os.path.join("models", "schema.yml"),
|
||||||
@@ -1184,6 +1198,7 @@ def expected_references_manifest(project):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"metrics": {},
|
"metrics": {},
|
||||||
|
"entities": {},
|
||||||
"selectors": {},
|
"selectors": {},
|
||||||
"docs": {
|
"docs": {
|
||||||
"doc.dbt.__overview__": ANY,
|
"doc.dbt.__overview__": ANY,
|
||||||
|
|||||||
@@ -355,6 +355,7 @@ def verify_manifest(project, expected_manifest, start_time, manifest_schema_path
|
|||||||
"parent_map",
|
"parent_map",
|
||||||
"child_map",
|
"child_map",
|
||||||
"metrics",
|
"metrics",
|
||||||
|
"entities",
|
||||||
"docs",
|
"docs",
|
||||||
"metadata",
|
"metadata",
|
||||||
"docs",
|
"docs",
|
||||||
@@ -381,7 +382,7 @@ def verify_manifest(project, expected_manifest, start_time, manifest_schema_path
|
|||||||
and metadata["send_anonymous_usage_stats"] is False
|
and metadata["send_anonymous_usage_stats"] is False
|
||||||
)
|
)
|
||||||
assert "adapter_type" in metadata and metadata["adapter_type"] == project.adapter_type
|
assert "adapter_type" in metadata and metadata["adapter_type"] == project.adapter_type
|
||||||
elif key in ["nodes", "sources", "exposures", "metrics", "disabled", "docs"]:
|
elif key in ["nodes", "sources", "exposures", "metrics", "entities", "disabled", "docs"]:
|
||||||
for unique_id, node in expected_manifest[key].items():
|
for unique_id, node in expected_manifest[key].items():
|
||||||
assert unique_id in manifest[key]
|
assert unique_id in manifest[key]
|
||||||
assert manifest[key][unique_id] == node, f"{unique_id} did not match"
|
assert manifest[key][unique_id] == node, f"{unique_id} did not match"
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ class TestPreviousVersionState:
|
|||||||
|
|
||||||
def test_backwards_compatible_versions(self, project):
|
def test_backwards_compatible_versions(self, project):
|
||||||
# manifest schema version 4 and greater should always be forward compatible
|
# manifest schema version 4 and greater should always be forward compatible
|
||||||
for schema_version in range(4, self.CURRENT_EXPECTED_MANIFEST_VERSION):
|
for schema_version in range(8, self.CURRENT_EXPECTED_MANIFEST_VERSION):
|
||||||
self.compare_previous_state(project, schema_version, True)
|
self.compare_previous_state(project, schema_version, True)
|
||||||
|
|
||||||
def test_nonbackwards_compatible_versions(self, project):
|
def test_nonbackwards_compatible_versions(self, project):
|
||||||
# schema versions 1, 2, 3 are all not forward compatible
|
# schema versions 1, 2, 3 are all not forward compatible
|
||||||
for schema_version in range(1, 4):
|
for schema_version in range(1, 7):
|
||||||
self.compare_previous_state(project, schema_version, False)
|
self.compare_previous_state(project, schema_version, False)
|
||||||
|
|||||||
Reference in New Issue
Block a user