From 7eaf625161013f41f64b91fdad6e37090e3b4c36 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 26 Feb 2013 17:05:36 +0400 Subject: [PATCH 01/16] PY-6287 Changes to settings of inspections applied via quickfix are not persisted --- .../AddIgnoredIdentifierQuickFix.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddIgnoredIdentifierQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddIgnoredIdentifierQuickFix.java index c38ff2ed26ec..3ae2e3c076aa 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddIgnoredIdentifierQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddIgnoredIdentifierQuickFix.java @@ -1,12 +1,11 @@ package com.jetbrains.python.inspections.quickfix; import com.intellij.codeInsight.intention.LowPriorityAction; -import com.intellij.codeInspection.InspectionProfile; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.*; import com.intellij.openapi.project.Project; -import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiElement; +import com.intellij.util.Consumer; import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection; import com.jetbrains.python.psi.impl.PyQualifiedName; import org.jetbrains.annotations.NotNull; @@ -44,15 +43,21 @@ public class AddIgnoredIdentifierQuickFix implements LocalQuickFix, LowPriorityA @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - final PyUnresolvedReferencesInspection instance = PyUnresolvedReferencesInspection.getInstance(descriptor.getPsiElement()); - String name = myIdentifier.toString(); - if (myIgnoreAllAttributes) { - name = name + END_WILDCARD; - } - if (!instance.ignoredIdentifiers.contains(name)) { - instance.ignoredIdentifiers.add(name); - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); - InspectionProfileManager.getInstance().fireProfileChanged(profile); - } + final PsiElement context = descriptor.getPsiElement(); + InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(context); + profile.modifyProfile(new Consumer() { + @Override + public void consume(ModifiableModel model) { + PyUnresolvedReferencesInspection inspection = + (PyUnresolvedReferencesInspection)model.getUnwrappedTool(PyUnresolvedReferencesInspection.class.getSimpleName(), context); + String name = myIdentifier.toString(); + if (myIgnoreAllAttributes) { + name += END_WILDCARD; + } + if (!inspection.ignoredIdentifiers.contains(name)) { + inspection.ignoredIdentifiers.add(name); + } + } + }); } } From 59ef18383b36f97405c69f2139cfd861df1e6310 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 26 Feb 2013 17:48:44 +0400 Subject: [PATCH 02/16] PY-8924 "Ignore errors like this" option is not saved --- .../validation/Pep8ExternalAnnotator.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java index 136b9f76efdb..65dfb6ff6769 100644 --- a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java +++ b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java @@ -1,10 +1,10 @@ package com.jetbrains.python.validation; import com.intellij.codeHighlighting.HighlightDisplayLevel; -import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.ModifiableModel; import com.intellij.codeInspection.ex.CustomEditInspectionToolsSettingsAction; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.execution.process.ProcessOutput; @@ -29,6 +29,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.util.ArrayUtil; +import com.intellij.util.Consumer; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.PythonHelpersLocator; @@ -169,7 +170,7 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator() { @Override @@ -211,11 +212,9 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator myErrors; - public IgnoreErrorFix(String code, List errors) { + public IgnoreErrorFix(String code) { myCode = code; - myErrors = errors; } @NotNull @@ -236,9 +235,14 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator() { + @Override + public void consume(ModifiableModel model) { + PyPep8Inspection tool = (PyPep8Inspection)model.getUnwrappedTool(PyPep8Inspection.INSPECTION_SHORT_NAME, file); + tool.ignoredErrors.add(myCode); + } + }); } @Override From f64ae0c21bf3f8eaa35467bc337c1b4222fe1f8a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 22 Feb 2013 13:03:40 +0100 Subject: [PATCH 03/16] spacing in py3 annotations (PY-8961) --- .../python/formatter/PythonFormattingModelBuilder.java | 1 + python/testData/formatter/spaceInAnnotations.py | 2 ++ python/testData/formatter/spaceInAnnotations_after.py | 2 ++ python/testSrc/com/jetbrains/python/PyFormatterTest.java | 8 ++++++++ 4 files changed, 13 insertions(+) create mode 100644 python/testData/formatter/spaceInAnnotations.py create mode 100644 python/testData/formatter/spaceInAnnotations_after.py diff --git a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java index fd215072fe78..63f8003108a3 100644 --- a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java @@ -84,6 +84,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C .afterInside(GT, ANNOTATION).spaces(1) .betweenInside(MINUS, GT, ANNOTATION).none() .beforeInside(ANNOTATION, FUNCTION_DECLARATION).spaces(1) + .beforeInside(ANNOTATION, NAMED_PARAMETER).none() .between(allButLambda(), PARAMETER_LIST).spaceIf(commonSettings.SPACE_BEFORE_METHOD_PARENTHESES) diff --git a/python/testData/formatter/spaceInAnnotations.py b/python/testData/formatter/spaceInAnnotations.py new file mode 100644 index 000000000000..9e8ed998c55e --- /dev/null +++ b/python/testData/formatter/spaceInAnnotations.py @@ -0,0 +1,2 @@ +def foo(x : int): + pass diff --git a/python/testData/formatter/spaceInAnnotations_after.py b/python/testData/formatter/spaceInAnnotations_after.py new file mode 100644 index 000000000000..219a2c76558e --- /dev/null +++ b/python/testData/formatter/spaceInAnnotations_after.py @@ -0,0 +1,2 @@ +def foo(x: int): + pass diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java index 7da411bbb1ea..6eb7165ef742 100644 --- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java +++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java @@ -66,6 +66,10 @@ public class PyFormatterTest extends PyTestCase { } public void testStarExpression() { // PY-1523 + doTestPy3(); + } + + private void doTestPy3() { PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON30); try { doTest(); @@ -304,6 +308,10 @@ public class PyFormatterTest extends PyTestCase { } } + public void testSpaceInAnnotations() { // PY-8961 + doTestPy3(); + } + private void doTest() { myFixture.configureByFile("formatter/" + getTestName(true) + ".py"); ApplicationManager.getApplication().runWriteAction(new Runnable() { From 9b598f97a12cdb51bafd38f6ed13be705012f2b5 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 26 Feb 2013 15:05:43 +0100 Subject: [PATCH 04/16] moving core part of PythonModuleBuilder to common code between PyCharm and the plugin, so that it can be used by the Flask project generator in the Python plugin --- .../python/module/PythonModuleBuilder.java | 48 +-------------- .../python/module/PythonModuleType.java | 5 -- .../python/PythonModuleTypeBase.java | 5 ++ .../module/PythonModuleBuilderBase.java | 59 +++++++++++++++++++ 4 files changed, 65 insertions(+), 52 deletions(-) create mode 100644 python/src/com/jetbrains/python/module/PythonModuleBuilderBase.java diff --git a/python/pluginSrc/com/jetbrains/python/module/PythonModuleBuilder.java b/python/pluginSrc/com/jetbrains/python/module/PythonModuleBuilder.java index 4705b895ad6c..fa0916a41a02 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PythonModuleBuilder.java +++ b/python/pluginSrc/com/jetbrains/python/module/PythonModuleBuilder.java @@ -1,14 +1,7 @@ package com.jetbrains.python.module; -import com.intellij.ide.util.projectWizard.ModuleBuilder; import com.intellij.ide.util.projectWizard.SourcePathsBuilder; -import com.intellij.openapi.module.ModuleType; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.SdkTypeId; -import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.util.Pair; -import com.jetbrains.python.sdk.PythonSdkType; import java.util.ArrayList; import java.util.List; @@ -16,25 +9,8 @@ import java.util.List; /** * @author yole */ -public class PythonModuleBuilder extends ModuleBuilder implements SourcePathsBuilder { +public class PythonModuleBuilder extends PythonModuleBuilderBase implements SourcePathsBuilder { private List> mySourcePaths; - private Sdk mySdk; - private final List mySdkChangedListeners = new ArrayList(); - - public void setupRootModel(final ModifiableRootModel rootModel) throws ConfigurationException { - if (mySdk != null) { - rootModel.setSdk(mySdk); - } - else { - rootModel.inheritSdk(); - } - - doAddContentEntry(rootModel); - } - - public ModuleType getModuleType() { - return PythonModuleType.getInstance(); - } public List> getSourcePaths() { return mySourcePaths; @@ -50,26 +26,4 @@ public class PythonModuleBuilder extends ModuleBuilder implements SourcePathsBui } mySourcePaths.add(sourcePathInfo); } - - public Sdk getSdk() { - return mySdk; - } - - public void setSdk(final Sdk sdk) { - if (mySdk != sdk) { - mySdk = sdk; - for (Runnable runnable : mySdkChangedListeners) { - runnable.run(); - } - } - } - - public void addSdkChangedListener(Runnable runnable) { - mySdkChangedListeners.add(runnable); - } - - @Override - public boolean isSuitableSdkType(SdkTypeId sdk) { - return sdk instanceof PythonSdkType; - } } diff --git a/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java b/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java index 1c80deca9a3d..1855a00b8963 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java +++ b/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java @@ -6,7 +6,6 @@ import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil; import com.intellij.ide.util.newProjectWizard.SupportForFrameworksStep; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.WizardContext; -import com.intellij.openapi.module.ModuleTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; @@ -20,10 +19,6 @@ import java.util.List; * @author yole */ public class PythonModuleType extends PythonModuleTypeBase { - public static PythonModuleType getInstance() { - return (PythonModuleType)ModuleTypeManager.getInstance().findByID(PYTHON_MODULE); - } - @Override public ModuleWizardStep[] createWizardSteps(final WizardContext wizardContext, final PythonModuleBuilder moduleBuilder, diff --git a/python/src/com/jetbrains/python/PythonModuleTypeBase.java b/python/src/com/jetbrains/python/PythonModuleTypeBase.java index f6eb24910cb9..c775ada20d2f 100644 --- a/python/src/com/jetbrains/python/PythonModuleTypeBase.java +++ b/python/src/com/jetbrains/python/PythonModuleTypeBase.java @@ -2,6 +2,7 @@ package com.jetbrains.python; import com.intellij.ide.util.projectWizard.ModuleBuilder; import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.module.ModuleTypeManager; import icons.PythonIcons; import org.jetbrains.annotations.NonNls; @@ -11,6 +12,10 @@ import javax.swing.*; * @author yole */ public abstract class PythonModuleTypeBase extends ModuleType { + public static ModuleType getInstance() { + return ModuleTypeManager.getInstance().findByID(PYTHON_MODULE); + } + @NonNls public static final String PYTHON_MODULE = "PYTHON_MODULE"; protected PythonModuleTypeBase() { diff --git a/python/src/com/jetbrains/python/module/PythonModuleBuilderBase.java b/python/src/com/jetbrains/python/module/PythonModuleBuilderBase.java new file mode 100644 index 000000000000..34415c59b611 --- /dev/null +++ b/python/src/com/jetbrains/python/module/PythonModuleBuilderBase.java @@ -0,0 +1,59 @@ +package com.jetbrains.python.module; + +import com.intellij.ide.util.projectWizard.ModuleBuilder; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkTypeId; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.jetbrains.python.PythonModuleTypeBase; +import com.jetbrains.python.sdk.PythonSdkType; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yole + */ +public class PythonModuleBuilderBase extends ModuleBuilder { + private final List mySdkChangedListeners = new ArrayList(); + private Sdk mySdk; + + public void setupRootModel(final ModifiableRootModel rootModel) throws ConfigurationException { + if (mySdk != null) { + rootModel.setSdk(mySdk); + } + else { + rootModel.inheritSdk(); + } + + doAddContentEntry(rootModel); + } + + @Override + public ModuleType getModuleType() { + return PythonModuleTypeBase.getInstance(); + } + + public Sdk getSdk() { + return mySdk; + } + + public void setSdk(final Sdk sdk) { + if (mySdk != sdk) { + mySdk = sdk; + for (Runnable runnable : mySdkChangedListeners) { + runnable.run(); + } + } + } + + public void addSdkChangedListener(Runnable runnable) { + mySdkChangedListeners.add(runnable); + } + + @Override + public boolean isSuitableSdkType(SdkTypeId sdk) { + return sdk instanceof PythonSdkType; + } +} From d841b84c4a01b0b6e3bfc935803de081fe331cde Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 12:10:04 +0100 Subject: [PATCH 05/16] allow using Flask plugin when running IntelliJ IDEA under debugger --- .../python/module/PyModuleService.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 python/openapi/src/com/jetbrains/python/module/PyModuleService.java diff --git a/python/openapi/src/com/jetbrains/python/module/PyModuleService.java b/python/openapi/src/com/jetbrains/python/module/PyModuleService.java new file mode 100644 index 000000000000..69214ec32be5 --- /dev/null +++ b/python/openapi/src/com/jetbrains/python/module/PyModuleService.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.module; + +import com.intellij.ide.util.projectWizard.ModuleBuilder; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.platform.DirectoryProjectGenerator; + +/** + * @author yole + */ +public abstract class PyModuleService { + public static PyModuleService getInstance() { + return ServiceManager.getService(PyModuleService.class); + } + + /** + * Creates a ModuleBuilder that creates a Python module and runs the specified DirectoryProjectGenerator to perform + * further initialization. The showGenerationSettings() method on the generator is not called, and the generateProject() method + * receives null as the 'settings' parameter. + * + * @param generator the generator to run for configuring the project + * @return the created module builder instance + */ + public abstract ModuleBuilder createPythonModuleBuilder(DirectoryProjectGenerator generator); +} From 132b4a07890131f4acf94badc5e8784d19e75adb Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 12:26:29 +0100 Subject: [PATCH 06/16] OpenAPI for accessing PythonModuleBuilder --- .../python/module/PythonModuleType.java | 4 +- .../python/module/PythonSdkSelectStep.java | 4 +- python/src/META-INF/python-plugin-common.xml | 2 + .../python/module/PyModuleServiceImpl.java | 14 +++++++ .../module/PythonModuleBuilderBase.java | 38 +++++++++++++++++++ 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 python/src/com/jetbrains/python/module/PyModuleServiceImpl.java diff --git a/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java b/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java index 1855a00b8963..b877b374d3d4 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java +++ b/python/pluginSrc/com/jetbrains/python/module/PythonModuleType.java @@ -18,10 +18,10 @@ import java.util.List; /** * @author yole */ -public class PythonModuleType extends PythonModuleTypeBase { +public class PythonModuleType extends PythonModuleTypeBase { @Override public ModuleWizardStep[] createWizardSteps(final WizardContext wizardContext, - final PythonModuleBuilder moduleBuilder, + final PythonModuleBuilderBase moduleBuilder, final ModulesProvider modulesProvider) { ArrayList steps = new ArrayList(); final Project project = getProject(wizardContext); diff --git a/python/pluginSrc/com/jetbrains/python/module/PythonSdkSelectStep.java b/python/pluginSrc/com/jetbrains/python/module/PythonSdkSelectStep.java index b3526b050e4b..d9277d6f3f5d 100644 --- a/python/pluginSrc/com/jetbrains/python/module/PythonSdkSelectStep.java +++ b/python/pluginSrc/com/jetbrains/python/module/PythonSdkSelectStep.java @@ -13,11 +13,11 @@ import javax.swing.*; */ public class PythonSdkSelectStep extends ModuleWizardStep { protected final PythonSdkChooserPanel myPanel; - protected final PythonModuleBuilder mySettingsHolder; + protected final PythonModuleBuilderBase mySettingsHolder; private final String myHelp; - public PythonSdkSelectStep(@NotNull final PythonModuleBuilder settingsHolder, + public PythonSdkSelectStep(@NotNull final PythonModuleBuilderBase settingsHolder, @Nullable final String helpId, @Nullable final Project project) { super(); diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml index 46f1629c1e8b..079051743919 100644 --- a/python/src/META-INF/python-plugin-common.xml +++ b/python/src/META-INF/python-plugin-common.xml @@ -71,6 +71,8 @@ + mySdkChangedListeners = new ArrayList(); + private final DirectoryProjectGenerator myGenerator; private Sdk mySdk; + public PythonModuleBuilderBase() { + myGenerator = null; + } + + public PythonModuleBuilderBase(DirectoryProjectGenerator generator) { + myGenerator = generator; + } + + @Override + public String getGroupName() { + return "Python"; + } + public void setupRootModel(final ModifiableRootModel rootModel) throws ConfigurationException { if (mySdk != null) { rootModel.setSdk(mySdk); @@ -56,4 +78,20 @@ public class PythonModuleBuilderBase extends ModuleBuilder { public boolean isSuitableSdkType(SdkTypeId sdk) { return sdk instanceof PythonSdkType; } + + @Nullable + @Override + public Module commitModule(@NotNull Project project, @Nullable ModifiableModuleModel model) { + Module module = super.commitModule(project, model); + if (module != null && myGenerator != null) { + ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + VirtualFile[] contentRoots = moduleRootManager.getContentRoots(); + VirtualFile dir = module.getProject().getBaseDir(); + if (contentRoots.length > 0 && contentRoots[0] != null) { + dir = contentRoots[0]; + } + myGenerator.generateProject(project, dir, null, module); + } + return module; + } } From 1c4463cae8f76a857d1f9e83f30945ca031b7b37 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 13:21:05 +0100 Subject: [PATCH 07/16] show path mappings combobox in Python plugin run configurations (PY-8868) --- .../python/run/PyPluginCommonOptionsForm.form | 13 +++++++-- .../python/run/PyPluginCommonOptionsForm.java | 28 ++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.form b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.form index 61eee424c21d..ba62e38b0472 100644 --- a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.form +++ b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.form @@ -1,9 +1,9 @@
- + - + @@ -99,6 +99,15 @@ + + + + + + + + + diff --git a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java index bb8580cf8a5e..bc876738663a 100644 --- a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java +++ b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java @@ -1,10 +1,14 @@ package com.jetbrains.python.run; import com.intellij.execution.configuration.EnvironmentVariablesComponent; +import com.intellij.execution.util.PathMappingsComponent; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.ui.configuration.ModulesAlphaComparator; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; @@ -12,6 +16,7 @@ import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.RawCommandLineEditor; import com.intellij.ui.components.JBLabel; import com.intellij.util.PathMappingSettings; +import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.Nullable; @@ -27,6 +32,7 @@ import java.util.Map; * @author yole */ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm { + private final Project myProject; private TextFieldWithBrowseButton myWorkingDirectoryTextField; private EnvironmentVariablesComponent myEnvsComponent; private RawCommandLineEditor myInterpreterOptionsTextField; @@ -38,10 +44,12 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm { private JBLabel myPythonInterpreterJBLabel; private JBLabel myInterpreterOptionsJBLabel; private JBLabel myWorkingDirectoryJBLabel; + private PathMappingsComponent myPathMappingsComponent; private JComponent labelAnchor; public PyPluginCommonOptionsForm(PyCommonOptionsFormData data) { // setting modules + myProject = data.getProject(); final List validModules = data.getValidModules(); Collections.sort(validModules, new ModulesAlphaComparator()); Module selection = validModules.size() > 0 ? validModules.get(0) : null; @@ -59,13 +67,18 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm { }; myUseSpecifiedSdkRadioButton.addActionListener(listener); myUseModuleSdkRadioButton.addActionListener(listener); + myInterpreterComboBox.addActionListener(listener); + myModuleComboBox.addActionListener(listener); setAnchor(myEnvsComponent.getLabel()); + myPathMappingsComponent.setAnchor(myEnvsComponent.getLabel()); + updateControls(); } private void updateControls() { myModuleComboBox.setEnabled(myUseModuleSdkRadioButton.isSelected()); myInterpreterComboBox.setEnabled(myUseSpecifiedSdkRadioButton.isSelected()); + myPathMappingsComponent.setVisible(PySdkUtil.isRemote(getSelectedSdk())); } public JPanel getMainPanel() { @@ -162,11 +175,24 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm { @Override public PathMappingSettings getMappingSettings() { - return null; //TODO: implement for plugin + return myPathMappingsComponent.getMappingSettings(); } @Override public void setMappingSettings(@Nullable PathMappingSettings mappingSettings) { + myPathMappingsComponent.setMappingSettings(mappingSettings); + } + + private Sdk getSelectedSdk() { + if (isUseModuleSdk()) { + Module module = getModule(); + return module == null ? null : ModuleRootManager.getInstance(module).getSdk(); + } + Sdk sdk = (Sdk)myInterpreterComboBox.getSelectedItem(); + if (sdk == null) { + return ProjectRootManager.getInstance(myProject).getProjectSdk(); + } + return sdk; } @Override From c18cade9356c60d185c46e4531a5a135c5bd7994 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 13:43:33 +0100 Subject: [PATCH 08/16] remote Python interpreters are always considered valid (PY-8079) --- python/src/com/jetbrains/python/sdk/PythonSdkType.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index 577d1dc4323f..50ac6a39ad36 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -769,6 +769,14 @@ public class PythonSdkType extends SdkType { return type == OrderRootType.CLASSES; } + public boolean sdkHasValidPath(@NotNull Sdk sdk) { + if (PySdkUtil.isRemote(sdk)) { + return true; + } + VirtualFile homeDir = sdk.getHomeDirectory(); + return homeDir != null && homeDir.isValid(); + } + public static boolean isStdLib(VirtualFile vFile, Sdk pythonSdk) { if (pythonSdk != null) { final VirtualFile libDir = PyProjectScopeBuilder.findLibDir(pythonSdk); From 711b773c4a4c9f74b381a7167a312c24245ad783 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 13:55:23 +0100 Subject: [PATCH 09/16] sort packages in Manage Python Packages (PY-6918); disprefer remote interpreters when sorting by preference --- .../jetbrains/python/packaging/PyManagePackagesDialog.java | 7 ++++++- .../jetbrains/python/run/PyPluginCommonOptionsForm.java | 2 ++ .../com/jetbrains/python/sdk/PreferredSdkComparator.java | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/python/pluginSrc/com/jetbrains/python/packaging/PyManagePackagesDialog.java b/python/pluginSrc/com/jetbrains/python/packaging/PyManagePackagesDialog.java index 10df2be1d38f..6261a4a6bab7 100644 --- a/python/pluginSrc/com/jetbrains/python/packaging/PyManagePackagesDialog.java +++ b/python/pluginSrc/com/jetbrains/python/packaging/PyManagePackagesDialog.java @@ -7,6 +7,7 @@ import com.intellij.openapi.ui.LabeledComponent; import com.intellij.ui.CollectionComboBoxModel; import com.jetbrains.python.packaging.ui.PyPackagesNotificationPanel; import com.jetbrains.python.packaging.ui.PyPackagesPanel; +import com.jetbrains.python.sdk.PreferredSdkComparator; import com.jetbrains.python.sdk.PySdkListCellRenderer; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -15,6 +16,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.*; +import java.util.List; /** * @author yole @@ -26,7 +29,9 @@ public class PyManagePackagesDialog extends DialogWrapper { super(project, true); setTitle("Manage Python Packages"); - final JComboBox sdkComboBox = new JComboBox(new CollectionComboBoxModel(PythonSdkType.getAllSdks(), sdk)); + List sdks = PythonSdkType.getAllSdks(); + Collections.sort(sdks, new PreferredSdkComparator()); + final JComboBox sdkComboBox = new JComboBox(new CollectionComboBoxModel(sdks, sdk)); sdkComboBox.setRenderer(new PySdkListCellRenderer(null)); PyPackagesNotificationPanel notificationPanel = new PyPackagesNotificationPanel(project); diff --git a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java index bc876738663a..e036c499fbce 100644 --- a/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java +++ b/python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java @@ -16,6 +16,7 @@ import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.RawCommandLineEditor; import com.intellij.ui.components.JBLabel; import com.intellij.util.PathMappingSettings; +import com.jetbrains.python.sdk.PreferredSdkComparator; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.Nullable; @@ -125,6 +126,7 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm { List sdkList = new ArrayList(); sdkList.add(null); final List allSdks = PythonSdkType.getAllSdks(); + Collections.sort(allSdks, new PreferredSdkComparator()); Sdk selection = null; for (Sdk sdk : allSdks) { String homePath = sdk.getHomePath(); diff --git a/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java b/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java index 26d166314d00..0cbf41fa9338 100644 --- a/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java +++ b/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java @@ -17,6 +17,11 @@ public class PreferredSdkComparator implements Comparator { public int compare(Sdk o1, Sdk o2) { final PythonSdkFlavor flavor1 = PythonSdkFlavor.getFlavor(o1); final PythonSdkFlavor flavor2 = PythonSdkFlavor.getFlavor(o2); + int remote1Weight = PySdkUtil.isRemote(o1) ? 0 : 1; + int remote2Weight = PySdkUtil.isRemote(o2) ? 0 : 1; + if (remote1Weight != remote2Weight) { + return remote2Weight - remote1Weight; + } int venv1weight = PythonSdkType.isVirtualEnv(o1) ? 0 : 1; int venv2weight = PythonSdkType.isVirtualEnv(o2) ? 0 : 1; if (venv1weight != venv2weight) { From 040b623afc2faf8037c9d226b52c267100775b5e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Feb 2013 14:09:13 +0100 Subject: [PATCH 10/16] don't swallow exceptions --- .../src/com/jetbrains/python/packaging/PyPIPackageUtil.java | 1 + .../jetbrains/python/packaging/ui/ManagePackagesDialog.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java index eaf67bf3cc49..003ccc5e1e66 100644 --- a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java @@ -130,6 +130,7 @@ public class PyPIPackageUtil { myXmlRpcClient.executeAsync("release_data", params, callback); } catch (Exception ignored) { + LOG.info(ignored); } } else diff --git a/python/src/com/jetbrains/python/packaging/ui/ManagePackagesDialog.java b/python/src/com/jetbrains/python/packaging/ui/ManagePackagesDialog.java index 3be7eb610a10..6c35ecc9aedb 100644 --- a/python/src/com/jetbrains/python/packaging/ui/ManagePackagesDialog.java +++ b/python/src/com/jetbrains/python/packaging/ui/ManagePackagesDialog.java @@ -6,6 +6,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.ui.DialogWrapper; @@ -49,6 +50,8 @@ import java.util.List; */ @SuppressWarnings("UseOfObsoleteCollectionType") public class ManagePackagesDialog extends DialogWrapper { + private static final Logger LOG = Logger.getInstance(ManagePackagesDialog.class); + @NonNls private static final String TEXT_PREFIX = "" + "