diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 09fe1bd98699..24b3ed199cdd 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -427,7 +427,22 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla final List> lines = new ArrayList<>(); for (PyClassLikeType base : bases) { if (base != null) { - final List baseClassMRO = mroLinearize(base, true, context, cache); + // Don't include ancestors of a metaclass instance + final List baseClassMRO; + if (base.isDefinition()) { + baseClassMRO = mroLinearize(base, true, context, cache); + } + else { + List metaclassInstanceMro = new ArrayList<>(); + metaclassInstanceMro.add(base); + if (base instanceof PyClassType) { + final PyClassImpl pyClass = as(((PyClassType)base).getPyClass(), PyClassImpl.class); + if (pyClass != null) { + ContainerUtil.addIfNotNull(metaclassInstanceMro, pyClass.getImplicitSuper(context)); + } + } + baseClassMRO = metaclassInstanceMro; + } if (!baseClassMRO.isEmpty()) { // mroMerge() updates passed MRO lists internally lines.add(new LinkedList<>(baseClassMRO)); diff --git a/python/testData/codeInsight/classMRO/DirectlyInstantiatedMetaclassAncestor.py b/python/testData/codeInsight/classMRO/DirectlyInstantiatedMetaclassAncestor.py new file mode 100644 index 000000000000..1382eff7461b --- /dev/null +++ b/python/testData/codeInsight/classMRO/DirectlyInstantiatedMetaclassAncestor.py @@ -0,0 +1,13 @@ +class MetaBase(type): + pass + + +class Meta(MetaBase): + pass + + +Base = Meta('Base', (), {}) + + +class MyClass(Base): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java index 1fcc619a197d..53e485b6bb9f 100644 --- a/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java +++ b/python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java @@ -125,6 +125,11 @@ public class PyClassMROTest extends PyTestCase { assertMRO(getClass("MyClass"), "Base", "object"); } + // PY-27656 + public void testDirectlyInstantiatedMetaclassAncestor() { + runWithLanguageLevel(LanguageLevel.PYTHON30, () -> assertMRO(getClass("MyClass"), "Meta", "object")); + } + // PY-20026 public void testUnresolvedMetaClassAncestors() { runWithLanguageLevel(LanguageLevel.PYTHON30, () -> assertMRO(getClass("CompositeFieldMeta"), "type", "object"));