Comments (3)
In some sense this is expected behavior. The term "generic" is overloaded, meaning both "this class can still be parameterized with type argument", and "this class has Generic
in its (effective) MRO".
Consider this example:
from typing import TypeVar, Generic
T = TypeVar('T')
class C(Generic[T]):
...
class D(C[int]):
...
is_generic_type(D) # True
D[int] # TypeError: <class '__main__.D'> is not a generic class
So is_generic_type()
means the second of the two meanings above. If you want the first one you should probably use get_parameters()
and check it is non-empty.
from typing_inspect.
I must agree that this is confusing.
I can understand why in the example is_generic_type(D) == True
, let me make another example:
Python 3.8.12 (default, Aug 31 2021, 01:23:42) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import typing
>>> import typing_inspect
>>> typing_inspect.is_generic_type(typing.List)
True
>>> isinstance(typing.List, typing.Protocol)
True
>>> class UrlList(typing.List[str]):
... ...
...
>>> typing_inspect.is_generic_type(UrlList)
True
>>> typing_inspect.get_parameters(UrlList)
()
That typing_inspect.is_generic_type(UrlList) == True
is OK – we all know that List is naturally a Generic type, in UrlList
the item type is just difined as an URL represented as a str
, not really a confusion. To check that it has any unused TypeVars by using typing_inspection.get_parameters
is probably OK.
However, SomeProtocol
just specify that a_method
must be implemented to be a SomeProtocol
, but never had some Generic parts (although technically it is a subclass of typing.Generic
). That also true for some built-in stuff like typing.Hashable
which is typing_inspect.is_generic_type(typing.Hashable) == True
but just specify that an __hash__
method exists – never had any generic parts and it suprised me very much that this is generic.
Or in other words, probably the confusing this is that you can do:
>>> class P(typing.Protocol): # No TypeVar is used!
... ...
...
>>> typing_inspect.is_generic_type(P) # No TypeVar but it is a Generic!
True
and P
is a generic type, but you cannot inherit Generic:
>>> class G(typing.Generic): # Also no TypeVar used!
... ...
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.8/typing.py", line 908, in __init_subclass__
raise TypeError("Cannot inherit from plain Generic")
TypeError: Cannot inherit from plain Generic
That is quite wired thing of the typing.Protocol
class.
In some way the originating PEP544 underlines that, as it says:
Protocol[T, S, ...] is allowed as a shorthand for Protocol, Generic[T, S, ...].
Hence it is a convenient shorthand when a TypeVar is used, not that every Protocol is Generic (again although it is implemented in that way that every Protocol is a Generic).
I would feel better if typing_inspect.is_generic_type(SomeProtocol)
would return False
instead of True
.
Mhmm or at least something like a function is_generic_and_has_used_type_var()
which also checks for an used TypeVar (should be only the case with typing.Protocol
, or are there other cases where you can inherit typing.Generic
without using a TypeVar
?)...
from typing_inspect.
FWIW I don't want to change the current behavior, because it would be back wards incompatible, but I think it is OK to add a second helper like is_generic_strict()
that would specifically exclude cases where parameters are empty.
from typing_inspect.
Related Issues (20)
- is_literal broken with new typing_extensions HOT 3
- get_origin gives inconsistent results for differently defined Unions HOT 3
- `is_generic_type(List)` is False in 3.9 HOT 6
- Add Final type
- get_origin(Dict) returns None in python 3.9 HOT 1
- Support Python 3.9 HOT 4
- Add a simple is_type(t) method HOT 2
- 0.6.0: test suite is failing HOT 3
- Python 3.9 support breaks List HOT 2
- ImportError on typing_extensions HOT 1
- Fix for Python 3.9.0/1 does not work with typing_extensions 3.7.4. HOT 1
- `typing_inspect.get_args` `Annotated` metadata args HOT 1
- test_typed_dict_typing_extension fails with typing_extensions==4.1.1 HOT 3
- New release? HOT 2
- `get_origin()` doesn't support PEP 585 generic types? HOT 2
- Breaks `marshmallow_dataclass.NewType` HOT 4
- `get_parameters` throws exception with non-indexed types from `typing` on python 3.10 HOT 1
- `typed_dict_keys` fails to return data on 3.10 HOT 1
- BUG: is_union_type return None sometime HOT 2
- `get_parameters` failed for Tuple HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from typing_inspect.