Skip to content

Commit 031f7c3

Browse files
committed
fix: ignore grants for model kinds that don't support it
1 parent 0c463d7 commit 031f7c3

5 files changed

Lines changed: 54 additions & 7 deletions

File tree

sqlmesh/core/model/kind.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ def full_history_restatement_only(self) -> bool:
154154
def supports_python_models(self) -> bool:
155155
return True
156156

157+
@property
158+
def supports_grants(self) -> bool:
159+
"""Whether this model kind supports grants configuration."""
160+
return self.is_materialized or self.is_view
161+
157162

158163
class ModelKindName(str, ModelKindMixin, Enum):
159164
"""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
@@ -446,11 +446,8 @@ def _root_validator(self) -> Self:
446446
)
447447

448448
# Validate grants configuration for model kind support
449-
if self.grants is not None:
450-
if kind.is_symbolic:
451-
raise ValueError(f"grants cannot be set for {kind.name} models")
452-
elif not (kind.is_materialized or kind.is_view):
453-
raise ValueError(f"grants field is not supported for {kind.name} models")
449+
if self.grants is not None and not kind.supports_grants:
450+
raise ValueError(f"grants cannot be set for {kind.name} models")
454451

455452
return self
456453

sqlmesh/dbt/model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -679,11 +679,12 @@ def to_sqlmesh(
679679
if physical_properties:
680680
model_kwargs["physical_properties"] = physical_properties
681681

682+
kind = self.model_kind(context)
683+
682684
# A falsy grants config (None or {}) is considered as unmanaged per dbt semantics
683-
if self.grants:
685+
if self.grants and kind.supports_grants:
684686
model_kwargs["grants"] = self.grants
685687

686-
kind = self.model_kind(context)
687688
allow_partials = model_kwargs.pop("allow_partials", None)
688689
if allow_partials is None:
689690
# 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,
@@ -11907,6 +11909,17 @@ def test_grants_invalid_model_kind_errors(kind: str):
1190711909
)
1190811910

1190911911

11912+
def test_model_kind_supports_grants():
11913+
assert FullKind().supports_grants is True
11914+
assert ViewKind().supports_grants is True
11915+
assert IncrementalByTimeRangeKind(time_column="ds").supports_grants is True
11916+
assert IncrementalByUniqueKeyKind(unique_key=["id"]).supports_grants is True
11917+
assert SCDType2ByTimeKind(unique_key=["id"]).supports_grants is True
11918+
11919+
assert EmbeddedKind().supports_grants is False
11920+
assert ExternalKind().supports_grants is False
11921+
11922+
1191011923
def test_grants_validation_no_grants():
1191111924
model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL")
1191211925
assert model.grants is None

tests/dbt/test_model.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,3 +1006,34 @@ def test_model_grants_engine_specific_bigquery() -> None:
10061006
assert grants_config is not None
10071007
assert grants_config["bigquery.dataviewer"] == ["user@domain.com"]
10081008
assert grants_config["select"] == ["analyst@company.com"]
1009+
1010+
1011+
def test_ephemeral_model_with_global_grants(create_empty_project):
1012+
dbt_project_dir, dbt_model_dir = create_empty_project()
1013+
1014+
yaml = YAML()
1015+
dbt_project_config = {
1016+
"name": "test_project",
1017+
"version": "1.0.0",
1018+
"config-version": 2,
1019+
"profile": "test",
1020+
"model-paths": ["models"],
1021+
"models": {"test_project": {"grants": {"select": ["reporter", "analyst"]}}},
1022+
}
1023+
dbt_project_file = dbt_project_dir / "dbt_project.yml"
1024+
with open(dbt_project_file, "w", encoding="utf-8") as f:
1025+
yaml.dump(dbt_project_config, f)
1026+
1027+
ephemeral_model_sql = """
1028+
{{ config(materialized='ephemeral') }}
1029+
SELECT 1 as id
1030+
"""
1031+
ephemeral_model_file = dbt_model_dir / "ephemeral_model.sql"
1032+
with open(ephemeral_model_file, "w", encoding="utf-8") as f:
1033+
f.write(ephemeral_model_sql)
1034+
1035+
context = Context(paths=dbt_project_dir)
1036+
model = context.get_model('"local"."main"."ephemeral_model"')
1037+
1038+
assert model.kind.is_embedded
1039+
assert model.grants is None # grants config is skipped for ephemeral / embedded models

0 commit comments

Comments
 (0)