Skip to content

Metaclass conflict check improvements #17682

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

Merged

Conversation

robsdedude
Copy link
Contributor

@robsdedude robsdedude commented Aug 16, 2024

This PR fixes some points of #14033:

  • Give metaclass errors to their own error code (I chose metaclass).
  • Document shortcomings of and workarounds for mypy's metaclass handling.

I didn't attempt to fix that mypy follows the logic for determining the metaclass as documented whereas it should follow what the interpreter is actually doing (#14033 (comment)). I think such a change is better kept as a separate PR, which is why I don't want to close the issue with this PR.

EDIT: (Now that #17713 is merged)
Fixes: #14033

This comment has been minimized.

This comment has been minimized.

@robsdedude
Copy link
Contributor Author

The tests passed locally. I'm not quite sure what's going on. I'll dig deeper when I'm back from vacation in about a week.

This comment has been minimized.

This comment has been minimized.

@robsdedude robsdedude force-pushed the metaclass-conflict-check-improvements branch from 6b0f4c3 to 27e9da3 Compare June 29, 2025 22:33

This comment has been minimized.

mypy/checker.py Outdated
self.fail(
"Metaclass conflict: the metaclass of a derived class must be "
"a (non-strict) subclass of the metaclasses of all its bases",
f"a (non-strict) subclass of the metaclasses of all its bases{explanation}",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware that adding the explanation makes error message differ from the runtime error. However, since type hints sometimes don't follow the actual runtime metaclasses (s. issue this PR is supposed fix), I think this information can be valuable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mypy errors don't necessarily have to mirror runtime errors exactly. It's nice to be consistent, but maybe we have more information so we can give a more detailed error, or we think a different wording is more informative.

@robsdedude
Copy link
Contributor Author

@hauntsaninja You offered to have a look, thanks again. The PR is ready for review.

This comment has been minimized.

Copy link
Contributor

github-actions bot commented Jul 1, 2025

Diff from mypy_primer, showing the effect of this PR on open source code:

artigraph (https://github.com/artigraph/artigraph)
- src/arti/versions/__init__.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/versions/__init__.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/versions/__init__.py:17: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/statistics/__init__.py:8: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/statistics/__init__.py:8: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/statistics/__init__.py:8: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/annotations/__init__.py:8: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/annotations/__init__.py:8: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/annotations/__init__.py:8: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/types/__init__.py:26: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/types/__init__.py:26: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/types/__init__.py:26: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/types/__init__.py:44: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/types/__init__.py:44: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/types/__init__.py:44: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/types/__init__.py:48: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/types/__init__.py:48: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/types/__init__.py:48: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/types/__init__.py:61: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/types/__init__.py:61: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/types/__init__.py:61: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/types/__init__.py:347: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/types/__init__.py:347: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/types/__init__.py:347: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/thresholds/__init__.py:11: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/thresholds/__init__.py:11: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/thresholds/__init__.py:11: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/partitions/__init__.py:21: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/partitions/__init__.py:21: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/partitions/__init__.py:21: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/formats/__init__.py:11: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/formats/__init__.py:11: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/formats/__init__.py:11: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/storage/__init__.py:24: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/storage/__init__.py:24: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/storage/__init__.py:24: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/storage/__init__.py:45: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/storage/__init__.py:45: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/storage/__init__.py:45: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/storage/__init__.py:65: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/storage/__init__.py:65: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/storage/__init__.py:65: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/artifacts/__init__.py:24: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/artifacts/__init__.py:24: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/artifacts/__init__.py:24: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/views/__init__.py:20: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/views/__init__.py:20: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/views/__init__.py:20: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/backends/__init__.py:133: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/backends/__init__.py:133: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/backends/__init__.py:133: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/producers/__init__.py:56: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/producers/__init__.py:56: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/producers/__init__.py:56: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/producers/__init__.py:464: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/producers/__init__.py:464: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/producers/__init__.py:464: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/graphs/__init__.py:94: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/graphs/__init__.py:94: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/graphs/__init__.py:94: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/graphs/__init__.py:294: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/graphs/__init__.py:294: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/graphs/__init__.py:294: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/executors/__init__.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/executors/__init__.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/executors/__init__.py:17: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- src/arti/storage/google/cloud/storage.py:18: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ src/arti/storage/google/cloud/storage.py:18: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ src/arti/storage/google/cloud/storage.py:18: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:13: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ tests/arti/internal/test_models.py:13: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ tests/arti/internal/test_models.py:13: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ tests/arti/internal/test_models.py:17: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ tests/arti/internal/test_models.py:17: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:43: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ tests/arti/internal/test_models.py:43: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ tests/arti/internal/test_models.py:43: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:54: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ tests/arti/internal/test_models.py:54: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ tests/arti/internal/test_models.py:54: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:84: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ tests/arti/internal/test_models.py:84: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ tests/arti/internal/test_models.py:84: note: "arti.internal.models.ModelMeta" (metaclass of "arti.internal.models.Model") conflicts with "pydantic._internal._model_construction.ModelMetaclass" (metaclass of "pydantic.main.BaseModel")
- tests/arti/internal/test_models.py:108: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]

... (truncated 2 lines) ...

comtypes (https://github.com/enthought/comtypes)
- comtypes/_post_coinit/unknwn.py:266: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [misc]
+ comtypes/_post_coinit/unknwn.py:266: error: Metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases  [metaclass]
+ comtypes/_post_coinit/unknwn.py:266: note: "comtypes._post_coinit.unknwn._compointer_meta" (metaclass of "comtypes._post_coinit.unknwn._compointer_base") conflicts with "_ctypes._PyCSimpleType" (metaclass of "_ctypes._SimpleCData")

steam.py (https://github.com/Gobot1234/steam.py)
- steam/utils.py:458: error: Dynamic metaclass not supported for "StructIO"  [misc]
+ steam/utils.py:458: error: Dynamic metaclass not supported for "StructIO"  [metaclass]

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the improvement!

@hauntsaninja hauntsaninja merged commit 657154b into python:master Jul 1, 2025
20 checks passed
@robsdedude robsdedude deleted the metaclass-conflict-check-improvements branch July 1, 2025 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Offer a simpler way to resolve metaclass conflicts
3 participants