diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index 4385a4db9248..af4272e6444c 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -346,6 +346,7 @@ class PyDB:
self.processThreadNotAlive(tId)
except:
sys.stderr.write('Error iterating through %s (%s) - %s\n' % (foundThreads, foundThreads.__class__, dir(foundThreads)))
+ sys.stderr.flush()
raise
finally:
@@ -457,9 +458,11 @@ class PyDB:
if not DictContains(sys.modules, module_name):
sys.stderr.write('pydev debugger: Unable to find module to reload: "'+module_name+'".\n')
sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n')
+ sys.stderr.flush()
else:
sys.stderr.write('pydev debugger: Reloading: '+module_name+'\n')
+ sys.stderr.flush()
xreload(sys.modules[module_name])
@@ -536,11 +539,13 @@ class PyDB:
if not os.path.exists(file):
sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
' to file that does not exist: %s (will have no effect)\n' % (file,))
+ sys.stderr.flush()
line = int(line)
if DEBUG_TRACE_BREAKPOINTS > 0:
sys.stderr.write('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name))
+ sys.stderr.flush()
if DictContains(self.breakpoints, file):
breakDict = self.breakpoints[file]
@@ -575,11 +580,13 @@ class PyDB:
del self.breakpoints[file][line] #remove the breakpoint in that line
if DEBUG_TRACE_BREAKPOINTS > 0:
sys.stderr.write('Removed breakpoint:%s\n' % (file,))
+ sys.stderr.flush()
except KeyError:
#ok, it's not there...
if DEBUG_TRACE_BREAKPOINTS > 0:
#Sometimes, when adding a breakpoint, it adds a remove command before (don't really know why)
sys.stderr.write("breakpoint not found: %s - %s\n" % (file, line))
+ sys.stderr.flush()
elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
#command to evaluate the given expression
@@ -823,8 +830,9 @@ class PyDB:
if hasattr(sys, 'exc_clear'): #jython does not have it
sys.exc_clear() #don't keep the traceback (let's keep it clear for when we go to the point of executing client code)
- if not sys.platform.startswith("java") and not sys.platform.startswith("cli"):
+ if not IS_PY3K and not sys.platform.startswith("java") and not sys.platform.startswith("cli"):
sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
+ sys.stderr.flush()
def run(self, file, globals=None, locals=None):
@@ -1087,6 +1095,7 @@ def settrace(host='localhost', stdoutToServer=False, stderrToServer=False, port=
if __name__ == '__main__':
sys.stderr.write("pydev debugger: starting\n")
+ sys.stderr.flush()
# parse the command line. --file is our last argument that is required
try:
setup = processCommandLine(sys.argv)
diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py
index 2dbc3c187340..8d53edfa7155 100644
--- a/python/helpers/pydev/pydevd_breakpoints.py
+++ b/python/helpers/pydev/pydevd_breakpoints.py
@@ -1,3 +1,4 @@
+from pydevd_constants import *
import sys
_original_excepthook = None
@@ -110,7 +111,10 @@ def get_class( kls ):
parts = kls.split('.')
module = ".".join(parts[:-1])
if (module == ""):
- module = "__builtin__"
+ if IS_PY3K:
+ module = "builtins"
+ else:
+ module = "__builtin__"
m = __import__( module )
for comp in parts[-1:]:
m = getattr(m, comp)
diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py
index 2a4ced0e657d..2ed09dd022c4 100644
--- a/python/helpers/pydev/pydevd_comm.py
+++ b/python/helpers/pydev/pydevd_comm.py
@@ -349,6 +349,7 @@ def StartClient(host, port):
return s
except:
sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
+ sys.stderr.flush()
traceback.print_exc()
sys.exit(1)
@@ -408,7 +409,7 @@ class NetCommandFactory:
cmd = NetCommand(CMD_ERROR, seq, text)
if DEBUG_TRACE_LEVEL > 2:
sys.stderr.write("Error: %s" % (text,))
- return cmd;
+ return cmd
def makeThreadCreatedMessage(self, thread):
cmdText = "" + self.threadToXML(thread) + ""
@@ -728,6 +729,9 @@ class InternalConsoleExec(InternalThreadCommand):
sys.stderr.write('%s\n' % (exc,))
cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating console expression " + exc)
dbg.writer.addCommand(cmd)
+ finally:
+ sys.stderr.flush()
+ sys.stdout.flush()
#=======================================================================================================================
# InternalGetCompletions
@@ -806,6 +810,7 @@ def PydevdFindThreadById(thread_id):
sys.stderr.write("Could not find thread %s\n" % thread_id)
sys.stderr.write("Available: %s\n" % [GetThreadId(t) for t in threads])
+ sys.stderr.flush()
except:
traceback.print_exc()
diff --git a/python/helpers/pydev/pydevd_file_utils.py b/python/helpers/pydev/pydevd_file_utils.py
index bee4c18b7b7f..ab5357ce38a9 100644
--- a/python/helpers/pydev/pydevd_file_utils.py
+++ b/python/helpers/pydev/pydevd_file_utils.py
@@ -100,6 +100,7 @@ try:
sys.stderr.write('pydev debugger: The debugger may still function, but it will work slower and may miss breakpoints.\n')
sys.stderr.write('pydev debugger: Related bug: http://bugs.python.org/issue1666807\n')
sys.stderr.write('-------------------------------------------------------------------------------\n')
+ sys.stderr.flush()
NORM_SEARCH_CACHE = {}
diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py
index e258499e59e6..71545f965c3d 100644
--- a/python/helpers/pydev/pydevd_frame.py
+++ b/python/helpers/pydev/pydevd_frame.py
@@ -109,6 +109,7 @@ class PyDBFrame:
except:
sys.stderr.write('Error while evaluating expression\n')
traceback.print_exc()
+ sys.stderr.flush()
return self.trace_dispatch
expression = breakpoint[line][3]
diff --git a/python/helpers/pydev/pydevd_tracing.py b/python/helpers/pydev/pydevd_tracing.py
index 202854a599f4..c49c17ee298a 100644
--- a/python/helpers/pydev/pydevd_tracing.py
+++ b/python/helpers/pydev/pydevd_tracing.py
@@ -58,6 +58,7 @@ def _InternalSetTrace(tracing_func):
#only warn about each message once...
TracingFunctionHolder._warnings_shown[message] = 1
sys.stderr.write('%s\n' % (message,))
+ sys.stderr.flush()
TracingFunctionHolder._original_tracing(tracing_func)
diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py
index f415372c8ff8..b454fe610607 100644
--- a/python/helpers/pydev/pydevd_vars.py
+++ b/python/helpers/pydev/pydevd_vars.py
@@ -227,6 +227,7 @@ def frameVarsToXML(frame):
except Exception:
traceback.print_exc()
sys.stderr.write("Unexpected error, recovered safely.\n")
+ sys.stderr.flush()
return xml
def iterFrames(initialFrame):
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java
index ff5bdc1bc39e..1fa24d8bbf92 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/PyDebugValue.java
@@ -86,7 +86,7 @@ public class PyDebugValue extends XValue {
result.append('[').append(removeId(myName)).append(']');
}
else if (("set".equals(myParent.getType())) && !isLen(myName)) {
- result.append("[").append(myName).append("]");
+ //set doesn't support indexing
}
else if (isLen(myName)) {
result.append('.').append(myName).append("()");
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractFrameCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractFrameCommand.java
index dc8695618fc1..28563a60d0fc 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractFrameCommand.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractFrameCommand.java
@@ -3,7 +3,7 @@ package com.jetbrains.python.debugger.pydev;
public abstract class AbstractFrameCommand extends AbstractThreadCommand {
- protected final String myFrameId;
+ private final String myFrameId;
protected AbstractFrameCommand(final RemoteDebugger debugger, final int commandCode, final String threadId, final String frameId) {
super(debugger, commandCode, threadId);
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractThreadCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractThreadCommand.java
index 5c85b07be8ef..5598941a69cf 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractThreadCommand.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractThreadCommand.java
@@ -2,7 +2,7 @@ package com.jetbrains.python.debugger.pydev;
public abstract class AbstractThreadCommand extends AbstractCommand {
- protected final String myThreadId;
+ private final String myThreadId;
protected AbstractThreadCommand(final RemoteDebugger debugger, final int commandCode, final String threadId) {
super(debugger, commandCode);
@@ -21,4 +21,8 @@ public abstract class AbstractThreadCommand extends AbstractCommand {
command == SUSPEND_THREAD;
}
+ public String getThreadId() {
+ return myThreadId;
+ }
+
}
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ConsoleExecCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ConsoleExecCommand.java
index a3f599f65983..bbd0540d5c1a 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ConsoleExecCommand.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ConsoleExecCommand.java
@@ -16,7 +16,7 @@ public class ConsoleExecCommand extends AbstractFrameCommand {
@Override
protected void buildPayload(Payload payload) {
super.buildPayload(payload);
- payload.add(myThreadId).add(myFrameId).add("FRAME").add(myExpression);
+ payload.add("FRAME").add(myExpression);
}
@Override
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ResumeCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ResumeCommand.java
index a3e407128da8..8712d676b5d7 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ResumeCommand.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ResumeCommand.java
@@ -16,8 +16,4 @@ public class ResumeCommand extends AbstractThreadCommand {
public ResumeCommand(final RemoteDebugger debugger, final String threadId, final Mode mode) {
super(debugger, mode.code, threadId);
}
-
- public String getThreadId() {
- return myThreadId;
- }
}
diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 1b02cfd7d813..ff3dc3ae8d56 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -148,6 +148,11 @@
Python
+
+ com.jetbrains.python.codeInsight.intentions.PyConvertLambdaToFunctionIntention
+ Python
+
+
@@ -306,7 +311,7 @@
-
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index f7d2a8834a2f..726f495e2c08 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -59,6 +59,12 @@ QFIX.statement.effect.introduce.variable=Introduce variable
QFIX.unresolved.reference=Reference can be resolved added self
+QFIX.unresolved.reference.create.function=Create function for reference
+
+QFIX.introduce.variable=Introduce variable for statement
+
+QFIX.unresolved.reference.add.future=Add 'from __future__ import with_statement''
+
# Intentions: INTN
INTN.Family.convert.import.unqualify=Convert 'import module' to 'from module import'
INTN.Family.convert.import.qualify=Convert 'from module import' to 'import module'
@@ -130,7 +136,9 @@ INTN.convert.dict.literal.to.dict.constructor=Convert dict literal to dict const
INTN.quoted.string=Convert between single-quoted and double-quoted strings
INTN.quoted.string.single.to.double=Convert single-quoted string to double-quoted string
-INTN.quoted.string.double.to.single=Convert double-quoted string to sungle-quoted string
+INTN.quoted.string.double.to.single=Convert double-quoted string to single-quoted string
+
+INTN.convert.lambda.to.function=Convert lambda to function
# Conflict checker
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
diff --git a/python/src/com/jetbrains/python/actions/StatementEffectQuickFix.java b/python/src/com/jetbrains/python/actions/StatementEffectFunctionCallQuickFix.java
similarity index 91%
rename from python/src/com/jetbrains/python/actions/StatementEffectQuickFix.java
rename to python/src/com/jetbrains/python/actions/StatementEffectFunctionCallQuickFix.java
index 805c89d9d26a..094a22551ff8 100644
--- a/python/src/com/jetbrains/python/actions/StatementEffectQuickFix.java
+++ b/python/src/com/jetbrains/python/actions/StatementEffectFunctionCallQuickFix.java
@@ -17,9 +17,9 @@ import org.jetbrains.annotations.NotNull;
*
* QuickFix to replace statement that has no effect with function call
*/
-public class StatementEffectQuickFix implements LocalQuickFix {
+public class StatementEffectFunctionCallQuickFix implements LocalQuickFix {
- public StatementEffectQuickFix() {
+ public StatementEffectFunctionCallQuickFix() {
}
@NotNull
diff --git a/python/src/com/jetbrains/python/actions/StatementEffectIntroduceVariableQuickFix.java b/python/src/com/jetbrains/python/actions/StatementEffectIntroduceVariableQuickFix.java
new file mode 100644
index 000000000000..dd1a215ecab7
--- /dev/null
+++ b/python/src/com/jetbrains/python/actions/StatementEffectIntroduceVariableQuickFix.java
@@ -0,0 +1,52 @@
+package com.jetbrains.python.actions;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ *
+ * Quickfix to introduce variable if statement seems to have no effect
+ */
+public class StatementEffectIntroduceVariableQuickFix implements LocalQuickFix {
+ PyExpression myExpression;
+ public StatementEffectIntroduceVariableQuickFix(PyExpression expression) {
+ myExpression = expression;
+ }
+
+ @NotNull
+ public String getName() {
+ return PyBundle.message("QFIX.introduce.variable");
+ }
+
+ @NonNls
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INSP.GROUP.python");
+ }
+
+ public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+ String name = "var";
+ if (myExpression != null) {
+ Application application = ApplicationManager.getApplication();
+ if (application != null && !application.isUnitTestMode()) {
+ name = Messages.showInputDialog(project, "Enter new variable name",
+ "New variable name", Messages.getQuestionIcon());
+ if (name == null) return;
+ }
+ if (name.isEmpty()) return;
+ PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
+ myExpression.replace(elementGenerator.createFromText(LanguageLevel.forElement(myExpression), PyAssignmentStatement.class,
+ name + " = " + myExpression.getText()));
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/actions/UnresolvedRefAddFutureImportQuickFix.java b/python/src/com/jetbrains/python/actions/UnresolvedRefAddFutureImportQuickFix.java
new file mode 100644
index 000000000000..0c2a3f4752b2
--- /dev/null
+++ b/python/src/com/jetbrains/python/actions/UnresolvedRefAddFutureImportQuickFix.java
@@ -0,0 +1,40 @@
+package com.jetbrains.python.actions;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ *
+ * QuickFix to add 'from __future__ import with_statement'' if python version is less than 2.6
+ */
+public class UnresolvedRefAddFutureImportQuickFix implements LocalQuickFix {
+ private PyReferenceExpression myElement;
+ public UnresolvedRefAddFutureImportQuickFix(PyReferenceExpression element) {
+ myElement = element;
+ }
+
+ @NotNull
+ public String getName() {
+ return PyBundle.message("QFIX.unresolved.reference.add.future");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INSP.GROUP.python");
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ PyFile file = (PyFile)myElement.getContainingFile();
+ if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
+ PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
+ PyFromImportStatement statement = elementGenerator.createFromText(LanguageLevel.forElement(myElement), PyFromImportStatement.class,
+ "from __future__ import with_statement");
+ file.addBefore(statement, file.getStatements().get(0));
+ }
+}
diff --git a/python/src/com/jetbrains/python/actions/UnresolvedRefCreateFunctionQuickFix.java b/python/src/com/jetbrains/python/actions/UnresolvedRefCreateFunctionQuickFix.java
new file mode 100644
index 000000000000..abadc1945150
--- /dev/null
+++ b/python/src/com/jetbrains/python/actions/UnresolvedRefCreateFunctionQuickFix.java
@@ -0,0 +1,48 @@
+package com.jetbrains.python.actions;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ *
+ * QuickFix to create function to unresolved unqualified reference
+ */
+public class UnresolvedRefCreateFunctionQuickFix implements LocalQuickFix {
+ private PyReferenceExpression myElement;
+
+ public UnresolvedRefCreateFunctionQuickFix(PyReferenceExpression element) {
+ myElement = element;
+ }
+
+ @NotNull
+ public String getName() {
+ return PyBundle.message("QFIX.unresolved.reference.create.function");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INSP.GROUP.python");
+ }
+
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ if (!CodeInsightUtilBase.preparePsiElementForWrite(myElement)) return;
+ PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
+ PyFunction function = elementGenerator.createFromText(LanguageLevel.forElement(myElement), PyFunction.class,
+ "def " + myElement.getText() + "():\n pass");
+
+ PyStatement statement = PsiTreeUtil.getParentOfType(myElement, PyStatement.class);
+ if (statement != null) {
+ PsiElement parent = statement.getParent();
+ if (parent != null)
+ parent.addBefore(function, statement);
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/actions/UnresolvedReferenceAddSelfQuickFix.java b/python/src/com/jetbrains/python/actions/UnresolvedReferenceAddSelfQuickFix.java
index daa91a227bc1..521bd804688e 100644
--- a/python/src/com/jetbrains/python/actions/UnresolvedReferenceAddSelfQuickFix.java
+++ b/python/src/com/jetbrains/python/actions/UnresolvedReferenceAddSelfQuickFix.java
@@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
/**
* User: catherine
*
- * QuickFix to remove redundant parentheses from if/while/except statement
+ * QuickFix to add self to unresolved reference
*/
public class UnresolvedReferenceAddSelfQuickFix implements LocalQuickFix {
private PyReferenceExpression myElement;
@@ -33,9 +33,8 @@ public class UnresolvedReferenceAddSelfQuickFix implements LocalQuickFix {
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
if (!CodeInsightUtilBase.preparePsiElementForWrite(myElement)) return;
- PyReferenceExpression ref = myElement;
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
- PyExpression expression = elementGenerator.createExpressionFromText("self." + ref.getText());
+ PyExpression expression = elementGenerator.createExpressionFromText("self." + myElement.getText());
myElement.replace(expression);
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java
new file mode 100644
index 000000000000..0a47186f99d5
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java
@@ -0,0 +1,95 @@
+package com.jetbrains.python.codeInsight.intentions;
+
+import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ * Intention to convert lambda to function
+ */
+public class PyConvertLambdaToFunctionIntention extends BaseIntentionAction {
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INTN.convert.lambda.to.function");
+ }
+
+ @NotNull
+ public String getText() {
+ return PyBundle.message("INTN.convert.lambda.to.function");
+ }
+
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ PyLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyLambdaExpression.class);
+ if (lambdaExpression != null) {
+ if (lambdaExpression.getBody() != null)
+ return true;
+ }
+ return false;
+ }
+
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ PyLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyLambdaExpression.class);
+ PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
+ if (lambdaExpression != null) {
+ String name = "function";
+ PsiElement parent = lambdaExpression.getParent();
+ if (parent instanceof PyAssignmentStatement) {
+ name = ((PyAssignmentStatement)parent).getLeftHandSideExpression().getText();
+ }
+ else {
+ Application application = ApplicationManager.getApplication();
+ if (application != null && !application.isUnitTestMode()) {
+ name = Messages.showInputDialog(project, "Enter new function name",
+ "New function name", Messages.getQuestionIcon());
+ if (name == null) return;
+ }
+ }
+ if (name.isEmpty()) return;
+ PyExpression body = lambdaExpression.getBody();
+ PyParameter[] parameters = lambdaExpression.getParameterList().getParameters();
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("def ");
+ stringBuilder.append(name);
+ stringBuilder.append("(");
+ int size = parameters.length;
+ for (int i = 0; i != size; ++i) {
+ PyParameter parameter = parameters[i];
+ stringBuilder.append(parameter.getName());
+ if ( i != size - 1)
+ stringBuilder.append(",");
+ }
+ stringBuilder.append("):\n return ");
+ stringBuilder.append(body.getText());
+
+ PyFunction function = elementGenerator.createFromText(LanguageLevel.forElement(lambdaExpression),
+ PyFunction.class, stringBuilder.toString());
+
+ PyStatement statement = PsiTreeUtil.getParentOfType(lambdaExpression, PyStatement.class);
+ if (statement != null) {
+ PsiElement parentOfStatement = statement.getParent();
+ if (parentOfStatement != null)
+ parentOfStatement.addBefore(function, statement);
+ }
+ if (parent instanceof PyAssignmentStatement) {
+ parent.delete();
+ }
+ else {
+ lambdaExpression.replace(elementGenerator.createFromText(LanguageLevel.forElement(lambdaExpression), PyExpression.class,
+ name));
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
index 6c4f634185fe..c6bc44206920 100644
--- a/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyStatementEffectInspection.java
@@ -2,12 +2,12 @@ package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
-import com.jetbrains.python.actions.StatementEffectQuickFix;
+import com.jetbrains.python.actions.StatementEffectFunctionCallQuickFix;
+import com.jetbrains.python.actions.StatementEffectIntroduceVariableQuickFix;
import com.jetbrains.python.console.PydevConsoleRunner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
@@ -16,8 +16,6 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.sql.Statement;
-
/**
* @author Alexey.Ivanov
*/
@@ -64,7 +62,7 @@ public class PyStatementEffectInspection extends PyInspection {
return;
}
}
- registerProblem(expression, "Statement seems to have no effect");
+ registerProblem(expression, "Statement seems to have no effect", new StatementEffectIntroduceVariableQuickFix(expression));
}
private boolean hasEffect(@Nullable PyExpression expression) {
@@ -125,7 +123,7 @@ public class PyStatementEffectInspection extends PyInspection {
ResolveResult[] results = referenceExpression.getReference().multiResolve(true);
for (ResolveResult res : results) {
if (res.getElement() instanceof PyFunction) {
- registerProblem(expression, "Statement seems to have no effect and can be replaced with function call to have effect", new StatementEffectQuickFix());
+ registerProblem(expression, "Statement seems to have no effect and can be replaced with function call to have effect", new StatementEffectFunctionCallQuickFix());
return true;
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
index c8bba4b57b14..ae8a6a7ef657 100644
--- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java
@@ -133,7 +133,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
super.visitPyStarImportElement(node);
myAllImports.add(node);
}
-
+
@Override
public void visitPyElement(final PyElement node) {
super.visitPyElement(node);
@@ -191,6 +191,11 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
}
else {
+ if (LanguageLevel.forElement(node).isOlderThan(LanguageLevel.PYTHON26)) {
+ if (refname.equals("with")) {
+ actions.add(new UnresolvedRefAddFutureImportQuickFix(refex));
+ }
+ }
PyClass containedClass = PsiTreeUtil.getParentOfType(node, PyClass.class);
if (containedClass != null) {
for (PyTargetExpression target : containedClass.getInstanceAttributes()) {
@@ -199,6 +204,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
}
}
}
+ actions.add(new UnresolvedRefCreateFunctionQuickFix(refex));
}
// unqualified:
// may be module's
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
index d1374fe7fc25..25d558abab00 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
@@ -373,7 +373,7 @@ public class PythonSdkType extends SdkType {
public static VirtualFile findSkeletonsDir(Sdk sdk) {
final VirtualFile[] virtualFiles = sdk.getRootProvider().getFiles(BUILTIN_ROOT_TYPE);
for (VirtualFile virtualFile : virtualFiles) {
- if (virtualFile.getPath().contains(SKELETON_DIR_NAME)) {
+ if (virtualFile.isValid() && virtualFile.getPath().contains(SKELETON_DIR_NAME)) {
return virtualFile;
}
}
diff --git a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
index 7f46db5bb7c9..5e92e29df616 100644
--- a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
+++ b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestConfigurationProducer.java
@@ -156,13 +156,11 @@ public class PythonDocTestConfigurationProducer extends RuntimeConfigurationProd
@Nullable
private RunnerAndConfigurationSettings createConfigurationFromFile(Location location, PsiElement element) {
PsiElement file = element.getContainingFile();
- if (file == null) return null;
+ if (file == null || !(file instanceof PyFile)) return null;
- if (file instanceof PyFile) {
- final PyFile pyFile = (PyFile)file;
- final List testCases = PythonDocTestUtil.getDocTestCasesFromFile(pyFile);
- if (testCases.isEmpty()) return null;
- }
+ final PyFile pyFile = (PyFile)file;
+ final List testCases = PythonDocTestUtil.getDocTestCasesFromFile(pyFile);
+ if (testCases.isEmpty()) return null;
final RunnerAndConfigurationSettings settings = makeConfigurationSettings(location, "doc tests from file");
final PythonDocTestRunConfiguration configuration = (PythonDocTestRunConfiguration)settings.getConfiguration();
diff --git a/python/testData/inspections/StatementEffectIntroduceVariable.py b/python/testData/inspections/StatementEffectIntroduceVariable.py
new file mode 100644
index 000000000000..107d3e6a49ce
--- /dev/null
+++ b/python/testData/inspections/StatementEffectIntroduceVariable.py
@@ -0,0 +1 @@
+a+ b
\ No newline at end of file
diff --git a/python/testData/inspections/StatementEffectIntroduceVariable_after.py b/python/testData/inspections/StatementEffectIntroduceVariable_after.py
new file mode 100644
index 000000000000..0db79b1d5e6f
--- /dev/null
+++ b/python/testData/inspections/StatementEffectIntroduceVariable_after.py
@@ -0,0 +1 @@
+var = a + b
\ No newline at end of file
diff --git a/python/testData/inspections/UnresolvedRefCreateFunction.py b/python/testData/inspections/UnresolvedRefCreateFunction.py
new file mode 100644
index 000000000000..aea8443bca14
--- /dev/null
+++ b/python/testData/inspections/UnresolvedRefCreateFunction.py
@@ -0,0 +1 @@
+ref
\ No newline at end of file
diff --git a/python/testData/inspections/UnresolvedRefCreateFunction_after.py b/python/testData/inspections/UnresolvedRefCreateFunction_after.py
new file mode 100644
index 000000000000..220da55cc19c
--- /dev/null
+++ b/python/testData/inspections/UnresolvedRefCreateFunction_after.py
@@ -0,0 +1,4 @@
+def ref():
+ pass
+
+ref
\ No newline at end of file
diff --git a/python/testData/inspections/UnresolvedWith.py b/python/testData/inspections/UnresolvedWith.py
new file mode 100644
index 000000000000..135ac77300fa
--- /dev/null
+++ b/python/testData/inspections/UnresolvedWith.py
@@ -0,0 +1,2 @@
+with open("x.txt") as f:
+ data = f.read()
\ No newline at end of file
diff --git a/python/testData/inspections/UnresolvedWith_after.py b/python/testData/inspections/UnresolvedWith_after.py
new file mode 100644
index 000000000000..66b1d3d0445a
--- /dev/null
+++ b/python/testData/inspections/UnresolvedWith_after.py
@@ -0,0 +1,4 @@
+from __future__ import with_statement
+
+with open("x.txt") as f:
+ data = f.read()
\ No newline at end of file
diff --git a/python/testData/intentions/afterConvertLambdaToFunction.py b/python/testData/intentions/afterConvertLambdaToFunction.py
new file mode 100644
index 000000000000..619b1e392e9c
--- /dev/null
+++ b/python/testData/intentions/afterConvertLambdaToFunction.py
@@ -0,0 +1,6 @@
+def func(seq):
+ def function(x, y):
+ return (x + y) / y
+
+ newlist = reduce(function
+ , seq)
\ No newline at end of file
diff --git a/python/testData/intentions/beforeConvertLambdaToFunction.py b/python/testData/intentions/beforeConvertLambdaToFunction.py
new file mode 100644
index 000000000000..eaa151a875ac
--- /dev/null
+++ b/python/testData/intentions/beforeConvertLambdaToFunction.py
@@ -0,0 +1,2 @@
+def func(seq):
+ newlist = reduce(lambda x, y: (x+y)/y, seq)
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PyIntentionTest.java b/python/testSrc/com/jetbrains/python/PyIntentionTest.java
index c5a4a0112bc3..5799c1ffb6f1 100644
--- a/python/testSrc/com/jetbrains/python/PyIntentionTest.java
+++ b/python/testSrc/com/jetbrains/python/PyIntentionTest.java
@@ -124,4 +124,8 @@ public class PyIntentionTest extends PyLightFixtureTestCase {
public void testQuotedString() {
doTest(PyBundle.message("INTN.quoted.string.double.to.single"));
}
+
+ public void testConvertLambdaToFunction() {
+ doTest(PyBundle.message("INTN.convert.lambda.to.function"));
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
index 0d8d046ffeb5..bc9f47b6e55c 100644
--- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java
@@ -6,6 +6,7 @@ import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
import com.jetbrains.python.inspections.*;
+import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.NonNls;
/**
@@ -188,6 +189,21 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
PyBundle.message("QFIX.statement.effect"), true, true);
}
+ public void testStatementEffectIntroduceVariable() { // PY-1265
+ doInspectionTest("StatementEffectIntroduceVariable.py", PyStatementEffectInspection.class,
+ PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true);
+ }
+
+ public void testUnresolvedWith() { // PY-2083
+ setLanguageLevel(LanguageLevel.PYTHON25);
+ doInspectionTest("UnresolvedWith.py", PyUnresolvedReferencesInspection.class,
+ PyBundle.message("QFIX.unresolved.reference.add.future"), true, true);
+ }
+
+ public void testUnresolvedRefCreateFunction() { // PY-2092
+ doInspectionTest("UnresolvedRefCreateFunction.py", PyUnresolvedReferencesInspection.class,
+ PyBundle.message("QFIX.unresolved.reference.create.function"), true, true);
+ }
@Override
@NonNls
protected String getTestDataPath() {