[3.12] gh-112509: Fix keys being present in both required_keys and optional_keys in TypedDict (GH-112512) (#112530)

(cherry picked from commit 4038869423)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Miss Islington (bot) 2023-11-29 18:55:06 +01:00 committed by GitHub
parent 01b882b390
commit c67812668f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 5 deletions

View file

@ -2846,8 +2846,14 @@ class _TypedDictMeta(type):
for base in bases:
annotations.update(base.__dict__.get('__annotations__', {}))
required_keys.update(base.__dict__.get('__required_keys__', ()))
optional_keys.update(base.__dict__.get('__optional_keys__', ()))
base_required = base.__dict__.get('__required_keys__', set())
required_keys |= base_required
optional_keys -= base_required
base_optional = base.__dict__.get('__optional_keys__', set())
required_keys -= base_optional
optional_keys |= base_optional
annotations.update(own_annotations)
for annotation_key, annotation_type in own_annotations.items():
@ -2859,14 +2865,23 @@ class _TypedDictMeta(type):
annotation_origin = get_origin(annotation_type)
if annotation_origin is Required:
required_keys.add(annotation_key)
is_required = True
elif annotation_origin is NotRequired:
optional_keys.add(annotation_key)
elif total:
is_required = False
else:
is_required = total
if is_required:
required_keys.add(annotation_key)
optional_keys.discard(annotation_key)
else:
optional_keys.add(annotation_key)
required_keys.discard(annotation_key)
assert required_keys.isdisjoint(optional_keys), (
f"Required keys overlap with optional keys in {name}:"
f" {required_keys=}, {optional_keys=}"
)
tp_dict.__annotations__ = annotations
tp_dict.__required_keys__ = frozenset(required_keys)
tp_dict.__optional_keys__ = frozenset(optional_keys)