Search code examples
pythonpython-3.xmypy

MyPy: How to type an argument that will forward to isinstance()


I'm writing a predicate function. Among other things, it can take an argument that is compatible with isinstance(), such that if you called my_pred(val, types), it would return isinstance(val, types).

However, I'm not sure how to type that second argument correctly when defining my predicate. The second argument of isinstance() appears to be a MyPy-internal type named _ClassInfo. Is there a way to get access to that type? Should I try to get access to that? Or should I just give up and type it as Any?

(I can't write the type correctly manually, because it's recursive and MyPy doesn't yet support recursive types correctly; a _ClassInfo can be a Type, or a tuple[_ClassInfo].)


Solution

  • So, these stubs come from typeshed, here is a link to where this is defined, where currently you have:

    if sys.version_info >= (3, 10):
        _ClassInfo: TypeAlias = type | types.UnionType | tuple[_ClassInfo, ...]
    else:
        _ClassInfo: TypeAlias = type | tuple[_ClassInfo, ...]
    
    def isinstance(__obj: object, __class_or_tuple: _ClassInfo) -> bool: ...
    

    So it looks like it is using a recursive definition.*, which mypy has had some limited support for since v0.990/v0.991:

    https://github.com/python/mypy/pull/13297

    Although, it isn't perfect, but I guess it handles this case.