11from __future__ import annotations
22
3+ import ast
34from dataclasses import dataclass
45from typing import Any
56from typing import Callable
67
78from inline_snapshot ._adapter_context import AdapterContext
9+ from inline_snapshot ._code_repr import HasRepr
810from inline_snapshot ._code_repr import mock_repr
11+ from inline_snapshot ._code_repr import value_code_repr
912from inline_snapshot ._compare_context import compare_context
1013from inline_snapshot ._customize ._custom_sequence import CustomSequence
1114from inline_snapshot ._exceptions import UsageError
15+ from inline_snapshot ._utils import clone
1216
1317from ._custom import Custom
1418from ._custom_call import CustomCall
@@ -51,6 +55,14 @@ def _get_handler(self, v, snapshot_value=None) -> Custom:
5155
5256 from inline_snapshot ._global_state import state
5357
58+ if isinstance (v , Custom ):
59+ original_value = v ._eval ()
60+ else :
61+ try :
62+ original_value = clone (v )
63+ except UsageError :
64+ original_value = v
65+
5466 result = v
5567
5668 while not isinstance (result , Custom ):
@@ -63,11 +75,22 @@ def _get_handler(self, v, snapshot_value=None) -> Custom:
6375 snapshot_value = snapshot_value ,
6476 )
6577 if r is None :
66- result = CustomCode (result )
78+
79+ with mock_repr (self ._snapshot_context ):
80+ repr_str = value_code_repr (result )
81+
82+ try :
83+ ast .parse (repr_str )
84+ except SyntaxError :
85+ result = self .create_call (HasRepr , [type (result ), repr_str ])
86+ # self.repr_str = HasRepr(type(value), self.repr_str).__repr__()
87+ # self._imports.append(ImportFrom("inline_snapshot", "HasRepr"))
88+ else :
89+ result = CustomCode (result , repr_str )
6790 else :
6891 result = r
6992
70- result .__dict__ ["original_value" ] = v . _eval () if isinstance ( v , Custom ) else v
93+ result .__dict__ ["original_value" ] = original_value
7194
7295 if not isinstance (v , Custom ) and self ._build_new_value :
7396 is_same = False
@@ -79,14 +102,14 @@ def _get_handler(self, v, snapshot_value=None) -> Custom:
79102 ):
80103 is_same = True
81104
82- if not is_same and v_eval == v :
105+ if not is_same and v_eval == original_value :
83106 is_same = True
84107
85108 if not is_same :
86109 raise UsageError (f"""\
87110 Customized value does not match original value:
88111
89- original_value={ v !r}
112+ original_value={ original_value !r}
90113
91114customized_value={ result ._eval ()!r}
92115customized_representation={ result !r}
@@ -95,31 +118,43 @@ def _get_handler(self, v, snapshot_value=None) -> Custom:
95118 return result
96119
97120 def _customize (self , value , snapshot_value = missing ):
98- with mock_repr (self ._snapshot_context ):
99- return self ._get_handler (value , snapshot_value )
121+ return self ._get_handler (value , snapshot_value )
100122
101123 def _customize_all (self , value ):
102124 if not isinstance (value , Custom ):
103125 value = self ._customize (value )
104126
127+ def with_original (new_value : Custom , old_value : Custom ) -> Custom :
128+ new_value .__dict__ ["original_value" ] = getattr (
129+ old_value , "original_value" , old_value ._eval ()
130+ )
131+ return new_value
132+
105133 if isinstance (value , CustomSequence ):
106- value .value = [self ._customize_all (c ) for c in value .value ]
134+ return with_original (
135+ type (value )([self ._customize_all (c ) for c in value .value ]), value
136+ )
107137 elif isinstance (value , CustomDict ):
108- value .value = {
109- self ._customize_all (k ): self ._customize_all (v )
110- for k , v in value .value .items ()
111- }
138+ return with_original (
139+ CustomDict (
140+ {
141+ self ._customize_all (k ): self ._customize_all (v )
142+ for k , v in value .value .items ()
143+ }
144+ ),
145+ value ,
146+ )
112147 elif isinstance (value , CustomCall ):
113- value . _function = self . _customize_all ( value . _function )
114- value . _args = [ self . _customize_all ( c ) for c in value . _args ]
115- value . _kwargs = {
116- k : self ._customize_all (v ) for k , v in value ._kwargs . items ()
117- }
118- value . _kwonly = {
119- k : self . _customize_all ( v ) for k , v in value . _kwonly . items ()
120- }
148+ return with_original (
149+ CustomCall (
150+ function = self . _customize_all ( value . function ),
151+ args = [ self ._customize_all (c ) for c in value .args ],
152+ kwargs = { k : self . _customize_all ( v ) for k , v in value . kwargs . items ()},
153+ ),
154+ value ,
155+ )
121156 elif isinstance (value , CustomDefault ):
122- value . value = self ._customize_all (value .value )
157+ return with_original ( CustomDefault ( self ._customize_all (value .value )), value )
123158
124159 return value
125160
0 commit comments