[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metaclass conflict error when base class uses an imported metaclass with no annotation #14182

Open
nsoranzo opened this issue Nov 24, 2022 · 2 comments
Assignees
Labels
bug mypy got something wrong topic-metaclasses

Comments

@nsoranzo
Copy link
nsoranzo commented Nov 24, 2022

Bug Report

Since mypy 0.990 I am getting a "Metaclass conflict" error for the definition of a class derived from a base class which uses a metaclass imported from a third-party library that doesn't provide type annotations.

To Reproduce

# Import metaclass from external module which doesn't provide type annotations
from mymodule import MyMeta


class Base(metaclass=MyMeta):
    pass


# This generates the error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
class Derived(Base):
    pass


# If there is type annotation for the metaclass, no issue.
class MyMeta2(type):
    pass


class Base2(metaclass=MyMeta2):
    pass


class Derived2(Base2):
    pass

Also available as gist at: https://mypy-play.net/?mypy=latest&python=3.11&gist=6d41ba53b2226e3bef16df71554b10b1

Expected Behavior

No errors.

Actual Behavior

metaclass_conflict.py:10: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class Derived(Base):
    ^
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.911
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
    show_error_codes = True
    ignore_missing_imports = True
    pretty = True
  • Python version used: 3.8

More info

I tried some debugging and found out that:

  • the error comes from the TypeChecker.check_metaclass_compatibility() method in mypy/checker.py
  • Using the reproducer example above, when mypy enters the check_metaclass_compatibility() method for the derived classes, the main difference between Derived (which errors) and Derived2 (which doesn't) is that typ.metaclass_type is None in the first case (instead of the expected MyMeta) and MyMeta2 in the second (correctly).
  • This pointed me to look at the TypeInfo.calculate_metaclass_type() method in mypy/nodes.py . When run for the Derived object, the only candidate metaclass is MyMeta (correctly), but then this is excluded in the following for loop because MyMeta.type.mro is [] (I supposed because it's missing type annotation).
@nsoranzo nsoranzo added the bug mypy got something wrong label Nov 24, 2022
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 24, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 24, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 25, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 26, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 26, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 26, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 26, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 26, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 27, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 27, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
nsoranzo added a commit to mr-c/galaxy that referenced this issue Nov 27, 2022
Fix hundreds of errors reported by mypy since 0.990, e.g.:

```
lib/galaxy/model/__init__.py:9626: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
    class CleanupEventLibraryAssociation(Base):
    ^
```

It should be possible to revert this workaround once
python/mypy#14182 is fixed.
@kbehlers
Copy link
kbehlers commented Dec 16, 2022

For anyone else that wanders through here because they are getting error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases [misc]

As mentioned in the description on this issue, check_metaclass_compatibility was introduced in v0.990 and is the source of the error.

I was getting the error when defining a custom Permission for Django Rest Framework.

That eventually led me to find a solved issue on djangorestframework-stubs typeddjango/djangorestframework-stubs#280. So in my case, although I couldn't see the conflict looking at the drf source code, it instead existed in the stub where there was an additional _SupportsHasPermission(Protocol) class in the mro.

mypy playground reproducing the specific red herring: https://mypy-play.net/?mypy=0.990&python=3.11&gist=bf79ced1e7ed3fa71a869056e8d42f8b

@zcutlip
Copy link
zcutlip commented Jan 28, 2023

Here's a similar problem. Not if it's related. In this case, inheriting from dict while setting a custom metaclass results in a mypy error, but no run-time error:

# Metclass type annotation clearly available
class MyMeta(type):
    pass

# mypy metclass conflict error
class MyExampleDict(dict, metaclass=MyMeta):

    def __init__(self, data: Dict):
        super().__init__(data)

However, if we make a metaclass that extends python's ABCMeta, mypy doesn't complain:

from abc import ABCMeta

class MyMeta2(ABCMeta):
    pass

# no mypy error with MyMeta2
class MyExampleDict2(dict, metaclass=MyMeta2):

    def __init__(self, data: Dict):
        super().__init__(data)

Note that neither of the above results in a Python run-time error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-metaclasses
Projects
None yet
Development

No branches or pull requests

5 participants