diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py index 6a3be8d504fd..f2ab969f76cf 100644 --- a/python/helpers/generator3.py +++ b/python/helpers/generator3.py @@ -2280,7 +2280,7 @@ def is_mac_skipped_module(path, f): return 0 def is_skipped_module(path, f): - return is_mac_skipped_module(path, f) or is_posix_skipped_module(path, f[:f.rindex('.')]) + return is_mac_skipped_module(path, f) or is_posix_skipped_module(path, f[:f.rindex('.')]) or 'pynestkernel' in path def is_module(d, root): diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml index a10887e3ebdf..f4f140dcd059 100644 --- a/python/src/META-INF/python-plugin-common.xml +++ b/python/src/META-INF/python-plugin-common.xml @@ -88,6 +88,8 @@ + + @@ -569,6 +571,7 @@ + diff --git a/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java b/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java new file mode 100644 index 000000000000..75056b874fce --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/PyTargetElementEvaluator.java @@ -0,0 +1,42 @@ +package com.jetbrains.python.codeInsight; + +import com.intellij.codeInsight.TargetElementEvaluator; +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; +import com.jetbrains.python.psi.PyReferenceExpression; +import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.resolve.QualifiedResolveResult; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author yole + */ +public class PyTargetElementEvaluator implements TargetElementEvaluator { + @Override + public boolean includeSelfInGotoImplementation(@NotNull PsiElement element) { + return false; + } + + @Nullable + @Override + public PsiElement getElementByReference(PsiReference ref, int flags) { + if ((flags & TargetElementUtilBase.ELEMENT_NAME_ACCEPTED) == 0){ + return null; + } + final PsiElement element = ref.getElement(); + PsiElement result = ref.resolve(); + if (result instanceof PyReferenceExpression && + PsiTreeUtil.getParentOfType(element, ScopeOwner.class) == PsiTreeUtil.getParentOfType(result, ScopeOwner.class)) { + QualifiedResolveResult resolveResult = ((PyReferenceExpression)result).followAssignmentsChain(PyResolveContext.noImplicits()); + PsiElement finalResult = resolveResult.getElement(); + if (PsiTreeUtil.getParentOfType(element, ScopeOwner.class) == PsiTreeUtil.getParentOfType(finalResult, ScopeOwner.class)) { + return finalResult; + } + } + return result; + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java index d20e65754516..7d750beaf938 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PyKeywordCompletionContributor.java @@ -236,6 +236,13 @@ public class PyKeywordCompletionContributor extends CompletionContributor { .inside(PyWithStatement.class) ); + private static final PsiElementPattern.Capture IN_EXCEPT_AFTER_REF = + psiElement().afterLeaf(psiElement() + .withElementType(PyTokenTypes.IDENTIFIER) + .inside(PyReferenceExpression.class) + .inside(PyExceptPart.class) + ); + private static final PsiElementPattern.Capture IN_COND_STMT = psiElement().inside(psiElement(PyStatementList.class).inside(psiElement(PyConditionalStatementPart.class))); @@ -526,7 +533,7 @@ public class PyKeywordCompletionContributor extends CompletionContributor { extend( CompletionType.BASIC, psiElement() .withLanguage(PythonLanguage.getInstance()) - .andOr(IN_IMPORT_AFTER_REF, IN_WITH_AFTER_REF) + .andOr(IN_IMPORT_AFTER_REF, IN_WITH_AFTER_REF, IN_EXCEPT_AFTER_REF) .andNot(AFTER_QUALIFIER) , new PyKeywordCompletionProvider("as") diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index f252bc25e109..58d71a17787f 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -498,7 +498,7 @@ public class PyPackageManagerImpl extends PyPackageManager { if (binaryFile != null) { final ProjectJdkImpl tmpSdk = new ProjectJdkImpl("", PythonSdkType.getInstance()); tmpSdk.setHomePath(path); - final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(tmpSdk); + final PyPackageManagerImpl manager = new PyPackageManagerImpl(tmpSdk); manager.installManagement(DISTRIBUTE); manager.installManagement(PIP); } diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index a741eb981fd9..7cd8ea4f44bc 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -648,6 +648,9 @@ public class PyUtil { if (turnDirIntoInit(directory) != null) { return true; } + if (LanguageLevel.forFile(directory.getVirtualFile()).isAtLeast(LanguageLevel.PYTHON33)) { + return true; + } return hasNamespacePackageFile(directory); } diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index b6b927948913..18a343707758 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -215,7 +215,10 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference final ScopeOwner owner = ScopeUtil.getScopeOwner(uexpr); if (owner != null) { final Scope scope = ControlFlowCache.getScope(owner); - if (owner == originalOwner && !scope.isGlobal(referencedName)) { + if (uexpr == originalOwner && originalOwner instanceof PyClass) { + uexpr = null; + } + else if (owner == originalOwner && !scope.isGlobal(referencedName)) { final ResolveResultList latest = resolveToLatestDefs(owner, myElement, referencedName); if (!latest.isEmpty()) { return latest; diff --git a/python/src/com/jetbrains/python/sdk/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/VirtualEnvSdkFlavor.java index aa31aa950cc0..c9ea879fbcfd 100644 --- a/python/src/com/jetbrains/python/sdk/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/VirtualEnvSdkFlavor.java @@ -112,19 +112,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { @Override public boolean isValidSdkPath(@NotNull File file) { if (!super.isValidSdkPath(file)) return false; - File bin = file.getParentFile(); - if (bin != null) { - File[] children = bin.listFiles(); - if (children != null) { - for (File f : children) { - //is it good enough to determine virtual env? - if (f.getName().equals("activate_this.py")) { - return true; - } - } - } - } - return false; + return PythonSdkType.getVirtualEnvRoot(file.getPath()) != null; } @Override diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/classInClassBody.py b/python/testData/inspections/PyUnresolvedReferencesInspection/classInClassBody.py new file mode 100644 index 000000000000..4429bc65b2cb --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/classInClassBody.py @@ -0,0 +1,4 @@ +class C: + print(C) #fail + def f(self): + print(C) #pass \ No newline at end of file diff --git a/python/testData/refactoring/rename/renameAugAssigned.py b/python/testData/refactoring/rename/renameAugAssigned.py new file mode 100644 index 000000000000..ac3483ed7c03 --- /dev/null +++ b/python/testData/refactoring/rename/renameAugAssigned.py @@ -0,0 +1,3 @@ +def cover(lab=1): + lab += 1 + return lab diff --git a/python/testData/refactoring/rename/renameAugAssigned_after.py b/python/testData/refactoring/rename/renameAugAssigned_after.py new file mode 100644 index 000000000000..214457f8878f --- /dev/null +++ b/python/testData/refactoring/rename/renameAugAssigned_after.py @@ -0,0 +1,3 @@ +def cover(bar=1): + bar += 1 + return bar diff --git a/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/FromPython33NamespacePackageImport.py b/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/FromPython33NamespacePackageImport.py new file mode 100644 index 000000000000..e5b0a6241440 --- /dev/null +++ b/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/FromPython33NamespacePackageImport.py @@ -0,0 +1,4 @@ +from p1.m1 import foo + +foo() +# diff --git a/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/p1/m1.py b/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/p1/m1.py new file mode 100644 index 000000000000..6584985db844 --- /dev/null +++ b/python/testData/resolve/multiFile/fromPython33NamespacePackageImport/p1/m1.py @@ -0,0 +1,2 @@ +def foo(): + pass \ No newline at end of file diff --git a/python/testData/resolve/multiFile/python33NamespacePackage/Python33NamespacePackage.py b/python/testData/resolve/multiFile/python33NamespacePackage/Python33NamespacePackage.py new file mode 100644 index 000000000000..259a9bd59848 --- /dev/null +++ b/python/testData/resolve/multiFile/python33NamespacePackage/Python33NamespacePackage.py @@ -0,0 +1,4 @@ +import p1 + +p1 +# diff --git a/python/testData/resolve/multiFile/python33NamespacePackage/p1/m1.py b/python/testData/resolve/multiFile/python33NamespacePackage/p1/m1.py new file mode 100644 index 000000000000..6584985db844 --- /dev/null +++ b/python/testData/resolve/multiFile/python33NamespacePackage/p1/m1.py @@ -0,0 +1,2 @@ +def foo(): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 1166b9921072..68440e23bb0e 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -404,6 +404,29 @@ public class PyMultiFileResolveTest extends PyResolveTestCase { assertResolvesTo(PyFunction.class, "foo"); } + // PY-7156 + public void testPython33NamespacePackage() { + setLanguageLevel(LanguageLevel.PYTHON33); + try { + final PsiElement element = doResolve(); + assertInstanceOf(element, PyImportedModule.class); + final PyImportedModule module = (PyImportedModule)element; + assertEquals("p1", module.getImportedPrefix().toString()); + } finally { + setLanguageLevel(null); + } + } + + // PY-7156 + public void testFromPython33NamespacePackageImport() { + setLanguageLevel(LanguageLevel.PYTHON33); + try { + assertResolvesTo(PyFunction.class, "foo"); + } finally { + setLanguageLevel(null); + } + } + private void prepareTestDirectory() { final String testName = getTestName(true); myFixture.copyDirectoryToProject(testName, ""); diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index c91ecf6fd1e3..c2c0c3442a11 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -523,12 +523,14 @@ public class PythonCompletionTest extends PyTestCase { } public void testTypeMembers() { // PY-5311 - myFixture.configureByText(PythonFileType.INSTANCE, "a = 'string'\n" + - "a."); + assertFalse(doTestByText("a = 'string'\n" + + "a.").contains("mro")); + } + private List doTestByText(String text) { + myFixture.configureByText(PythonFileType.INSTANCE, text); myFixture.completeBasic(); - final List strings = myFixture.getLookupElementStrings(); - assertFalse(strings.contains("mro")); + return myFixture.getLookupElementStrings(); } public void testDunderAllReference() { // PY-5502 @@ -588,4 +590,16 @@ public class PythonCompletionTest extends PyTestCase { public void testUnknownNewReturnType() { // PY-6671 doTest(); } + + public void testAsInWith() { // PY-3701 + setLanguageLevel(LanguageLevel.PYTHON27); + assertTrue(doTestByText("with foo ").contains("as")); + } + + public void testAsInExcept() { // PY-1846 + setLanguageLevel(LanguageLevel.PYTHON27); + assertTrue(doTestByText("try:\n" + + " pass\n" + + "except IOError ").contains("as")); + } } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index b4a532e133df..49d530b3777f 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -180,6 +180,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase { doTest(); } + // PY-5995 + public void testClassInClassBody() { + doTest(); + } + private void doTest() { myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py"); myFixture.enableInspections(PyUnresolvedReferencesInspection.class); diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java index f196e27d3f4d..58cf712cfcec 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java @@ -87,6 +87,10 @@ public class PyRenameTest extends PyTestCase { doTest("bar"); } + public void testRenameAugAssigned() { // PY-3698 + doTest("bar"); + } + public void testRenameProperty() { // PY-5948 setLanguageLevel(LanguageLevel.PYTHON26); try {