Skip to content

Commit f303a16

Browse files
committed
move virtual_environment_model attribute into model meta
1 parent 92dc16d commit f303a16

10 files changed

Lines changed: 60 additions & 32 deletions

File tree

sqlmesh/core/context.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2909,7 +2909,6 @@ def _nodes_to_snapshots(self, nodes: t.Dict[str, Node]) -> t.Dict[str, Snapshot]
29092909
config = self.config_for_node(node)
29102910
kwargs["ttl"] = config.snapshot_ttl
29112911
kwargs["table_naming_convention"] = config.physical_table_naming_convention
2912-
kwargs["virtual_environment_mode"] = config.virtual_environment_mode
29132912

29142913
snapshot = Snapshot.from_node(
29152914
node,

sqlmesh/core/loader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ def _load_sql_models(
603603
infer_names=self.config.model_naming.infer_names,
604604
signal_definitions=signals,
605605
default_catalog_per_gateway=self.context.default_catalog_per_gateway,
606+
virtual_environment_mode=self.config.virtual_environment_mode,
606607
**loading_default_kwargs or {},
607608
)
608609

@@ -683,6 +684,7 @@ def _load_python_models(
683684
audit_definitions=audits,
684685
signal_definitions=signals,
685686
default_catalog_per_gateway=self.context.default_catalog_per_gateway,
687+
virtual_environment_mode=self.config.virtual_environment_mode,
686688
):
687689
if model.enabled:
688690
models[model.fqn] = model

sqlmesh/core/model/decorator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sqlglot import exp
99
from sqlglot.dialects.dialect import DialectType
1010

11+
from sqlmesh.core.config.common import VirtualEnvironmentMode
1112
from sqlmesh.core.macros import MacroRegistry
1213
from sqlmesh.core.signal import SignalRegistry
1314
from sqlmesh.utils.jinja import JinjaMacroRegistry
@@ -154,6 +155,7 @@ def model(
154155
variables: t.Optional[t.Dict[str, t.Any]] = None,
155156
infer_names: t.Optional[bool] = False,
156157
blueprint_variables: t.Optional[t.Dict[str, t.Any]] = None,
158+
virtual_environment_mode: VirtualEnvironmentMode = VirtualEnvironmentMode.default,
157159
) -> Model:
158160
"""Get the model registered by this function."""
159161
env: t.Dict[str, t.Tuple[t.Any, t.Optional[bool]]] = {}
@@ -228,6 +230,7 @@ def model(
228230
"audit_definitions": audit_definitions,
229231
"signal_definitions": signal_definitions,
230232
"blueprint_variables": blueprint_variables,
233+
"virtual_environment_mode": virtual_environment_mode,
231234
**rendered_fields,
232235
}
233236

sqlmesh/core/model/definition.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ def _data_hash_values(self) -> t.List[str]:
10621062
self.gateway,
10631063
self.interval_unit.value if self.interval_unit is not None else None,
10641064
str(self.optimize_query) if self.optimize_query is not None else None,
1065+
self.virtual_environment_mode.value,
10651066
]
10661067

10671068
for column_name, column_type in (self.columns_to_types_ or {}).items():
@@ -2950,6 +2951,7 @@ def render_expression(
29502951
)
29512952
),
29522953
"formatting": str,
2954+
"virtual_environment_mode": lambda value: exp.Literal.string(value.value),
29532955
}
29542956

29552957

sqlmesh/core/model/meta.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
1111

1212
from sqlmesh.core import dialect as d
13+
from sqlmesh.core.config.common import VirtualEnvironmentMode
1314
from sqlmesh.core.config.linter import LinterConfig
1415
from sqlmesh.core.dialect import normalize_model_name
1516
from sqlmesh.core.model.common import (
@@ -83,6 +84,7 @@ class ModelMeta(_Node):
8384
default=None, exclude=True, alias="ignored_rules"
8485
)
8586
formatting: t.Optional[bool] = Field(default=None, exclude=True)
87+
virtual_environment_mode: VirtualEnvironmentMode = VirtualEnvironmentMode.default
8688

8789
_bool_validator = bool_validator
8890
_model_kind_validator = model_kind_validator

sqlmesh/core/plan/builder.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ def _is_forward_only_change(self, s_id: SnapshotId) -> bool:
773773
if snapshot.name in self._context_diff.modified_snapshots:
774774
_, old = self._context_diff.modified_snapshots[snapshot.name]
775775
# If the model kind has changed in a breaking way, then we can't consider this to be a forward-only change.
776-
if snapshot.is_model and _is_breaking_kind_change(old, snapshot):
776+
if snapshot.is_model and _should_force_breaking_change(old, snapshot):
777777
return False
778778
return (
779779
snapshot.is_model and snapshot.model.forward_only and bool(snapshot.previous_versions)
@@ -888,7 +888,10 @@ def _modified_and_added_snapshots(self) -> t.List[Snapshot]:
888888
]
889889

890890

891-
def _is_breaking_kind_change(old: Snapshot, new: Snapshot) -> bool:
891+
def _should_force_breaking_change(old: Snapshot, new: Snapshot) -> bool:
892+
if old.virtual_environment_mode != new.virtual_environment_mode:
893+
# If the virtual environment mode has changed, then it's a breaking change
894+
return True
892895
if old.model.kind.name == new.model.kind.name:
893896
# If the kind hasn't changed, then it's not a breaking change
894897
return False

sqlmesh/core/snapshot/definition.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ class SnapshotInfoMixin(ModelKindMixin):
339339
dev_table_suffix: str
340340
table_naming_convention: TableNamingConvention = Field(default=TableNamingConvention.default)
341341
forward_only: bool
342-
virtual_environment_mode: VirtualEnvironmentMode
343342

344343
@cached_property
345344
def identifier(self) -> str:
@@ -385,6 +384,10 @@ def is_new_version(self) -> bool:
385384
def fully_qualified_table(self) -> t.Optional[exp.Table]:
386385
raise NotImplementedError
387386

387+
@property
388+
def virtual_environment_mode(self) -> VirtualEnvironmentMode:
389+
raise NotImplementedError
390+
388391
@property
389392
def is_forward_only(self) -> bool:
390393
return self.forward_only or self.change_category == SnapshotChangeCategory.FORWARD_ONLY
@@ -506,8 +509,10 @@ class SnapshotTableInfo(PydanticModel, SnapshotInfoMixin, frozen=True):
506509
dev_table_suffix: str
507510
model_gateway: t.Optional[str] = None
508511
forward_only: bool = False
509-
table_naming_convention: TableNamingConvention = Field(default=TableNamingConvention.default)
510-
virtual_environment_mode: VirtualEnvironmentMode = Field(default=VirtualEnvironmentMode.default)
512+
table_naming_convention: TableNamingConvention = TableNamingConvention.default
513+
virtual_environment_mode_: VirtualEnvironmentMode = Field(
514+
default=VirtualEnvironmentMode.default, alias="virtual_environment_mode"
515+
)
511516

512517
def __lt__(self, other: SnapshotTableInfo) -> bool:
513518
return self.name < other.name
@@ -539,6 +544,10 @@ def table_info(self) -> SnapshotTableInfo:
539544
"""Helper method to return self."""
540545
return self
541546

547+
@property
548+
def virtual_environment_mode(self) -> VirtualEnvironmentMode:
549+
return self.virtual_environment_mode_
550+
542551
@property
543552
def data_version(self) -> SnapshotDataVersion:
544553
return SnapshotDataVersion(
@@ -637,7 +646,6 @@ class Snapshot(PydanticModel, SnapshotInfoMixin):
637646
default=TableNamingConvention.default, alias="table_naming_convention"
638647
)
639648
forward_only: bool = False
640-
virtual_environment_mode: VirtualEnvironmentMode = Field(default=VirtualEnvironmentMode.default)
641649

642650
@field_validator("ttl")
643651
@classmethod
@@ -690,7 +698,6 @@ def from_node(
690698
version: t.Optional[str] = None,
691699
cache: t.Optional[t.Dict[str, SnapshotFingerprint]] = None,
692700
table_naming_convention: TableNamingConvention = TableNamingConvention.default,
693-
virtual_environment_mode: VirtualEnvironmentMode = VirtualEnvironmentMode.default,
694701
) -> Snapshot:
695702
"""Creates a new snapshot for a node.
696703
@@ -702,7 +709,6 @@ def from_node(
702709
version: The version that a snapshot is associated with. Usually set during the planning phase.
703710
cache: Cache of node name to fingerprints.
704711
table_naming_convention: Convention to follow when generating the physical table name
705-
virtual_environment_mode: Mode for handling virtual environments
706712
707713
Returns:
708714
The newly created snapshot.
@@ -735,7 +741,6 @@ def from_node(
735741
ttl=ttl,
736742
version=version,
737743
table_naming_convention=table_naming_convention,
738-
virtual_environment_mode=virtual_environment_mode,
739744
)
740745

741746
def __eq__(self, other: t.Any) -> bool:
@@ -1418,6 +1423,12 @@ def custom_materialization(self) -> t.Optional[str]:
14181423
return t.cast(CustomKind, self.model.kind).materialization
14191424
return None
14201425

1426+
@property
1427+
def virtual_environment_mode(self) -> VirtualEnvironmentMode:
1428+
return (
1429+
self.model.virtual_environment_mode if self.is_model else VirtualEnvironmentMode.default
1430+
)
1431+
14211432
def _ensure_categorized(self) -> None:
14221433
if not self.change_category:
14231434
raise SQLMeshError(f"Snapshot {self.snapshot_id} has not been categorized yet.")

tests/core/test_model.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,8 @@ def test_render_definition_with_defaults():
19081908
dialect spark,
19091909
kind VIEW (
19101910
materialized FALSE
1911-
)
1911+
),
1912+
virtual_environment_mode 'full'
19121913
);
19131914
19141915
{query}
@@ -5731,7 +5732,7 @@ def test_default_catalog_sql(assert_exp_eq):
57315732
The system is not designed to actually support having an engine that doesn't support default catalog
57325733
to start supporting it or the reverse of that. If that did happen then bugs would occur.
57335734
"""
5734-
HASH_WITH_CATALOG = "516937963"
5735+
HASH_WITH_CATALOG = "1269513823"
57355736

57365737
# Test setting default catalog doesn't change hash if it matches existing logic
57375738
expressions = d.parse(
@@ -5897,7 +5898,7 @@ def test_default_catalog_sql(assert_exp_eq):
58975898

58985899

58995900
def test_default_catalog_python():
5900-
HASH_WITH_CATALOG = "770057346"
5901+
HASH_WITH_CATALOG = "2728996410"
59015902

59025903
@model(name="db.table", kind="full", columns={'"COL"': "int"})
59035904
def my_model(context, **kwargs):
@@ -5989,7 +5990,7 @@ def test_default_catalog_external_model():
59895990
Since external models fqns are the only thing affected by default catalog, and when they change new snapshots
59905991
are made, the hash will be the same across different names.
59915992
"""
5992-
EXPECTED_HASH = "3614876346"
5993+
EXPECTED_HASH = "763256265"
59935994

59945995
model = create_external_model("db.table", columns={"a": "int", "limit": "int"})
59955996
assert model.default_catalog is None

tests/core/test_plan_stages.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,19 +1312,19 @@ def test_build_plan_stages_virtual_environment_mode_filtering(
13121312
name="full_model",
13131313
query=parse_one("select 1, ds"),
13141314
kind=dict(name=ModelKindName.INCREMENTAL_BY_TIME_RANGE, time_column="ds"),
1315+
virtual_environment_mode=VirtualEnvironmentMode.FULL,
13151316
)
13161317
)
1317-
snapshot_full.virtual_environment_mode = VirtualEnvironmentMode.FULL
13181318
snapshot_full.categorize_as(SnapshotChangeCategory.BREAKING)
13191319

13201320
snapshot_dev_only = make_snapshot(
13211321
SqlModel(
13221322
name="dev_only_model",
13231323
query=parse_one("select 2, ds"),
13241324
kind=dict(name=ModelKindName.INCREMENTAL_BY_TIME_RANGE, time_column="ds"),
1325+
virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY,
13251326
)
13261327
)
1327-
snapshot_dev_only.virtual_environment_mode = VirtualEnvironmentMode.DEV_ONLY
13281328
snapshot_dev_only.categorize_as(SnapshotChangeCategory.BREAKING)
13291329

13301330
# Mock state reader
@@ -1506,9 +1506,9 @@ def test_build_plan_stages_virtual_environment_mode_no_updates(
15061506
name="dev_only_model",
15071507
query=parse_one("select 1, ds"),
15081508
kind=dict(name=ModelKindName.INCREMENTAL_BY_TIME_RANGE, time_column="ds"),
1509+
virtual_environment_mode=VirtualEnvironmentMode.DEV_ONLY,
15091510
)
15101511
)
1511-
snapshot_dev_only.virtual_environment_mode = VirtualEnvironmentMode.DEV_ONLY
15121512
snapshot_dev_only.categorize_as(SnapshotChangeCategory.BREAKING)
15131513

15141514
# Mock state reader

0 commit comments

Comments
 (0)