Skip to content

Commit 0963049

Browse files
fix: treat Python model gateways as literals
Signed-off-by: Joseph Finlayson <joseph.finlayson@gmail.com>
1 parent 140651b commit 0963049

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

sqlmesh/core/model/decorator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ def models(
125125

126126
blueprints = blueprints[0]
127127

128+
gateway = self.kwargs.get("gateway")
129+
if isinstance(gateway, str) and gateway.lstrip().startswith("@"):
130+
gateway = parse_one(gateway, dialect=dialect)
131+
128132
return create_models_from_blueprints(
129-
gateway=self.kwargs.get("gateway"),
133+
gateway=gateway,
130134
blueprints=blueprints,
131135
get_variables=get_variables,
132136
loader=self.model,

sqlmesh/core/model/definition.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,9 +2071,14 @@ def create_models_from_blueprints(
20712071
loader_kwargs["default_catalog"] = original_default_catalog
20722072
blueprint_variables = _extract_blueprint_variables(blueprint, path)
20732073

2074-
if gateway:
2074+
gateway_name: t.Optional[str]
2075+
if isinstance(gateway, str):
2076+
# Python decorator gateway names are literals, not SQL expressions. In particular,
2077+
# parsing a gateway such as "secondary-gw" as SQL would interpret it as subtraction.
2078+
gateway_name = gateway.lower()
2079+
elif gateway:
20752080
rendered_gateway = render_expression(
2076-
expression=exp.maybe_parse(gateway, dialect=dialect),
2081+
expression=gateway,
20772082
module_path=module_path,
20782083
macros=loader_kwargs.get("macros"),
20792084
jinja_macros=loader_kwargs.get("jinja_macros"),

tests/core/test_model.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5039,6 +5039,38 @@ def python_model_prop(context, **kwargs):
50395039
assert m.interval_unit == IntervalUnit.QUARTER_HOUR
50405040

50415041

5042+
def test_explicit_hyphenated_gateway_python_model() -> None:
5043+
@model(
5044+
name="model_schema.python_explicit_gateway",
5045+
kind="full",
5046+
gateway="secondary-gw",
5047+
columns={"some_col": "int"},
5048+
)
5049+
def python_explicit_gateway(context, **kwargs):
5050+
yield {"some_col": 1}
5051+
5052+
requested_variable_gateways: t.List[t.Optional[str]] = []
5053+
5054+
def get_variables(gateway: t.Optional[str]) -> t.Dict[str, str]:
5055+
requested_variable_gateways.append(gateway)
5056+
return {}
5057+
5058+
loaded_models = model.get_registry()["model_schema.python_explicit_gateway"].models(
5059+
get_variables=get_variables,
5060+
module_path=Path("."),
5061+
path=Path("."),
5062+
dialect="duckdb",
5063+
defaults=ModelDefaultsConfig().dict(),
5064+
default_catalog="default_db",
5065+
default_catalog_per_gateway={"secondary-gw": "secondary_db"},
5066+
)
5067+
5068+
assert len(loaded_models) == 1
5069+
assert loaded_models[0].gateway == "secondary-gw"
5070+
assert loaded_models[0].catalog == "secondary_db"
5071+
assert requested_variable_gateways == ["secondary-gw"]
5072+
5073+
50425074
def test_model_defaults_gateway_python_model() -> None:
50435075
@model(
50445076
name="model_schema.python_gateway_default",

0 commit comments

Comments
 (0)