1111from typing import Type
1212from typing import Union
1313
14+ from pydantic import Extra
1415from pydantic .error_wrappers import ValidationError
1516from typing_extensions import get_args
1617from typing_extensions import get_origin
@@ -72,7 +73,7 @@ def get_dict_value_type(dict_type: Type[Any], key: Optional[str] = None) -> Type
7273 return get_dict_value_type (root_type , key ) # type: ignore
7374
7475 if key is None :
75- raise KeyError ('Key name or alias is required for object introspection' )
76+ raise KeyError ('Field name or alias is required for object introspection' )
7677
7778 # NOTE: Pydantic model, find corresponding field and return it's type
7879 fields = dict_type .__fields__
@@ -84,8 +85,8 @@ def get_dict_value_type(dict_type: Type[Any], key: Optional[str] = None) -> Type
8485 else :
8586 return field .outer_type_
8687
87- # NOTE: typically when we try the wrong Union path
88- raise KeyError ('Key not found' )
88+ # NOTE: Either we try the wrong Union path or model was modifier by user
89+ raise KeyError (f'Field ` { key } ` not found in { dict_type } ' )
8990
9091
9192@lru_cache (None )
@@ -157,9 +158,16 @@ def _process_storage(storage: Any, storage_type: Type[Any], bigmap_diffs: Dict[i
157158
158159 # NOTE: Dict, process recursively
159160 elif isinstance (storage , dict ):
161+ # NOTE: Ignore missing fields along with extra ones
162+ ignore = getattr (getattr (storage_type , 'Config' , None ), 'extra' , None ) == Extra .ignore
163+
160164 for key , value in storage .items ():
161- value_type = get_dict_value_type (storage_type , key ) # type: ignore
162- storage [key ] = _process_storage (value , value_type , bigmap_diffs )
165+ try :
166+ value_type = get_dict_value_type (storage_type , key ) # type: ignore
167+ storage [key ] = _process_storage (value , value_type , bigmap_diffs )
168+ except IntrospectionError :
169+ if not ignore :
170+ raise
163171
164172 else :
165173 pass
0 commit comments