-
-
Notifications
You must be signed in to change notification settings - Fork 579
Enable subscripting generic types in annotations. #401
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
Conversation
Some classes like lxml.etree._ElementTree are generic types that can contain different kinds of elements. The type of these elements has to be specified in type annotations. For example: element_tree: lxml.etree._ElementTree[lxml.etree._Element] This requires adding a __class_getitem__ class method to these class, as specified in PEP 560. This commit adds these class methods. The list of generic types in lxml was taken from: https://github.com/abelcheung/types-lxml/wiki/Using-specialised-class-directly
Hmm. Thanks. I'm reluctant to apply this, because I'd rather not see users import non-public classes in their code. The internal element classes deliberately use underscore names to mark them as internal. |
I also don't like using non-public classes in type annotations. The problem is that currently we cannot use the public symbols because they are defined as functions and not as classes. Trying to use
The What do think about applying this patch to
It looks a bit disruptive, but all the tests pass. I will have to make similar changes to: |
Note that Honestly, users could just avoid using generic types for this. After all, static typing is optional and designed to be incomplete across a code base. That's a good thing. Not everything needs to be typed. Most programming errors that exact typing of I'm certainly not going to change anything in the API just to help users with statically typing their code. Static typing is not a design goal. Usability and abstraction are. |
In the types-lxml tests I see two uses for this generic:
This seems like a reasonable use of generics. Otherwise, every time someone tries to access an HTML method they will have to cast _Element to HTMLElement to prevent mypy from complaining.
From my experience, adding type annotations helps me design better code. If the type annotations become too convoluted, it is usually a sign that either I made some wrong assumptions in my types specifications or that the API is not optimal. In the case of lxml, the typing stubs seem to suggest that _Element should be part of the public API. |
I'm wondering if |
A
because the return type of a function should not be an abstract class. I just made another PR that transforms Element from a factory function into a class. |
That's not how I understand Protocols. I see them as Python's form of interfaces – they define methods and their signatures and arbitrary classes can implement them, even without saying that they implement them. That's very much what lxml's XML element classes are: arbitrary objects that implement a common interface. What you get back from the parse/select/etc. functions and methods is some object, class not interesting, but with a well defined interface. The more I think about this, the more it seems a perfect match for lxml's API. I created an issue in |
Some classes like
lxml.etree._ElementTree
are generic types that can contain different kinds of elements. The type of these elements has to be specified in type annotations. For example:This requires adding a
__class_getitem__
class method to these class, as specified in PEP 560. This commit adds these class methods.The list of generic types in lxml was taken from:
https://github.com/abelcheung/types-lxml/wiki/Using-specialised-class-directly