diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java index d408ab096d74..f448239d4f38 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java +++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java @@ -44,6 +44,7 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -79,7 +80,7 @@ public final class PyExtractSuperclassHelper { // PY-12171 final PyMemberInfo objectMember = MembersManager.findMember(selectedMemberInfos, ALLOW_OBJECT); - if (LanguageLevel.forElement(clazz).isPy3K()) { + if (LanguageLevel.forElement(clazz).isPy3K() && !isObjectParentDeclaredExplicitly(clazz)) { // Remove object from list if Py3 if (objectMember != null) { selectedMemberInfos.remove(objectMember); @@ -110,7 +111,13 @@ public final class PyExtractSuperclassHelper { afterData.addElement(newClass); project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringDone(getRefactoringId(), afterData); + } + /** + * If class explicitly extends object we shall move it even in Py3K + */ + private static boolean isObjectParentDeclaredExplicitly(@NotNull final PyClass clazz) { + return Arrays.stream(clazz.getSuperClassExpressions()).filter(o -> PyNames.OBJECT.equals(o.getName())).findFirst().isPresent(); } private static PyClass placeNewClass(final Project project, PyClass newClass, @NotNull final PyClass clazz, final String targetFile) { diff --git a/python/testData/refactoring/extractsuperclass/py3ParentHasObject.after.py b/python/testData/refactoring/extractsuperclass/py3ParentHasObject.after.py new file mode 100644 index 000000000000..dd03d9a179c9 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/py3ParentHasObject.after.py @@ -0,0 +1,7 @@ +class Parent(object): + def spam(self): + pass + + +class Child(Parent): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/py3ParentHasObject.before.py b/python/testData/refactoring/extractsuperclass/py3ParentHasObject.before.py new file mode 100644 index 000000000000..6cee68ee7f75 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/py3ParentHasObject.before.py @@ -0,0 +1,3 @@ +class Child(object): + def spam(self): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java index 92f0ba72cfe1..90e9a8931f79 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java @@ -44,6 +44,12 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { super("extractsuperclass"); } + // Checks if class explicitly extends object we shall move it even in Py3K (PY-19137) + public void testPy3ParentHasObject() throws Exception { + setLanguageLevel(LanguageLevel.PYTHON30); + doSimpleTest("Child", "Parent", null, true, false, ".spam"); + } + // Checks that moving methods between files moves imports as well public void testImportMultiFile() throws Throwable { multiFileTestHelper(".do_useful_stuff", false);