33and therefore this migration applies deterministic sorting to the keys of the dictionary.
44"""
55
6- import ast
76import json
87import typing as t
8+ from dataclasses import dataclass
99
1010from sqlglot import exp
1111
1212from sqlmesh .utils .migration import index_text_type , blob_text_type
1313
1414
15+ # Make sure `SqlValue` is defined so it can be used by `eval` call in the migration
16+ @dataclass
17+ class SqlValue :
18+ """A SQL string representing a generated SQLGlot AST."""
19+
20+ sql : str
21+
22+
1523def _deterministic_repr (obj : t .Any ) -> str :
1624 """
1725 This is a copy of the function from utils.metaprogramming
@@ -27,7 +35,10 @@ def _normalize_for_repr(o: t.Any) -> t.Any:
2735 return type (o )(normalized )
2836 return o
2937
30- return repr (_normalize_for_repr (obj ))
38+ try :
39+ return repr (_normalize_for_repr (obj ))
40+ except Exception :
41+ return repr (obj )
3142
3243
3344def migrate (state_sync , ** kwargs ): # type: ignore
@@ -75,33 +86,16 @@ def migrate(state_sync, **kwargs): # type: ignore
7586 old_payload = executable ["payload" ]
7687 try :
7788 # Try to parse the old payload and re-serialize it deterministically
78- parsed_value = ast . literal_eval (old_payload )
89+ parsed_value = eval (old_payload )
7990 new_payload = _deterministic_repr (parsed_value )
8091
8192 # Only update if the representation changed
8293 if old_payload != new_payload :
8394 executable ["payload" ] = new_payload
8495 migration_needed = True
85- except (ValueError , SyntaxError ):
86- # Special handling for dictionaries containing SqlValue objects
87- # These can't be parsed by ast.literal_eval but we can still make them deterministic
88- if old_payload .startswith ("{" ) and "SqlValue(" in old_payload :
89- try :
90- # Use eval in a safe context to parse SqlValue objects
91- # This is safe because we're only running this on our own serialized data
92- from sqlmesh .utils .metaprogramming import SqlValue
93-
94- safe_globals = {"SqlValue" : SqlValue }
95- parsed_value = eval (old_payload , safe_globals , {})
96- new_payload = _deterministic_repr (parsed_value )
97-
98- # Only update if the representation changed
99- if old_payload != new_payload :
100- executable ["payload" ] = new_payload
101- migration_needed = True
102- except (ValueError , SyntaxError , NameError ):
103- # If we still can't parse it, leave it as-is
104- pass
96+ except Exception :
97+ # If we still can't eval it, leave it as-is
98+ pass
10599
106100 new_snapshots .append (
107101 {
0 commit comments