@@ -3185,6 +3185,7 @@ def test_grants_through_plan_apply(sushi_context, mocker):
31853185 from sqlmesh .core .model .meta import GrantsTargetLayer
31863186
31873187 model = sushi_context .get_model ("sushi.waiter_revenue_by_day" )
3188+
31883189 mocker .patch .object (DuckDBEngineAdapter , "SUPPORTS_GRANTS" , True )
31893190 sync_grants_mock = mocker .patch .object (DuckDBEngineAdapter , "sync_grants_config" )
31903191
@@ -3206,18 +3207,20 @@ def test_grants_through_plan_apply(sushi_context, mocker):
32063207
32073208 sync_grants_mock .reset_mock ()
32083209
3210+ new_grants = ({"select" : ["analyst" , "reporter" , "manager" ], "insert" : ["etl_user" ]},)
32093211 model_updated = model_with_grants .copy (
32103212 update = {
32113213 "query" : parse_one (model .query .sql () + " LIMIT 1000" ),
3212- "grants" : { "select" : [ "analyst" , "reporter" , "manager" ], "insert" : [ "etl_user" ]} ,
3214+ "grants" : new_grants ,
32133215 "stamp" : "update model and grants" ,
32143216 }
32153217 )
32163218 sushi_context .upsert_model (model_updated )
32173219
32183220 sushi_context .plan ("dev" , no_prompts = True , auto_apply = True )
32193221
3220- assert sync_grants_mock .call_count == 2
3221-
3222- expected_grants = {"select" : ["analyst" , "reporter" , "manager" ], "insert" : ["etl_user" ]}
3223- assert all (call [0 ][1 ] == expected_grants for call in sync_grants_mock .call_args_list )
3222+ # Applies grants 3 times:
3223+ # 2 x physical (duplicated): create, promote (will diff but won't apply since it's the same grants)
3224+ # 1 x virtual
3225+ assert sync_grants_mock .call_count == 3
3226+ assert all (call [0 ][1 ] == new_grants for call in sync_grants_mock .call_args_list )
0 commit comments