diff --git a/python/helpers/StdlibTypes2.properties b/python/helpers/StdlibTypes2.properties
index c24e569c1e86..45274f025196 100644
--- a/python/helpers/StdlibTypes2.properties
+++ b/python/helpers/StdlibTypes2.properties
@@ -66,7 +66,7 @@ __builtin__.getattr = \
:rtype: object or unknown \n\
__builtin__.globals = \
- :rtype: dict of (bytes, object)
+ :rtype: dict of (string, unknown)
__builtin__.hasattr = \
:type name: string \n\
@@ -84,7 +84,7 @@ __builtin__.len = \
:rtype: int \n\
__builtin__.locals = \
- :rtype: dict of (bytes, object)
+ :rtype: dict of (string, unknown)
__builtin__.map = \
:type function: collections.Callable or None \n\
@@ -138,7 +138,7 @@ __builtin__.round = \
:rtype: float \n\
__builtin__.vars = \
- :rtype: dict of (bytes, object)
+ :rtype: dict of (string, unknown)
__builtin__.xrange.__init__ = \
:type start: int \n\
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index 28880d1a2b5b..70c63569b1dc 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -103,7 +103,8 @@ DONT_TRACE = {
'pydevd_vm_type.py':1,
'pydevd.py':1 ,
'pydevd_psyco_stub.py':1,
- '_pydev_execfile.py':1
+ '_pydev_execfile.py':1,
+ '_pydev_jython_execfile.py':1
}
if IS_PY3K:
@@ -135,11 +136,7 @@ class PyDBCommandThread(PyDBDaemonThread):
if self.killReceived:
return
- run_traced = True
-
- import pydevd_tracing
- if run_traced:
- pydevd_tracing.SetTrace(None) # no debugging on this thread
+ threading.settrace(None) # no debugging on this thread
try:
while not self.killReceived:
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
index dfd2644e406a..5aacd414fb03 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.form
@@ -22,60 +22,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -98,23 +49,74 @@
-
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
index 8f176853fbf8..3bf58506046b 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
@@ -17,6 +17,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.ui.CollectionComboBoxModel;
+import com.intellij.ui.IdeBorderFactory;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.ReSTService;
@@ -51,6 +52,8 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
private JPanel myErrorPanel;
private TextFieldWithBrowseButton myRequirementsPathField;
private JCheckBox analyzeDoctest;
+ private JPanel myDocStringsPanel;
+ private JPanel myRestPanel;
public PyIntegratedToolsConfigurable(@NotNull Module module) {
myModule = module;
@@ -67,6 +70,9 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
myRequirementsPathField.addBrowseFolderListener("Choose path to the package requirements file:", null, myProject,
FileChooserDescriptorFactory.createSingleLocalFileDescriptor());
myRequirementsPathField.setText(getRequirementsPath());
+
+ myDocStringsPanel.setBorder(IdeBorderFactory.createTitledBorder("Docstrings"));
+ myRestPanel.setBorder(IdeBorderFactory.createTitledBorder("reStructuredText"));
}
@NotNull
diff --git a/python/src/com/jetbrains/python/debugger/PySignatureUtil.java b/python/src/com/jetbrains/python/debugger/PySignatureUtil.java
index 1d70341508c8..be827d965fbb 100644
--- a/python/src/com/jetbrains/python/debugger/PySignatureUtil.java
+++ b/python/src/com/jetbrains/python/debugger/PySignatureUtil.java
@@ -1,11 +1,16 @@
package com.jetbrains.python.debugger;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
+import com.jetbrains.appengine.util.StringUtils;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyTypeParser;
+import com.jetbrains.python.psi.types.PyUnionType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,13 +30,27 @@ public class PySignatureUtil {
}
if (pyType != null) {
- return pyType.getName();
+ return getPrintableName(pyType);
}
else {
return type;
}
}
+ private static String getPrintableName(PyType type) {
+ if (type instanceof PyUnionType) {
+ return StringUtil.join(Collections2.transform(((PyUnionType)type).getMembers(), new Function() {
+ @Override
+ public String apply(@Nullable PyType input) {
+ return getPrintableName(input);
+ }
+ }), " or ");
+ }
+ else {
+ return type.getName();
+ }
+ }
+
@Nullable
public static String getArgumentType(@NotNull PyFunction function, @NotNull String name) {
PySignatureCacheManager cacheManager = PySignatureCacheManager.getInstance(function.getProject());
diff --git a/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java b/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java
index 3c81974adacf..64c3ff48a5c3 100644
--- a/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyShadowingBuiltinsInspection.java
@@ -1,10 +1,24 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameIdentifierOwner;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.refactoring.rename.PsiElementRenameHandler;
+import com.intellij.refactoring.rename.RenameProcessor;
+import com.intellij.refactoring.rename.RenamePsiElementProcessor;
+import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer;
+import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import org.jetbrains.annotations.NotNull;
@@ -62,7 +76,55 @@ public class PyShadowingBuiltinsInspection extends PyInspection {
final PsiElement builtin = builtinCache.getByName(name);
if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
final PsiElement identifier = element.getNameIdentifier();
- registerProblem(identifier != null ? identifier : element, "Shadows a built-in with the same name");
+ registerProblem(identifier != null ? identifier : element, "Shadows a built-in with the same name",
+ new PyRenameElementQuickFix());
+ }
+ }
+ }
+
+ private static class PyRenameElementQuickFix implements LocalQuickFix {
+ @NotNull
+ @Override
+ public String getName() {
+ return "Rename element";
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Rename element";
+ }
+
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ final PsiNameIdentifierOwner nameOwner = element instanceof PsiNameIdentifierOwner ?
+ (PsiNameIdentifierOwner)element :
+ PsiTreeUtil.getParentOfType(element, PsiNameIdentifierOwner.class, true);
+ if (nameOwner != null) {
+ final VirtualFile virtualFile = nameOwner.getContainingFile().getVirtualFile();
+ if (virtualFile != null) {
+ final Editor editor = FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, virtualFile), true);
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ renameInUnitTestMode(project, nameOwner, editor);
+ }
+ else {
+ if (nameOwner instanceof PyNamedParameter || nameOwner instanceof PyTargetExpression) {
+ new VariableInplaceRenamer(nameOwner, editor).performInplaceRename();
+ }
+ else {
+ PsiElementRenameHandler.invoke(nameOwner, project, ScopeUtil.getScopeOwner(nameOwner), editor);
+ }
+ }
+ }
+ }
+ }
+
+ private static void renameInUnitTestMode(@NotNull Project project, @NotNull PsiNameIdentifierOwner nameOwner,
+ @Nullable Editor editor) {
+ final PsiElement substitution = RenamePsiElementProcessor.forElement(nameOwner).substituteElementToRename(nameOwner, editor);
+ if (substitution != null) {
+ new RenameProcessor(project, substitution, "a", false, false).run();
}
}
}
diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
index 20e807ae8090..ee17f05041f7 100644
--- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
@@ -171,7 +171,6 @@ public abstract class PythonCommandLineState extends CommandLineState {
private ProcessHandler startRemoteProcess(Sdk sdk, GeneralCommandLine commandLine) throws ExecutionException {
PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance();
if (manager != null) {
-
ProcessHandler processHandler =
null;
@@ -288,12 +287,13 @@ public abstract class PythonCommandLineState extends CommandLineState {
boolean passParentEnvs,
List pathList,
final String interpreterPath) {
+ Map envs = commandLine.getEnvParams();
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(interpreterPath);
if (flavor != null) {
flavor.initPythonPath(commandLine, pathList);
}
else {
- PythonSdkFlavor.initPythonPath(commandLine.getEnvParams(), passParentEnvs, pathList);
+ PythonSdkFlavor.initPythonPath(envs, passParentEnvs, pathList);
}
}
@@ -339,8 +339,6 @@ public abstract class PythonCommandLineState extends CommandLineState {
}
return pythonPath;
-
-
}
@NotNull
diff --git a/python/src/com/jetbrains/python/sdk/PythonEnvUtil.java b/python/src/com/jetbrains/python/sdk/PythonEnvUtil.java
index 2bc2031eeb94..015c04759b02 100644
--- a/python/src/com/jetbrains/python/sdk/PythonEnvUtil.java
+++ b/python/src/com/jetbrains/python/sdk/PythonEnvUtil.java
@@ -78,11 +78,13 @@ public class PythonEnvUtil {
}
public static void addToEnv(Map envs, String key, String value) {
- if (envs.containsKey(key)) {
- envs.put(key, appendToPathEnvVar(envs.get(key), value));
- }
- else {
- envs.put(key, value);
+ if (!StringUtil.isEmpty(value)) {
+ if (envs.containsKey(key)) {
+ envs.put(key, appendToPathEnvVar(envs.get(key), value));
+ }
+ else {
+ envs.put(key, value);
+ }
}
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java
index 7b3b32d1ba6d..07d5fa82ec4f 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java
@@ -7,10 +7,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
/**
* @author yole
@@ -73,7 +70,13 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
@Override
public void initPythonPath(GeneralCommandLine cmd, Collection path) {
- addToEnv(cmd, "IRONPYTHONPATH", StringUtil.join(path, File.pathSeparator));
+ Map env = getEnv(cmd);
+ initPythonPath(path, env);
+ }
+
+ @Override
+ public void initPythonPath(Collection path, Map env) {
+ addToEnv("IRONPYTHONPATH", StringUtil.join(path, File.pathSeparator), env);
}
@NotNull
diff --git a/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java
index 8a8640481041..cce2d4bce95d 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java
@@ -5,12 +5,14 @@ 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;
import javax.swing.*;
import java.io.File;
import java.util.Collection;
+import java.util.Map;
/**
* @author yole
@@ -23,14 +25,6 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
public static JythonSdkFlavor INSTANCE = new JythonSdkFlavor();
- public static String appendSystemJythonPath(String pythonPath) {
- String syspath = System.getenv(JYTHONPATH);
- if (syspath != null) {
- pythonPath += File.pathSeparator + syspath;
- }
- return pythonPath;
- }
-
public boolean isValidSdkPath(@NotNull File file) {
return FileUtil.getNameWithoutExtension(file).toLowerCase().startsWith("jython");
}
@@ -47,13 +41,19 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
@Override
public void initPythonPath(GeneralCommandLine cmd, Collection path) {
- final String jythonPath = StringUtil.join(path, File.pathSeparator);
- addToEnv(cmd, JYTHONPATH, appendSystemJythonPath(jythonPath));
+ initPythonPath(path, getEnv(cmd));
ParamsGroup param_group = cmd.getParametersList().getParamsGroup(PythonCommandLineState.GROUP_EXE_OPTIONS);
assert param_group != null;
param_group.addParameter(getPythonPathCmdLineArgument(path));
}
+ @Override
+ public void initPythonPath(Collection path, Map env) {
+ path = appendSystemEnvPaths(path, JYTHONPATH);
+ final String jythonPath = StringUtil.join(path, File.pathSeparator);
+ addToEnv(JYTHONPATH, jythonPath, env);
+ }
+
@NotNull
@Override
public String getName() {
@@ -61,7 +61,7 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
}
public static String getPythonPathCmdLineArgument(Collection path) {
- return "-Dpython.path=" + appendSystemJythonPath(StringUtil.join(path, File.pathSeparator));
+ return "-Dpython.path=" + StringUtil.join(appendSystemEnvPaths(path, JYTHONPATH), File.pathSeparator);
}
@Override
diff --git a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
index 09debcfe2889..cf77e38d3f33 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
@@ -32,7 +32,11 @@ public abstract class PythonSdkFlavor {
private static final Logger LOG = Logger.getInstance(PythonSdkFlavor.class);
public static Collection appendSystemPythonPath(Collection pythonPath) {
- String syspath = System.getenv(PythonEnvUtil.PYTHONPATH);
+ return appendSystemEnvPaths(pythonPath, PythonEnvUtil.PYTHONPATH);
+ }
+
+ protected static Collection appendSystemEnvPaths(Collection pythonPath, String envname) {
+ String syspath = System.getenv(envname);
if (syspath != null) {
pythonPath.addAll(Lists.newArrayList(syspath.split(File.pathSeparator)));
}
@@ -186,20 +190,14 @@ public abstract class PythonSdkFlavor {
}
public void initPythonPath(GeneralCommandLine cmd, Collection path) {
- addToEnv(cmd, PythonEnvUtil.PYTHONPATH, appendSystemPythonPath(path));
+ initPythonPath(path, getEnv(cmd));
}
- public static void addToEnv(GeneralCommandLine cmd, final String key, Collection values) {
- Map envs = getEnv(cmd);
- PythonEnvUtil.addToEnv(envs, key, values);
- }
-
- public static void addToEnv(GeneralCommandLine cmd, final String key, String value) {
- Map envs = getEnv(cmd);
+ public static void addToEnv(final String key, String value, Map envs) {
PythonEnvUtil.addToEnv(envs, key, value);
}
- private static Map getEnv(GeneralCommandLine cmd) {
+ static Map getEnv(GeneralCommandLine cmd) {
Map envs = cmd.getEnvParams();
if (envs == null) {
envs = new HashMap();
@@ -232,4 +230,9 @@ public abstract class PythonSdkFlavor {
public Icon getIcon() {
return PythonIcons.Python.Python;
}
+
+ public void initPythonPath(Collection path, Map env) {
+ path = appendSystemPythonPath(path);
+ addToEnv(PythonEnvUtil.PYTHONPATH, StringUtil.join(path, File.pathSeparator), env);
+ }
}
diff --git a/python/testData/inspections/RenameFunctionShadowingBuiltins.py b/python/testData/inspections/RenameFunctionShadowingBuiltins.py
new file mode 100644
index 000000000000..ed54b1c887d9
--- /dev/null
+++ b/python/testData/inspections/RenameFunctionShadowingBuiltins.py
@@ -0,0 +1,6 @@
+def id(x):
+ return x
+
+
+def f():
+ return id('foo')
diff --git a/python/testData/inspections/RenameFunctionShadowingBuiltins_after.py b/python/testData/inspections/RenameFunctionShadowingBuiltins_after.py
new file mode 100644
index 000000000000..57ac3e896508
--- /dev/null
+++ b/python/testData/inspections/RenameFunctionShadowingBuiltins_after.py
@@ -0,0 +1,6 @@
+def a(x):
+ return x
+
+
+def f():
+ return a('foo')
diff --git a/python/testData/inspections/RenameShadowingBuiltins.py b/python/testData/inspections/RenameShadowingBuiltins.py
new file mode 100644
index 000000000000..f22217991759
--- /dev/null
+++ b/python/testData/inspections/RenameShadowingBuiltins.py
@@ -0,0 +1,3 @@
+def f(name):
+ file = open(name, 'rb')
+ return file.read()
diff --git a/python/testData/inspections/RenameShadowingBuiltins_after.py b/python/testData/inspections/RenameShadowingBuiltins_after.py
new file mode 100644
index 000000000000..4f8354971055
--- /dev/null
+++ b/python/testData/inspections/RenameShadowingBuiltins_after.py
@@ -0,0 +1,3 @@
+def f(name):
+ a = open(name, 'rb')
+ return a.read()
diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
index 84b60a170548..4a7aba094c2b 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
@@ -424,6 +424,19 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
}
+ // PY-8788
+ public void testRenameShadowingBuiltins() {
+ doInspectionTest("RenameShadowingBuiltins.py", PyShadowingBuiltinsInspection.class,
+ "Rename element", true, true);
+ }
+
+ // PY-8788
+ public void testRenameFunctionShadowingBuiltins() {
+ doInspectionTest("RenameFunctionShadowingBuiltins.py", PyShadowingBuiltinsInspection.class,
+ "Rename element", true, true);
+
+ }
+
@Override
@NonNls
protected String getTestDataPath() {