Skip to content

Unexpected error behaviour: Parameterized generics cannot be used with class or instance checks #12155

Closed

Description

@JohanSchott

mypy reports success for

import numpy as np
x = "a"
assert isinstance(x, np.float64)

but fails for

from numpy import float64
x = "a"
assert isinstance(x, float64)

with the error fails.py:3: error: Parameterized generics cannot be used with class or instance checks

I'm using mypy (0.931) and numpy (1.22.2).

Why do I get different results?

Activity

  1. JelleZijlstra commented on Feb 9, 2022

    @JelleZijlstra
    Member

    Interesting. float64 is defined here: https://github.com/numpy/numpy/blob/51abd9693a78907f2ca7dfacee2017ef44fb9f49/numpy/__init__.pyi#L2973. It's obviously meant as a type alias, but apparently mypy sometimes interprets it as a variable assignment.

  2. lindycoder commented on Aug 1, 2023

    @lindycoder

    I have the same issue with Unions

    version:

    $  mypy --version
    mypy 1.4.1 (compiled: yes)
    $ python --version
    Python 3.10.9
    

    Config:

    [tool.mypy]
    namespace_packages=true
    explicit_package_bases=true
    strict=true
    show_error_codes=true
    

    Code

    from dataclasses import dataclass
    
    
    @dataclass
    class A:
        val_a: str
    
    @dataclass
    class B:
        val_b: str
    
    ABUnion = A|B
    
    obj = A(val_a="hey")
    
    assert isinstance(obj, ABUnion)
    
    

    Result:

    $ mypy check.py 
    check.py:16: error: Parameterized generics cannot be used with class or instance checks  [misc]
    check.py:16: error: Argument 2 to "isinstance" has incompatible type "<typing special form>"; expected "_ClassInfo"  [arg-type]
    Found 2 errors in 1 file (checked 1 source file)
    

    Code works fine

    Thank you!

    Edit:
    One solution is to use get_args on the union

    from typing import get_args
    
    assert isinstance(obj, get_args(ABUnion))
    

    This passes both code and check, but does not work as a type guard

    Edit 2:
    This work as type guard with a TypeGuard, obj is correctly scoped to a shorter set of the union

    from dataclasses import dataclass
    from typing import get_args, TypeGuard
    
    
    @dataclass
    class A:
        val_a: str
        common: str
    
    @dataclass
    class B:
        val_b: str
        common: str
    
    @dataclass
    class C:  # no common
        val_c: str
    
    ABUnion = A|B  # has common
    ABCUnion = A|B|C
    
    obj: ABCUnion  = A(val_a="hey", common="common")
    
    def is_ab(val: ABCUnion) -> TypeGuard[ABUnion]:
        return type(val) in get_args(ABUnion)
    
    if is_ab(obj):
        print(obj.common)
    
  3. tibbe commented on Aug 31, 2023

    @tibbe

    Any status update?

    Note that isinstance is defined as working on unions: "If classinfo is a tuple of type objects (or recursively, other such tuples) or a Union Type of multiple types, return True if object is an instance of any of the types."

  4. brandon-neth commented on Jan 25, 2024

    @brandon-neth

    I'm also wondering about the status on this.

  5. hunterC90 commented on Feb 22, 2024

    @hunterC90

    Should this have the label topic-pep-604? I'm not 100% sure but it seems like it when I look at others open issues that have the label.

  6. msetina commented on Apr 24, 2024

    @msetina

    Any new development on mitigating this.
    I am using cryptography and their aliases are not disected properly and even get_args does not help to mark object as suitable.
    Also a Union of child classes is not properly inspected when variable of object is of parent class but the object is of child class.

  7. added 2 commits that reference this issue on Jun 12, 2024
    754d8f3
    0fa9f0c
  8. added a commit that references this issue on Jun 13, 2024
    98a22c4
  9. gbhand commented on Jul 23, 2025

    @gbhand

    @msetina cryptography seems to use old-style unions, which appear to still be unsupported #17680

    @lindycoder's workaround has been successful as far as I've tried

    from numpy import float64
    x = "a"
    assert isinstance(x, float64)

    yields error: Parameterized generics cannot be used with class or instance checks [misc]

    while this passes

    from typing import get_args
    x = "a"
    assert isinstance(x, get_args(float64))

    with latest release

    $ mypy --version
    mypy 1.17.0 (compiled: yes)
    

    Relating to cryptography the workaround also seems to do the trick for the general case, can you give a more specific example of the inheritance-related failure?

    from cryptography.hazmat.primitives.hashes import SHA256
    from cryptography.x509.base import _AllowedHashTypes
    
    assert isinstance(SHA256, _AllowedHashTypes) # fails with [misc, arg-type]
    assert isinstance(SHA256, get_args(_AllowedHashTypes)) # passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-pep-604PEP 604 (union | operator)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions