diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index e9e1f5368af3..2ff03ba81579 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -3,6 +3,8 @@ package com.jetbrains.python.psi.types; import com.google.common.collect.ImmutableSet; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.*; import com.intellij.util.ProcessingContext; import com.intellij.util.SmartList; @@ -15,7 +17,10 @@ import com.jetbrains.python.psi.resolve.VariantsProcessor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; import static com.jetbrains.python.psi.resolve.ResolveImportUtil.ROLE_IN_IMPORT.NONE; // .impl looks impure @@ -59,7 +64,10 @@ public class PyModuleType implements PyType { // Modules don't descend from obje // file modules for (PsiFile f : mydir.getFiles()) { final String filename = f.getName(); - if (f instanceof PyFile && !filename.equals(PyNames.INIT_DOT_PY)) result.add(f); + // if we have a binary module, we'll most likely also have a stub for it in site-packages + if ((f instanceof PyFile && !filename.equals(PyNames.INIT_DOT_PY)) || isBinaryModule(filename)) { + result.add(f); + } } // dir modules for (PsiDirectory dir : mydir.getSubdirectories()) { @@ -70,6 +78,16 @@ public class PyModuleType implements PyType { // Modules don't descend from obje return result; } + private static boolean isBinaryModule(String filename) { + final String ext = FileUtil.getExtension(filename); + if (SystemInfo.isWindows) { + return "pyd".equalsIgnoreCase(ext); + } + else { + return "so".equals(ext); + } + } + public Object[] getCompletionVariants(String completionPrefix, PyExpression expressionHook, ProcessingContext context) { Set names_already = context.get(CTX_NAMES); List result = new ArrayList(); diff --git a/python/testData/completion/fromImportBinary.after.py b/python/testData/completion/fromImportBinary.after.py new file mode 100644 index 000000000000..396b0ed9aa2d --- /dev/null +++ b/python/testData/completion/fromImportBinary.after.py @@ -0,0 +1 @@ +from root import binary_mod \ No newline at end of file diff --git a/python/testData/completion/fromImportBinary.py b/python/testData/completion/fromImportBinary.py new file mode 100644 index 000000000000..c39defa55564 --- /dev/null +++ b/python/testData/completion/fromImportBinary.py @@ -0,0 +1 @@ +from root import b \ No newline at end of file diff --git a/python/testData/completion/root/binary_mod.pyd b/python/testData/completion/root/binary_mod.pyd new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/completion/root/binary_mod.so b/python/testData/completion/root/binary_mod.so new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index 1e63891d4e48..3b04cf555d0d 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -180,5 +180,13 @@ public class PythonCompletionTest extends PyLightFixtureTestCase { public void testChainedCall() { // PY-1565 doTest(); } + + public void testFromImportBinary() { + myFixture.copyFileToProject("completion/root/binary_mod.pyd"); + myFixture.copyFileToProject("completion/root/binary_mod.so"); + myFixture.configureByFiles("completion/fromImportBinary.py", "completion/root/__init__.py"); + myFixture.completeBasic(); + myFixture.checkResultByFile("completion/fromImportBinary.after.py"); + } } \ No newline at end of file