2222from sqlmesh .utils .metaprogramming import (
2323 Executable ,
2424 ExecutableKind ,
25+ _deterministic_repr ,
2526 build_env ,
2627 func_globals ,
2728 normalize_source ,
@@ -48,7 +49,7 @@ def test_print_exception(mocker: MockerFixture):
4849 except Exception as ex :
4950 print_exception (ex , test_env , out_mock )
5051
51- expected_message = r""" File ".*?.tests.utils.test_metaprogramming\.py", line 47 , in test_print_exception
52+ expected_message = r""" File ".*?.tests.utils.test_metaprogramming\.py", line 48 , in test_print_exception
5253 eval\("test_fun\(\)", env\).*
5354
5455 File '/test/path.py' \(or imported file\), line 2, in test_fun
@@ -457,3 +458,162 @@ def test_serialize_env_with_enum_import_appearing_in_two_functions() -> None:
457458 }
458459
459460 assert serialized_env == expected_env
461+
462+
463+ def test_deterministic_repr_basic_types ():
464+ """Test _deterministic_repr with basic Python types."""
465+ # Test basic types that should use standard repr
466+ assert _deterministic_repr (42 ) == "42"
467+ assert _deterministic_repr ("hello" ) == "'hello'"
468+ assert _deterministic_repr (True ) == "True"
469+ assert _deterministic_repr (None ) == "None"
470+ assert _deterministic_repr (3.14 ) == "3.14"
471+
472+
473+ def test_deterministic_repr_dict_ordering ():
474+ """Test that _deterministic_repr produces consistent output for dicts with different key ordering."""
475+ # Same dict with different key ordering
476+ dict1 = {"c" : 3 , "a" : 1 , "b" : 2 }
477+ dict2 = {"a" : 1 , "b" : 2 , "c" : 3 }
478+ dict3 = {"b" : 2 , "c" : 3 , "a" : 1 }
479+
480+ repr1 = _deterministic_repr (dict1 )
481+ repr2 = _deterministic_repr (dict2 )
482+ repr3 = _deterministic_repr (dict3 )
483+
484+ # All should produce the same representation
485+ assert repr1 == repr2 == repr3
486+ assert repr1 == "{'a': 1, 'b': 2, 'c': 3}"
487+
488+
489+ def test_deterministic_repr_mixed_key_types ():
490+ """Test _deterministic_repr with mixed key types (strings and numbers)."""
491+ dict1 = {42 : "number" , "string" : "text" , 1 : "one" }
492+ dict2 = {"string" : "text" , 1 : "one" , 42 : "number" }
493+
494+ repr1 = _deterministic_repr (dict1 )
495+ repr2 = _deterministic_repr (dict2 )
496+
497+ # Should produce consistent ordering despite mixed key types
498+ assert repr1 == repr2
499+ # Numbers come before strings when sorting by string representation
500+ assert repr1 == "{1: 'one', 42: 'number', 'string': 'text'}"
501+
502+
503+ def test_deterministic_repr_nested_structures ():
504+ """Test _deterministic_repr with deeply nested dictionaries."""
505+ nested1 = {"outer" : {"z" : 26 , "a" : 1 }, "list" : [3 , {"y" : 2 , "x" : 1 }], "simple" : "value" }
506+
507+ nested2 = {"simple" : "value" , "list" : [3 , {"x" : 1 , "y" : 2 }], "outer" : {"a" : 1 , "z" : 26 }}
508+
509+ repr1 = _deterministic_repr (nested1 )
510+ repr2 = _deterministic_repr (nested2 )
511+
512+ assert repr1 == repr2
513+ # Verify structure is maintained with sorted keys
514+ expected = "{'list': [3, {'x': 1, 'y': 2}], 'outer': {'a': 1, 'z': 26}, 'simple': 'value'}"
515+ assert repr1 == expected
516+
517+
518+ def test_deterministic_repr_lists_and_tuples ():
519+ """Test _deterministic_repr preserves order for lists/tuples but sorts nested dicts."""
520+ # Lists should maintain their order
521+ list_with_dicts = [{"b" : 2 , "a" : 1 }, {"d" : 4 , "c" : 3 }]
522+ list_repr = _deterministic_repr (list_with_dicts )
523+ expected_list = "[{'a': 1, 'b': 2}, {'c': 3, 'd': 4}]"
524+ assert list_repr == expected_list
525+
526+ # Tuples should maintain their order
527+ tuple_with_dicts = ({"z" : 26 , "a" : 1 }, {"y" : 25 , "b" : 2 })
528+ tuple_repr = _deterministic_repr (tuple_with_dicts )
529+ expected_tuple = "({'a': 1, 'z': 26}, {'b': 2, 'y': 25})"
530+ assert tuple_repr == expected_tuple
531+
532+
533+ def test_deterministic_repr_empty_containers ():
534+ """Test _deterministic_repr with empty containers."""
535+ assert _deterministic_repr ({}) == "{}"
536+ assert _deterministic_repr ([]) == "[]"
537+ assert _deterministic_repr (()) == "()"
538+
539+
540+ def test_deterministic_repr_special_characters ():
541+ """Test _deterministic_repr handles special characters correctly."""
542+ special_dict = {
543+ "quotes" : "text with 'single' and \" double\" quotes" ,
544+ "unicode" : "unicode: ñáéíóú" ,
545+ "newlines" : "text\n with\n newlines" ,
546+ "backslashes" : "path\\ to\\ file" ,
547+ }
548+
549+ result = _deterministic_repr (special_dict )
550+
551+ # Should be valid Python that can be evaluated
552+ reconstructed = eval (result )
553+ assert reconstructed == special_dict
554+
555+ # Should be deterministic - same input produces same output
556+ result2 = _deterministic_repr (special_dict )
557+ assert result == result2
558+
559+
560+ def test_deterministic_repr_executable_integration ():
561+ """Test that _deterministic_repr works correctly with Executable.value()."""
562+ # Test the integration with Executable.value which is the main use case
563+ variables1 = {"env" : "dev" , "debug" : True , "timeout" : 30 }
564+ variables2 = {"timeout" : 30 , "debug" : True , "env" : "dev" }
565+
566+ exec1 = Executable .value (variables1 )
567+ exec2 = Executable .value (variables2 )
568+
569+ # Should produce identical payloads despite different input ordering
570+ assert exec1 .payload == exec2 .payload
571+ assert exec1 .payload == "{'debug': True, 'env': 'dev', 'timeout': 30}"
572+
573+ # Should be valid Python
574+ reconstructed = eval (exec1 .payload )
575+ assert reconstructed == variables1
576+
577+
578+ def test_deterministic_repr_complex_example ():
579+ """Test _deterministic_repr with a complex real-world-like structure."""
580+ complex_vars = {
581+ "database_config" : {
582+ "host" : "localhost" ,
583+ "port" : 5432 ,
584+ "credentials" : {"username" : "admin" , "password" : "secret" },
585+ },
586+ "feature_flags" : ["flag_b" , "flag_a" ],
587+ "metadata" : {
588+ "version" : "1.0.0" ,
589+ "environment" : "production" ,
590+ "tags" : {"team" : "data" , "project" : "analytics" },
591+ },
592+ 42 : "numeric_key" ,
593+ "arrays" : [{"config" : {"nested" : True , "level" : 2 }}, {"simple" : "value" }],
594+ }
595+
596+ expected_structure = {
597+ 42 : "numeric_key" ,
598+ "arrays" : [{"config" : {"level" : 2 , "nested" : True }}, {"simple" : "value" }],
599+ "database_config" : {
600+ "credentials" : {"password" : "secret" , "username" : "admin" },
601+ "host" : "localhost" ,
602+ "port" : 5432 ,
603+ },
604+ "feature_flags" : ["flag_b" , "flag_a" ],
605+ "metadata" : {
606+ "environment" : "production" ,
607+ "tags" : {"project" : "analytics" , "team" : "data" },
608+ "version" : "1.0.0" ,
609+ },
610+ }
611+
612+ actual_repr = _deterministic_repr (complex_vars )
613+ expected_repr = repr (expected_structure )
614+ assert actual_repr == expected_repr
615+
616+ # Should be valid Python
617+ reconstructed = eval (actual_repr )
618+ assert isinstance (reconstructed , dict )
619+ assert reconstructed == complex_vars
0 commit comments