mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-17 19:31:34 +00:00
Compare commits
1 Commits
v1.7.11
...
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.Exposure: "exposure",
|
||||
NodeType.Metric: "metric",
|
||||
NodeType.Entity: "entity",
|
||||
}
|
||||
|
||||
results = {k: 0 for k in names.keys()}
|
||||
@@ -83,6 +84,8 @@ def _generate_stats(manifest: Manifest):
|
||||
stats[exposure.resource_type] += 1
|
||||
for metric in manifest.metrics.values():
|
||||
stats[metric.resource_type] += 1
|
||||
for entity in manifest.entities.values():
|
||||
stats[entity.resource_type] += 1
|
||||
for macro in manifest.macros.values():
|
||||
stats[macro.resource_type] += 1
|
||||
return stats
|
||||
@@ -398,6 +401,8 @@ class Compiler:
|
||||
linker.dependency(node.unique_id, (manifest.sources[dependency].unique_id))
|
||||
elif dependency in manifest.metrics:
|
||||
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:
|
||||
raise GraphDependencyNotFoundError(node, dependency)
|
||||
|
||||
@@ -410,6 +415,8 @@ class Compiler:
|
||||
self.link_node(linker, exposure, manifest)
|
||||
for metric in manifest.metrics.values():
|
||||
self.link_node(linker, metric, manifest)
|
||||
for entity in manifest.entities.values():
|
||||
self.link_node(linker, entity, manifest)
|
||||
|
||||
cycle = linker.find_cycles()
|
||||
|
||||
|
||||
@@ -381,6 +381,7 @@ class PartialProject(RenderComponents):
|
||||
sources: Dict[str, Any]
|
||||
tests: Dict[str, Any]
|
||||
metrics: Dict[str, Any]
|
||||
entities: Dict[str, Any]
|
||||
exposures: Dict[str, Any]
|
||||
vars_value: VarProvider
|
||||
|
||||
@@ -391,6 +392,7 @@ class PartialProject(RenderComponents):
|
||||
sources = cfg.sources
|
||||
tests = cfg.tests
|
||||
metrics = cfg.metrics
|
||||
entities = cfg.entities
|
||||
exposures = cfg.exposures
|
||||
if cfg.vars is None:
|
||||
vars_dict: Dict[str, Any] = {}
|
||||
@@ -446,6 +448,7 @@ class PartialProject(RenderComponents):
|
||||
sources=sources,
|
||||
tests=tests,
|
||||
metrics=metrics,
|
||||
entities=entities,
|
||||
exposures=exposures,
|
||||
vars=vars_value,
|
||||
config_version=cfg.config_version,
|
||||
@@ -550,6 +553,7 @@ class Project:
|
||||
sources: Dict[str, Any]
|
||||
tests: Dict[str, Any]
|
||||
metrics: Dict[str, Any]
|
||||
entities: Dict[str, Any]
|
||||
exposures: Dict[str, Any]
|
||||
vars: VarProvider
|
||||
dbt_version: List[VersionSpecifier]
|
||||
@@ -624,6 +628,7 @@ class Project:
|
||||
"sources": self.sources,
|
||||
"tests": self.tests,
|
||||
"metrics": self.metrics,
|
||||
"entities": self.entities,
|
||||
"exposures": self.exposures,
|
||||
"vars": self.vars.to_dict(),
|
||||
"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,
|
||||
tests=project.tests,
|
||||
metrics=project.metrics,
|
||||
entities=project.entities,
|
||||
exposures=project.exposures,
|
||||
vars=project.vars,
|
||||
config_version=project.config_version,
|
||||
@@ -312,6 +313,7 @@ class RuntimeConfig(Project, Profile, AdapterRequiredConfig):
|
||||
"sources": self._get_config_paths(self.sources),
|
||||
"tests": self._get_config_paths(self.tests),
|
||||
"metrics": self._get_config_paths(self.metrics),
|
||||
"entities": self._get_config_paths(self.entities),
|
||||
"exposures": self._get_config_paths(self.exposures),
|
||||
}
|
||||
|
||||
@@ -500,6 +502,7 @@ class UnsetProfileConfig(RuntimeConfig):
|
||||
"sources": self.sources,
|
||||
"tests": self.tests,
|
||||
"metrics": self.metrics,
|
||||
"entities": self.entities,
|
||||
"exposures": self.exposures,
|
||||
"vars": self.vars.to_dict(),
|
||||
"require-dbt-version": [v.to_version_string() for v in self.dbt_version],
|
||||
@@ -562,6 +565,7 @@ class UnsetProfileConfig(RuntimeConfig):
|
||||
sources=project.sources,
|
||||
tests=project.tests,
|
||||
metrics=project.metrics,
|
||||
entities=project.entities,
|
||||
exposures=project.exposures,
|
||||
vars=project.vars,
|
||||
config_version=project.config_version,
|
||||
|
||||
@@ -45,6 +45,8 @@ class UnrenderedConfig(ConfigSource):
|
||||
model_configs = unrendered.get("tests")
|
||||
elif resource_type == NodeType.Metric:
|
||||
model_configs = unrendered.get("metrics")
|
||||
elif resource_type == NodeType.Entity:
|
||||
model_configs = unrendered.get("entities")
|
||||
elif resource_type == NodeType.Exposure:
|
||||
model_configs = unrendered.get("exposures")
|
||||
else:
|
||||
@@ -70,6 +72,8 @@ class RenderedConfig(ConfigSource):
|
||||
model_configs = self.project.tests
|
||||
elif resource_type == NodeType.Metric:
|
||||
model_configs = self.project.metrics
|
||||
elif resource_type == NodeType.Entity:
|
||||
model_configs = self.project.entities
|
||||
elif resource_type == NodeType.Exposure:
|
||||
model_configs = self.project.exposures
|
||||
else:
|
||||
|
||||
@@ -33,6 +33,7 @@ from dbt.contracts.graph.nodes import (
|
||||
Macro,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
SeedNode,
|
||||
SourceDefinition,
|
||||
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
|
||||
# to limit the number of macros in the context by using
|
||||
# the TestMacroNamespace
|
||||
|
||||
@@ -227,6 +227,7 @@ class SchemaSourceFile(BaseSourceFile):
|
||||
sources: List[str] = field(default_factory=list)
|
||||
exposures: 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
|
||||
ndp: List[str] = field(default_factory=list)
|
||||
# any macro patches in this file by macro unique_id.
|
||||
|
||||
@@ -29,6 +29,7 @@ from dbt.contracts.graph.nodes import (
|
||||
GenericTestNode,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
UnpatchedSourceDefinition,
|
||||
ManifestNode,
|
||||
GraphMemberNode,
|
||||
@@ -212,6 +213,39 @@ class MetricLookup(dbtClassMixin):
|
||||
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
|
||||
class DisabledLookup(dbtClassMixin):
|
||||
def __init__(self, manifest: "Manifest"):
|
||||
@@ -456,6 +490,9 @@ class Disabled(Generic[D]):
|
||||
MaybeMetricNode = Optional[Union[Metric, Disabled[Metric]]]
|
||||
|
||||
|
||||
MaybeEntityNode = Optional[Union[Entity, Disabled[Entity]]]
|
||||
|
||||
|
||||
MaybeDocumentation = Optional[Documentation]
|
||||
|
||||
|
||||
@@ -599,6 +636,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
docs: MutableMapping[str, Documentation] = field(default_factory=dict)
|
||||
exposures: MutableMapping[str, Exposure] = 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)
|
||||
files: MutableMapping[str, AnySourceFile] = field(default_factory=dict)
|
||||
metadata: ManifestMetadata = field(default_factory=ManifestMetadata)
|
||||
@@ -620,6 +658,9 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
_metric_lookup: Optional[MetricLookup] = field(
|
||||
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(
|
||||
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):
|
||||
_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):
|
||||
_update_into(self.nodes, new_node)
|
||||
|
||||
@@ -685,6 +729,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self.flat_graph = {
|
||||
"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()},
|
||||
"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()},
|
||||
"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.sources.values(),
|
||||
self.metrics.values(),
|
||||
self.entities.values(),
|
||||
)
|
||||
for resource in all_resources:
|
||||
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()},
|
||||
exposures={k: _deepcopy(v) for k, v in self.exposures.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()},
|
||||
metadata=self.metadata,
|
||||
disabled={k: _deepcopy(v) for k, v in self.disabled.items()},
|
||||
@@ -791,6 +838,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self.sources.values(),
|
||||
self.exposures.values(),
|
||||
self.metrics.values(),
|
||||
self.entities.values(),
|
||||
)
|
||||
)
|
||||
forward_edges, backward_edges = build_node_edges(edge_members)
|
||||
@@ -816,6 +864,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
docs=self.docs,
|
||||
exposures=self.exposures,
|
||||
metrics=self.metrics,
|
||||
entities=self.entities,
|
||||
selectors=self.selectors,
|
||||
metadata=self.metadata,
|
||||
disabled=self.disabled,
|
||||
@@ -837,6 +886,8 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
return self.exposures[unique_id]
|
||||
elif unique_id in self.metrics:
|
||||
return self.metrics[unique_id]
|
||||
elif unique_id in self.entities:
|
||||
return self.entities[unique_id]
|
||||
else:
|
||||
# something terrible has happened
|
||||
raise dbt.exceptions.DbtInternalError(
|
||||
@@ -873,6 +924,12 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self._metric_lookup = MetricLookup(self)
|
||||
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):
|
||||
self._ref_lookup = RefableLookup(self)
|
||||
|
||||
@@ -973,6 +1030,31 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
return Disabled(disabled[0])
|
||||
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
|
||||
def resolve_doc(
|
||||
self,
|
||||
@@ -1083,6 +1165,11 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self.metrics[metric.unique_id] = metric
|
||||
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):
|
||||
# There can be multiple disabled nodes for the same unique_id
|
||||
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)
|
||||
if isinstance(node, Metric):
|
||||
source_file.metrics.append(node.unique_id)
|
||||
if isinstance(node, Entity):
|
||||
source_file.entities.append(node.unique_id)
|
||||
if isinstance(node, Exposure):
|
||||
source_file.exposures.append(node.unique_id)
|
||||
else:
|
||||
@@ -1125,6 +1214,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self.docs,
|
||||
self.exposures,
|
||||
self.metrics,
|
||||
self.entities,
|
||||
self.selectors,
|
||||
self.files,
|
||||
self.metadata,
|
||||
@@ -1137,6 +1227,7 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin):
|
||||
self._source_lookup,
|
||||
self._ref_lookup,
|
||||
self._metric_lookup,
|
||||
self._entity_lookup,
|
||||
self._disabled_lookup,
|
||||
self._analysis_lookup,
|
||||
)
|
||||
@@ -1178,6 +1269,9 @@ class WritableManifest(ArtifactMixin):
|
||||
metrics: Mapping[UniqueID, Metric] = field(
|
||||
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(
|
||||
metadata=dict(description=("The selectors defined in selectors.yml"))
|
||||
)
|
||||
@@ -1202,7 +1296,8 @@ class WritableManifest(ArtifactMixin):
|
||||
|
||||
@classmethod
|
||||
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):
|
||||
for unique_id, node in dct["nodes"].items():
|
||||
|
||||
@@ -368,6 +368,11 @@ class MetricConfig(BaseConfig):
|
||||
enabled: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class EntityConfig(BaseConfig):
|
||||
enabled: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExposureConfig(BaseConfig):
|
||||
enabled: bool = True
|
||||
@@ -604,6 +609,7 @@ class SnapshotConfig(EmptySnapshotConfig):
|
||||
|
||||
RESOURCE_TYPES: Dict[NodeType, Type[BaseConfig]] = {
|
||||
NodeType.Metric: MetricConfig,
|
||||
NodeType.Entity: EntityConfig,
|
||||
NodeType.Exposure: ExposureConfig,
|
||||
NodeType.Source: SourceConfig,
|
||||
NodeType.Seed: SeedConfig,
|
||||
|
||||
@@ -55,6 +55,7 @@ from .model_config import (
|
||||
TestConfig,
|
||||
SourceConfig,
|
||||
MetricConfig,
|
||||
EntityConfig,
|
||||
ExposureConfig,
|
||||
EmptySnapshotConfig,
|
||||
SnapshotConfig,
|
||||
@@ -272,7 +273,7 @@ class ParsedNode(NodeInfoMixin, ParsedNodeMandatory, SerializableType):
|
||||
@classmethod
|
||||
def _deserialize(cls, dct: Dict[str, int]):
|
||||
# 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.
|
||||
resource_type = dct["resource_type"]
|
||||
if resource_type == "model":
|
||||
@@ -392,6 +393,7 @@ class CompiledNode(ParsedNode):
|
||||
refs: List[List[str]] = field(default_factory=list)
|
||||
sources: 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)
|
||||
compiled_path: Optional[str] = None
|
||||
compiled: bool = False
|
||||
@@ -906,6 +908,7 @@ class Exposure(GraphNode):
|
||||
refs: List[List[str]] = field(default_factory=list)
|
||||
sources: 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())
|
||||
|
||||
@property
|
||||
@@ -997,6 +1000,7 @@ class Metric(GraphNode):
|
||||
depends_on: DependsOn = field(default_factory=DependsOn)
|
||||
refs: 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())
|
||||
|
||||
@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
|
||||
# ====================================
|
||||
@@ -1126,6 +1187,7 @@ GraphMemberNode = Union[
|
||||
ResultNode,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
]
|
||||
|
||||
# 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":
|
||||
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)
|
||||
tests: 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)
|
||||
vars: Optional[Dict[str, Any]] = field(
|
||||
default=None,
|
||||
|
||||
@@ -20,7 +20,7 @@ from .selector_spec import (
|
||||
|
||||
INTERSECTION_DELIMITER = ","
|
||||
|
||||
DEFAULT_INCLUDES: List[str] = ["fqn:*", "source:*", "exposure:*", "metric:*"]
|
||||
DEFAULT_INCLUDES: List[str] = ["fqn:*", "source:*", "exposure:*", "metric:*", "entity:*"]
|
||||
DEFAULT_EXCLUDES: List[str] = []
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from dbt.contracts.graph.nodes import (
|
||||
SourceDefinition,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
GraphMemberNode,
|
||||
)
|
||||
from dbt.contracts.graph.manifest import Manifest
|
||||
@@ -51,8 +52,8 @@ class GraphQueue:
|
||||
node = self.manifest.expect(node_id)
|
||||
if node.resource_type != NodeType.Model:
|
||||
return False
|
||||
# must be a Model - tell mypy this won't be a Source or Exposure or Metric
|
||||
assert not isinstance(node, (SourceDefinition, Exposure, 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, Entity))
|
||||
if node.is_ephemeral:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -163,6 +163,9 @@ class NodeSelector(MethodManager):
|
||||
elif unique_id in self.manifest.metrics:
|
||||
metric = self.manifest.metrics[unique_id]
|
||||
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]
|
||||
return not node.empty and node.config.enabled
|
||||
|
||||
@@ -182,6 +185,8 @@ class NodeSelector(MethodManager):
|
||||
node = self.manifest.exposures[unique_id]
|
||||
elif unique_id in self.manifest.metrics:
|
||||
node = self.manifest.metrics[unique_id]
|
||||
elif unique_id in self.manifest.entities:
|
||||
node = self.manifest.entities[unique_id]
|
||||
else:
|
||||
raise DbtInternalError(f"Node {unique_id} not found in the manifest!")
|
||||
return self.node_is_match(node)
|
||||
|
||||
@@ -12,6 +12,7 @@ from dbt.contracts.graph.nodes import (
|
||||
SingularTestNode,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
GenericTestNode,
|
||||
SourceDefinition,
|
||||
ResultNode,
|
||||
@@ -43,6 +44,7 @@ class MethodName(StrEnum):
|
||||
State = "state"
|
||||
Exposure = "exposure"
|
||||
Metric = "metric"
|
||||
Entity = "entity"
|
||||
Result = "result"
|
||||
SourceStatus = "source_status"
|
||||
|
||||
@@ -71,7 +73,7 @@ def is_selected_node(fqn: List[str], node_selector: str):
|
||||
return True
|
||||
|
||||
|
||||
SelectorTarget = Union[SourceDefinition, ManifestNode, Exposure, Metric]
|
||||
SelectorTarget = Union[SourceDefinition, ManifestNode, Exposure, Metric, Entity]
|
||||
|
||||
|
||||
class SelectorMethod(metaclass=abc.ABCMeta):
|
||||
@@ -118,6 +120,14 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
||||
continue
|
||||
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(
|
||||
self, included_nodes: Set[UniqueId]
|
||||
) -> Iterator[Tuple[UniqueId, SelectorTarget]]:
|
||||
@@ -126,6 +136,7 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
||||
self.source_nodes(included_nodes),
|
||||
self.exposure_nodes(included_nodes),
|
||||
self.metric_nodes(included_nodes),
|
||||
self.entity_nodes(included_nodes),
|
||||
)
|
||||
|
||||
def configurable_nodes(
|
||||
@@ -136,11 +147,12 @@ class SelectorMethod(metaclass=abc.ABCMeta):
|
||||
def non_source_nodes(
|
||||
self,
|
||||
included_nodes: Set[UniqueId],
|
||||
) -> Iterator[Tuple[UniqueId, Union[Exposure, ManifestNode, Metric]]]:
|
||||
) -> Iterator[Tuple[UniqueId, Union[Exposure, ManifestNode, Metric, Entity]]]:
|
||||
yield from chain(
|
||||
self.parsed_nodes(included_nodes),
|
||||
self.exposure_nodes(included_nodes),
|
||||
self.metric_nodes(included_nodes),
|
||||
self.entity_nodes(included_nodes),
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
@@ -270,6 +282,33 @@ class MetricSelectorMethod(SelectorMethod):
|
||||
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):
|
||||
def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]:
|
||||
"""Yields nodes from included that match the given path."""
|
||||
@@ -530,6 +569,8 @@ class StateSelectorMethod(SelectorMethod):
|
||||
previous_node = manifest.exposures[node]
|
||||
elif node in manifest.metrics:
|
||||
previous_node = manifest.metrics[node]
|
||||
elif node in manifest.entities:
|
||||
previous_node = manifest.entities[node]
|
||||
|
||||
if checker(previous_node, real_node):
|
||||
yield node
|
||||
@@ -616,6 +657,7 @@ class MethodManager:
|
||||
MethodName.State: StateSelectorMethod,
|
||||
MethodName.Exposure: ExposureSelectorMethod,
|
||||
MethodName.Metric: MetricSelectorMethod,
|
||||
MethodName.Entity: EntitySelectorMethod,
|
||||
MethodName.Result: ResultSelectorMethod,
|
||||
MethodName.SourceStatus: SourceStatusSelectorMethod,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class NodeType(StrEnum):
|
||||
Macro = "macro"
|
||||
Exposure = "exposure"
|
||||
Metric = "metric"
|
||||
Entity = "entity"
|
||||
|
||||
@classmethod
|
||||
def executable(cls) -> List["NodeType"]:
|
||||
@@ -52,11 +53,14 @@ class NodeType(StrEnum):
|
||||
cls.Analysis,
|
||||
cls.Exposure,
|
||||
cls.Metric,
|
||||
cls.Entity,
|
||||
]
|
||||
|
||||
def pluralize(self) -> str:
|
||||
if self is self.Analysis:
|
||||
return "analyses"
|
||||
if self is self.Entity:
|
||||
return "entities"
|
||||
return f"{self}s"
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ from dbt.contracts.graph.nodes import (
|
||||
ColumnInfo,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
SeedNode,
|
||||
ManifestNode,
|
||||
ResultNode,
|
||||
@@ -340,7 +341,7 @@ class ManifestLoader:
|
||||
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
|
||||
# the unique_id instead of the name. Sources are loaded from yaml files, so
|
||||
# aren't in place yet
|
||||
@@ -376,7 +377,7 @@ class ManifestLoader:
|
||||
# copy the selectors from the root_project to the manifest
|
||||
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
|
||||
# determine whether they need processing.
|
||||
start_process = time.perf_counter()
|
||||
@@ -384,6 +385,7 @@ class ManifestLoader:
|
||||
self.process_refs(self.root_project.project_name)
|
||||
self.process_docs(self.root_project)
|
||||
self.process_metrics(self.root_project)
|
||||
self.process_entities(self.root_project)
|
||||
|
||||
# update tracking data
|
||||
self._perf_info.process_manifest_elapsed = time.perf_counter() - start_process
|
||||
@@ -838,6 +840,10 @@ class ManifestLoader:
|
||||
if metric.created_at < self.started_at:
|
||||
continue
|
||||
_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
|
||||
# node, and updates 'depends_on.nodes' with the unique id
|
||||
@@ -858,6 +864,23 @@ class ManifestLoader:
|
||||
continue
|
||||
_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
|
||||
# sources: source and table descriptions, column descriptions
|
||||
# macros: macro argument descriptions
|
||||
@@ -913,6 +936,16 @@ class ManifestLoader:
|
||||
config.project_name,
|
||||
)
|
||||
_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
|
||||
# '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)
|
||||
|
||||
|
||||
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):
|
||||
"""Given a manifest and exposure in that manifest, process its 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)
|
||||
|
||||
|
||||
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(
|
||||
manifest: Manifest,
|
||||
current_project: str,
|
||||
@@ -1239,6 +1318,55 @@ def _process_metrics_for_node(
|
||||
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):
|
||||
"""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)
|
||||
|
||||
|
||||
# TODO: Remove this code because metrics can't be based on sources
|
||||
def _process_sources_for_metric(manifest: Manifest, current_project: str, metric: Metric):
|
||||
target_source: Optional[Union[Disabled, SourceDefinition]] = None
|
||||
for source_name, table_name in metric.sources:
|
||||
|
||||
@@ -242,7 +242,7 @@ class PartialParsing:
|
||||
self.remove_source_override_target(source)
|
||||
|
||||
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]):
|
||||
if dis_node.file_id == file_id:
|
||||
node = dis_node
|
||||
@@ -441,6 +441,18 @@ class PartialParsing:
|
||||
if metric_element:
|
||||
self.delete_schema_metric(schema_file, 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:
|
||||
macro = self.saved_manifest.macros[unique_id]
|
||||
file_id = macro.file_id
|
||||
@@ -746,6 +758,29 @@ class PartialParsing:
|
||||
self.delete_schema_metric(schema_file, 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
|
||||
# and determine which parts have changed
|
||||
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:
|
||||
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):
|
||||
for element in elem_list:
|
||||
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 (
|
||||
generate_parse_exposure,
|
||||
generate_parse_metrics,
|
||||
generate_parse_entities,
|
||||
generate_test_context,
|
||||
)
|
||||
from dbt.context.macro_resolver import MacroResolver
|
||||
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 (
|
||||
ParsedNodePatch,
|
||||
ColumnInfo,
|
||||
@@ -35,6 +36,7 @@ from dbt.contracts.graph.nodes import (
|
||||
UnpatchedSourceDefinition,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
)
|
||||
from dbt.contracts.graph.unparsed import (
|
||||
HasColumnDocs,
|
||||
@@ -47,6 +49,7 @@ from dbt.contracts.graph.unparsed import (
|
||||
UnparsedNodeUpdate,
|
||||
UnparsedExposure,
|
||||
UnparsedMetric,
|
||||
UnparsedEntity,
|
||||
UnparsedSourceDefinition,
|
||||
)
|
||||
from dbt.exceptions import (
|
||||
@@ -94,6 +97,7 @@ schema_file_keys = (
|
||||
"analyses",
|
||||
"exposures",
|
||||
"metrics",
|
||||
"entities",
|
||||
)
|
||||
|
||||
|
||||
@@ -114,6 +118,7 @@ class ParserRef:
|
||||
def __init__(self):
|
||||
self.column_info: Dict[str, ColumnInfo] = {}
|
||||
|
||||
# TODO: Mimic this for dimension information at the entity level
|
||||
def add(
|
||||
self,
|
||||
column: Union[HasDocs, UnparsedColumn],
|
||||
@@ -536,6 +541,11 @@ class SchemaParser(SimpleParser[GenericTestBlock, GenericTestNode]):
|
||||
metric_parser = MetricParser(self, yaml_block)
|
||||
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:
|
||||
if "version" not in yaml_dct:
|
||||
@@ -1183,3 +1193,107 @@ class MetricParser(YamlReader):
|
||||
except (ValidationError, JSONValidationError) as exc:
|
||||
raise YamlParseDictError(self.yaml.path, self.key, data, exc)
|
||||
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
|
||||
|
||||
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.task.runnable import GraphRunnableTask, ManifestTask
|
||||
from dbt.task.test import TestSelector
|
||||
@@ -22,6 +22,7 @@ class ListTask(GraphRunnableTask):
|
||||
NodeType.Source,
|
||||
NodeType.Exposure,
|
||||
NodeType.Metric,
|
||||
NodeType.Entity,
|
||||
)
|
||||
)
|
||||
ALL_RESOURCE_VALUES = DEFAULT_RESOURCE_VALUES | frozenset((NodeType.Analysis,))
|
||||
@@ -82,6 +83,8 @@ class ListTask(GraphRunnableTask):
|
||||
yield self.manifest.exposures[node]
|
||||
elif node in self.manifest.metrics:
|
||||
yield self.manifest.metrics[node]
|
||||
elif node in self.manifest.entities:
|
||||
yield self.manifest.entities[node]
|
||||
else:
|
||||
raise DbtRuntimeError(
|
||||
f'Got an unexpected result from node selection: "{node}"'
|
||||
@@ -105,6 +108,11 @@ class ListTask(GraphRunnableTask):
|
||||
# metrics are searched for by pkg.metric_name
|
||||
metric_selector = ".".join([node.package_name, node.name])
|
||||
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:
|
||||
# everything else is from `fqn`
|
||||
yield ".".join(node.fqn)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"CatalogMetadata": {
|
||||
"type": "object",
|
||||
@@ -48,12 +48,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.2.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-04-15T20:38:22.701177Z"
|
||||
"default": "2023-01-23T21:56:17.789289Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -64,7 +64,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -75,7 +75,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -112,7 +112,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -163,7 +163,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -194,7 +194,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -241,7 +241,7 @@
|
||||
}
|
||||
},
|
||||
"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#",
|
||||
|
||||
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",
|
||||
"exposures",
|
||||
"metrics",
|
||||
"entities",
|
||||
"selectors"
|
||||
],
|
||||
"properties": {
|
||||
@@ -85,6 +86,13 @@
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
"description": "The selectors defined in selectors.yml"
|
||||
@@ -173,7 +181,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"ManifestMetadata": {
|
||||
"type": "object",
|
||||
@@ -185,12 +193,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.4.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-12-13T03:30:15.966964Z"
|
||||
"default": "2023-01-23T21:56:17.790304Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -201,7 +209,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "4f2b967b-7e02-46de-a7ea-268a05e3fab1"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -262,7 +270,6 @@
|
||||
"AnalysisNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -276,7 +283,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -400,7 +414,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.970579
|
||||
"default": 1674510977.792257
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -454,6 +468,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -498,7 +522,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -811,7 +835,6 @@
|
||||
"SingularTestNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -825,7 +848,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -941,7 +971,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.973521
|
||||
"default": 1674510977.79368
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -995,6 +1025,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -1039,7 +1079,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -1156,7 +1196,6 @@
|
||||
"HookNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -1170,7 +1209,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -1294,7 +1340,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.975156
|
||||
"default": 1674510977.795094
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -1348,6 +1394,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -1402,12 +1458,11 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -1421,7 +1476,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -1545,7 +1607,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.976732
|
||||
"default": 1674510977.7959611
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -1599,6 +1661,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -1643,12 +1715,11 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -1662,7 +1733,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -1786,7 +1864,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.978195
|
||||
"default": 1674510977.796774
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -1840,6 +1918,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -1884,12 +1972,11 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -1903,7 +1990,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -2027,7 +2121,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.979718
|
||||
"default": 1674510977.797567
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -2081,6 +2175,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -2125,13 +2229,12 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"test_metadata",
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -2148,7 +2251,14 @@
|
||||
"$ref": "#/definitions/TestMetadata"
|
||||
},
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -2264,7 +2374,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.981434
|
||||
"default": 1674510977.79852
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -2318,6 +2428,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -2382,7 +2502,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -2414,7 +2534,6 @@
|
||||
"SnapshotNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -2429,7 +2548,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -2529,7 +2655,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.984685
|
||||
"default": 1674510977.79998
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -2583,6 +2709,16 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"depends_on": {
|
||||
"$ref": "#/definitions/DependsOn",
|
||||
"default": {
|
||||
@@ -2627,7 +2763,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -2837,7 +2973,6 @@
|
||||
"SeedNode": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -2851,7 +2986,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -2976,7 +3118,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.987447
|
||||
"default": 1674510977.801306
|
||||
},
|
||||
"config_call_dict": {
|
||||
"type": "object",
|
||||
@@ -3008,7 +3150,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -3178,7 +3320,6 @@
|
||||
"SourceDefinition": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"database",
|
||||
"schema",
|
||||
"name",
|
||||
"resource_type",
|
||||
@@ -3194,7 +3335,14 @@
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schema": {
|
||||
"type": "string"
|
||||
@@ -3335,11 +3483,11 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.989922
|
||||
"default": 1674510977.802621
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -3445,12 +3593,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.4.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-12-13T03:30:15.961825Z"
|
||||
"default": "2023-01-23T21:56:17.787436Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -3461,7 +3609,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "4f2b967b-7e02-46de-a7ea-268a05e3fab1"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -3472,7 +3620,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -3814,7 +3962,7 @@
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.990816
|
||||
"default": 1674510977.8031092
|
||||
},
|
||||
"supported_languages": {
|
||||
"oneOf": [
|
||||
@@ -4070,13 +4218,23 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.993354
|
||||
"default": 1674510977.8040562
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -4126,7 +4284,6 @@
|
||||
"description",
|
||||
"label",
|
||||
"calculation_method",
|
||||
"timestamp",
|
||||
"expression",
|
||||
"filters",
|
||||
"time_grains",
|
||||
@@ -4169,9 +4326,6 @@
|
||||
"calculation_method": {
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"expression": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -4193,6 +4347,16 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"timestamp": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"window": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -4281,13 +4445,23 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"entities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"created_at": {
|
||||
"type": "number",
|
||||
"default": 1670902215.995033
|
||||
"default": 1674510977.804972
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -4355,6 +4529,148 @@
|
||||
},
|
||||
"additionalProperties": 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#",
|
||||
|
||||
@@ -37,12 +37,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.2.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-04-15T20:38:22.700175Z"
|
||||
"default": "2023-01-23T21:56:17.788708Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -53,7 +53,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -64,7 +64,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -148,7 +148,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -183,7 +183,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -195,12 +195,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.2.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-04-15T20:38:22.697740Z"
|
||||
"default": "2023-01-23T21:56:17.787436Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -211,7 +211,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -222,7 +222,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -361,7 +361,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -394,7 +394,7 @@
|
||||
}
|
||||
},
|
||||
"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#",
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
},
|
||||
"dbt_version": {
|
||||
"type": "string",
|
||||
"default": "1.2.0a1"
|
||||
"default": "1.5.0a1"
|
||||
},
|
||||
"generated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"default": "2022-04-15T20:38:22.697740Z"
|
||||
"default": "2023-01-23T21:56:17.787436Z"
|
||||
},
|
||||
"invocation_id": {
|
||||
"oneOf": [
|
||||
@@ -55,7 +55,7 @@
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": "34abf75e-59d3-442f-920c-fa3843d98014"
|
||||
"default": "10c9c26b-6682-4d46-84d2-12f641a070e5"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
@@ -66,7 +66,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -205,7 +205,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -238,7 +238,7 @@
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"type": "object",
|
||||
@@ -273,7 +273,7 @@
|
||||
}
|
||||
},
|
||||
"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#",
|
||||
|
||||
@@ -35,6 +35,7 @@ def basic_uncompiled_model():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
deferred=False,
|
||||
description='',
|
||||
@@ -67,6 +68,7 @@ def basic_compiled_model():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
deferred=True,
|
||||
description='',
|
||||
@@ -123,6 +125,7 @@ def basic_uncompiled_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities':[],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'deferred': False,
|
||||
@@ -172,6 +175,7 @@ def basic_compiled_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities':[],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'deferred': True,
|
||||
@@ -359,6 +363,7 @@ def basic_uncompiled_schema_test_node():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
deferred=False,
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
@@ -392,6 +397,7 @@ def basic_compiled_schema_test_node():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
deferred=False,
|
||||
description='',
|
||||
@@ -430,6 +436,7 @@ def basic_uncompiled_schema_test_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities':[],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'description': '',
|
||||
@@ -480,6 +487,7 @@ def basic_compiled_schema_test_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'deferred': False,
|
||||
'database': 'test_db',
|
||||
|
||||
@@ -10,6 +10,8 @@ from dbt.contracts.graph.model_config import (
|
||||
SnapshotConfig,
|
||||
SourceConfig,
|
||||
ExposureConfig,
|
||||
MetricConfig,
|
||||
EntityConfig,
|
||||
EmptySnapshotConfig,
|
||||
Hook,
|
||||
)
|
||||
@@ -24,6 +26,7 @@ from dbt.contracts.graph.nodes import (
|
||||
Macro,
|
||||
Exposure,
|
||||
Metric,
|
||||
Entity,
|
||||
SeedNode,
|
||||
Docs,
|
||||
MacroDependsOn,
|
||||
@@ -139,6 +142,7 @@ def base_parsed_model_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'description': '',
|
||||
@@ -185,6 +189,7 @@ def basic_parsed_model_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -235,6 +240,7 @@ def complex_parsed_model_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||
'database': 'test_db',
|
||||
'deferred': True,
|
||||
@@ -292,6 +298,7 @@ def complex_parsed_model_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||
deferred=True,
|
||||
description='My parsed node',
|
||||
@@ -714,6 +721,7 @@ def patched_model_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='The foo model',
|
||||
database='test_db',
|
||||
@@ -773,6 +781,7 @@ def base_parsed_hook_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'deferred': False,
|
||||
@@ -819,6 +828,7 @@ def base_parsed_hook_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
deferred=False,
|
||||
@@ -849,6 +859,7 @@ def complex_parsed_hook_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||
'deferred': False,
|
||||
'database': 'test_db',
|
||||
@@ -906,6 +917,7 @@ def complex_parsed_hook_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||
description='My parsed node',
|
||||
deferred=False,
|
||||
@@ -1000,6 +1012,7 @@ def basic_parsed_schema_test_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'deferred': False,
|
||||
'database': 'test_db',
|
||||
@@ -1046,6 +1059,7 @@ def basic_parsed_schema_test_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -1075,6 +1089,7 @@ def complex_parsed_schema_test_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': ['model.test.bar']},
|
||||
'database': 'test_db',
|
||||
'deferred': False,
|
||||
@@ -1138,6 +1153,7 @@ def complex_parsed_schema_test_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.test.bar']),
|
||||
description='My parsed node',
|
||||
database='test_db',
|
||||
@@ -1432,6 +1448,7 @@ def basic_timestamp_snapshot_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'deferred': False,
|
||||
'database': 'test_db',
|
||||
@@ -1489,6 +1506,7 @@ def basic_timestamp_snapshot_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -1537,6 +1555,7 @@ def basic_intermediate_timestamp_snapshot_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -1572,6 +1591,7 @@ def basic_check_snapshot_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'depends_on': {'macros': [], 'nodes': []},
|
||||
'database': 'test_db',
|
||||
'deferred': False,
|
||||
@@ -1629,6 +1649,7 @@ def basic_check_snapshot_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -1677,6 +1698,7 @@ def basic_intermediate_check_snapshot_object():
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
description='',
|
||||
database='test_db',
|
||||
@@ -2115,6 +2137,7 @@ def basic_parsed_exposure_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'fqn': ['test', 'exposures', 'my_exposure'],
|
||||
'unique_id': 'exposure.test.my_exposure',
|
||||
'package_name': 'test',
|
||||
@@ -2177,6 +2200,7 @@ def complex_parsed_exposure_dict():
|
||||
'refs': [],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'fqn': ['test', 'exposures', 'my_exposure'],
|
||||
'unique_id': 'exposure.test.my_exposure',
|
||||
'package_name': 'test',
|
||||
@@ -2251,47 +2275,24 @@ def test_compare_changed_exposure(func, basic_parsed_exposure_object):
|
||||
|
||||
|
||||
# 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
|
||||
def basic_parsed_metric_dict():
|
||||
return {
|
||||
'name': 'new_customers',
|
||||
'label': 'New Customers',
|
||||
'model': 'ref("dim_customers")',
|
||||
'model': "ref('dim_customers')",
|
||||
'calculation_method': 'count',
|
||||
'expression': 'user_id',
|
||||
'timestamp': 'signup_date',
|
||||
'time_grains': ['day', 'week', 'month'],
|
||||
'dimensions': ['plan', 'country'],
|
||||
'filters': [
|
||||
{
|
||||
"field": "is_paying",
|
||||
"value": "true",
|
||||
"operator": "=",
|
||||
}
|
||||
],
|
||||
'filters': [],
|
||||
'resource_type': 'metric',
|
||||
'refs': [['dim_customers']],
|
||||
'sources': [],
|
||||
'metrics': [],
|
||||
'entities': [],
|
||||
'fqn': ['test', 'metrics', 'my_metric'],
|
||||
'unique_id': 'metric.test.my_metric',
|
||||
'package_name': 'test',
|
||||
@@ -2300,26 +2301,98 @@ def basic_parsed_metric_dict():
|
||||
'description': '',
|
||||
'meta': {},
|
||||
'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,
|
||||
'depends_on': {
|
||||
'nodes': [],
|
||||
'macros': [],
|
||||
},
|
||||
'config': {
|
||||
'enabled': True,
|
||||
},
|
||||
'unrendered_config': {},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def basic_parsed_metric_object():
|
||||
return Metric(
|
||||
name='my_metric',
|
||||
resource_type=NodeType.Metric,
|
||||
calculation_method='count',
|
||||
fqn=['test', 'metrics', 'my_metric'],
|
||||
unique_id='metric.test.my_metric',
|
||||
def basic_parsed_entity_object():
|
||||
return Entity(
|
||||
name='my_entity',
|
||||
model="ref('my_model')",
|
||||
dimensions=[],
|
||||
resource_type=NodeType.Entity,
|
||||
fqn=['test', 'entities', 'my_entity'],
|
||||
refs=[['my_model']],
|
||||
unique_id='entity.test.my_entity',
|
||||
package_name='test',
|
||||
path='models/something.yml',
|
||||
original_file_path='models/something.yml',
|
||||
description='',
|
||||
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,
|
||||
UnparsedSourceTableDefinition, UnparsedDocumentationFile, UnparsedColumn,
|
||||
UnparsedNodeUpdate, Docs, UnparsedExposure, MaturityType, ExposureOwner,
|
||||
ExposureType, UnparsedMetric, MetricFilter, MetricTime, MetricTimePeriod
|
||||
ExposureType, UnparsedMetric, UnparsedEntity, MetricFilter, MetricTime,
|
||||
MetricTimePeriod
|
||||
)
|
||||
from dbt.contracts.results import FreshnessStatus
|
||||
from dbt.node_types import NodeType
|
||||
@@ -783,3 +784,49 @@ class TestUnparsedMetric(ContractTestCase):
|
||||
tst = self.get_ok_dict()
|
||||
tst['tags'] = [123]
|
||||
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,
|
||||
SourceDefinition,
|
||||
Exposure,
|
||||
Metric
|
||||
Metric,
|
||||
Entity
|
||||
)
|
||||
|
||||
from dbt.contracts.graph.unparsed import (
|
||||
@@ -42,7 +43,7 @@ from .utils import MockMacro, MockDocumentation, MockSource, MockNode, MockMater
|
||||
|
||||
|
||||
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',
|
||||
'package_name', 'path', 'original_file_path', 'raw_code', 'language',
|
||||
'description', 'columns', 'fqn', 'build_path', 'compiled_path', 'patch_path', 'docs',
|
||||
@@ -123,6 +124,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[['multi']],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
fqn=['root', 'my_metric'],
|
||||
unique_id='metric.root.my_metric',
|
||||
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 = {
|
||||
'model.snowplow.events': ModelNode(
|
||||
name='events',
|
||||
@@ -144,6 +168,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -166,6 +191,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -188,6 +214,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[['events']],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.root.events']),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -210,6 +237,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[['events']],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.root.dep']),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -232,6 +260,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[['events']],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.root.events']),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -254,6 +283,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[['events']],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(nodes=['model.root.nested', 'model.root.sibling']),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -288,6 +318,8 @@ class ManifestTest(unittest.TestCase):
|
||||
exposure.validate(exposure.to_dict(omit_none=True))
|
||||
for metric in self.metrics.values():
|
||||
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():
|
||||
node.validate(node.to_dict(omit_none=True))
|
||||
for source in self.sources.values():
|
||||
@@ -303,7 +335,7 @@ class ManifestTest(unittest.TestCase):
|
||||
def test__no_nodes(self):
|
||||
manifest = Manifest(
|
||||
nodes={}, sources={}, macros={}, docs={}, disabled={}, files={},
|
||||
exposures={}, metrics={}, selectors={},
|
||||
exposures={}, metrics={}, selectors={}, entities={},
|
||||
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
||||
)
|
||||
|
||||
@@ -316,6 +348,7 @@ class ManifestTest(unittest.TestCase):
|
||||
'macros': {},
|
||||
'exposures': {},
|
||||
'metrics': {},
|
||||
'entities': {},
|
||||
'selectors': {},
|
||||
'parent_map': {},
|
||||
'child_map': {},
|
||||
@@ -336,7 +369,7 @@ class ManifestTest(unittest.TestCase):
|
||||
nodes = copy.copy(self.nested_nodes)
|
||||
manifest = Manifest(
|
||||
nodes=nodes, sources={}, macros={}, docs={}, disabled={}, files={},
|
||||
exposures={}, metrics={}, selectors={},
|
||||
exposures={}, metrics={}, entities={}, selectors={},
|
||||
metadata=ManifestMetadata(generated_at=datetime.utcnow()),
|
||||
)
|
||||
serialized = manifest.writable_manifest().to_dict(omit_none=True)
|
||||
@@ -402,20 +435,23 @@ class ManifestTest(unittest.TestCase):
|
||||
def test__build_flat_graph(self):
|
||||
exposures = copy.copy(self.exposures)
|
||||
metrics = copy.copy(self.metrics)
|
||||
entities = copy.copy(self.entities)
|
||||
nodes = copy.copy(self.nested_nodes)
|
||||
sources = copy.copy(self.sources)
|
||||
manifest = Manifest(nodes=nodes, sources=sources, macros={}, docs={},
|
||||
disabled={}, files={}, exposures=exposures,
|
||||
metrics=metrics, selectors={})
|
||||
metrics=metrics, entities=entities, selectors={})
|
||||
manifest.build_flat_graph()
|
||||
flat_graph = manifest.flat_graph
|
||||
flat_exposures = flat_graph['exposures']
|
||||
flat_metrics = flat_graph['metrics']
|
||||
flat_entities = flat_graph['entities']
|
||||
flat_nodes = flat_graph['nodes']
|
||||
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_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_sources), set(self.sources))
|
||||
for node in flat_nodes.values():
|
||||
@@ -466,6 +502,7 @@ class ManifestTest(unittest.TestCase):
|
||||
'macros': {},
|
||||
'exposures': {},
|
||||
'metrics': {},
|
||||
'entities': {},
|
||||
'selectors': {},
|
||||
'parent_map': {},
|
||||
'child_map': {},
|
||||
@@ -509,11 +546,14 @@ class ManifestTest(unittest.TestCase):
|
||||
)
|
||||
manifest = Manifest(nodes=nodes, sources=self.sources, macros={}, docs={},
|
||||
disabled={}, files={}, exposures=self.exposures,
|
||||
metrics=self.metrics, selectors={})
|
||||
metrics=self.metrics, entities=self.entities, selectors={})
|
||||
expect = {
|
||||
'metrics': frozenset([
|
||||
('root', 'my_metric')
|
||||
]),
|
||||
'entities': frozenset([
|
||||
('root', 'my_entity')
|
||||
]),
|
||||
'exposures': frozenset([
|
||||
('root', 'my_exposure')
|
||||
]),
|
||||
@@ -548,6 +588,7 @@ class ManifestTest(unittest.TestCase):
|
||||
refs=[],
|
||||
sources=[],
|
||||
metrics=[],
|
||||
entities=[],
|
||||
depends_on=DependsOn(),
|
||||
config=self.model_config,
|
||||
tags=[],
|
||||
@@ -735,6 +776,7 @@ class MixedManifestTest(unittest.TestCase):
|
||||
'sources': {},
|
||||
'exposures': {},
|
||||
'metrics': {},
|
||||
'entities': {},
|
||||
'selectors': {},
|
||||
'parent_map': {},
|
||||
'child_map': {},
|
||||
@@ -824,7 +866,7 @@ class MixedManifestTest(unittest.TestCase):
|
||||
manifest.build_flat_graph()
|
||||
flat_graph = manifest.flat_graph
|
||||
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))
|
||||
compiled_count = 0
|
||||
for node in flat_nodes.values():
|
||||
@@ -870,6 +912,7 @@ class TestManifestSearch(unittest.TestCase):
|
||||
files={},
|
||||
exposures={},
|
||||
metrics={},
|
||||
entities={},
|
||||
selectors={},
|
||||
)
|
||||
|
||||
@@ -892,6 +935,7 @@ def make_manifest(nodes=[], sources=[], macros=[], docs=[]):
|
||||
files={},
|
||||
exposures={},
|
||||
metrics={},
|
||||
entities={},
|
||||
selectors={},
|
||||
)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ node_type_pluralizations = {
|
||||
NodeType.Macro: "macros",
|
||||
NodeType.Exposure: "exposures",
|
||||
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",
|
||||
"fqn": ["test", "model"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"tags": [],
|
||||
"meta": {},
|
||||
"config": model_config,
|
||||
@@ -339,6 +340,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
"unique_id": "model.test.second_model",
|
||||
"fqn": ["test", "second_model"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"tags": [],
|
||||
"meta": {},
|
||||
"config": second_config,
|
||||
@@ -488,6 +490,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
"file_key_name": "models.model",
|
||||
"fqn": ["test", "not_null_model_id"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "not_null_model_id",
|
||||
"original_file_path": model_schema_yml_path,
|
||||
"package_name": "test",
|
||||
@@ -541,6 +544,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
"extra_ctes_injected": True,
|
||||
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"meta": {},
|
||||
"name": "snapshot_seed",
|
||||
"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",
|
||||
"fqn": ["test", "test_nothing_model_"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "test_nothing_model_",
|
||||
"original_file_path": model_schema_yml_path,
|
||||
"package_name": "test",
|
||||
@@ -634,6 +639,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
"file_key_name": "models.model",
|
||||
"fqn": ["test", "unique_model_id"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "unique_model_id",
|
||||
"original_file_path": model_schema_yml_path,
|
||||
"package_name": "test",
|
||||
@@ -735,6 +741,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
"maturity": "medium",
|
||||
"meta": {"tool": "my_tool", "languages": ["python"]},
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"tags": ["my_department"],
|
||||
"name": "notebook_exposure",
|
||||
"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"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "simple_exposure",
|
||||
"original_file_path": os.path.join("models", "schema.yml"),
|
||||
"owner": {
|
||||
@@ -783,6 +791,7 @@ def expected_seeded_manifest(project, model_database=None, quote_model=False):
|
||||
},
|
||||
},
|
||||
"metrics": {},
|
||||
"entities": {},
|
||||
"selectors": {},
|
||||
"parent_map": {
|
||||
"model.test.model": ["seed.test.seed"],
|
||||
@@ -865,6 +874,7 @@ def expected_references_manifest(project):
|
||||
"docs": {"node_color": None, "show": True},
|
||||
"fqn": ["test", "ephemeral_copy"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "ephemeral_copy",
|
||||
"original_file_path": ephemeral_copy_path,
|
||||
"package_name": "test",
|
||||
@@ -918,6 +928,7 @@ def expected_references_manifest(project):
|
||||
"docs": {"node_color": None, "show": True},
|
||||
"fqn": ["test", "ephemeral_summary"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "ephemeral_summary",
|
||||
"original_file_path": ephemeral_summary_path,
|
||||
"package_name": "test",
|
||||
@@ -973,6 +984,7 @@ def expected_references_manifest(project):
|
||||
"docs": {"node_color": None, "show": True},
|
||||
"fqn": ["test", "view_summary"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"name": "view_summary",
|
||||
"original_file_path": view_summary_path,
|
||||
"package_name": "test",
|
||||
@@ -1082,6 +1094,7 @@ def expected_references_manifest(project):
|
||||
"extra_ctes_injected": True,
|
||||
"fqn": ["test", "snapshot_seed", "snapshot_seed"],
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"meta": {},
|
||||
"name": "snapshot_seed",
|
||||
"original_file_path": snapshot_path,
|
||||
@@ -1168,6 +1181,7 @@ def expected_references_manifest(project):
|
||||
"maturity": "medium",
|
||||
"meta": {"tool": "my_tool", "languages": ["python"]},
|
||||
"metrics": [],
|
||||
"entities": [],
|
||||
"tags": ["my_department"],
|
||||
"name": "notebook_exposure",
|
||||
"original_file_path": os.path.join("models", "schema.yml"),
|
||||
@@ -1184,6 +1198,7 @@ def expected_references_manifest(project):
|
||||
},
|
||||
},
|
||||
"metrics": {},
|
||||
"entities": {},
|
||||
"selectors": {},
|
||||
"docs": {
|
||||
"doc.dbt.__overview__": ANY,
|
||||
|
||||
@@ -355,6 +355,7 @@ def verify_manifest(project, expected_manifest, start_time, manifest_schema_path
|
||||
"parent_map",
|
||||
"child_map",
|
||||
"metrics",
|
||||
"entities",
|
||||
"docs",
|
||||
"metadata",
|
||||
"docs",
|
||||
@@ -381,7 +382,7 @@ def verify_manifest(project, expected_manifest, start_time, manifest_schema_path
|
||||
and metadata["send_anonymous_usage_stats"] is False
|
||||
)
|
||||
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():
|
||||
assert unique_id in manifest[key]
|
||||
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):
|
||||
# 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)
|
||||
|
||||
def test_nonbackwards_compatible_versions(self, project):
|
||||
# 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)
|
||||
|
||||
Reference in New Issue
Block a user