Skip to content

Binding an abc to TypeVar loses abstract class check #1830

Closed
@euresti

Description

@euresti

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions