-
-
Notifications
You must be signed in to change notification settings - Fork 44
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
Support PEP 695 generics #348
base: main
Are you sure you want to change the base?
Conversation
Wow, fantastic work @viccie30! 🚀 🚀 It looks very good already. Annotation scopesI wonder if we need to do anything special. Griffe's way of resolving names is not the same as Python itself. The following order is applied when resolving a name in a given scope:
To me it sounds like the annotation scope is therefore already supported. Have you noticed resolution failures, or incorrect resolution for type parameters while working on this feature? Pre-PEP 695 genericsNo need to add support in this PR. Nobody ever asked for it yet. Recording varianceCould be interesting, simply for documentation purposes, but not critical here either. This can be done in subsequent work. Sphinx-style / Numpydoc-styleLet's not modify those. Sphinx-style is very limited anyway. Numpydoc-style has a somewhat precise style-guide: I'd like to wait and see if they update it for type aliases / type parameters, and how, before we implement anything (even if we've already taken a few liberties in our own parser). I'll even have to think a bit more about adding support in the Google-style parser itself (do you have use-cases yourself? please share even if they seem completely obvious to you!), but since we have a new kind of object ( |
Thank you!
Yes, the current code cannot correctly resolve references to type parameters in function parameter annotations, function return annotations and class base annotations. In all cases the An example: class Class[T](list[T]):
def func[U](self, arg1: T, arg2: U) -> U: ... When I can see two possible solutions:
Solution 1 would be cleaner in my opinion, but it would be a breaking change for consumers.
I won't work on these additions for now then.
My use cases for documenting type parameters are mostly documenting custom generic containers or decorators: class MyCustomMapping[K, V]:
"""A custom mapping.
Type Parameters:
K: Key type. Does not have to be hashable, but has to be symmetrically equality comparable.
V: Value type. Must be serializable to JSON for processing.
"""
def my_decorator[**P, R](callable: Callable[P, R]) -> Callable[Concatenate[int, P], str]:
"""Decorator for auto-stringizing.
Parameters:
callable: Callable to wrap.
Type Parameters:
P: Original parameters of `callable`.
R: Original return type of `callable`. Must be convertible to `str`.
""" Personally I like to document type aliases the same as attributes: with a docstring immediately below it. If PEP 727 is accepted, then also parsing documentation using I only use sections for objects I can't document more directly, like parameters and return values. For classes, attributes, functions, etc. I always document them in their own docstrings. Since it's not possible to add a docstring for type parameters, I think that the section for type parameters is needed. I simply added the type aliases section for completeness, but I don't intend on ever using it myself. It is however used by mkdocstrings/python to auto-generate a type aliases section in summaries, which makes it useful. |
Thanks a lot, that's super clear. So, given your first example, I understand that the code cannot resolve (I'm not used to generics, even less PEP 695, so please bear with me 😅 ) I can definitely see the usefulness of the "Type Parameters" section. I suppose the following is not even valid (would require inheriting from K = TypeVar("K")
"""Key type. Does not have to be hashable, but has to be symmetrically equality comparable."""
V = TypeVar("V")
"""Value type. Must be serializable to JSON for processing."""
class MyCustomMapping[K, V]:
"""A custom mapping.""" Same for this, not valid I suppose: class MyCustomMapping[Annotated[K, ...], Annotated[V, ...]]:
"""A custom mapping.""" Is there any way with modern syntax to attach more information to |
OK so my use of |
If a generic class has type parameters and methods in that class use those type parameters, I think it would be useful to link them. See for instance this screenshot I took using mkdocstrings/python#221:
That is valid, but does not mean what you might expect it to mean.
This is indeed invalid, type parameter lists must only contain identifiers, possibly prefixed with stars and followed by bound or constraint, or default. I don't see any way to document type parameters outside of docstrings. |
Right! Very valid use-case indeed. Thanks. I'll mention the
Yeah OK that's what I gathered. We can safely expect that no one will use that. OK, well that's unfortunate. I'll keep thinking about it, and in the meantime we can move forward with type alias and type parameter docstring sections (which you already implemented 👍) That leaves the question of the implementation for annotation scopes. I agree with you option 1 would be more elegant. I'll see how much it could break things. |
I looked at that extension, but I did not figure out a way to use it in my implementation.
There's probably more weird Python tricks that can't be parsed by inspecting the AST, like dynamically adding stuff at run time and other things, so I don't think it's necessary to add this.
I'll see if I can push an alternate version of the third commit tomorrow that changes the semantics of |
This would fix #342.
There are a few things about which I'm not sure:
annotation_scope
attribute toExprName
, becauseparent
is already overloaded: either the parent scope or the previous part of the path in aExprAttribute
.