You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
type builtin function should return an instance of typing.Type? #1758
I attempted modifying the definition in Typeshed by first changing __new__ to have the signature def __new__(cls, o: _T) -> Type[_T], but that had no effect. I then tried commenting out both __init__s entirely in case mypy was defaulting to looking at those, but that also did nothing. I'm not entirely sure why the change to __new__ isn't working, though it may be related to issue 1020?
I did find a workaround for this particular case by doing:
I think mypy would have to special-case type(x) to return Type[C] where C is what it knows of the type of x. The same should apply for x.__class__. Previously such types were hard to express. They're still a
little cumbersome internally in mypy but at least they're possible.
Are you interested in trying to fix this? I expect complications in the
case what's known about x is not a simple class but a union or type
variable.
@overload
def __init__(self, o: object) -> None: ...
@overload
def __init__(self, name: str, bases: Tuple[type, ...], dict: Dict[str, Any]) -> None: ...
@overload
def __new__(cls, o: object) -> type: ...
@overload
def __new__(cls, name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type: ...
def __call__(self, *args: Any, **kwds: Any) -> Any: ...
def __subclasses__(self) -> List[type]: ...
# Note: the documentation doesn't specify what the return type is, the standard
# implementation seems to be returning a list.
def mro(self) -> List[type]: ...
I attempted modifying the definition in Typeshed by first changing new
to have the signature def new(cls, o: _T) -> Type[_T], but that had
no effect. I then tried commenting out both __init__s entirely in case
mypy was defaulting to looking at those, but that also did nothing. I'm not
entirely sure why the change to new isn't working, though it may be
related to issue 1020 #1020?
I did find a workaround for this particular case by doing:
from typing import cast, Type
...snip...
s = SomeObject()
t2 = cast(Type[SomeObject], type(s))
typechecks
t2.test_static_method()
t2.test_class_method()
...but it would be nice if type could be changed so this casting is
unnecessary, though I'm not entirely sure how this would be done.
I would expect it to work in general, but maybe the problem is that type isn't a normal function, it's the constructor of a class? Does it make sense to make type a generic class?
Yes general case already works (it's the reason Type[T] exists :-).
The definition of type() is complicated because it overloads a class and a function. The 1-arg version type(x) is a function that is roughly equivalent to x.__class__ (the "roughly" is because a metaclass can override __class__ but not type()). But type is also a class. The 3-arg version instantiates that class, and metaclasses are defined by subclassing it.
I don't think we can express this fully by clever overloads in a stub; mypy must understand that type(x) doesn't just return an instance of type; it returns a value whose type is Type[X] where X is the type of the argument x. Ditto for x.__class__. (IMO mypy should treat these two the same, despite the possible difference. There are very few actual use cases for overloading __class__; it was allowed to enable extension modules to create perfect proxy classes.)
Activity
gvanrossum commentedon Jun 28, 2016
I think mypy would have to special-case
type(x)to returnType[C]whereCis what it knows of the type ofx. The same should apply forx.__class__. Previously such types were hard to express. They're still alittle cumbersome internally in mypy but at least they're possible.
Are you interested in trying to fix this? I expect complications in the
case what's known about x is not a simple class but a union or type
variable.
On Mon, Jun 27, 2016 at 9:08 PM, Michael Lee notifications@github.com
wrote:
--Guido van Rossum (python.org/~guido)
Michael0x2a commentedon Jun 29, 2016
(For the record: I've talked to @gvanrossum offline and am currently working on this)
ddfisher commentedon Jun 29, 2016
Is there some reason we shouldn't make the general case of
def f(x: T) -> Type[T]work?rwbarton commentedon Jun 29, 2016
I would expect it to work in general, but maybe the problem is that
typeisn't a normal function, it's the constructor of a class? Does it make sense to maketypea generic class?gvanrossum commentedon Jun 29, 2016
Yes general case already works (it's the reason
Type[T]exists :-).The definition of
type()is complicated because it overloads a class and a function. The 1-arg versiontype(x)is a function that is roughly equivalent tox.__class__(the "roughly" is because a metaclass can override__class__but nottype()). Buttypeis also a class. The 3-arg version instantiates that class, and metaclasses are defined by subclassing it.I don't think we can express this fully by clever overloads in a stub; mypy must understand that
type(x)doesn't just return an instance oftype; it returns a value whose type isType[X]whereXis the type of the argumentx. Ditto forx.__class__. (IMO mypy should treat these two the same, despite the possible difference. There are very few actual use cases for overloading__class__; it was allowed to enable extension modules to create perfect proxy classes.)Make type(obj) return Type[...] instead of type