-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactoring to make testing easier & adding tests (#96)
* Add pytest package * Use tool.poetry.group.dev.dependencies instead of tool.poetry.dev-dependencies * make build_node_ancestor_tree staticmethod for testing * Add jaffle_shop's manifest.json for testing * Split files * Add tests for knowledge propagation * Add types * Add test for get_prior_knowledge * run pytest on github actions
- Loading branch information
Showing
9 changed files
with
11,716 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: Tests | ||
|
||
on: | ||
- push | ||
- pull_request | ||
|
||
jobs: | ||
tests: | ||
name: Run pytest | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check out the repository | ||
uses: actions/checkout@v3 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v3 | ||
with: | ||
python-version: "3.10" | ||
|
||
- name: Upgrade pip | ||
run: | | ||
pip install --constraint=.github/workflows/constraints.txt pip | ||
pip --version | ||
- name: Install Poetry | ||
run: | | ||
pip install --constraint=.github/workflows/constraints.txt poetry | ||
poetry --version | ||
- name: Install required packages | ||
run: | | ||
poetry install | ||
- name: Run pytest | ||
run: | | ||
poetry run python -m pytest |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
from typing import ( | ||
Any, | ||
Dict, | ||
List, | ||
Optional, | ||
) | ||
|
||
from dbt_osmosis.vendored.dbt_core_interface.project import ( | ||
ManifestNode, | ||
) | ||
|
||
|
||
ColumnLevelKnowledge = Dict[str, Any] | ||
Knowledge = Dict[str, ColumnLevelKnowledge] | ||
|
||
|
||
def _build_node_ancestor_tree( | ||
manifest: ManifestNode, | ||
node: ManifestNode, | ||
family_tree: Optional[Dict[str, List[str]]] = None, | ||
members_found: Optional[List[str]] = None, | ||
depth: int = 0, | ||
) -> Dict[str, List[str]]: | ||
"""Recursively build dictionary of parents in generational order""" | ||
if family_tree is None: | ||
family_tree = {} | ||
if members_found is None: | ||
members_found = [] | ||
if not hasattr(node, "depends_on"): | ||
return family_tree | ||
for parent in getattr(node.depends_on, "nodes", []): | ||
member = manifest.nodes.get(parent, manifest.sources.get(parent)) | ||
if member and parent not in members_found: | ||
family_tree.setdefault(f"generation_{depth}", []).append(parent) | ||
members_found.append(parent) | ||
# Recursion | ||
family_tree = _build_node_ancestor_tree( | ||
manifest, member, family_tree, members_found, depth + 1 | ||
) | ||
return family_tree | ||
|
||
|
||
def _inherit_column_level_knowledge( | ||
manifest: ManifestNode, | ||
family_tree: Dict[str, Any], | ||
placeholders: List[str], | ||
) -> Knowledge: | ||
"""Inherit knowledge from ancestors in reverse insertion order to ensure that the most | ||
recent ancestor is always the one to inherit from | ||
""" | ||
knowledge: Knowledge = {} | ||
for generation in reversed(family_tree): | ||
for ancestor in family_tree[generation]: | ||
member: ManifestNode = manifest.nodes.get(ancestor, manifest.sources.get(ancestor)) | ||
if not member: | ||
continue | ||
for name, info in member.columns.items(): | ||
knowledge_default = {"progenitor": ancestor, "generation": generation} | ||
knowledge.setdefault(name, knowledge_default) | ||
deserialized_info = info.to_dict() | ||
# Handle Info: | ||
# 1. tags are additive | ||
# 2. descriptions are overriden | ||
# 3. meta is merged | ||
# 4. tests are ignored until I am convinced those shouldn't be | ||
# hand curated with love | ||
if deserialized_info["description"] in placeholders: | ||
deserialized_info.pop("description", None) | ||
deserialized_info["tags"] = list( | ||
set(deserialized_info.pop("tags", []) + knowledge[name].get("tags", [])) | ||
) | ||
if not deserialized_info["tags"]: | ||
deserialized_info.pop("tags") # poppin' tags like Macklemore | ||
deserialized_info["meta"] = { | ||
**knowledge[name].get("meta", {}), | ||
**deserialized_info["meta"], | ||
} | ||
if not deserialized_info["meta"]: | ||
deserialized_info.pop("meta") | ||
knowledge[name].update(deserialized_info) | ||
return knowledge | ||
|
||
|
||
class ColumnLevelKnowledgePropagator: | ||
@staticmethod | ||
def get_node_columns_with_inherited_knowledge( | ||
manifest: ManifestNode, | ||
node: ManifestNode, | ||
placeholders: List[str], | ||
) -> Knowledge: | ||
"""Build a knowledgebase for the model based on iterating through ancestors""" | ||
family_tree = _build_node_ancestor_tree(manifest, node) | ||
knowledge = _inherit_column_level_knowledge(manifest, family_tree, placeholders) | ||
return knowledge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.