14
14
from inline_snapshot ._adapter .adapter import adapter_map
15
15
from inline_snapshot ._source_file import SourceFile
16
16
17
+ from ._adapter .adapter import AdapterContext
18
+ from ._adapter .adapter import FrameContext
17
19
from ._adapter .adapter import get_adapter_type
18
20
from ._change import CallArg
19
21
from ._change import Change
@@ -83,12 +85,17 @@ class GenericValue(Snapshot):
83
85
_old_value : Any
84
86
_current_op = "undefined"
85
87
_ast_node : ast .Expr
86
- _file : SourceFile
88
+ _context : AdapterContext
89
+
90
+ @property
91
+ def _file (self ):
92
+ return self ._context .file
87
93
88
94
def get_adapter (self , value ):
89
- return get_adapter_type (value )(self ._file )
95
+ return get_adapter_type (value )(self ._context )
90
96
91
- def _re_eval (self , value ):
97
+ def _re_eval (self , value , context : AdapterContext ):
98
+ self ._context = context
92
99
93
100
def re_eval (old_value , node , value ):
94
101
if isinstance (old_value , Unmanaged ):
@@ -168,13 +175,13 @@ def __getitem__(self, _item):
168
175
169
176
170
177
class UndecidedValue (GenericValue ):
171
- def __init__ (self , old_value , ast_node , source ):
178
+ def __init__ (self , old_value , ast_node , context : AdapterContext ):
172
179
173
180
old_value = adapter_map (old_value , map_unmanaged )
174
181
self ._old_value = old_value
175
182
self ._new_value = undefined
176
183
self ._ast_node = ast_node
177
- self ._file = SourceFile ( source )
184
+ self ._context = context
178
185
179
186
def _change (self , cls ):
180
187
self .__class__ = cls
@@ -186,7 +193,7 @@ def _get_changes(self) -> Iterator[Change]:
186
193
187
194
def handle (node , obj ):
188
195
189
- adapter = self . get_adapter (obj )
196
+ adapter = get_adapter_type (obj )
190
197
if adapter is not None and hasattr (adapter , "items" ):
191
198
for item in adapter .items (obj , node ):
192
199
yield from handle (item .node , item .value )
@@ -259,7 +266,12 @@ def __eq__(self, other):
259
266
_missing_values += 1
260
267
261
268
if not compare_only () and self ._new_value is undefined :
262
- adapter = Adapter (self ._file ).get_adapter (self ._old_value , other )
269
+ frame = inspect .currentframe ()
270
+ assert frame is not None
271
+ frame = frame .f_back
272
+ assert frame is not None
273
+
274
+ adapter = Adapter (self ._context ).get_adapter (self ._old_value , other )
263
275
it = iter (adapter .assign (self ._old_value , self ._ast_node , clone (other )))
264
276
self ._changes = []
265
277
while True :
@@ -473,18 +485,18 @@ def __getitem__(self, index):
473
485
child_node = self ._ast_node .values [pos ]
474
486
475
487
self ._new_value [index ] = UndecidedValue (
476
- old_value .get (index , undefined ), child_node , self ._file
488
+ old_value .get (index , undefined ), child_node , self ._context
477
489
)
478
490
479
491
return self ._new_value [index ]
480
492
481
- def _re_eval (self , value ):
482
- super ()._re_eval (value )
493
+ def _re_eval (self , value , context : AdapterContext ):
494
+ super ()._re_eval (value , context )
483
495
484
496
if self ._new_value is not undefined and self ._old_value is not undefined :
485
497
for key , s in self ._new_value .items ():
486
498
if key in self ._old_value :
487
- s ._re_eval (self ._old_value [key ])
499
+ s ._re_eval (self ._old_value [key ], context )
488
500
489
501
def _new_code (self ):
490
502
return (
@@ -594,6 +606,12 @@ def snapshot(obj: Any = undefined) -> Any:
594
606
595
607
expr = Source .executing (frame )
596
608
609
+ source = getattr (expr , "source" , None ) if expr is not None else None
610
+ context = AdapterContext (
611
+ file = SourceFile (source ),
612
+ frame = FrameContext (globals = frame .f_globals , locals = frame .f_locals ),
613
+ )
614
+
597
615
module = inspect .getmodule (frame )
598
616
if module is not None and module .__file__ is not None :
599
617
_files_with_snapshots .add (module .__file__ )
@@ -604,12 +622,12 @@ def snapshot(obj: Any = undefined) -> Any:
604
622
node = expr .node
605
623
if node is None :
606
624
# we can run without knowing of the calling expression but we will not be able to fix code
607
- snapshots [key ] = SnapshotReference (obj , None )
625
+ snapshots [key ] = SnapshotReference (obj , None , context )
608
626
else :
609
627
assert isinstance (node , ast .Call )
610
- snapshots [key ] = SnapshotReference (obj , expr )
628
+ snapshots [key ] = SnapshotReference (obj , expr , context )
611
629
else :
612
- snapshots [key ]._re_eval (obj )
630
+ snapshots [key ]._re_eval (obj , context )
613
631
614
632
return snapshots [key ]._value
615
633
@@ -627,12 +645,11 @@ def used_externals(tree):
627
645
628
646
629
647
class SnapshotReference :
630
- def __init__ (self , value , expr ):
648
+ def __init__ (self , value , expr , context : AdapterContext ):
631
649
self ._expr = expr
632
650
node = expr .node .args [0 ] if expr is not None and expr .node .args else None
633
651
source = expr .source if expr is not None else None
634
- self ._value = UndecidedValue (value , node , source )
635
- self ._uses_externals = []
652
+ self ._value = UndecidedValue (value , node , context )
636
653
637
654
def _changes (self ):
638
655
@@ -657,5 +674,5 @@ def _changes(self):
657
674
658
675
yield from self ._value ._get_changes ()
659
676
660
- def _re_eval (self , obj ):
661
- self ._value ._re_eval (obj )
677
+ def _re_eval (self , obj , context : AdapterContext ):
678
+ self ._value ._re_eval (obj , context )
0 commit comments