@@ -52,7 +52,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method'
5252
5353from __future__ import annotations
5454
55- from typing import Sequence , Tuple , cast
55+ from typing import Sequence , Tuple , Union , cast
5656from typing_extensions import TypeAlias as _TypeAlias
5757
5858from mypy .expandtype import expand_type
@@ -109,11 +109,17 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method'
109109# snapshots are immutable).
110110#
111111# For example, the snapshot of the 'int' type is ('Instance', 'builtins.int', ()).
112- SnapshotItem : _TypeAlias = Tuple [object , ...]
112+
113+ # Type snapshots are strict, they must be hashable and ordered (e.g. for Unions).
114+ Primitive : _TypeAlias = Union [str , float , int , bool ] # float is for Literal[3.14] support.
115+ SnapshotItem : _TypeAlias = Tuple [Union [Primitive , "SnapshotItem" ], ...]
116+
117+ # Symbol snapshots can be more lenient.
118+ SymbolSnapshot : _TypeAlias = Tuple [object , ...]
113119
114120
115121def compare_symbol_table_snapshots (
116- name_prefix : str , snapshot1 : dict [str , SnapshotItem ], snapshot2 : dict [str , SnapshotItem ]
122+ name_prefix : str , snapshot1 : dict [str , SymbolSnapshot ], snapshot2 : dict [str , SymbolSnapshot ]
117123) -> set [str ]:
118124 """Return names that are different in two snapshots of a symbol table.
119125
@@ -155,7 +161,7 @@ def compare_symbol_table_snapshots(
155161 return triggers
156162
157163
158- def snapshot_symbol_table (name_prefix : str , table : SymbolTable ) -> dict [str , SnapshotItem ]:
164+ def snapshot_symbol_table (name_prefix : str , table : SymbolTable ) -> dict [str , SymbolSnapshot ]:
159165 """Create a snapshot description that represents the state of a symbol table.
160166
161167 The snapshot has a representation based on nested tuples and dicts
@@ -165,7 +171,7 @@ def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> dict[str, Sna
165171 things defined in other modules are represented just by the names of
166172 the targets.
167173 """
168- result : dict [str , SnapshotItem ] = {}
174+ result : dict [str , SymbolSnapshot ] = {}
169175 for name , symbol in table .items ():
170176 node = symbol .node
171177 # TODO: cross_ref?
@@ -206,7 +212,7 @@ def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> dict[str, Sna
206212 return result
207213
208214
209- def snapshot_definition (node : SymbolNode | None , common : tuple [ object , ...] ) -> tuple [ object , ...] :
215+ def snapshot_definition (node : SymbolNode | None , common : SymbolSnapshot ) -> SymbolSnapshot :
210216 """Create a snapshot description of a symbol table node.
211217
212218 The representation is nested tuples and dicts. Only externally
@@ -290,11 +296,11 @@ def snapshot_type(typ: Type) -> SnapshotItem:
290296 return typ .accept (SnapshotTypeVisitor ())
291297
292298
293- def snapshot_optional_type (typ : Type | None ) -> SnapshotItem | None :
299+ def snapshot_optional_type (typ : Type | None ) -> SnapshotItem :
294300 if typ :
295301 return snapshot_type (typ )
296302 else :
297- return None
303+ return ( "<not set>" ,)
298304
299305
300306def snapshot_types (types : Sequence [Type ]) -> SnapshotItem :
@@ -396,7 +402,7 @@ def visit_parameters(self, typ: Parameters) -> SnapshotItem:
396402 "Parameters" ,
397403 snapshot_types (typ .arg_types ),
398404 tuple (encode_optional_str (name ) for name in typ .arg_names ),
399- tuple (typ .arg_kinds ),
405+ tuple (k . value for k in typ .arg_kinds ),
400406 )
401407
402408 def visit_callable_type (self , typ : CallableType ) -> SnapshotItem :
@@ -407,7 +413,7 @@ def visit_callable_type(self, typ: CallableType) -> SnapshotItem:
407413 snapshot_types (typ .arg_types ),
408414 snapshot_type (typ .ret_type ),
409415 tuple (encode_optional_str (name ) for name in typ .arg_names ),
410- tuple (typ .arg_kinds ),
416+ tuple (k . value for k in typ .arg_kinds ),
411417 typ .is_type_obj (),
412418 typ .is_ellipsis_args ,
413419 snapshot_types (typ .variables ),
@@ -464,7 +470,7 @@ def visit_type_alias_type(self, typ: TypeAliasType) -> SnapshotItem:
464470 return ("TypeAliasType" , typ .alias .fullname , snapshot_types (typ .args ))
465471
466472
467- def snapshot_untyped_signature (func : OverloadedFuncDef | FuncItem ) -> tuple [ object , ...] :
473+ def snapshot_untyped_signature (func : OverloadedFuncDef | FuncItem ) -> SymbolSnapshot :
468474 """Create a snapshot of the signature of a function that has no explicit signature.
469475
470476 If the arguments to a function without signature change, it must be
@@ -476,7 +482,7 @@ def snapshot_untyped_signature(func: OverloadedFuncDef | FuncItem) -> tuple[obje
476482 if isinstance (func , FuncItem ):
477483 return (tuple (func .arg_names ), tuple (func .arg_kinds ))
478484 else :
479- result = []
485+ result : list [ SymbolSnapshot ] = []
480486 for item in func .items :
481487 if isinstance (item , Decorator ):
482488 if item .var .type :
0 commit comments