33from pathlib import Path
44
55from sqlmesh import Context
6+ from sqlmesh .core .config .common import VirtualEnvironmentMode
67from sqlmesh .core .model .meta import GrantsTargetLayer
78from sqlmesh .dbt .common import Dependencies
89from sqlmesh .dbt .context import DbtContext
910from sqlmesh .dbt .model import ModelConfig
10- from sqlmesh .dbt .target import PostgresConfig
11+ from sqlmesh .dbt .target import BigQueryConfig , DuckDbConfig , PostgresConfig
1112from sqlmesh .dbt .test import TestConfig
1213from sqlmesh .utils .yaml import YAML
1314
@@ -168,14 +169,7 @@ def test_load_invalid_ref_audit_constraints(
168169 assert context .snapshots [fqn ].model .audits == []
169170
170171
171- def test_model_grants_to_native_config () -> None :
172- """Test that dbt grants configuration is converted to SQLMesh native grants."""
173- from sqlmesh .dbt .context import DbtContext
174- from sqlmesh .dbt .target import DuckDbConfig
175- from sqlmesh .core .config .common import VirtualEnvironmentMode
176- from pathlib import Path
177-
178- # Create a model with grants configuration
172+ def test_model_grants_to_sqlmesh_grants_config () -> None :
179173 grants_config = {
180174 "select" : ["user1" , "user2" ],
181175 "insert" : ["admin_user" ],
@@ -203,74 +197,66 @@ def test_model_grants_to_native_config() -> None:
203197
204198
205199def test_model_grants_empty_permissions () -> None :
206- """Test that empty grants lists are filtered out in native grants."""
207- from sqlmesh .dbt .context import DbtContext
208- from sqlmesh .dbt .target import DuckDbConfig
209- from sqlmesh .core .config .common import VirtualEnvironmentMode
210- from pathlib import Path
211-
212- # Create a model with empty grants lists (should be filtered out)
213200 model_config = ModelConfig (
214201 name = "test_model_empty" ,
215202 sql = "SELECT 1 as id" ,
216- grants = {"select" : [], "insert" : ["admin_user" ]}, # select empty, insert granted
203+ grants = {"select" : [], "insert" : ["admin_user" ]},
217204 path = Path ("test_model_empty.sql" ),
218205 )
219206
220- # Create minimal context for conversion with proper target setup
221207 context = DbtContext ()
222208 context .project_name = "test_project"
223209 context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
224210
225- # Convert to SQLMesh model
226211 sqlmesh_model = model_config .to_sqlmesh (
227212 context , virtual_environment_mode = VirtualEnvironmentMode .FULL
228213 )
229214
230- # Verify that only non-empty grants are preserved
231215 model_grants = sqlmesh_model .grants
232- expected_grants = {"insert" : ["admin_user" ]} # select should be filtered out
216+ expected_grants = {"insert" : ["admin_user" ]}
233217 assert model_grants == expected_grants
234218
235219
236220def test_model_no_grants () -> None :
237- """Test that models without grants don't generate grant post_statements."""
238- from sqlmesh .dbt .context import DbtContext
239- from sqlmesh .dbt .target import DuckDbConfig
240- from sqlmesh .core .config .common import VirtualEnvironmentMode
241- from pathlib import Path
242-
243- # Create a model without grants
244221 model_config = ModelConfig (
245222 name = "test_model_no_grants" ,
246223 sql = "SELECT 1 as id" ,
247- grants = {}, # No grants
248224 path = Path ("test_model_no_grants.sql" ),
249225 )
250226
251- # Create minimal context for conversion with proper target setup
252227 context = DbtContext ()
253228 context .project_name = "test_project"
254229 context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
255230
256- # Convert to SQLMesh model
257231 sqlmesh_model = model_config .to_sqlmesh (
258232 context , virtual_environment_mode = VirtualEnvironmentMode .FULL
259233 )
260234
261- # Verify that no grants configuration is set
262235 grants_config = sqlmesh_model .grants
263236 assert grants_config is None
264237
265238
266- def test_model_grants_valid_special_characters () -> None :
267- """Test that valid special characters in grantee names are accepted."""
268- from sqlmesh .dbt .context import DbtContext
269- from sqlmesh .dbt .target import DuckDbConfig
270- from sqlmesh .core .config .common import VirtualEnvironmentMode
271- from pathlib import Path
239+ def test_model_empty_grants () -> None :
240+ model_config = ModelConfig (
241+ name = "test_model_empty_grants" ,
242+ sql = "SELECT 1 as id" ,
243+ grants = {},
244+ path = Path ("test_model_empty_grants.sql" ),
245+ )
246+
247+ context = DbtContext ()
248+ context .project_name = "test_project"
249+ context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
250+
251+ sqlmesh_model = model_config .to_sqlmesh (
252+ context , virtual_environment_mode = VirtualEnvironmentMode .FULL
253+ )
272254
273- # Test various valid grantee formats
255+ grants_config = sqlmesh_model .grants
256+ assert grants_config == {}
257+
258+
259+ def test_model_grants_valid_special_characters () -> None :
274260 valid_grantees = [
275261 "user@domain.com" ,
276262 "service-account@project.iam.gserviceaccount.com" ,
@@ -292,35 +278,29 @@ def test_model_grants_valid_special_characters() -> None:
292278 context .project_name = "test_project"
293279 context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
294280
295- # Should not raise any errors
296281 sqlmesh_model = model_config .to_sqlmesh (
297282 context , virtual_environment_mode = VirtualEnvironmentMode .FULL
298283 )
299284
300- # Verify that native grants configuration contains all grantees
301285 grants_config = sqlmesh_model .grants
302286 assert grants_config is not None
303287 assert "select" in grants_config
304288 assert grants_config ["select" ] == valid_grantees
305289
306290
307291def test_model_grants_engine_specific_bigquery () -> None :
308- """Test BigQuery-specific grant syntax."""
309- from sqlmesh .dbt .context import DbtContext
310- from sqlmesh .dbt .target import BigQueryConfig
311- from sqlmesh .core .config .common import VirtualEnvironmentMode
312- from pathlib import Path
313-
314292 model_config = ModelConfig (
315293 name = "test_model_bigquery" ,
316294 sql = "SELECT 1 as id" ,
317- grants = {"bigquery.dataviewer" : ["user@domain.com" ], "select" : ["analyst@company.com" ]},
295+ grants = {
296+ "bigquery.dataviewer" : ["user@domain.com" ],
297+ "select" : ["analyst@company.com" ],
298+ },
318299 path = Path ("test_model.sql" ),
319300 )
320301
321302 context = DbtContext ()
322303 context .project_name = "test_project"
323- # Create a BigQuery target
324304 context .target = BigQueryConfig (
325305 name = "bigquery_target" ,
326306 project = "test-project" ,
@@ -334,115 +314,7 @@ def test_model_grants_engine_specific_bigquery() -> None:
334314 context , virtual_environment_mode = VirtualEnvironmentMode .FULL
335315 )
336316
337- # Verify that native grants configuration contains BigQuery permissions
338317 grants_config = sqlmesh_model .grants
339318 assert grants_config is not None
340319 assert grants_config ["bigquery.dataviewer" ] == ["user@domain.com" ]
341320 assert grants_config ["select" ] == ["analyst@company.com" ]
342-
343-
344- def test_model_grants_engine_specific_snowflake () -> None :
345- """Test Snowflake-specific grant syntax."""
346- from sqlmesh .dbt .context import DbtContext
347- from sqlmesh .dbt .target import SnowflakeConfig
348- from sqlmesh .core .config .common import VirtualEnvironmentMode
349- from pathlib import Path
350-
351- model_config = ModelConfig (
352- name = "test_model_snowflake" ,
353- sql = "SELECT 1 as id" ,
354- grants = {"select" : ["role1" ], "all" : ["admin_role" ]},
355- path = Path ("test_model.sql" ),
356- )
357-
358- context = DbtContext ()
359- context .project_name = "test_project"
360- # Create a Snowflake target
361- context .target = SnowflakeConfig (
362- name = "snowflake_target" ,
363- account = "test_account" ,
364- warehouse = "test_warehouse" ,
365- database = "test_db" ,
366- schema = "test_schema" ,
367- user = "test_user" ,
368- password = "test_password" , # Add required authentication
369- )
370-
371- sqlmesh_model = model_config .to_sqlmesh (
372- context , virtual_environment_mode = VirtualEnvironmentMode .FULL
373- )
374-
375- # Verify that native grants configuration contains Snowflake permissions
376- grants_config = sqlmesh_model .grants
377- assert grants_config is not None
378- assert grants_config ["select" ] == ["role1" ]
379- assert grants_config ["all" ] == ["admin_role" ]
380-
381-
382- def test_model_grants_project_level_inheritance () -> None :
383- """Test that grants from dbt_project.yml are inherited by models."""
384- from sqlmesh .dbt .context import DbtContext
385- from sqlmesh .dbt .target import DuckDbConfig
386- from sqlmesh .core .config .common import VirtualEnvironmentMode
387- from pathlib import Path
388-
389- # Test model with project-level grants inheritance
390- # Simulate what would happen when dbt processes grants from dbt_project.yml
391- model_config = ModelConfig (
392- name = "test_model_inheritance" ,
393- sql = "SELECT 1 as id" ,
394- # This simulates grants that come from dbt_project.yml (+grants) being merged
395- # with model-specific grants through SQLMesh's KEY_EXTEND strategy
396- grants = {"select" : ["project_user" ], "insert" : ["model_user" ]}, # project + model merged
397- path = Path ("test_model.sql" ),
398- )
399-
400- context = DbtContext ()
401- context .project_name = "test_project"
402- context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
403-
404- sqlmesh_model = model_config .to_sqlmesh (
405- context , virtual_environment_mode = VirtualEnvironmentMode .FULL
406- )
407-
408- # Verify both project-level and model-level grants were processed in native grants
409- grants_config = sqlmesh_model .grants
410- assert grants_config is not None
411- assert grants_config ["select" ] == ["project_user" ]
412- assert grants_config ["insert" ] == ["model_user" ]
413-
414-
415- def test_model_grants_additive_syntax () -> None :
416- """Test that additive grants (+prefix) work correctly."""
417- from sqlmesh .dbt .context import DbtContext
418- from sqlmesh .dbt .target import DuckDbConfig
419- from sqlmesh .core .config .common import VirtualEnvironmentMode
420- from pathlib import Path
421-
422- # Test model that would receive +grants from dbt_project.yml
423- # This simulates the result after dbt processes +grants syntax
424- model_config = ModelConfig (
425- name = "test_model_additive" ,
426- sql = "SELECT 1 as id" ,
427- # This simulates what the final grants dict looks like after dbt processes
428- # +grants from dbt_project.yml and merges with model grants
429- grants = {
430- "select" : ["base_user" , "additional_user" ], # base + additive merged
431- "insert" : ["admin_user" ], # model-specific
432- },
433- path = Path ("test_model.sql" ),
434- )
435-
436- context = DbtContext ()
437- context .project_name = "test_project"
438- context .target = DuckDbConfig (name = "target" , schema = "test_schema" )
439-
440- sqlmesh_model = model_config .to_sqlmesh (
441- context , virtual_environment_mode = VirtualEnvironmentMode .FULL
442- )
443-
444- # Verify that native grants configuration contains all merged grants
445- grants_config = sqlmesh_model .grants
446- assert grants_config is not None
447- assert grants_config ["select" ] == ["base_user" , "additional_user" ]
448- assert grants_config ["insert" ] == ["admin_user" ]
0 commit comments