Visitar URL original
fix: Catch missing dbt parser dependency in dbt CLI commands by kchawlani19 · Pull Request #6534 · feast-dev/feast · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
fix(dbt): handle missing dbt-artifacts-parser import errors in CLI
Catch ImportError in `feast dbt import` and `feast dbt list` so missing dbt parser dependency returns a clean CLI error. Add regression tests to verify both commands exit with actionable install guidance.

Signed-off-by: kchawlani19 <kchawlan@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
  • Loading branch information
2 people authored and ntkathole committed Jul 30, 2026
commit 5b5cda6d621cbdb762c7df67164dd803538b47f4
7 changes: 2 additions & 5 deletions sdk/python/feast/cli/dbt_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,7 @@ def import_command(
try:
parser = DbtManifestParser(manifest_path)
parser.parse()
except FileNotFoundError as e:
click.echo(f"{Fore.RED}Error: {e}{Style.RESET_ALL}", err=True)
raise SystemExit(1)
except ValueError as e:
except (FileNotFoundError, ValueError, ImportError) as e:
click.echo(f"{Fore.RED}Error: {e}{Style.RESET_ALL}", err=True)
raise SystemExit(1)

Expand Down Expand Up @@ -374,7 +371,7 @@ def list_command(
try:
parser = DbtManifestParser(manifest_path)
parser.parse()
except (FileNotFoundError, ValueError) as e:
except (FileNotFoundError, ValueError, ImportError) as e:
click.echo(f"{Fore.RED}Error: {e}{Style.RESET_ALL}", err=True)
raise SystemExit(1)

Expand Down
50 changes: 50 additions & 0 deletions sdk/python/tests/integration/dbt/test_dbt_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,26 @@ def test_dbt_list_show_columns(self, manifest_path):
assert "driver_id" in result.output
assert "conv_rate" in result.output

def test_dbt_list_import_error(self, manifest_path, monkeypatch):
from click.testing import CliRunner

from feast.cli.dbt_import import list_command
from feast.dbt.parser import DbtManifestParser

def _raise_import_error(self): # pragma: no cover - behavior tested via CLI
raise ImportError(
"dbt-artifacts-parser is required for dbt integration.\n"
"Install with: pip install 'feast[dbt]' or pip install dbt-artifacts-parser"
)

monkeypatch.setattr(DbtManifestParser, "parse", _raise_import_error)

runner = CliRunner()
result = runner.invoke(list_command, ["-m", manifest_path])
assert result.exit_code == 1
assert "dbt-artifacts-parser is required for dbt integration" in result.output
assert "feast[dbt]" in result.output

def test_dbt_import_dry_run(self, manifest_path):
from click.testing import CliRunner

Expand All @@ -1086,6 +1106,36 @@ def test_dbt_import_dry_run(self, manifest_path):
assert result.exit_code == 0
assert "Dry run" in result.output

def test_dbt_import_import_error(self, manifest_path, monkeypatch):
from click.testing import CliRunner

from feast.cli.dbt_import import import_command
from feast.dbt.parser import DbtManifestParser

def _raise_import_error(self): # pragma: no cover - behavior tested via CLI
raise ImportError(
"dbt-artifacts-parser is required for dbt integration.\n"
"Install with: pip install 'feast[dbt]' or pip install dbt-artifacts-parser"
)

monkeypatch.setattr(DbtManifestParser, "parse", _raise_import_error)

runner = CliRunner()
result = runner.invoke(
import_command,
[
"-m",
manifest_path,
"-e",
"driver_id",
"--dry-run",
],
obj={"CHDIR": ".", "FS_YAML_FILE": "feature_store.yaml"},
)
assert result.exit_code == 1
assert "dbt-artifacts-parser is required for dbt integration" in result.output
assert "feast[dbt]" in result.output

def test_dbt_import_output_codegen(self, manifest_path, tmp_path):
from click.testing import CliRunner

Expand Down