diff --git a/.changes/unreleased/Features-20230530-164847.yaml b/.changes/unreleased/Features-20230530-164847.yaml new file mode 100644 index 00000000000..eb4e47a619a --- /dev/null +++ b/.changes/unreleased/Features-20230530-164847.yaml @@ -0,0 +1,6 @@ +kind: Features +body: add access selection syntax +time: 2023-05-30T16:48:47.740037-05:00 +custom: + Author: dave-connors-3 + Issue: "7738" diff --git a/core/dbt/graph/selector_methods.py b/core/dbt/graph/selector_methods.py index f8442fc4973..e132175e972 100644 --- a/core/dbt/graph/selector_methods.py +++ b/core/dbt/graph/selector_methods.py @@ -36,6 +36,7 @@ class MethodName(StrEnum): FQN = "fqn" Tag = "tag" Group = "group" + Access = "access" Source = "source" Path = "path" File = "file" @@ -230,6 +231,16 @@ def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[Uniqu yield node +class AccessSelectorMethod(SelectorMethod): + def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]: + """yields model nodes matching the specified access level""" + for node, real_node in self.parsed_nodes(included_nodes): + if not isinstance(real_node, ModelNode): + continue + if selector == real_node.access: + yield node + + class SourceSelectorMethod(SelectorMethod): def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]: """yields nodes from included are the specified source.""" @@ -713,6 +724,7 @@ class MethodManager: MethodName.FQN: QualifiedNameSelectorMethod, MethodName.Tag: TagSelectorMethod, MethodName.Group: GroupSelectorMethod, + MethodName.Access: AccessSelectorMethod, MethodName.Source: SourceSelectorMethod, MethodName.Path: PathSelectorMethod, MethodName.File: FileSelectorMethod, diff --git a/test/unit/test_graph_selector_methods.py b/test/unit/test_graph_selector_methods.py index 5bc881747da..eaac2479979 100644 --- a/test/unit/test_graph_selector_methods.py +++ b/test/unit/test_graph_selector_methods.py @@ -32,6 +32,7 @@ QualifiedNameSelectorMethod, TagSelectorMethod, GroupSelectorMethod, + AccessSelectorMethod, SourceSelectorMethod, PathSelectorMethod, FileSelectorMethod, @@ -63,6 +64,7 @@ def make_model( depends_on_macros=None, version=None, latest_version=None, + access=None, ): if refs is None: refs = [] @@ -121,6 +123,7 @@ def make_model( checksum=FileHash.from_contents(""), version=version, latest_version=latest_version, + access=access, ) @@ -921,6 +924,22 @@ def test_select_group(manifest, view_model): assert not search_manifest_using_method(manifest, method, "not_my_group") +def test_select_access(manifest, view_model): + change_node( + manifest, + view_model.replace( + access="public", + ), + ) + methods = MethodManager(manifest, None) + method = methods.get_method("access", []) + assert isinstance(method, AccessSelectorMethod) + assert method.arguments == [] + + assert search_manifest_using_method(manifest, method, "public") == {"view_model"} + assert not search_manifest_using_method(manifest, method, "private") + + def test_select_source(manifest): methods = MethodManager(manifest, None) method = methods.get_method("source", [])