diff options
Diffstat (limited to 'python/testSrc/com/jetbrains/python')
11 files changed, 370 insertions, 32 deletions
diff --git a/python/testSrc/com/jetbrains/python/PyAddImportTest.java b/python/testSrc/com/jetbrains/python/PyAddImportTest.java index 01f83847aa56..f95187aff819 100644 --- a/python/testSrc/com/jetbrains/python/PyAddImportTest.java +++ b/python/testSrc/com/jetbrains/python/PyAddImportTest.java @@ -17,8 +17,13 @@ package com.jetbrains.python; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.psi.PsiPolyVariantReference; import com.jetbrains.python.codeInsight.imports.AddImportHelper; +import com.jetbrains.python.fixtures.PyResolveTestCase; import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.PyElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author yole @@ -53,4 +58,46 @@ public class PyAddImportTest extends PyTestCase { }.execute(); myFixture.checkResultByFile("addImport/" + getTestName(true) + ".after.py"); } + + // PY-6020 + public void testLocalFromImport() { + doAddLocalImport("foo", "package.module"); + } + + // PY-6020 + public void testLocalImport() { + doAddLocalImport("module", null); + } + + // PY-13668 + public void testLocalImportInlineFunctionBody() { + testLocalImport(); + } + + // PY-13668 + public void testLocalImportInlineBranch() { + testLocalImport(); + } + + /** + * Add local import statement + * @param name reference name in corresponding import element + * @param qualifier if not {@code null} form {@code from qualifier import name} will be used, otherwise {@code import name} + */ + private void doAddLocalImport(@NotNull final String name, @Nullable final String qualifier) { + myFixture.configureByFile("addImport/" + getTestName(true) + ".py"); + new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) { + @Override + protected void run(Result result) throws Throwable { + final PsiPolyVariantReference reference = PyResolveTestCase.findReferenceByMarker(myFixture.getFile()); + if (qualifier != null) { + AddImportHelper.addLocalFromImportStatement((PyElement)reference.getElement(), qualifier, name); + } + else { + AddImportHelper.addLocalImportStatement((PyElement)reference.getElement(), name); + } + } + }.execute(); + myFixture.checkResultByFile("addImport/" + getTestName(true) + ".after.py"); + } } diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index 88243f065a3b..b0e41bcffddc 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -829,6 +829,12 @@ public class PyTypeTest extends PyTestCase { " pass\n"); } + // PY-12801 + public void testTupleConcatenation() { + doTest("(int, bool, str)", + "expr = (1,) + (True, 'spam') + ()"); + } + private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) { return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing(); } diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java index f365eea4da34..a1366ac2e17a 100644 --- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java +++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java @@ -626,23 +626,85 @@ public class PythonCompletionTest extends PyTestCase { } // PY-4073 - public void testSpecialFunctionAttributes() throws Exception { - setLanguageLevel(LanguageLevel.PYTHON27); - try { - List<String> suggested = doTestByText("def func(): pass; func.func_<caret>"); - assertNotNull(suggested); - assertContainsElements(suggested, - "func_defaults", "func_globals", "func_closure", - "func_code", "func_name", "func_doc", "func_dict"); - - suggested = doTestByText("def func(): pass; func.__<caret>"); - assertNotNull(suggested); - assertContainsElements(suggested, "__defaults__", "__globals__", "__closure__", - "__code__", "__name__", "__doc__", "__dict__", "__module__"); - assertDoesntContain(suggested, "__annotations__", "__kwdefaults__"); - } - finally { - setLanguageLevel(null); - } + public void testFunctionSpecialAttributes() { + runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() { + @Override + public void run() { + List<String> suggested = doTestByText("def func(): pass; func.func_<caret>"); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.LEGACY_FUNCTION_SPECIAL_ATTRIBUTES); + + suggested = doTestByText("def func(): pass; func.__<caret>"); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES); + assertDoesntContain(suggested, PyNames.PY3_ONLY_FUNCTION_SPECIAL_ATTRIBUTES); + } + }); + } + + // PY-9342 + public void testBoundMethodSpecialAttributes() { + List<String> suggested = doTestByText("{}.update.im_<caret>"); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.LEGACY_METHOD_SPECIAL_ATTRIBUTES); + + suggested = doTestByText("{}.update.__<caret>"); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES); + assertDoesntContain(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES); + } + + // PY-9342 + public void testWeakQualifierBoundMethodAttributes() { + assertUnderscoredMethodSpecialAttributesSuggested(); + } + + private void assertUnderscoredMethodSpecialAttributesSuggested() { + myFixture.configureByFile("completion/" + getTestName(true) + ".py"); + myFixture.completeBasic(); + final List<String> suggested = myFixture.getLookupElementStrings(); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES); + assertDoesntContain(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES); + } + + // PY-9342 + public void testUnboundMethodSpecialAttributes() { + runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() { + @Override + public void run() { + assertUnderscoredMethodSpecialAttributesSuggested(); + } + }); + runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() { + @Override + public void run() { + assertUnderscoredFunctionAttributesSuggested(); + } + }); + } + + // PY-9342 + public void testStaticMethodSpecialAttributes() { + assertUnderscoredFunctionAttributesSuggested(); + } + + // PY-9342 + public void testLambdaSpecialAttributes() { + assertUnderscoredFunctionAttributesSuggested(); + } + + // PY-9342 + public void testReassignedMethodSpecialAttributes() { + assertUnderscoredMethodSpecialAttributesSuggested(); + } + + private void assertUnderscoredFunctionAttributesSuggested() { + myFixture.configureByFile("completion/" + getTestName(true) + ".py"); + myFixture.completeBasic(); + final List<String> suggested = myFixture.getLookupElementStrings(); + assertNotNull(suggested); + assertContainsElements(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES); + assertDoesntContain(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES); } } diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java index bbaf31252c3e..65815c112b2e 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java @@ -20,16 +20,15 @@ import com.intellij.execution.ExecutionException; import com.intellij.execution.Executor; import com.intellij.execution.configurations.ConfigurationFactory; import com.intellij.execution.configurations.ConfigurationType; -import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.executors.DefaultRunExecutor; -import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironmentBuilder; import com.intellij.openapi.project.Project; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.debugger.PyDebugRunner; import com.jetbrains.python.run.AbstractPythonRunConfiguration; import com.jetbrains.python.run.PythonCommandLineState; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -59,11 +58,9 @@ public abstract class PyCommandLineTestCase extends PyTestCase { protected List<String> buildRunCommandLine(AbstractPythonRunConfiguration configuration) { try { - final Executor executor = DefaultRunExecutor.getRunExecutorInstance(); - ExecutionEnvironment env = new ExecutionEnvironmentBuilder(myFixture.getProject(), executor).setRunProfile(configuration).build(); - final PythonCommandLineState state = (PythonCommandLineState)configuration.getState(executor, env); - final GeneralCommandLine generalCommandLine = state.generateCommandLine(); - return generalCommandLine.getParametersList().getList(); + PythonCommandLineState state = getState(configuration, DefaultRunExecutor.getRunExecutorInstance()); + assert state != null; + return state.generateCommandLine().getParametersList().getList(); } catch (ExecutionException e) { throw new RuntimeException(e); @@ -72,15 +69,21 @@ public abstract class PyCommandLineTestCase extends PyTestCase { protected List<String> buildDebugCommandLine(AbstractPythonRunConfiguration configuration) { try { - final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance(); - ExecutionEnvironment env = new ExecutionEnvironmentBuilder(myFixture.getProject(), executor).setRunProfile(configuration).build(); - final PythonCommandLineState state = (PythonCommandLineState)configuration.getState(executor, env); - final GeneralCommandLine generalCommandLine = - state.generateCommandLine(PyDebugRunner.createCommandLinePatchers(configuration.getProject(), state, configuration, PORT)); - return generalCommandLine.getParametersList().getList(); + PythonCommandLineState state = getState(configuration, DefaultDebugExecutor.getDebugExecutorInstance()); + assert state != null; + return state.generateCommandLine(PyDebugRunner.createCommandLinePatchers(configuration.getProject(), state, configuration, PORT)) + .getParametersList() + .getList(); } catch (ExecutionException e) { throw new RuntimeException(e); } } + + + private static PythonCommandLineState getState(@NotNull AbstractPythonRunConfiguration configuration, @NotNull Executor executor) throws ExecutionException { + return (PythonCommandLineState)ExecutionEnvironmentBuilder.create(executor, configuration) + .build() + .getState(); + } } diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java index 45d582a783a8..99da2a43aea1 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java @@ -18,6 +18,8 @@ package com.jetbrains.python.fixtures; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ex.QuickFixWrapper; +import com.intellij.find.findUsages.CustomUsageSearcher; +import com.intellij.find.findUsages.FindUsagesOptions; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; @@ -33,6 +35,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.TestDataPath; @@ -42,6 +45,10 @@ import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; import com.intellij.testFramework.fixtures.TestFixtureBuilder; import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; +import com.intellij.usageView.UsageInfo; +import com.intellij.usages.Usage; +import com.intellij.usages.rules.PsiElementUsage; +import com.intellij.util.CommonProcessors.CollectProcessor; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.PythonMockSdk; import com.jetbrains.python.PythonModuleTypeBase; @@ -55,6 +62,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * @author yole @@ -184,6 +194,36 @@ public abstract class PyTestCase extends UsefulTestCase { myFixture.getEditor().getCaretModel().moveToOffset(element.getTextOffset()); } + /** + * Finds all usages of element. Works much like method in {@link com.intellij.testFramework.fixtures.CodeInsightTestFixture#findUsages(com.intellij.psi.PsiElement)}, + * but supports {@link com.intellij.find.findUsages.CustomUsageSearcher} and {@link com.intellij.psi.search.searches.ReferencesSearch} as well + * + * @param element what to find + * @return usages + */ + @NotNull + protected Collection<PsiElement> findUsage(@NotNull final PsiElement element) { + final Collection<PsiElement> result = new ArrayList<PsiElement>(); + final CollectProcessor<Usage> usageCollector = new CollectProcessor<Usage>(); + for (final CustomUsageSearcher searcher : CustomUsageSearcher.EP_NAME.getExtensions()) { + searcher.processElementUsages(element, usageCollector, new FindUsagesOptions(myFixture.getProject())); + } + for (final Usage usage : usageCollector.getResults()) { + if (usage instanceof PsiElementUsage) { + result.add(((PsiElementUsage)usage).getElement()); + } + } + for (final PsiReference reference : ReferencesSearch.search(element).findAll()) { + result.add(reference.getElement()); + } + + for (final UsageInfo info : myFixture.findUsages(element)) { + result.add(info.getElement()); + } + + return result; + } + protected static class PyLightProjectDescriptor implements LightProjectDescriptor { private final String myPythonVersion; diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index a0a2a1232b2e..3451712f6bcd 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -371,6 +371,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doMultiFileTest(); } + // PY-9342 + public void testMethodSpecialAttributes() { + doTest(); + } + // PY-11472 public void testUnusedImportBeforeStarImport() { doMultiFileTest(); diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java index 769e72077461..a54c68a0db09 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java @@ -51,7 +51,7 @@ public class PyIntroduceConstantTest extends PyIntroduceTestCase { public void testSuggestUniqueNames() { // PY-4409 doTestSuggestions(PyExpression.class, "S1"); } - + public void testSuggestUniqueNamesGlobalScope() { // PY-4409 doTestSuggestions(PyExpression.class, "S1"); } @@ -60,6 +60,11 @@ public class PyIntroduceConstantTest extends PyIntroduceTestCase { doTestInplace(null); } + // PY-13484 + public void testFromParameterDefaultValue() { + doTest(); + } + @Override protected String getTestDataPath() { return super.getTestDataPath() + "/refactoring/introduceConstant"; diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java index f2117977cbf3..33a191f2b9a0 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java @@ -245,6 +245,8 @@ public class PyIntroduceVariableTest extends PyIntroduceTestCase { } } + public void testSelectionBreaksBinaryOperator() {doTest();} + private void doTestCannotPerform() { boolean thrownExpectedException = false; try { diff --git a/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java b/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java new file mode 100644 index 000000000000..2d97e747f00b --- /dev/null +++ b/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java @@ -0,0 +1,142 @@ +package com.jetbrains.python.sdkTools; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkModificator; +import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.UsefulTestCase; +import com.jetbrains.python.sdk.InvalidSdkException; +import com.jetbrains.python.sdk.PythonSdkType; +import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher; +import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker; +import org.hamcrest.Matchers; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * Engine to create SDK for tests. + * See {@link #createTempSdk(com.intellij.openapi.vfs.VirtualFile, SdkCreationType, com.intellij.openapi.module.Module)} + * + * @author Ilya.Kazakevich + */ +public final class PyTestSdkTools { + + private static final Sdk[] NO_SDK = new Sdk[0]; + + private PyTestSdkTools() { + + } + + /** + * Creates SDK by its path and associates it with module. + * + * @param sdkHome path to sdk + * @param sdkCreationType SDK creation strategy (see {@link SdkCreationType} doc) + * @return sdk + */ + @NotNull + public static Sdk createTempSdk(@NotNull final VirtualFile sdkHome, + @NotNull final SdkCreationType sdkCreationType, + @NotNull final Module module + ) + throws InvalidSdkException, IOException { + final Ref<Sdk> ref = Ref.create(); + UsefulTestCase.edt(new Runnable() { + + @Override + public void run() { + final Sdk sdk = SdkConfigurationUtil.setupSdk(NO_SDK, sdkHome, PythonSdkType.getInstance(), true, null, null); + Assert.assertNotNull("Failed to create SDK on " + sdkHome, sdk); + ref.set(sdk); + } + }); + final Sdk sdk = ref.get(); + if (sdkCreationType != SdkCreationType.EMPTY_SDK) { + generateTempSkeletonsOrPackages(sdk, sdkCreationType == SdkCreationType.SDK_PACKAGES_AND_SKELETONS, module); + } + UsefulTestCase.edt(new Runnable() { + @Override + public void run() { + SdkConfigurationUtil.addSdk(sdk); + } + }); + return sdk; + } + + + /** + * Adds installed eggs to SDK, generates skeletons (optionally) and associates it with modle. + * + * @param sdk sdk to process + * @param addSkeletons add skeletons or only packages + * @param module module to associate with + * @throws InvalidSdkException bas sdk + * @throws IOException failed to read eggs + */ + private static void generateTempSkeletonsOrPackages(@NotNull final Sdk sdk, + final boolean addSkeletons, + @NotNull final Module module) + throws InvalidSdkException, IOException { + final Project project = module.getProject(); + ModuleRootModificationUtil.setModuleSdk(module, sdk); + + UsefulTestCase.edt(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + ProjectRootManager.getInstance(project).setProjectSdk(sdk); + } + }); + } + }); + + + final SdkModificator modificator = sdk.getSdkModificator(); + modificator.removeRoots(OrderRootType.CLASSES); + + for (final String path : PythonSdkType.getSysPathsFromScript(sdk.getHomePath())) { + PythonSdkType.addSdkRoot(modificator, path); + } + if (!addSkeletons) { + UsefulTestCase.edt(new Runnable() { + @Override + public void run() { + modificator.commitChanges(); + } + }); + return; + } + + final File tempDir = FileUtil.createTempDirectory(PyTestSdkTools.class.getName(), null); + final File skeletonsDir = new File(tempDir, PythonSdkType.SKELETON_DIR_NAME); + FileUtil.createDirectory(skeletonsDir); + final String skeletonsPath = skeletonsDir.toString(); + PythonSdkType.addSdkRoot(modificator, skeletonsPath); + + UsefulTestCase.edt(new Runnable() { + @Override + public void run() { + modificator.commitChanges(); + } + }); + + final SkeletonVersionChecker checker = new SkeletonVersionChecker(0); + final PySkeletonRefresher refresher = new PySkeletonRefresher(project, null, sdk, skeletonsPath, null, null); + final List<String> errors = refresher.regenerateSkeletons(checker, null); + Assert.assertThat("Errors found", errors, Matchers.empty()); + } +} diff --git a/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java b/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java new file mode 100644 index 000000000000..231f243f564e --- /dev/null +++ b/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java @@ -0,0 +1,20 @@ +package com.jetbrains.python.sdkTools; + +/** + * SDK creation type + * @author Ilya.Kazakevich + */ +public enum SdkCreationType { + /** + * SDK only (no packages nor skeletons) + */ + EMPTY_SDK, + /** + * SDK + installed packages from syspath + */ + SDK_PACKAGES_ONLY, + /** + * SDK + installed packages from syspath + skeletons + */ + SDK_PACKAGES_AND_SKELETONS +} diff --git a/python/testSrc/com/jetbrains/python/sdkTools/package-info.java b/python/testSrc/com/jetbrains/python/sdkTools/package-info.java new file mode 100644 index 000000000000..8b8fb74b9167 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/sdkTools/package-info.java @@ -0,0 +1,6 @@ +/** + * Engine to create SDK in tests. + * See {@link com.jetbrains.python.sdkTools.PyTestSdkTools} + * @author Ilya.Kazakevich + */ +package com.jetbrains.python.sdkTools;
\ No newline at end of file |