builtins.type are closely related. However, mypy and pyright treat them somewhat inconsistently (both internally to each type checker and across the two type checkers).
I’d like to fix the internal inconsistency in pyright, but before I make the change, I want to make sure my understanding of the spec is correct here.
PEP 484 says:
Typeis parameterized it requires exactly one parameter. Plain
Typewithout brackets is equivalent to
Type[Any]and this in turn is equivalent to
type(the root of Python’s metaclass hierarchy). This equivalence also motivates the name,
Type, as opposed to alternatives like
SubType, which were proposed while this feature was under discussion; this is similar to the relationship between e.g.
Regarding the behavior of
type), accessing attributes of a variable with this type only provides attributes and methods defined by
If I’m interpreting this correctly, type checkers should treat all of the following type annotations the same with regard to attribute access:
from typing import Any, Type def func1(t1: Type, t2: Type[Any], t3: type, t4: type[Any]): v1 = t1.x # No Error v2 = t2.x # Mypy: No Error, Pyright: Error *** Mismatch *** v3 = t3.x # Error v4 = t4.x # Mypy: No Error, Pyright: Error *** Mismatch ***
Pyright currently emits errors for v2, v3, v4
Mypy currently emits an error only for v3
Pyre currently emits errors for none of these cases
If I’m reading the spec correctly, an error should be emitted for all four. Does that make sense?
Mypy was the reference implementation for PEP 484, so I’m always cautious when my understanding of PEP 484 appears to differ from mypy’s behavior.