From e0ddef7bf1be7e48f6acc4a3fd6873e4b1a6162f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 9 Jul 2014 21:50:24 +0400 Subject: [PATCH] PY-13140 Top-level module names starting with underscore are not imported via wildcard import --- .../psi/impl/PyStarImportElementImpl.java | 26 +++++++++++++++++-- .../PrivateModuleNames/a.py | 5 ++++ .../PrivateModuleNames/lib.py | 3 +++ .../modulePrivateName/ImportedFile.py | 1 + .../modulePrivateName/ModulePrivateName.py | 5 ++++ .../ImportedFile.py | 4 +++ .../ModulePrivateNameInDunderAll.py | 5 ++++ .../python/PyMultiFileResolveTest.java | 10 +++++++ .../PyUnresolvedReferencesInspectionTest.java | 4 +++ 9 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/a.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/lib.py create mode 100644 python/testData/resolve/multiFile/modulePrivateName/ImportedFile.py create mode 100644 python/testData/resolve/multiFile/modulePrivateName/ModulePrivateName.py create mode 100644 python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ImportedFile.py create mode 100644 python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ModulePrivateNameInDunderAll.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java index 307ac8e22841..3c3072453326 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java @@ -15,6 +15,8 @@ */ package com.jetbrains.python.psi.impl; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.psi.PsiElement; @@ -50,7 +52,13 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo for (PsiElement importedFile : new HashSet(importedFiles)) { // resolver gives lots of duplicates final PsiElement source = PyUtil.turnDirIntoInit(importedFile); if (source instanceof PyFile) { - chain.add(((PyFile) source).iterateNames()); + // PY-13140 + Iterable declaredNames = ((PyFile)source).iterateNames(); + // Filter out names starting with underscore only if __all__ attribute is not defined in the module + if (((PyFile)source).getDunderAll() == null) { + declaredNames = excludeUnderscoredNames(declaredNames); + } + chain.add(declaredNames); } } return chain; @@ -58,6 +66,19 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo return Collections.emptyList(); } + private static Iterable excludeUnderscoredNames(Iterable declaredNames) { + return Iterables.filter(declaredNames, new Predicate() { + @Override + public boolean apply(@Nullable PyElement input) { + String name = input != null ? input.getName() : null; + if (name != null && name.startsWith("_")) { + return false; + } + return true; + } + }); + } + @Nullable public PsiElement getElementNamed(final String name) { if (PyUtil.isClassPrivateName(name)) { @@ -76,7 +97,8 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo final PsiElement result = results != null && !results.isEmpty() ? results.get(0).getElement() : null; if (result != null) { final List all = sourceFile.getDunderAll(); - if (all != null && !all.contains(name)) { + // PY-13140 + if (all != null ? !all.contains(name) : name.startsWith("_")) { continue; } return result; diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/a.py new file mode 100644 index 000000000000..71615d7a4c6a --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/a.py @@ -0,0 +1,5 @@ +from lib import * + +normal_name +_private_name +__magic_name__ \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/lib.py b/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/lib.py new file mode 100644 index 000000000000..b92c948f871f --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/PrivateModuleNames/lib.py @@ -0,0 +1,3 @@ +normal_name = 'spam' +private_name = 'ham' +__magic_name__ = 'green eggs' diff --git a/python/testData/resolve/multiFile/modulePrivateName/ImportedFile.py b/python/testData/resolve/multiFile/modulePrivateName/ImportedFile.py new file mode 100644 index 000000000000..8fb15497b2ab --- /dev/null +++ b/python/testData/resolve/multiFile/modulePrivateName/ImportedFile.py @@ -0,0 +1 @@ +_private_name = "spam" \ No newline at end of file diff --git a/python/testData/resolve/multiFile/modulePrivateName/ModulePrivateName.py b/python/testData/resolve/multiFile/modulePrivateName/ModulePrivateName.py new file mode 100644 index 000000000000..ac8143c386f7 --- /dev/null +++ b/python/testData/resolve/multiFile/modulePrivateName/ModulePrivateName.py @@ -0,0 +1,5 @@ +from ImportedFile import * + +_private_name +# + diff --git a/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ImportedFile.py b/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ImportedFile.py new file mode 100644 index 000000000000..9fb658fce3a0 --- /dev/null +++ b/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ImportedFile.py @@ -0,0 +1,4 @@ +__all__ = [ + "_private_name", +] +_private_name = "spam" \ No newline at end of file diff --git a/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ModulePrivateNameInDunderAll.py b/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ModulePrivateNameInDunderAll.py new file mode 100644 index 000000000000..ac8143c386f7 --- /dev/null +++ b/python/testData/resolve/multiFile/modulePrivateNameInDunderAll/ModulePrivateNameInDunderAll.py @@ -0,0 +1,5 @@ +from ImportedFile import * + +_private_name +# + diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index e942388659ba..4585832844eb 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -363,4 +363,14 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase { public void testFromPackageModuleImportStarElementNamedAsModule() { assertResolvesTo(PyFunction.class, "foo"); } + + // PY-13140 + public void testModulePrivateName() { + assertNull(doResolve()); + } + + // PY-13140 + public void testModulePrivateNameInDunderAll() { + assertResolvesTo(PyTargetExpression.class, "_private_name"); + } } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index e614edd8e627..68f8f0e18a93 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -366,6 +366,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doMultiFileTest(); } + public void testPrivateModuleNames() { + doMultiFileTest(); + } + @NotNull @Override protected Class getInspectionClass() {