Skip to content

Commit

Permalink
parse group resource
Browse files Browse the repository at this point in the history
  • Loading branch information
MichelleArk committed Feb 9, 2023
1 parent 3f7a1e5 commit b40bf3c
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 68 deletions.
3 changes: 3 additions & 0 deletions core/dbt/compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def print_compile_stats(stats):
NodeType.Source: "source",
NodeType.Exposure: "exposure",
NodeType.Metric: "metric",
NodeType.Group: "group",
}

results = {k: 0 for k in names.keys()}
Expand Down Expand Up @@ -87,6 +88,8 @@ def _generate_stats(manifest: Manifest):
stats[metric.resource_type] += 1
for macro in manifest.macros.values():
stats[macro.resource_type] += 1
for group in manifest.groups.values():
stats[group.resource_type] += 1
return stats


Expand Down
13 changes: 13 additions & 0 deletions core/dbt/contracts/graph/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
GenericTestNode,
Exposure,
Metric,
Group,
UnpatchedSourceDefinition,
ManifestNode,
GraphMemberNode,
Expand Down Expand Up @@ -599,6 +600,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)
groups: MutableMapping[str, Group] = 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)
Expand Down Expand Up @@ -775,6 +777,7 @@ def deepcopy(self):
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()},
groups={k: _deepcopy(v) for k, v in self.groups.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()},
Expand Down Expand Up @@ -816,6 +819,7 @@ def writable_manifest(self):
docs=self.docs,
exposures=self.exposures,
metrics=self.metrics,
groups=self.groups,
selectors=self.selectors,
metadata=self.metadata,
disabled=self.disabled,
Expand Down Expand Up @@ -1083,6 +1087,11 @@ def add_metric(self, source_file: SchemaSourceFile, metric: Metric):
self.metrics[metric.unique_id] = metric
source_file.metrics.append(metric.unique_id)

def add_group(self, source_file: SchemaSourceFile, group: Group):
_check_duplicates(group, self.groups)
self.groups[group.unique_id] = group
source_file.metrics.append(group.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:
Expand Down Expand Up @@ -1125,6 +1134,7 @@ def __reduce_ex__(self, protocol):
self.docs,
self.exposures,
self.metrics,
self.groups,
self.selectors,
self.files,
self.metadata,
Expand Down Expand Up @@ -1178,6 +1188,9 @@ class WritableManifest(ArtifactMixin):
metrics: Mapping[UniqueID, Metric] = field(
metadata=dict(description=("The metrics defined in the dbt project and its dependencies"))
)
groups: Mapping[UniqueID, Group] = field(
metadata=dict(description=("The groups defined in the dbt project"))
)
selectors: Mapping[UniqueID, Any] = field(
metadata=dict(description=("The selectors defined in selectors.yml"))
)
Expand Down
13 changes: 13 additions & 0 deletions core/dbt/contracts/graph/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,18 @@ def same_contents(self, old: Optional["Metric"]) -> bool:
)


# ====================================
# Group node
# ====================================


@dataclass
class Group(BaseNode):
name: str
owner: Owner
resource_type: NodeType = field(metadata={"restrict": [NodeType.Group]})


# ====================================
# Patches
# ====================================
Expand Down Expand Up @@ -1133,6 +1145,7 @@ class ParsedMacroPatch(ParsedPatch):
GraphMemberNode,
Documentation,
Macro,
Group,
]

TestNode = Union[
Expand Down
12 changes: 12 additions & 0 deletions core/dbt/contracts/graph/unparsed.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,15 @@ def validate(cls, data):

if data.get("model") is not None and data.get("calculation_method") == "derived":
raise ValidationError("Derived metrics cannot have a 'model' property")


@dataclass
class UnparsedGroup(dbtClassMixin, Replaceable):
name: str
owner: Owner

@classmethod
def validate(cls, data):
super(UnparsedGroup, cls).validate(data)
if data["owner"].get("name") is None and data["owner"].get("email") is None:
raise ValidationError("Group owner must have at least one of 'name' or 'email'.")
3 changes: 3 additions & 0 deletions core/dbt/contracts/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ def upgrade_manifest_json(manifest: dict) -> dict:
upgrade_node_content(node_content)
if node_content["resource_type"] == "seed":
upgrade_seed_content(node_content)
# add group key
if "groups" not in manifest:
manifest["groups"] = {}
for metric_content in manifest.get("metrics", {}).values():
# handle attr renames + value translation ("expression" -> "derived")
metric_content = rename_metric_attr(metric_content)
Expand Down
1 change: 1 addition & 0 deletions core/dbt/node_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class NodeType(StrEnum):
Macro = "macro"
Exposure = "exposure"
Metric = "metric"
Group = "group"

@classmethod
def executable(cls) -> List["NodeType"]:
Expand Down
41 changes: 41 additions & 0 deletions core/dbt/parser/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
UnpatchedSourceDefinition,
Exposure,
Metric,
Group,
)
from dbt.contracts.graph.unparsed import (
HasColumnDocs,
Expand All @@ -48,6 +49,7 @@
UnparsedExposure,
UnparsedMetric,
UnparsedSourceDefinition,
UnparsedGroup,
)
from dbt.exceptions import (
CompilationError,
Expand Down Expand Up @@ -536,6 +538,11 @@ def parse_file(self, block: FileBlock, dct: Dict = None) -> None:
metric_parser = MetricParser(self, yaml_block)
metric_parser.parse()

# parse groups
if "groups" in dct:
group_parser = GroupParser(self, yaml_block)
group_parser.parse()


def check_format_version(file_path, yaml_dct) -> None:
if "version" not in yaml_dct:
Expand Down Expand Up @@ -1183,3 +1190,37 @@ def parse(self):
except (ValidationError, JSONValidationError) as exc:
raise YamlParseDictError(self.yaml.path, self.key, data, exc)
self.parse_metric(unparsed)


class GroupParser(YamlReader):
def __init__(self, schema_parser: SchemaParser, yaml: YamlBlock):
super().__init__(schema_parser, yaml, NodeType.Group.pluralize())
self.schema_parser = schema_parser
self.yaml = yaml

def parse_group(self, unparsed: UnparsedGroup):
package_name = self.project.project_name
unique_id = f"{NodeType.Group}.{package_name}.{unparsed.name}"
path = self.yaml.path.relative_path

parsed = Group(
resource_type=NodeType.Group,
package_name=package_name,
path=path,
original_file_path=self.yaml.path.original_file_path,
unique_id=unique_id,
name=unparsed.name,
owner=unparsed.owner,
)

self.manifest.add_group(self.yaml.file, parsed)

def parse(self):
for data in self.get_key_dicts():
try:
UnparsedGroup.validate(data)
unparsed = UnparsedGroup.from_dict(data)
except (ValidationError, JSONValidationError) as exc:
raise YamlParseDictError(self.yaml.path, self.key, data, exc)

self.parse_group(unparsed)
Loading

0 comments on commit b40bf3c

Please sign in to comment.