22
33import dataclasses
44
5- from typing import Any , Dict , Set
5+ from typing import Any , Dict , Optional , Set
66
77from pytype .abstract import abstract
88from pytype .abstract import abstract_utils
1111from pytype .pytd import pytd
1212
1313
14+ class TypedDictKeyMissing (function .DictKeyMissing ):
15+
16+ def __init__ (self , typed_dict : "TypedDict" , key : Optional [str ]):
17+ super ().__init__ (key )
18+ self .typed_dict = typed_dict
19+
20+
1421@dataclasses .dataclass
1522class TypedDictProperties :
1623 """Collection of typed dict properties passed between various stages."""
@@ -29,7 +36,7 @@ def optional(self):
2936 return self .keys - self .required
3037
3138 def add (self , k , v , total ):
32- self .fields [k ] = v
39+ self .fields [k ] = v # pylint: disable=unsupported-assignment-operation
3340 if total :
3441 self .required .add (k )
3542
@@ -220,13 +227,10 @@ def __repr__(self):
220227
221228 def _check_str_key (self , name ):
222229 if name not in self .fields :
223- self .ctx .errorlog .typed_dict_error (self .ctx .vm .frames , self , name )
224- return False
225- return True
230+ raise TypedDictKeyMissing (self , name )
226231
227232 def _check_str_key_value (self , node , name , value_var ):
228- if not self ._check_str_key (name ):
229- return
233+ self ._check_str_key (name )
230234 typ = abstract_utils .get_atomic_value (self .fields [name ])
231235 bad , _ = self .ctx .matcher (node ).bad_matches (value_var , typ )
232236 for view , error_details in bad :
@@ -240,10 +244,9 @@ def _check_key(self, name_var):
240244 """Check that key is in the typed dict."""
241245 try :
242246 name = abstract_utils .get_atomic_python_constant (name_var , str )
243- except abstract_utils .ConversionError :
244- self .ctx .errorlog .typed_dict_error (self .ctx .vm .frames , self , name = None )
245- return False
246- return self ._check_str_key (name )
247+ except abstract_utils .ConversionError as e :
248+ raise TypedDictKeyMissing (self , None ) from e
249+ self ._check_str_key (name )
247250
248251 def _check_value (self , node , name_var , value_var ):
249252 """Check that value has the right type."""
@@ -254,13 +257,12 @@ def _check_value(self, node, name_var, value_var):
254257 def getitem_slot (self , node , name_var ):
255258 # A typed dict getitem should have a concrete string arg. If we have a var
256259 # with multiple bindings just fall back to Any.
257- if not self ._check_key (name_var ):
258- return node , self .ctx .new_unsolvable (node )
260+ self ._check_key (name_var )
259261 return super ().getitem_slot (node , name_var )
260262
261263 def setitem_slot (self , node , name_var , value_var ):
262- if self ._check_key (name_var ):
263- self ._check_value (node , name_var , value_var )
264+ self ._check_key (name_var )
265+ self ._check_value (node , name_var , value_var )
264266 return super ().setitem_slot (node , name_var , value_var )
265267
266268 def set_str_item (self , node , name , value_var ):
0 commit comments