Closed
Description
I was looking at the docstring of Type and noticed that it used a TypeVar for the argument. I wasn't using TypeVars so I started adding them to my code. But then I noticed I was getting fewer errors and mypy was not warning me about creating abstract base classes. Here's my simplified code:
from abc import ABCMeta, abstractmethod
from six import add_metaclass
from typing import TypeVar, Type
@add_metaclass(ABCMeta)
class User(object):
@abstractmethod
def foo(self):
pass
class BasicUser(User):
def foo(self):
return 'yay'
try:
u = User() # This fails correctly.
except TypeError:
pass
basic = BasicUser()
# Using a TypeVar
U = TypeVar('U', bound=User)
def new_user(user_class):
# type: (Type[U]) -> U
user = user_class() # This passes typechecking.
return user
joe = new_user(BasicUser)
try:
jo2 = new_user(User) # This should probably fail but doesn't.
except TypeError:
pass
# Not using a TypeVar
def new_user2(user_class):
# type: (Type[User]) -> User
user = user_class() # This fails typecheck.
return user
jar = new_user2(BasicUser)
try:
ja2 = new_user2(User)
except TypeError:
pass
(This was in python 2)
I can't tell what's better. It's annoying that (Type[User]) -> User
wouldn't work. But I sort of understand that it can't guarantee to work. What I've done to work around this is have user_class instead be a function that returns a User.
def new_user3(user_class_fn):
# type: (Callable[[], User]) -> User
user = user_class_fn()
return user
def get_basic_user():
# type: () -> User
return BasicUser()
def get_user():
# type: () -> User
return User() # this fails correctly
jar = new_user3(get_basic_user)
try:
ja2 = new_user3(get_user)
except TypeError:
pass