Skip to content

Commit 40af4ec

Browse files
committed
fix: ignore grants for model kinds that don't support it
1 parent ef2ca9b commit 40af4ec

File tree

5 files changed

+54
-7
lines changed

5 files changed

+54
-7
lines changed

sqlmesh/core/model/kind.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ def full_history_restatement_only(self) -> bool:
150150
def supports_python_models(self) -> bool:
151151
return True
152152

153+
@property
154+
def supports_grants(self) -> bool:
155+
"""Whether this model kind supports grants configuration."""
156+
return self.is_materialized or self.is_view
157+
153158

154159
class ModelKindName(str, ModelKindMixin, Enum):
155160
"""The kind of model, determining how this data is computed and stored in the warehouse."""

sqlmesh/core/model/meta.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,8 @@ def _root_validator(self) -> Self:
442442
)
443443

444444
# Validate grants configuration for model kind support
445-
if self.grants is not None:
446-
if kind.is_symbolic:
447-
raise ValueError(f"grants cannot be set for {kind.name} models")
448-
elif not (kind.is_materialized or kind.is_view):
449-
raise ValueError(f"grants field is not supported for {kind.name} models")
445+
if self.grants is not None and not kind.supports_grants:
446+
raise ValueError(f"grants cannot be set for {kind.name} models")
450447

451448
return self
452449

sqlmesh/dbt/model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,11 +646,12 @@ def to_sqlmesh(
646646
if physical_properties:
647647
model_kwargs["physical_properties"] = physical_properties
648648

649+
kind = self.model_kind(context)
650+
649651
# A falsy grants config (None or {}) is considered as unmanaged per dbt semantics
650-
if self.grants:
652+
if self.grants and kind.supports_grants:
651653
model_kwargs["grants"] = self.grants
652654

653-
kind = self.model_kind(context)
654655
allow_partials = model_kwargs.pop("allow_partials", None)
655656
if allow_partials is None:
656657
# Set allow_partials to True for dbt models to preserve the original semantics.

tests/core/test_model.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
TimeColumn,
5454
ExternalKind,
5555
ViewKind,
56+
EmbeddedKind,
57+
SCDType2ByTimeKind,
5658
create_external_model,
5759
create_seed_model,
5860
create_sql_model,
@@ -11791,6 +11793,17 @@ def test_grants_invalid_model_kind_errors(kind: str):
1179111793
)
1179211794

1179311795

11796+
def test_model_kind_supports_grants():
11797+
assert FullKind().supports_grants is True
11798+
assert ViewKind().supports_grants is True
11799+
assert IncrementalByTimeRangeKind(time_column="ds").supports_grants is True
11800+
assert IncrementalByUniqueKeyKind(unique_key=["id"]).supports_grants is True
11801+
assert SCDType2ByTimeKind(unique_key=["id"]).supports_grants is True
11802+
11803+
assert EmbeddedKind().supports_grants is False
11804+
assert ExternalKind().supports_grants is False
11805+
11806+
1179411807
def test_grants_validation_no_grants():
1179511808
model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL")
1179611809
assert model.grants is None

tests/dbt/test_model.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,34 @@ def test_model_grants_engine_specific_bigquery() -> None:
732732
assert grants_config is not None
733733
assert grants_config["bigquery.dataviewer"] == ["user@domain.com"]
734734
assert grants_config["select"] == ["analyst@company.com"]
735+
736+
737+
def test_ephemeral_model_with_global_grants(create_empty_project):
738+
dbt_project_dir, dbt_model_dir = create_empty_project()
739+
740+
yaml = YAML()
741+
dbt_project_config = {
742+
"name": "test_project",
743+
"version": "1.0.0",
744+
"config-version": 2,
745+
"profile": "test",
746+
"model-paths": ["models"],
747+
"models": {"test_project": {"grants": {"select": ["reporter", "analyst"]}}},
748+
}
749+
dbt_project_file = dbt_project_dir / "dbt_project.yml"
750+
with open(dbt_project_file, "w", encoding="utf-8") as f:
751+
yaml.dump(dbt_project_config, f)
752+
753+
ephemeral_model_sql = """
754+
{{ config(materialized='ephemeral') }}
755+
SELECT 1 as id
756+
"""
757+
ephemeral_model_file = dbt_model_dir / "ephemeral_model.sql"
758+
with open(ephemeral_model_file, "w", encoding="utf-8") as f:
759+
f.write(ephemeral_model_sql)
760+
761+
context = Context(paths=dbt_project_dir)
762+
model = context.get_model('"local"."main"."ephemeral_model"')
763+
764+
assert model.kind.is_embedded
765+
assert model.grants is None # grants config is skipped for ephemeral / embedded models

0 commit comments

Comments
 (0)