bpo-39627: Fix TypedDict totality check for inherited keys (#18503)

(Adapted from https://github.com/python/typing/pull/700)
This commit is contained in:
Vlad Emelianov 2020-02-13 20:53:29 +01:00 committed by GitHub
parent fbeba8f248
commit 10e87e5ef4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 13 deletions

View file

@ -1828,23 +1828,30 @@ class _TypedDictMeta(type):
ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new
tp_dict = super(_TypedDictMeta, cls).__new__(cls, name, (dict,), ns)
anns = ns.get('__annotations__', {})
annotations = {}
own_annotations = ns.get('__annotations__', {})
own_annotation_keys = set(own_annotations.keys())
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
anns = {n: _type_check(tp, msg) for n, tp in anns.items()}
required = set(anns if total else ())
optional = set(() if total else anns)
own_annotations = {
n: _type_check(tp, msg) for n, tp in own_annotations.items()
}
required_keys = set()
optional_keys = set()
for base in bases:
base_anns = base.__dict__.get('__annotations__', {})
anns.update(base_anns)
if getattr(base, '__total__', True):
required.update(base_anns)
else:
optional.update(base_anns)
annotations.update(base.__dict__.get('__annotations__', {}))
required_keys.update(base.__dict__.get('__required_keys__', ()))
optional_keys.update(base.__dict__.get('__optional_keys__', ()))
tp_dict.__annotations__ = anns
tp_dict.__required_keys__ = frozenset(required)
tp_dict.__optional_keys__ = frozenset(optional)
annotations.update(own_annotations)
if total:
required_keys.update(own_annotation_keys)
else:
optional_keys.update(own_annotation_keys)
tp_dict.__annotations__ = annotations
tp_dict.__required_keys__ = frozenset(required_keys)
tp_dict.__optional_keys__ = frozenset(optional_keys)
if not hasattr(tp_dict, '__total__'):
tp_dict.__total__ = total
return tp_dict