-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-44863: In TypedDict allow inherit from Generic and preserve bases #27663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
6cfdc5f
c022e44
2fa00b8
b829d8a
c5762df
4c5db0a
34189dd
0cfd637
5e808af
a2482ff
071c1b6
3ce517b
2f003e0
964f7d3
c3c0e51
d34c99e
cea66c4
0ed4326
b1fcd16
2905f29
afa5e51
94138f6
2572930
c2e1d8d
d3d9456
311852c
dc98753
9bed1d4
6c152e7
f88201b
6ea95df
80e9104
dbbb707
56b69e0
4a40825
4b50ae2
ecc7726
5b5a983
99a1430
79c2bb4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2252,10 +2252,12 @@ def __new__(cls, name, bases, ns, total=True): | |
Subclasses and instances of TypedDict return actual dictionaries. | ||
""" | ||
for base in bases: | ||
if type(base) is not _TypedDictMeta: | ||
if not (type(base) is _TypedDictMeta or base is Generic): | ||
sransara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
raise TypeError('cannot inherit from both a TypedDict type ' | ||
'and a non-TypedDict base class') | ||
tp_dict = type.__new__(_TypedDictMeta, name, (dict,), ns) | ||
|
||
generic_base = (Generic,) if _collect_type_vars(ns.get("__orig_bases__", ())) else () | ||
sransara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tp_dict = type.__new__(_TypedDictMeta, name, (*generic_base, dict,), ns) | ||
JelleZijlstra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
annotations = {} | ||
own_annotations = ns.get('__annotations__', {}) | ||
|
@@ -2294,6 +2296,15 @@ def __subclasscheck__(cls, other): | |
|
||
__instancecheck__ = __subclasscheck__ | ||
|
||
def __getitem__(cls, params): | ||
if not isinstance(params, tuple): | ||
params = (params,) | ||
msg = "Parameters to generic types must be types." | ||
params = tuple(_type_check(p, msg) for p in params) | ||
nparams = len(cls.__dict__.get("__parameters__", ())) | ||
_check_generic(cls, params, nparams) | ||
return types.GenericAlias(cls, params) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there are no need to define There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had two issues by not overriding the default:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Fidget-Spinner What is your opinion about issue mentioned by Samodya? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For 1st issue: For the 2nd behavior: >>> type(G[int])
<class 'types.GenericAlias'>
>>> G.__mro__
(<class '__main__.G'>, <class 'dict'>, <class 'object'>) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re 1: Dunder proxying behavior isn't specified in the PEP draft either :) I switched gears to add this feature through a bpo and implementation as I am not sure whether this change needed a PEP/PEP update (my reasoning in the ticket description). By any chance do you know a PEP that specifies the behavior of Re 2: I see. Thank you. But that does seem like something that shouldn't be allowed for a non generic Typeddict (Not a big deal though since it doesn't really do anything). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering following is the behavior for normal Generic class, I will revert the overriding of
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason why you're using the builtin IMO, I'd prefer you use the typing version. It's much easier to subclass and customize. It also supports older Python versions if you're porting this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
|
||
def TypedDict(typename, fields=None, /, *, total=True, **kwargs): | ||
"""A simple typed namespace. At runtime it is equivalent to a plain dict. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Allow ``TypedDict`` subclasses to also include ``Generic`` as a base class | ||
in class based syntax. Thereby allowing the user to define a ``Generic | ||
TypedDict``, just like a user defined ``Generic class`` but with | ||
``TypedDict`` semantics. | ||
sransara marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.