diff --git a/.changes/unreleased/Features-20220512-215748.yaml b/.changes/unreleased/Features-20220512-215748.yaml new file mode 100644 index 00000000000..9ba18345114 --- /dev/null +++ b/.changes/unreleased/Features-20220512-215748.yaml @@ -0,0 +1,7 @@ +kind: Features +body: Adds file selectors and support for file selectors in the default method selector +time: 2022-05-12T21:57:48.289674-07:00 +custom: + Author: jwills + Issue: "5240" + PR: "5241" diff --git a/core/dbt/graph/selector_methods.py b/core/dbt/graph/selector_methods.py index 00cc902679a..2c489bcea04 100644 --- a/core/dbt/graph/selector_methods.py +++ b/core/dbt/graph/selector_methods.py @@ -39,6 +39,7 @@ class MethodName(StrEnum): Tag = "tag" Source = "source" Path = "path" + File = "file" Package = "package" Config = "config" TestName = "test_name" @@ -280,7 +281,7 @@ def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[Uniqu class PathSelectorMethod(SelectorMethod): def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]: - """Yields nodes from inclucded that match the given path.""" + """Yields nodes from included that match the given path.""" # use '.' and not 'root' for easy comparison root = Path.cwd() paths = set(p.relative_to(root) for p in root.glob(selector)) @@ -294,6 +295,14 @@ def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[Uniqu yield node +class FileSelectorMethod(SelectorMethod): + def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]: + """Yields nodes from included that match the given file name.""" + for node, real_node in self.all_nodes(included_nodes): + if Path(real_node.original_file_path).name == selector: + yield node + + class PackageSelectorMethod(SelectorMethod): def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[UniqueId]: """Yields nodes from included that have the specified package""" @@ -589,6 +598,7 @@ class MethodManager: MethodName.Tag: TagSelectorMethod, MethodName.Source: SourceSelectorMethod, MethodName.Path: PathSelectorMethod, + MethodName.File: FileSelectorMethod, MethodName.Package: PackageSelectorMethod, MethodName.Config: ConfigSelectorMethod, MethodName.TestName: TestNameSelectorMethod, diff --git a/core/dbt/graph/selector_spec.py b/core/dbt/graph/selector_spec.py index 2acf41a9316..0942cbc9f2a 100644 --- a/core/dbt/graph/selector_spec.py +++ b/core/dbt/graph/selector_spec.py @@ -80,6 +80,8 @@ def __post_init__(self): def default_method(cls, value: str) -> MethodName: if _probably_path(value): return MethodName.Path + elif value.lower().endswith(".sql"): + return MethodName.File else: return MethodName.FQN diff --git a/test/unit/test_graph_selector_methods.py b/test/unit/test_graph_selector_methods.py index 8ddc232dd98..aee735a9d24 100644 --- a/test/unit/test_graph_selector_methods.py +++ b/test/unit/test_graph_selector_methods.py @@ -1,4 +1,5 @@ import copy + import pytest from unittest import mock @@ -31,6 +32,7 @@ TagSelectorMethod, SourceSelectorMethod, PathSelectorMethod, + FileSelectorMethod, PackageSelectorMethod, ConfigSelectorMethod, TestNameSelectorMethod, @@ -703,6 +705,20 @@ def test_select_path(manifest): manifest, method, 'models/missing*') +def test_select_file(manifest): + methods = MethodManager(manifest, None) + method = methods.get_method('file', []) + assert isinstance(method, FileSelectorMethod) + assert method.arguments == [] + + assert search_manifest_using_method( + manifest, method, 'table_model.sql') == {'table_model'} + assert search_manifest_using_method( + manifest, method, 'union_model.sql') == {'union_model', 'mynamespace.union_model'} + assert not search_manifest_using_method( + manifest, method, 'missing.sql') + + def test_select_package(manifest): methods = MethodManager(manifest, None) method = methods.get_method('package', [])