Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/unreleased/Fixes-20220909-164413.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Fixes
body: Raise better error message when dispatching a package that is not installed
time: 2022-09-09T16:44:13.382685-06:00
custom:
Author: "dbeatty10"
Issue: "5801"
PR: "5804"
36 changes: 21 additions & 15 deletions core/dbt/context/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,25 @@ def _get_adapter_macro_prefixes(self) -> List[str]:
search_prefixes = get_adapter_type_names(self._adapter.type()) + ["default"]
return search_prefixes

def _get_search_packages(self, namespace: Optional[str] = None) -> List[Optional[str]]:
search_packages: List[Optional[str]] = [None]

if namespace is None:
search_packages = [None]
elif isinstance(namespace, str):
macro_search_order = self._adapter.config.get_macro_search_order(namespace)
if macro_search_order:
search_packages = macro_search_order
elif not macro_search_order and namespace in self._adapter.config.dependencies:
search_packages = [self.config.project_name, namespace]
else:
raise CompilationError(
f"In adapter.dispatch, got a {type(namespace)} macro_namespace argument "
f'("{namespace}"), but macro_namespace should be None or a string.'
)

return search_packages

def dispatch(
self,
macro_name: str,
Expand All @@ -154,20 +173,7 @@ def dispatch(
if packages is not None:
raise MacroDispatchArgError(macro_name)

namespace = macro_namespace

if namespace is None:
search_packages = [None]
elif isinstance(namespace, str):
search_packages = self._adapter.config.get_macro_search_order(namespace)
if not search_packages and namespace in self._adapter.config.dependencies:
search_packages = [self.config.project_name, namespace]
else:
# Not a string and not None so must be a list
raise CompilationError(
f"In adapter.dispatch, got a list macro_namespace argument "
f'("{macro_namespace}"), but macro_namespace should be None or a string.'
)
search_packages = self._get_search_packages(macro_namespace)

attempts = []

Expand All @@ -191,7 +197,7 @@ def dispatch(
return macro

searched = ", ".join(repr(a) for a in attempts)
msg = f"In dispatch: No macro named '{macro_name}' found\n Searched for: {searched}"
msg = f"In dispatch: No macro named '{macro_name}' found within namespace: '{macro_namespace}'\n Searched for: {searched}"
raise CompilationError(msg)


Expand Down
25 changes: 25 additions & 0 deletions tests/functional/macros/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,28 @@
{{ adapter_macro('some_macro', arg1, arg2) }}
{%- endmacro %}
"""

macros__incorrect_dispatch = """
{% macro cowsay() %}
{{ return(adapter.dispatch('cowsay', 'farm_utils')()) }}
{%- endmacro %}

{% macro default__cowsay() %}
'moo'
{% endmacro %}
"""

# Note the difference between `test_utils` below and `farm_utils` above
models__incorrect_dispatch = """
select {{ test_utils.cowsay() }} as cowsay
"""

dbt_project__incorrect_dispatch = """
name: 'test_utils'
version: '1.0'
config-version: 2

profile: 'default'

macro-paths: ["macros"]
"""
41 changes: 41 additions & 0 deletions tests/functional/macros/test_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@
check_relations_equal,
)

from dbt.tests.fixtures.project import write_project_files
from tests.functional.macros.fixtures import (
dbt_project__incorrect_dispatch,
models__dep_macro,
models__with_undefined_macro,
models__local_macro,
models__ref_macro,
models__override_get_columns_macros,
models__deprecated_adapter_macro_model,
models__incorrect_dispatch,
macros__my_macros,
macros__no_default_macros,
macros__override_get_columns_macros,
macros__package_override_get_columns_macros,
macros__deprecated_adapter_macro,
macros__incorrect_dispatch,
)


Expand Down Expand Up @@ -203,6 +207,43 @@ def test_overrides(self, project):
run_dbt()


class TestMisnamedMacroNamespace:
@pytest.fixture(scope="class", autouse=True)
def setUp(self, project_root):
test_utils_files = {
"dbt_project.yml": dbt_project__incorrect_dispatch,
"macros": {
"cowsay.sql": macros__incorrect_dispatch,
},
}
write_project_files(project_root, "test_utils", test_utils_files)

@pytest.fixture(scope="class")
def models(self):
return {
"my_model.sql": models__incorrect_dispatch,
}

@pytest.fixture(scope="class")
def packages(self):
return {
"packages": [
{"local": "test_utils"},
]
}

def test_misnamed_macro_namespace(
self,
project,
):
run_dbt(["deps"])

with pytest.raises(dbt.exceptions.CompilationError) as exc:
run_dbt()

assert "In dispatch: No macro named 'cowsay' found" in str(exc.value)


class TestAdapterMacroDeprecated:
@pytest.fixture(scope="class")
def models(self):
Expand Down