-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
I've run into a snippit of code which essentially boils down into this:
class SomeObject(object):
@classmethod
def test_class_method(cls) -> None:
print('Test class method')
@staticmethod
def test_static_method() -> None:
print('Test static method')
s = SomeObject()
t = type(s)
# Doesn't typecheck
t.test_static_method()
t.test_class_method()
The behavior I was expecting was for t
to be of type Type[SomeObject]
-- instead, it's of type type
, due to how type
is annotated in Typeshed:
class type:
__bases__ = ... # type: Tuple[type, ...]
__name__ = ... # type: str
__qualname__ = ... # type: str
__module__ = ... # type: str
__dict__ = ... # type: Dict[str, Any]
__mro__ = ... # type: Tuple[type, ...]
@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?
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.