Repository navigation
How to convert annotations to Format.SOURCE in __annotate__? #124412
Description
Activity
- addedtype-featureA feature request or enhancementA feature request or enhancement
on Sep 24, 2024 The use cases for this would be cases where types get provided outside annotations (e.g., with the functional syntax for
NamedTupleandTypedDict, and withmake_dataclass), and you want the__annotate__method to support the SOURCE format.The implementation is
repr()for most cases, but for types we want the fully qualified name instead of<type 'int'>, and there are a few other special cases. Currently we havetyping._convert_to_source, which takes an annotations dict and usestyping._type_reprto repr each annotation.Since we already have use cases from two standard library modules (typing and dataclasses), I think it makes sense to add something to
annotationlib. I would suggest:annotationlib.repr_annotations(dict), similar to the currenttyping._convert_sourceannotationlib.repr_type(type), which works liketyping._type_reprbut without the special case for tuples
Reacted by sobolevnI want to investigate on this feature, because I still have a limited understanding of
__annotate__and all of its corner-cases.Will probably work on this tomorrow 👍
Thanks! We'll also want to add the new functions to PEP 749.
We also need this in annotationlib itself, for the edge case where a user-created object has
__annotations__but not__annotate__. Currently, in that case SOURCE returns non-strings:>>> class X: ... @property ... def __annotations__(self): ... return {"x": int} ... >>> x = X() >>> import annotationlib >>> annotationlib.get_annotations(x, format=annotationlib.Format.SOURCE) {'x': <class 'int'>}I think the most reasonable behavior for this case is to return
{'x': 'int'}.My initial reaction is, this seems like a least-worst option, and it may even be the least-worst option. I'd like to marinate on it further. I won't mind too much if you go ahead and merge without my blessing--as long as you don't mind me retroactively pushing back if I (eventually) arrive at some other conclusion.
I will say, shenanigans like this are an argument against calling this format
SOURCE.Reacted by Jelle Zijlstra and Carl Meyer- added a commit that references this issue
on Sep 26, 2024 - added a commit that references this issue
on Sep 26, 2024 @JelleZijlstra can this be closed now? Sorry, I was not quick enough to send a PR :( It was only partially ready yesterday, due to some other work.
Let's leave it open for a while to allow Larry to ruminate.
Jelle has convinced himself that we should change the name away from
SOURCE, I think he preferredSTRINGSwhich is fine.It's a day later and this approach seems like a good idea. Ship it! We can always regret it later.
Reacted by Jelle ZijlstraTo be precise I propose
STRING, since the other formats are also in the singular.STRINGis fine by me. My only counter-proposal isTEXT, which is also sufficiently singular. I don't have a strong opinion about it either way; I don't thinkTEXTdoes any better job of conveying the intended semantics of the format.
Feature or enhancement
Let's say you have a dict of some custom annotations like I have in #122262
How users are expected to convert say an annotation dict of
{'user': CustomUser[AuthToken], 'auth_callback': Callable[[CustomUser[T]], T]}to string?There are several ways right now:
reprfor simple types, which might not work for complex onescpython/Lib/annotationlib.py
Lines 466 to 501 in 536bc8a
annotateobjectcpython/Lib/typing.py
Lines 2955 to 2956 in 536bc8a
I propose adding a public and documented API for that.
Linked PRs