diff options
author | Jelle Zijlstra <jelle.zijlstra@gmail.com> | 2023-11-29 17:36:48 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-29 17:36:48 (GMT) |
commit | 403886942376210662610627b01fea6acd77d331 (patch) | |
tree | e70297a9e1e59194ee4ad32840fbd1facc722dbe /Lib/typing.py | |
parent | e0449b9a7fffc0c0eed806bf4cbb8f1f65397bbb (diff) | |
download | cpython-403886942376210662610627b01fea6acd77d331.zip cpython-403886942376210662610627b01fea6acd77d331.tar.gz cpython-403886942376210662610627b01fea6acd77d331.tar.bz2 |
gh-112509: Fix keys being present in both required_keys and optional_keys in TypedDict (#112512)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 216f0c1..b3af701 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2884,8 +2884,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(): @@ -2897,14 +2903,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) |