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
4 changes: 2 additions & 2 deletions sqlmesh_dbt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import sys
import click
from sqlmesh_dbt.operations import DbtOperations, create
from sqlmesh_dbt.error import cli_global_error_handler
from sqlmesh_dbt.error import cli_global_error_handler, ErrorHandlingGroup
from pathlib import Path
from sqlmesh_dbt.options import YamlParamType
import functools
Expand Down Expand Up @@ -43,7 +43,7 @@ def _cleanup() -> None:
exclude_option = click.option("--exclude", multiple=True, help="Specify the nodes to exclude.")


@click.group(invoke_without_command=True)
@click.group(cls=ErrorHandlingGroup, invoke_without_command=True)
@click.option("--profile", help="Which existing profile to load. Overrides output.profile")
@click.option("-t", "--target", help="Which target to load for the given profile")
@click.option(
Expand Down
7 changes: 7 additions & 0 deletions sqlmesh_dbt/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ def wrapper(*args: t.List[t.Any], **kwargs: t.Any) -> t.Any:
raise

return wrapper


class ErrorHandlingGroup(click.Group):
def add_command(self, cmd: click.Command, name: t.Optional[str] = None) -> None:
if cmd.callback:
cmd.callback = cli_global_error_handler(cmd.callback)
super().add_command(cmd, name=name)
65 changes: 65 additions & 0 deletions tests/dbt/cli/test_global_flags.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import typing as t
from pathlib import Path
import pytest
from pytest_mock import MockerFixture
from click.testing import Result
from sqlmesh.utils.errors import SQLMeshError
from sqlglot.errors import SqlglotError

pytestmark = pytest.mark.slow

Expand All @@ -28,3 +31,65 @@ def test_profile_and_target(jaffle_shop_duckdb: Path, invoke_cli: t.Callable[...
result = invoke_cli(["--profile", "jaffle_shop", "--target", "dev"])
assert result.exit_code == 0
assert "No command specified" in result.output


def test_run_error_handler(
jaffle_shop_duckdb: Path, invoke_cli: t.Callable[..., Result], mocker: MockerFixture
) -> None:
mock_run = mocker.patch("sqlmesh_dbt.operations.DbtOperations.run")
mock_run.side_effect = SQLMeshError("Test error message")

result = invoke_cli(["run"])
assert result.exit_code == 1
assert "Error: Test error message" in result.output
assert "Traceback" not in result.output

# test SqlglotError in run command
mock_run = mocker.patch("sqlmesh_dbt.operations.DbtOperations.run")
mock_run.side_effect = SqlglotError("Invalid SQL syntax")

result = invoke_cli(["run"])

assert result.exit_code == 1
assert "Error: Invalid SQL syntax" in result.output
assert "Traceback" not in result.output

# test ValueError in run command
mock_run = mocker.patch("sqlmesh_dbt.operations.DbtOperations.run")
mock_run.side_effect = ValueError("Invalid configuration value")

result = invoke_cli(["run"])

assert result.exit_code == 1
assert "Error: Invalid configuration value" in result.output
assert "Traceback" not in result.output

# test SQLMeshError in list command
mock_list = mocker.patch("sqlmesh_dbt.operations.DbtOperations.list_")
mock_list.side_effect = SQLMeshError("List command error")

result = invoke_cli(["list"])

assert result.exit_code == 1
assert "Error: List command error" in result.output
assert "Traceback" not in result.output

# test SQLMeshError in main command without subcommand
mock_create = mocker.patch("sqlmesh_dbt.cli.create")
mock_create.side_effect = SQLMeshError("Failed to load project")
result = invoke_cli(["--profile", "jaffle_shop"])

assert result.exit_code == 1
assert "Error: Failed to load project" in result.output
assert "Traceback" not in result.output
mocker.stopall()

# test error with select option
mock_run_select = mocker.patch("sqlmesh_dbt.operations.DbtOperations.run")
mock_run_select.side_effect = SQLMeshError("Error with selector")

result = invoke_cli(["run", "--select", "model1"])

assert result.exit_code == 1
assert "Error: Error with selector" in result.output
assert "Traceback" not in result.output