@@ -8405,6 +8405,141 @@ def test_blueprinting_with_quotes(tmp_path: Path) -> None:
84058405 assert t .cast (exp .Query , m2 .render_query ()).sql () == '''SELECT 'c d' AS "c1", "c d" AS "c2"'''
84068406
84078407
8408+ def test_blueprint_variable_precedence_sql (tmp_path : Path , assert_exp_eq : t .Callable ) -> None :
8409+ init_example_project (tmp_path , dialect = "duckdb" , template = ProjectTemplate .EMPTY )
8410+
8411+ blueprint_variables = tmp_path / "models/blueprint_variables.sql"
8412+ blueprint_variables .parent .mkdir (parents = True , exist_ok = True )
8413+ blueprint_variables .write_text (
8414+ """
8415+ MODEL (
8416+ name s.@{bp_name},
8417+ blueprints (
8418+ (bp_name := m1, var1 := 'v1', var2 := 'v2'),
8419+ (bp_name := m2, var1 := 'v3'),
8420+ ),
8421+ );
8422+
8423+ @DEF(bp_name, override);
8424+
8425+ SELECT
8426+ @var1 AS var1_macro_var,
8427+ @{var1} AS var1_identifier,
8428+ @VAR('var1') AS var1_var_macro_func,
8429+ @BLUEPRINT_VAR('var1') AS var1_blueprint_var_macro_func,
8430+
8431+ @var2 AS var2_macro_var,
8432+ @{var2} AS var2_identifier,
8433+ @VAR('var2') AS var2_var_macro_func,
8434+ @BLUEPRINT_VAR('var2') AS var2_blueprint_var_macro_func,
8435+
8436+ @bp_name AS bp_name_macro_var,
8437+ @{bp_name} AS bp_name_identifier,
8438+ @VAR('bp_name') AS bp_name_var_macro_func,
8439+ @BLUEPRINT_VAR('bp_name') AS bp_name_blueprint_var_macro_func,
8440+ """
8441+ )
8442+
8443+ ctx = Context (
8444+ config = Config (
8445+ model_defaults = ModelDefaultsConfig (dialect = "duckdb" ),
8446+ variables = {"var2" : "1" },
8447+ ),
8448+ paths = tmp_path ,
8449+ )
8450+ assert len (ctx .models ) == 2
8451+
8452+ m1 = ctx .get_model ("s.m1" , raise_if_missing = True )
8453+ m2 = ctx .get_model ("s.m2" , raise_if_missing = True )
8454+
8455+ assert_exp_eq (
8456+ m1 .render_query (),
8457+ """
8458+ SELECT
8459+ 'v1' AS "var1_macro_var",
8460+ "v1" AS "var1_identifier",
8461+ NULL AS "var1_var_macro_func",
8462+ 'v1' AS "var1_blueprint_var_macro_func",
8463+ 'v2' AS "var2_macro_var",
8464+ "v2" AS "var2_identifier",
8465+ '1' AS "var2_var_macro_func",
8466+ 'v2' AS "var2_blueprint_var_macro_func",
8467+ "override" AS "bp_name_macro_var",
8468+ "override" AS "bp_name_identifier",
8469+ NULL AS "bp_name_var_macro_func",
8470+ "m1" AS "bp_name_blueprint_var_macro_func"
8471+ """ ,
8472+ )
8473+ assert_exp_eq (
8474+ m2 .render_query (),
8475+ """
8476+ SELECT
8477+ 'v3' AS "var1_macro_var",
8478+ "v3" AS "var1_identifier",
8479+ NULL AS "var1_var_macro_func",
8480+ 'v3' AS "var1_blueprint_var_macro_func",
8481+ '1' AS "var2_macro_var",
8482+ "1" AS "var2_identifier",
8483+ '1' AS "var2_var_macro_func",
8484+ NULL AS "var2_blueprint_var_macro_func",
8485+ "override" AS "bp_name_macro_var",
8486+ "override" AS "bp_name_identifier",
8487+ NULL AS "bp_name_var_macro_func",
8488+ "m2" AS "bp_name_blueprint_var_macro_func"
8489+ """ ,
8490+ )
8491+
8492+
8493+ def test_blueprint_variable_precedence_python (tmp_path : Path , mocker : MockerFixture ) -> None :
8494+ init_example_project (tmp_path , dialect = "duckdb" , template = ProjectTemplate .EMPTY )
8495+
8496+ blueprint_variables = tmp_path / "models/blueprint_variables.py"
8497+ blueprint_variables .parent .mkdir (parents = True , exist_ok = True )
8498+ blueprint_variables .write_text (
8499+ """
8500+ import pandas as pd
8501+ from sqlglot import exp
8502+ from sqlmesh import model
8503+
8504+
8505+ @model(
8506+ "s.@{bp_name}",
8507+ blueprints=[{"bp_name": "m", "var1": exp.to_column("v1"), "var2": 1}],
8508+ kind="FULL",
8509+ columns={"x": "INT"},
8510+ )
8511+ def entrypoint(context, *args, **kwargs):
8512+ assert "bp_name" not in kwargs
8513+ assert "var1" not in kwargs
8514+ assert kwargs.get("var2") == "1"
8515+
8516+ assert context.var("bp_name") is None
8517+ assert context.var("var1") is None
8518+ assert context.var("var2") == "1"
8519+
8520+ assert context.blueprint_var("bp_name") == "m"
8521+ assert context.blueprint_var("var1") == exp.to_column("v1")
8522+ assert context.blueprint_var("var2") == 1
8523+
8524+ return pd.DataFrame({"x": [1]})
8525+ """
8526+ )
8527+
8528+ ctx = Context (
8529+ config = Config (
8530+ model_defaults = ModelDefaultsConfig (dialect = "duckdb" ),
8531+ variables = {"var2" : "1" },
8532+ ),
8533+ paths = tmp_path ,
8534+ )
8535+ assert len (ctx .models ) == 1
8536+
8537+ m = ctx .get_model ("s.m" , raise_if_missing = True )
8538+ context = ExecutionContext (mocker .Mock (), {}, None , None )
8539+
8540+ assert list (m .render (context = context ))[0 ].to_dict () == {"x" : {0 : 1 }}
8541+
8542+
84088543@time_machine .travel ("2020-01-01 00:00:00 UTC" )
84098544def test_dynamic_date_spine_model (assert_exp_eq ):
84108545 @macro ()
0 commit comments