Merge remote-tracking branch 'origin/master'

Conflicts:
	python/ideSrc/com/jetbrains/python/PyIdeCommonOptionsForm.java
	python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.form
	python/pluginSrc/com/jetbrains/python/run/PyPluginCommonOptionsForm.java
This commit is contained in:
Ekaterina Tuzova
2013-02-27 19:26:16 +04:00
34 changed files with 466 additions and 216 deletions
@@ -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);
}
+2 -2
View File
@@ -4,9 +4,9 @@
<id>Pythonid</id>
<name>Python</name>
<idea-version since-build="122.0" until-build="123.0"/>
<idea-version since-build="128.0" until-build="129.999"/>
<description>Smart editing for Python scripts</description>
<version>2.10.0</version>
<version>2.10.1</version>
<depends>com.intellij.modules.ultimate</depends>
<depends>com.intellij.modules.java</depends>
<depends>Coverage</depends>
@@ -4,9 +4,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
import com.intellij.openapi.projectRoots.ui.ProjectJdksEditor;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.jetbrains.python.sdk.PySdkListCellRenderer;
import com.jetbrains.python.sdk.PythonSdkType;
import javax.swing.*;
@@ -21,7 +21,7 @@ public class PythonSdkComboBox extends ComboboxWithBrowseButton {
private Project myProject;
public PythonSdkComboBox() {
getComboBox().setRenderer(new SdkListCellRenderer("<No Interpreter>"));
getComboBox().setRenderer(new PySdkListCellRenderer("<No Interpreter>", null));
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Sdk selectedSdk = getSelectedSdk();
@@ -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<Pair<String, String>> mySourcePaths;
private Sdk mySdk;
private final List<Runnable> mySdkChangedListeners = new ArrayList<Runnable>();
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<Pair<String, String>> 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;
}
}
@@ -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;
@@ -19,14 +18,10 @@ import java.util.List;
/**
* @author yole
*/
public class PythonModuleType extends PythonModuleTypeBase<PythonModuleBuilder> {
public static PythonModuleType getInstance() {
return (PythonModuleType)ModuleTypeManager.getInstance().findByID(PYTHON_MODULE);
}
public class PythonModuleType extends PythonModuleTypeBase<PythonModuleBuilderBase> {
@Override
public ModuleWizardStep[] createWizardSteps(final WizardContext wizardContext,
final PythonModuleBuilder moduleBuilder,
final PythonModuleBuilderBase moduleBuilder,
final ModulesProvider modulesProvider) {
ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
final Project project = getProject(wizardContext);
@@ -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();
@@ -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,8 +29,10 @@ public class PyManagePackagesDialog extends DialogWrapper {
super(project, true);
setTitle("Manage Python Packages");
final JComboBox sdkComboBox = new JComboBox(new CollectionComboBoxModel(PythonSdkType.getAllSdks(), sdk));
sdkComboBox.setRenderer(new PySdkListCellRenderer(null));
List<Sdk> sdks = PythonSdkType.getAllSdks();
Collections.sort(sdks, new PreferredSdkComparator());
final JComboBox sdkComboBox = new JComboBox(new CollectionComboBoxModel(sdks, sdk));
sdkComboBox.setRenderer(new PySdkListCellRenderer());
PyPackagesNotificationPanel notificationPanel = new PyPackagesNotificationPanel(project);
final PyPackagesPanel packagesPanel = new PyPackagesPanel(project, notificationPanel);
@@ -7,9 +7,11 @@ import com.intellij.psi.ResolveState;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.AccessDirection;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.CompletionVariantsProcessor;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
@@ -20,11 +22,13 @@ import java.util.List;
/**
* @author yole
*/
public class PyJavaClassType implements PyType {
public class PyJavaClassType implements PyCallableType {
private final PsiClass myClass;
private final boolean myDefinition;
public PyJavaClassType(final PsiClass aClass) {
public PyJavaClassType(final PsiClass aClass, boolean definition) {
myClass = aClass;
myDefinition = definition;
}
@Nullable
@@ -68,4 +72,18 @@ public class PyJavaClassType implements PyType {
@Override
public void assertValid(String message) {
}
@Override
public boolean isCallable() {
return myDefinition;
}
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
if (myDefinition) {
return new PyJavaClassType(myClass, false);
}
return null;
}
}
@@ -23,7 +23,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
@Nullable
public PyType getReferenceType(@NotNull final PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor) {
if (referenceTarget instanceof PsiClass) {
return new PyJavaClassType((PsiClass) referenceTarget);
return new PyJavaClassType((PsiClass) referenceTarget, true);
}
if (referenceTarget instanceof PsiPackage) {
return new PyJavaPackageType((PsiPackage) referenceTarget, anchor == null ? null : ModuleUtil.findModuleForPsiElement(anchor));
@@ -44,7 +44,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
final PsiClassType classType = (PsiClassType)type;
final PsiClass psiClass = classType.resolve();
if (psiClass != null) {
return new PyJavaClassType(psiClass);
return new PyJavaClassType(psiClass, false);
}
}
return null;
@@ -67,7 +67,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
if (paramType instanceof PsiClassType) {
final PsiClass psiClass = ((PsiClassType)paramType).resolve();
if (psiClass != null) {
superMethodParameterTypes.add(new PyJavaClassType(psiClass));
superMethodParameterTypes.add(new PyJavaClassType(psiClass, false));
}
}
}
@@ -1,114 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.run.PyPluginCommonOptionsForm">
<grid id="8816" binding="myHideablePanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="447" height="197"/>
<xy x="20" y="20" width="429" height="215"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<component id="c3528" class="com.intellij.ui.components.JBLabel" binding="myWorkingDirectoryJBLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value=""/>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.working_directory"/>
</properties>
</component>
<component id="78c75" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myWorkingDirectoryTextField">
<constraints>
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="c3528" class="com.intellij.ui.components.JBLabel" binding="myWorkingDirectoryJBLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value=""/>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.working_directory"/>
</properties>
</component>
<component id="78c75" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myWorkingDirectoryTextField">
<constraints>
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="32654" class="com.intellij.execution.configuration.EnvironmentVariablesComponent" binding="myEnvsComponent">
<constraints>
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelLocation value="West"/>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.environment_variables"/>
</properties>
</component>
<component id="cdd29" class="com.intellij.ui.components.JBLabel" binding="myInterpreterOptionsJBLabel">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.interpreter_options"/>
</properties>
</component>
<component id="1a856" class="com.intellij.ui.RawCommandLineEditor" binding="myInterpreterOptionsTextField">
<constraints>
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<dialogCaption resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.captions.interpreter_options_dialog"/>
<text value=""/>
</properties>
</component>
<component id="a4f87" class="com.intellij.ui.components.JBLabel" binding="myPythonInterpreterJBLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Python Interpreter:"/>
</properties>
</component>
<component id="64e87" class="javax.swing.JRadioButton" binding="myUseModuleSdkRadioButton" default-binding="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text value="Use SDK of module:"/>
</properties>
</component>
<component id="5f300" class="javax.swing.JComboBox" binding="myModuleComboBox">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="b7269" class="javax.swing.JRadioButton" binding="myUseSpecifiedSdkRadioButton">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.interpreter"/>
</properties>
</component>
<component id="fc9a3" class="javax.swing.JComboBox" binding="myInterpreterComboBox" default-binding="true">
<constraints>
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="a3bda">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="-1" height="15"/>
<preferred-size width="-1" height="15"/>
<maximum-size width="-1" height="15"/>
</grid>
</constraints>
</vspacer>
</children>
</grid>
</component>
<component id="32654" class="com.intellij.execution.configuration.EnvironmentVariablesComponent" binding="myEnvsComponent">
<constraints>
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelLocation value="West"/>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.environment_variables"/>
</properties>
</component>
<component id="cdd29" class="com.intellij.ui.components.JBLabel" binding="myInterpreterOptionsJBLabel">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.interpreter_options"/>
</properties>
</component>
<component id="1a856" class="com.intellij.ui.RawCommandLineEditor" binding="myInterpreterOptionsTextField">
<constraints>
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<dialogCaption resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.captions.interpreter_options_dialog"/>
<text value=""/>
</properties>
</component>
<component id="a4f87" class="com.intellij.ui.components.JBLabel" binding="myPythonInterpreterJBLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Python Interpreter:"/>
</properties>
</component>
<component id="64e87" class="javax.swing.JRadioButton" binding="myUseModuleSdkRadioButton" default-binding="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text value="Use SDK of module:"/>
</properties>
</component>
<component id="5f300" class="javax.swing.JComboBox" binding="myModuleComboBox">
<constraints>
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="b7269" class="javax.swing.JRadioButton" binding="myUseSpecifiedSdkRadioButton">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="com/jetbrains/python/PyBundle" key="runcfg.labels.interpreter"/>
</properties>
</component>
<component id="fc9a3" class="javax.swing.JComboBox" binding="myInterpreterComboBox" default-binding="true">
<constraints>
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="a3bda">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="-1" height="15"/>
<preferred-size width="-1" height="15"/>
<maximum-size width="-1" height="15"/>
</grid>
</constraints>
</vspacer>
<component id="86ab7" class="com.intellij.execution.util.PathMappingsComponent" binding="myPathMappingsComponent">
<constraints>
<grid row="6" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelLocation value="West"/>
<text value="Path mappings"/>
</properties>
</component>
</children>
</grid>
<buttonGroups>
@@ -2,10 +2,14 @@ package com.jetbrains.python.run;
import com.intellij.execution.configuration.EnvironmentVariablesComponent;
import com.intellij.ide.util.PropertiesComponent;
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;
@@ -14,6 +18,8 @@ import com.intellij.ui.HideableDecorator;
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.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -30,6 +36,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;
@@ -42,11 +49,13 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm {
private JBLabel myInterpreterOptionsJBLabel;
private JBLabel myWorkingDirectoryJBLabel;
private JPanel myHideablePanel;
private PathMappingsComponent myPathMappingsComponent;
private JComponent labelAnchor;
private final HideableDecorator myDecorator;
public PyPluginCommonOptionsForm(PyCommonOptionsFormData data) {
// setting modules
myProject = data.getProject();
final List<Module> validModules = data.getValidModules();
Collections.sort(validModules, new ModulesAlphaComparator());
Module selection = validModules.size() > 0 ? validModules.get(0) : null;
@@ -64,6 +73,8 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm {
};
myUseSpecifiedSdkRadioButton.addActionListener(listener);
myUseModuleSdkRadioButton.addActionListener(listener);
myInterpreterComboBox.addActionListener(listener);
myModuleComboBox.addActionListener(listener);
setAnchor(myEnvsComponent.getLabel());
@@ -86,11 +97,14 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm {
};
myDecorator.setOn(PropertiesComponent.getInstance().getBoolean(EXPAND_PROPERTY_KEY, true));
myDecorator.setContentComponent(myMainPanel);
myPathMappingsComponent.setAnchor(myEnvsComponent.getLabel());
updateControls();
}
private void updateControls() {
myModuleComboBox.setEnabled(myUseModuleSdkRadioButton.isSelected());
myInterpreterComboBox.setEnabled(myUseSpecifiedSdkRadioButton.isSelected());
myPathMappingsComponent.setVisible(PySdkUtil.isRemote(getSelectedSdk()));
}
public JPanel getMainPanel() {
@@ -137,6 +151,7 @@ public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm {
List<Sdk> sdkList = new ArrayList<Sdk>();
sdkList.add(null);
final List<Sdk> allSdks = PythonSdkType.getAllSdks();
Collections.sort(allSdks, new PreferredSdkComparator());
Sdk selection = null;
for (Sdk sdk : allSdks) {
String homePath = sdk.getHomePath();
@@ -187,11 +202,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
@@ -0,0 +1,22 @@
package com.jetbrains.jython;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.inspections.PyCallingNonCallableInspection;
/**
* @author yole
*/
public class PyJythonHighlightingTest extends LightCodeInsightFixtureTestCase {
public void testCallableJavaClass() {
myFixture.configureByFile("callableJavaClass.py");
myFixture.enableInspections(PyCallingNonCallableInspection.class);
myFixture.checkHighlighting(true, false, false);
}
@Override
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/highlighting/jython/";
}
}
@@ -11,6 +11,11 @@ import org.jetbrains.annotations.Nullable;
* @author yole
*/
public interface PyCallableType extends PyType {
/**
* Returns true if the type is callable.
*/
boolean isCallable();
/**
* Returns the type which is the result of calling an instance of this type.
*
@@ -71,6 +71,8 @@
<applicationService serviceInterface="com.jetbrains.python.packaging.PyPackageService"
serviceImplementation="com.jetbrains.python.packaging.PyPackageService"/>
<applicationService serviceInterface="com.jetbrains.python.module.PyModuleService"
serviceImplementation="com.jetbrains.python.module.PyModuleServiceImpl"/>
<typedHandler implementation="com.jetbrains.python.codeInsight.KeywordTypedHandler" id="pyCommaAfterKwd"/>
<typedHandler implementation="com.jetbrains.django.lang.template.editor.DjangoBracesInterpolationTypedHandler"
@@ -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<T extends ModuleBuilder> extends ModuleType<T> {
public static ModuleType getInstance() {
return ModuleTypeManager.getInstance().findByID(PYTHON_MODULE);
}
@NonNls public static final String PYTHON_MODULE = "PYTHON_MODULE";
protected PythonModuleTypeBase() {
@@ -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)
@@ -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<ModifiableModel>() {
@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);
}
}
});
}
}
@@ -0,0 +1,14 @@
package com.jetbrains.python.module;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.platform.DirectoryProjectGenerator;
/**
* @author yole
*/
public class PyModuleServiceImpl extends PyModuleService {
@Override
public ModuleBuilder createPythonModuleBuilder(DirectoryProjectGenerator generator) {
return new PythonModuleBuilderBase(generator);
}
}
@@ -0,0 +1,97 @@
package com.jetbrains.python.module;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.jetbrains.python.PythonModuleTypeBase;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class PythonModuleBuilderBase extends ModuleBuilder {
private final List<Runnable> mySdkChangedListeners = new ArrayList<Runnable>();
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);
}
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;
}
@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;
}
}
@@ -130,6 +130,7 @@ public class PyPIPackageUtil {
myXmlRpcClient.executeAsync("release_data", params, callback);
}
catch (Exception ignored) {
LOG.info(ignored);
}
}
else
@@ -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 = "<html><head>" +
" <style type=\"text/css\">" +
" p {" +
@@ -462,6 +465,7 @@ public class ManagePackagesDialog extends DialogWrapper {
}
@Override
public void handleError(Exception exception, URL url, String method) {
LOG.info("Error retrieving releases from PyPI", exception);
}
});
}
@@ -481,6 +485,7 @@ public class ManagePackagesDialog extends DialogWrapper {
}
@Override
public void handleError(Exception exception, URL url, String method) {
LOG.info("Error retrieving package details from PyPI", exception);
}
});
}
@@ -220,6 +220,26 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
return PyBuiltinCache.getInstance(myClass).getObjectType("type");
}
@Override
public boolean isCallable() {
if (isDefinition()) {
return true;
}
if (isMethodType(this)) {
return true;
}
final PyClass cls = getPyClass();
if (PyABCUtil.isSubclass(cls, PyNames.CALLABLE)) {
return true;
}
return false;
}
private static boolean isMethodType(@NotNull PyClassType type) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(type.getPyClass());
return type.equals(builtinCache.getClassMethodType()) || type.equals(builtinCache.getStaticMethodType());
}
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
@@ -22,6 +22,11 @@ public class PyFunctionType implements PyCallableType {
myCallable = callable;
}
@Override
public boolean isCallable() {
return true;
}
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
@@ -427,19 +427,6 @@ public class PyTypeChecker {
if (type == null || type instanceof PyTypeReference) {
return null;
}
else if (type instanceof PyClassType) {
final PyClassType classType = (PyClassType)type;
if (classType.isDefinition()) {
return true;
}
if (isMethodType(classType)) {
return true;
}
final PyClass cls = classType.getPyClass();
if (PyABCUtil.isSubclass(cls, PyNames.CALLABLE)) {
return true;
}
}
else if (type instanceof PyUnionType) {
Boolean result = true;
for (PyType member : ((PyUnionType)type).getMembers()) {
@@ -454,16 +441,11 @@ public class PyTypeChecker {
return result;
}
else if (type instanceof PyCallableType) {
return true;
return ((PyCallableType) type).isCallable();
}
return false;
}
private static boolean isMethodType(@NotNull PyClassType type) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(type.getPyClass());
return type.equals(builtinCache.getClassMethodType()) || type.equals(builtinCache.getStaticMethodType());
}
/**
* Hack for skipping type checking for method calls of union members if there are several call alternatives.
*
@@ -112,6 +112,8 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
if (project == null || project.isDefault() || !PlatformUtils.isPyCharm()) {
myMakeAvailableToAllProjectsCheckbox.setSelected(true);
myMakeAvailableToAllProjectsCheckbox.setVisible(false);
mySetAsProjectInterpreterCheckbox.setSelected(false);
mySetAsProjectInterpreterCheckbox.setVisible(false);
}
else if (isNewProject) {
mySetAsProjectInterpreterCheckbox.setText("Set as project interpreter for the project being created");
@@ -220,7 +222,7 @@ public class CreateVirtualEnvDialog extends IdeaDialog {
}
private void updateSdkList(final List<Sdk> allSdks, @Nullable Sdk initialSelection) {
mySdkCombo.setRenderer(new PySdkListCellRenderer(null));
mySdkCombo.setRenderer(new PySdkListCellRenderer());
List<Sdk> baseSdks = new ArrayList<Sdk>();
for (Sdk s : allSdks) {
if (!PythonSdkType.isInvalid(s) && !PythonSdkType.isVirtualEnv(s) && !RemoteSdkDataHolder.isRemoteSdk(s.getHomePath())) {
@@ -17,6 +17,11 @@ public class PreferredSdkComparator implements Comparator<Sdk> {
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) {
@@ -13,9 +13,16 @@ import javax.swing.*;
import java.util.Map;
public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
private final String myNullText;
private final Map<Sdk, SdkModificator> mySdkModifiers;
public PySdkListCellRenderer(@Nullable Map<Sdk, SdkModificator> sdkModifiers) {
public PySdkListCellRenderer() {
myNullText = "";
mySdkModifiers = null;
}
public PySdkListCellRenderer(String nullText, @Nullable Map<Sdk, SdkModificator> sdkModifiers) {
myNullText = nullText;
mySdkModifiers = sdkModifiers;
}
@@ -46,6 +53,9 @@ public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
setIcon(icon);
}
}
else {
setText(myNullText);
}
}
private LayeredIcon wrapIconWithWarningDecorator(Icon icon) {
@@ -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);
@@ -5,7 +5,6 @@ import com.intellij.execution.configurations.ParamsGroup;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.run.PythonCommandLineState;
import com.jetbrains.python.sdk.PythonEnvUtil;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
@@ -19,6 +18,7 @@ import java.util.Map;
*/
public class JythonSdkFlavor extends PythonSdkFlavor {
private static final String JYTHONPATH = "JYTHONPATH";
private static final String PYTHON_PATH_PREFIX = "-Dpython.path=";
private JythonSdkFlavor() {
}
@@ -42,9 +42,14 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
@Override
public void initPythonPath(GeneralCommandLine cmd, Collection<String> path) {
initPythonPath(path, getEnv(cmd));
ParamsGroup param_group = cmd.getParametersList().getParamsGroup(PythonCommandLineState.GROUP_EXE_OPTIONS);
assert param_group != null;
param_group.addParameter(getPythonPathCmdLineArgument(path));
ParamsGroup paramGroup = cmd.getParametersList().getParamsGroup(PythonCommandLineState.GROUP_EXE_OPTIONS);
assert paramGroup != null;
for (String param : paramGroup.getParameters()) {
if (param.startsWith(PYTHON_PATH_PREFIX)) {
return;
}
}
paramGroup.addParameter(getPythonPathCmdLineArgument(path));
}
@Override
@@ -61,7 +66,7 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
}
public static String getPythonPathCmdLineArgument(Collection<String> path) {
return "-Dpython.path=" + StringUtil.join(appendSystemEnvPaths(path, JYTHONPATH), File.pathSeparator);
return PYTHON_PATH_PREFIX + StringUtil.join(appendSystemEnvPaths(path, JYTHONPATH), File.pathSeparator);
}
@Override
@@ -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<Pep8ExternalAnnotat
annotation = holder.createWeakWarningAnnotation(problemRange, message);
}
annotation.registerUniversalFix(new ReformatFix(), null, null);
annotation.registerFix(new IgnoreErrorFix(problem.myCode, annotationResult.ignoredErrors));
annotation.registerFix(new IgnoreErrorFix(problem.myCode));
annotation.registerFix(new CustomEditInspectionToolsSettingsAction(HighlightDisplayKey.find(PyPep8Inspection.INSPECTION_SHORT_NAME),
new Computable<String>() {
@Override
@@ -211,11 +212,9 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
private static class IgnoreErrorFix implements IntentionAction {
private final String myCode;
private final List<String> myErrors;
public IgnoreErrorFix(String code, List<String> errors) {
public IgnoreErrorFix(String code) {
myCode = code;
myErrors = errors;
}
@NotNull
@@ -236,9 +235,14 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
myErrors.add(myCode);
DaemonCodeAnalyzer.getInstance(project).restart(file);
public void invoke(@NotNull Project project, Editor editor, final PsiFile file) throws IncorrectOperationException {
InspectionProjectProfileManager.getInstance(project).getInspectionProfile(file).modifyProfile(new Consumer<ModifiableModel>() {
@Override
public void consume(ModifiableModel model) {
PyPep8Inspection tool = (PyPep8Inspection)model.getUnwrappedTool(PyPep8Inspection.INSPECTION_SHORT_NAME, file);
tool.ignoredErrors.add(myCode);
}
});
}
@Override
@@ -0,0 +1,2 @@
def foo(x : int):
pass
@@ -0,0 +1,2 @@
def foo(x: int):
pass
@@ -0,0 +1,2 @@
from java.util import ArrayList
l = ArrayList()
@@ -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() {