diff --git a/python/helpers/generator3.py b/python/helpers/generator3.py
index b737a3def8ff..7d9625093305 100644
--- a/python/helpers/generator3.py
+++ b/python/helpers/generator3.py
@@ -27,6 +27,8 @@ but seemingly no one uses them in C extensions yet anyway.
VERSION = "1.99" # Must be a number-dot-number string, updated with each change that affects generated skeletons
# Note: DON'T FORGET TO UPDATE!
+VERSION_CONTROL_HEADER_FORMAT = '# from %s by generator %s'
+
import sys
import os
import string
@@ -1789,8 +1791,7 @@ class ModuleRedeclarator(object):
else:
mod_name = " does not know its name"
out(0, "# module ", p_name, mod_name) # line 2
- version_control_header_format = '# from %s by generator %s'
- out(0, version_control_header_format % (
+ out(0, VERSION_CONTROL_HEADER_FORMAT % (
self.mod_filename or getattr(self.module, "__file__", "(built-in)"), VERSION)
) # line 3
if p_name == BUILTIN_MOD_NAME and version[0] == 2 and version[1] >= 6:
@@ -2115,7 +2116,7 @@ def buildOutputName(subdir, name):
fname = target_name + ".py"
return fname
-def redoModule(name, out_name, mod_file_name, doing_builtins, imported_module_names):
+def redoModule(name, outfile, mod_file_name, doing_builtins, imported_module_names):
# gobject does 'del _gobject' in its __init__.py, so the chained attribute lookup code
# fails to find 'gobject._gobject'. thus we need to pull the module directly out of
# sys.modules
@@ -2134,15 +2135,11 @@ def redoModule(name, out_name, mod_file_name, doing_builtins, imported_module_na
report("Failed to find CLR module " + name)
break
if mod:
- action("opening %r", out_name)
- outfile = fopen(out_name, "w")
action("restoring")
r = ModuleRedeclarator(mod, outfile, mod_file_name, doing_builtins=doing_builtins)
r.redo(name, imported_module_names)
action("flushing")
r.flush()
- action("closing %r", out_name)
- outfile.close()
else:
report("Failed to find imported module in sys.modules")
@@ -2283,57 +2280,72 @@ def processOne(name, mod_file_name, doing_builtins):
sys.stdout.flush()
action("doing nothing")
#noinspection PyBroadException
+ outfile = None
try:
- fname = buildOutputName(subdir, name)
-
- old_modules = list(sys.modules.keys())
- imported_module_names = []
- class MyFinder:
- def find_module(self, fullname, path=None):
- if fullname != name:
- imported_module_names.append(fullname)
- return None
-
- my_finder = None
- if hasattr(sys, 'meta_path'):
- my_finder = MyFinder()
- sys.meta_path.append(my_finder)
- else:
- imported_module_names = None
-
- action("importing %r", name)
try:
+ fname = buildOutputName(subdir, name)
+ action("opening %r", fname)
+ outfile = fopen(fname, "w")
+ old_modules = list(sys.modules.keys())
+ imported_module_names = []
+ class MyFinder:
+ def find_module(self, fullname, path=None):
+ if fullname != name:
+ imported_module_names.append(fullname)
+ return None
+
+ my_finder = None
+ if hasattr(sys, 'meta_path'):
+ my_finder = MyFinder()
+ sys.meta_path.append(my_finder)
+ else:
+ imported_module_names = None
+
+ action("importing")
__import__(name) # sys.modules will fill up with what we want
- except ImportError:
+
+ if my_finder:
+ sys.meta_path.remove(my_finder)
+ if imported_module_names is None:
+ imported_module_names = [m for m in sys.modules.keys() if m not in old_modules]
+
+ redoModule(name, outfile, mod_file_name, doing_builtins, imported_module_names)
+ # The C library may have called Py_InitModule() multiple times to define several modules (gtk._gtk and gtk.gdk);
+ # restore all of them
+ if imported_module_names:
+ for m in sys.modules.keys():
+ action("looking at possible submodule %r", m)
+ # if module has __file__ defined, it has Python source code and doesn't need a skeleton
+ if m not in old_modules and m not in imported_module_names and m != name and not hasattr(sys.modules[m], '__file__'):
+ if not quiet:
+ say(m)
+ sys.stdout.flush()
+ fname = buildOutputName(subdir, m)
+ action("opening %r", fname)
+ subfile = fopen(fname, "w")
+ try:
+ redoModule(m, subfile, mod_file_name, doing_builtins, imported_module_names)
+ finally:
+ action("closing %r", fname)
+ subfile.close()
+ except:
exctype, value = sys.exc_info()[:2]
- report("Name %r failed to import: %r", name, str(value))
+ msg = "Failed to process %r while %s: %s" % (name, _current_action, str(value))
+ report(msg)
+ if outfile is not None and not outfile.closed:
+ outfile.write("# encoding: %s\n" % OUT_ENCODING)
+ outfile.write("# module %s\n" % name)
+ outfile.write(VERSION_CONTROL_HEADER_FORMAT % (mod_file_name, VERSION))
+ outfile.write("\n\n")
+ outfile.write("# Skeleton generation error:\n#\n# " + msg + "\n")
+ if debug_mode:
+ if sys.platform == 'cli':
+ traceback.print_exc(file=sys.stderr)
+ raise
return False
-
- if my_finder:
- sys.meta_path.remove(my_finder)
- if imported_module_names is None:
- imported_module_names = [m for m in sys.modules.keys() if m not in old_modules]
-
- redoModule(name, fname, mod_file_name, doing_builtins, imported_module_names)
- # The C library may have called Py_InitModule() multiple times to define several modules (gtk._gtk and gtk.gdk);
- # restore all of them
- if imported_module_names:
- for m in sys.modules.keys():
- action("looking at possible submodule %r", m)
- # if module has __file__ defined, it has Python source code and doesn't need a skeleton
- if m not in old_modules and m not in imported_module_names and m != name and not hasattr(sys.modules[m], '__file__'):
- if not quiet:
- say(m)
- sys.stdout.flush()
- fname = buildOutputName(subdir, m)
- redoModule(m, fname, mod_file_name, doing_builtins, imported_module_names)
- except:
- report("Failed to process %r while %s", name, _current_action)
- if debug_mode:
- if sys.platform == 'cli':
- traceback.print_exc(file=sys.stderr)
- raise
- return False
+ finally:
+ if outfile is not None and not outfile.closed:
+ outfile.close()
return True
if __name__ == "__main__":
@@ -2434,7 +2446,7 @@ if __name__ == "__main__":
names.remove('__main__') # we don't want ourselves processed
ok = True
for name in names:
- ok = ok and processOne(name, None, True)
+ ok = processOne(name, None, True) and ok
if not ok:
sys.exit(1)
diff --git a/python/helpers/pydev/pydev_ipython_console.py b/python/helpers/pydev/pydev_ipython_console.py
index 7bb0049ad3de..fb835ce61709 100644
--- a/python/helpers/pydev/pydev_ipython_console.py
+++ b/python/helpers/pydev/pydev_ipython_console.py
@@ -15,14 +15,13 @@ try:
from pydev_ipython_console_010 import PyDevFrontEnd
sys.stderr.write('PyDev console: using IPython 0.10\n')
-except ImportError:
+except :
#IPython 0.11 broke compatibility...
from pydev_ipython_console_011 import PyDevFrontEnd
sys.stderr.write('PyDev console: using IPython 0.11\n')
-
#=======================================================================================================================
# InterpreterInterface
#=======================================================================================================================
diff --git a/python/helpers/pydev/pydev_log.py b/python/helpers/pydev/pydev_log.py
new file mode 100644
index 000000000000..2e66f3342717
--- /dev/null
+++ b/python/helpers/pydev/pydev_log.py
@@ -0,0 +1,30 @@
+import logging
+import os
+import sys
+from pydevd_constants import DebugInfoHolder
+
+logger = logging.getLogger('pydev')
+#hdlr = logging.FileHandler('/var/tmp/pycharm-debug-%d.log'%os.getpid())
+#formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+#hdlr.setFormatter(formatter)
+#logger.addHandler(hdlr)
+logger.setLevel(logging.DEBUG)
+
+def debug(message):
+ logger.debug(message)
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL>2:
+ sys.stderr.write(message)
+
+def warn(message):
+ logger.warn(message)
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL>1:
+ sys.stderr.write(message)
+
+def info(message):
+ logger.info(message)
+ sys.stderr.write(message)
+
+def error(message):
+ logger.error(message)
+ sys.stderr.write(message)
+
diff --git a/python/helpers/pydev/pydev_monkey.py b/python/helpers/pydev/pydev_monkey.py
index 391b6aae4b83..bd2f23f479b5 100644
--- a/python/helpers/pydev/pydev_monkey.py
+++ b/python/helpers/pydev/pydev_monkey.py
@@ -46,9 +46,10 @@ def patch_args(args):
return new_args
def monkey_patch_os(funcname, create_func):
- original_name = 'original_' + funcname
- setattr(os, original_name, getattr(os, funcname))
- setattr(os, funcname, create_func(original_name))
+ if hasattr(os, funcname):
+ original_name = 'original_' + funcname
+ setattr(os, original_name, getattr(os, funcname))
+ setattr(os, funcname, create_func(original_name))
def create_execl(original_name):
def new_execl(path, *args):
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index bfde4b94e951..2d5fe30fe309 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -63,6 +63,7 @@ import traceback
import pydevd_vm_type
import pydevd_tracing
import pydevd_io
+import pydev_log
from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
import time
import os
@@ -623,12 +624,12 @@ class PyDB:
except:
pass
- if DEBUG_TRACE_BREAKPOINTS > 0:
+ if DebugInfoHolder.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:
+ if DebugInfoHolder.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()
@@ -660,10 +661,13 @@ class PyDB:
if is_notify_on_terminate:
update_exception_hook(self)
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.error("Exceptions to hook on terminate: %s\n" % (self.always_exception_set,))
+
if is_notify_always:
self.always_exception_set.add(exception)
- if DEBUG_TRACE_BREAKPOINTS > 0:
- sys.stderr.write("Exceptions to hook : %s\n" % (self.always_exception_set,))
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.error("Exceptions to hook always: %s\n" % (self.always_exception_set,))
self.setTracingForUntracedContexts()
elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
@@ -1023,43 +1027,48 @@ class PyDB:
def processCommandLine(argv):
""" parses the arguments.
removes our arguments from the command line """
- retVal = {}
- retVal['client'] = ''
- retVal['server'] = False
- retVal['port'] = 0
- retVal['file'] = ''
- retVal['multiproc'] = False
+ setup = {}
+ setup['client'] = ''
+ setup['server'] = False
+ setup['port'] = 0
+ setup['file'] = ''
+ setup['multiproc'] = False
i = 0
del argv[0]
while (i < len(argv)):
if (argv[i] == '--port'):
del argv[i]
- retVal['port'] = int(argv[i])
+ setup['port'] = int(argv[i])
del argv[i]
elif (argv[i] == '--vm_type'):
del argv[i]
- retVal['vm_type'] = argv[i]
+ setup['vm_type'] = argv[i]
del argv[i]
elif (argv[i] == '--client'):
del argv[i]
- retVal['client'] = argv[i]
+ setup['client'] = argv[i]
del argv[i]
elif (argv[i] == '--server'):
del argv[i]
- retVal['server'] = True
+ setup['server'] = True
elif (argv[i] == '--file'):
del argv[i]
- retVal['file'] = argv[i]
+ setup['file'] = argv[i]
i = len(argv) # pop out, file is our last argument
elif (argv[i] == '--DEBUG_RECORD_SOCKET_READS'):
del argv[i]
- retVal['DEBUG_RECORD_SOCKET_READS'] = True
+ setup['DEBUG_RECORD_SOCKET_READS'] = True
+ elif (argv[i] == '--DEBUG'):
+ del argv[i]
+ setup['DEBUG_RECORD_SOCKET_READS'] = True
+ setup['DEBUG_TRACE_BREAKPOINTS'] = 1
+ setup['DEBUG_TRACE_LEVEL'] = 3
elif (argv[i] == '--multiproc'):
del argv[i]
- retVal['multiproc'] = True
+ setup['multiproc'] = True
else:
raise ValueError("unexpected option " + argv[i])
- return retVal
+ return setup
def usage(doExit=0):
sys.stdout.write('Usage:\n')
@@ -1262,26 +1271,36 @@ if __name__ == '__main__':
sys.modules['psyco'] = pydevd_psyco_stub
- PydevdLog(2, "Executing file ", setup['file'])
- PydevdLog(2, "arguments:", str(sys.argv))
+ pydev_log.debug("Executing file %s" % setup['file'])
+ pydev_log.debug("arguments: %s"% str(sys.argv))
+
+
pydevd_vm_type.SetupType(setup.get('vm_type', None))
DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
+ DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('', -1)
+ DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)
port = setup['port']
if setup['multiproc']:
+ pydev_log.debug("Started in multiproc mode")
dispatcher = Dispatcher()
dispatcher.connect(setup)
if dispatcher.port is not None:
port = dispatcher.port
- sys.stderr.write("pydev debugger: process %d is connecting\n"% os.getpid())
+ pydev_log.debug("Received port %d" %port)
+ pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
+
import pydev_monkey
- pydev_monkey.patch_new_process_functions()
+ try:
+ pydev_monkey.patch_new_process_functions()
+ except:
+ logger.error("Error patching process functions")
else:
- sys.stderr.write("pydev debugger: couldn't get port for new debug process\n")
+ pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
else:
- sys.stderr.write("pydev debugger: starting\n")
+ pydev_log.info("pydev debugger: starting\n")
debugger = PyDB()
debugger.connect(setup['client'], port)
diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py
index 626b86e87bd6..22fbbc17006f 100644
--- a/python/helpers/pydev/pydevd_breakpoints.py
+++ b/python/helpers/pydev/pydevd_breakpoints.py
@@ -1,5 +1,6 @@
from pydevd_constants import *
import sys
+import pydev_log
_original_excepthook = None
_handle_exceptions = None
@@ -44,8 +45,8 @@ class LineBreakpoint:
return breakDict
def trace(self, file, line, func_name):
- if DEBUG_TRACE_BREAKPOINTS > 0:
- sys.stderr.write('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name))
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name))
sys.stderr.flush()
def add(self, breakpoints, file, line, func_name):
diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py
index c1311a6dc094..290e02f41831 100644
--- a/python/helpers/pydev/pydevd_comm.py
+++ b/python/helpers/pydev/pydevd_comm.py
@@ -166,7 +166,7 @@ def PydevdLog(level, *args):
1 warnings/significant events
2 informational trace
"""
- if level <= DEBUG_TRACE_LEVEL:
+ if level <= DebugInfoHolder.DEBUG_TRACE_LEVEL:
#yes, we can have errors printing if the console of the program has been finished (and we're still trying to print something)
try:
sys.stderr.write('%s\n' % (args,))
@@ -325,7 +325,7 @@ class WriterThread(PyDBDaemonThread):
#but the thread was still not liberated
return
out = cmd.getOutgoing()
- if DEBUG_TRACE_LEVEL >= 1:
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
out_message = 'sending cmd: '
out_message += ID_TO_MEANING.get(out[:3], 'UNKNOWN')
out_message += ' '
@@ -343,7 +343,7 @@ class WriterThread(PyDBDaemonThread):
time.sleep(self.timeout)
except Exception:
GlobalDebuggerHolder.globalDbg.FinishDebuggingSession()
- if DEBUG_TRACE_LEVEL >= 0:
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 0:
traceback.print_exc()
@@ -434,7 +434,7 @@ class NetCommandFactory:
def makeErrorMessage(self, seq, text):
cmd = NetCommand(CMD_ERROR, seq, text)
- if DEBUG_TRACE_LEVEL > 2:
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL > 2:
sys.stderr.write("Error: %s" % (text,))
return cmd
diff --git a/python/helpers/pydev/pydevd_constants.py b/python/helpers/pydev/pydevd_constants.py
index b59f433df55b..d715fba5a89b 100644
--- a/python/helpers/pydev/pydevd_constants.py
+++ b/python/helpers/pydev/pydevd_constants.py
@@ -16,13 +16,14 @@ except:
setattr(__builtin__, 'True', 1)
setattr(__builtin__, 'False', 0)
-DEBUG_TRACE_LEVEL = -1
-DEBUG_TRACE_BREAKPOINTS = -1
+
class DebugInfoHolder:
#we have to put it here because it can be set through the command line (so, the
#already imported references would not have it).
DEBUG_RECORD_SOCKET_READS = False
+ DEBUG_TRACE_LEVEL = -1
+ DEBUG_TRACE_BREAKPOINTS = -1
#Optimize with psyco? This gave a 50% speedup in the debugger in tests
USE_PSYCO_OPTIMIZATION = True
diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py
index e39d7283bf97..bfd2f44f86ca 100644
--- a/python/helpers/pydev/pydevd_frame.py
+++ b/python/helpers/pydev/pydevd_frame.py
@@ -8,6 +8,7 @@ from pydevd_breakpoints import * #@UnusedWildImport
import traceback #@Reimport
import os.path
import sys
+import pydev_log
basename = os.path.basename
@@ -166,8 +167,8 @@ class PyDBFrame:
return self.trace_dispatch
except:
- sys.stderr.write('Error while evaluating condition \'%s\': %s\n' % (breakpoint.condition, sys.exc_info()[1]))
- sys.stderr.flush()
+ pydev_log.info('Error while evaluating condition \'%s\': %s\n' % (breakpoint.condition, sys.exc_info()[1]))
+
return self.trace_dispatch
if breakpoint.expression is not None:
@@ -332,8 +333,7 @@ class PyDBFrame:
if not val:
flag = False
except:
- sys.stderr.write('Error while evaluating condition \'%s\': %s\n' % (django_breakpoint.condition, sys.exc_info()[1]))
- sys.stderr.flush()
+ pydev_log.info('Error while evaluating condition \'%s\': %s\n' % (django_breakpoint.condition, sys.exc_info()[1]))
if django_breakpoint.expression is not None:
try:
diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py
index eede24de8cc9..5b380f58d339 100644
--- a/python/helpers/pydev/pydevd_vars.py
+++ b/python/helpers/pydev/pydevd_vars.py
@@ -8,6 +8,7 @@ from types import * #@UnusedWildImport
from code import compile_command
from code import InteractiveInterpreter
import pydevconsole
+import pydev_log
try:
from StringIO import StringIO
@@ -244,8 +245,8 @@ def frameVarsToXML(frame):
xml += varToXML(v, str(k))
except Exception:
traceback.print_exc()
- sys.stderr.write("Unexpected error, recovered safely.\n")
- sys.stderr.flush()
+ pydev_log.error("Unexpected error, recovered safely.\n")
+
return xml
def iterFrames(initialFrame):
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/PySourcePosition.java b/python/pydevSrc/com/jetbrains/python/debugger/PySourcePosition.java
index 808c739ae5a2..8bc97d22634e 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/PySourcePosition.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/PySourcePosition.java
@@ -1,6 +1,8 @@
package com.jetbrains.python.debugger;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.Nullable;
public abstract class PySourcePosition {
@@ -8,10 +10,22 @@ public abstract class PySourcePosition {
private final int line;
protected PySourcePosition(final String file, final int line) {
- this.file = FileUtil.toSystemIndependentName(file);
+ this.file = normalize(file);
this.line = line;
}
+ @Nullable
+ private static String normalize(@Nullable String file) {
+ if (file == null) {
+ return file;
+ }
+ String res = FileUtil.toSystemIndependentName(file);
+ if (SystemInfo.isWindows) {
+ res = res.toLowerCase();
+ }
+ return res;
+ }
+
public String getFile() {
return file;
}
diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 338a400c790a..5a439e52cb8c 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -586,7 +586,7 @@
-
diff --git a/python/src/com/jetbrains/python/actions/CreatePackageAction.java b/python/src/com/jetbrains/python/actions/CreatePackageAction.java
index 125bcde05362..1474750b3a1c 100644
--- a/python/src/com/jetbrains/python/actions/CreatePackageAction.java
+++ b/python/src/com/jetbrains/python/actions/CreatePackageAction.java
@@ -48,7 +48,7 @@ public class CreatePackageAction extends DumbAwareAction {
}
}
- private static void createInitPyInHierarchy(PsiDirectory created, PsiDirectory ancestor) {
+ public static void createInitPyInHierarchy(PsiDirectory created, PsiDirectory ancestor) {
do {
createInitPy(created);
created = created.getParent();
@@ -58,6 +58,9 @@ public class CreatePackageAction extends DumbAwareAction {
private static void createInitPy(PsiDirectory directory) {
final FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance();
final FileTemplate template = fileTemplateManager.getInternalTemplate("Python Script");
+ if (directory.findFile(PyNames.INIT_DOT_PY) != null) {
+ return;
+ }
if (template != null) {
try {
FileTemplateUtil.createFromTemplate(template, PyNames.INIT_DOT_PY, fileTemplateManager.getDefaultProperties(), directory);
diff --git a/python/src/com/jetbrains/python/codeInsight/codeFragment/PyCodeFragmentUtil.java b/python/src/com/jetbrains/python/codeInsight/codeFragment/PyCodeFragmentUtil.java
index c58cade63a2b..0d3be71ba1dc 100644
--- a/python/src/com/jetbrains/python/codeInsight/codeFragment/PyCodeFragmentUtil.java
+++ b/python/src/com/jetbrains/python/codeInsight/codeFragment/PyCodeFragmentUtil.java
@@ -11,6 +11,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
+import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBinaryExpressionNavigator;
@@ -76,6 +77,9 @@ public class PyCodeFragmentUtil {
if (next instanceof ConditionalInstruction){
continue;
}
+ if (next instanceof ReadWriteInstruction && ((ReadWriteInstruction)next).getAccess().isAssertTypeAccess()) {
+ continue;
+ }
final PsiElement nextElement = next.getElement();
// Ignore binary operations control flow
if (nextElement != null && PyBinaryExpressionNavigator.getBinaryExpressionByOperand(nextElement) != null){
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
index 431b8b369bdc..384925c8a8a7 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
@@ -29,7 +29,7 @@ public class PyNamedTupleType extends PyClassType implements PyCallableType {
private final boolean myDefinition;
private final PsiElement myDeclaration;
private final List myFields;
-
+
private static final ImmutableSet ourClassMembers = ImmutableSet.of("_fields", "_make");
private static final ImmutableSet ourInstanceMembers = ImmutableSet.of("_asdict", "_replace");
@@ -83,7 +83,7 @@ public class PyNamedTupleType extends PyClassType implements PyCallableType {
@Override
public String getName() {
- return "namedtuple '" + myName + "'";
+ return myName;
}
@Override
@@ -99,6 +99,16 @@ public class PyNamedTupleType extends PyClassType implements PyCallableType {
return null;
}
+ @Override
+ public PyClassType toInstance() {
+ return myIsDefinition ? new PyNamedTupleType(myDeclaration, myName, myFields, false) : this;
+ }
+
+ @Override
+ public String toString() {
+ return "PyNamedTupleType: " + myName;
+ }
+
@Nullable
public static PyType fromCall(PyCallExpression call) {
final String name = PyUtil.strValue(call.getArgument(0, PyExpression.class));
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties
index f44c59b3c64b..e83613538001 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/StdlibTypes2.properties
@@ -128,7 +128,7 @@ __builtin__.int.__sub__ = \
:rtype: int \n\
__builtin__.int.__mul__ = \
- :type y: int or long or float or complex or string or list \n\
+ :type y: int or long or float or complex \n\
:rtype: int \n\
__builtin__.int.__floordiv__ = \
@@ -631,7 +631,7 @@ __builtin__.str.encode = \
:rtype: bytes \n\
__builtin__.str.endswith = \
- :type suffix: string \n\
+ :type suffix: string or tuple \n\
:type start: int or long or None \n\
:type end: int or long or None \n\
:rtype: bool \n\
@@ -730,7 +730,7 @@ __builtin__.str.splitlines = \
:rtype: list of bytes \n\
__builtin__.str.startswith = \
- :type prefix: string \n\
+ :type prefix: string or tuple \n\
:type start: int or long or None \n\
:type end: int or long or None \n\
:rtype: bool \n\
@@ -805,7 +805,7 @@ __builtin__.unicode.encode = \
:rtype: bytes \n\
__builtin__.unicode.endswith = \
- :type suffix: string \n\
+ :type suffix: string or tuple \n\
:type start: int or long or None \n\
:type end: int or long or None \n\
:rtype: bool \n\
@@ -910,7 +910,7 @@ __builtin__.unicode.splitlines = \
:rtype: list of unicode \n\
__builtin__.unicode.startswith = \
- :type prefix: string \n\
+ :type prefix: string or tuple \n\
:type start: int or long or None \n\
:type end: int or long or None \n\
:rtype: bool \n\
@@ -1108,6 +1108,82 @@ __builtin__.file.writelines = \
:type sequence_of_strings: collections.Iterable of string \n\
+## 9.4. decimal
+
+decimal.Decimal.as_tuple = \
+ :rtype: decimal.DecimalTuple \n\
+
+decimal.Decimal.__add__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__sub__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__mul__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__floordiv__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__mod__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__pow__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__div__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__truediv__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__radd__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rsub__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rmul__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rfloordiv__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rmod__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rpow__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rdiv__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__rtruediv__ = \
+ :type other: decimal.Decimal or int or long or float or complex \n\
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__pos__ = \
+ :rtype: decimal.Decimal \n\
+
+decimal.Decimal.__neg__ = \
+ :rtype: decimal.Decimal \n\
+
+
## 18.2. json
json.loads = \
diff --git a/python/src/com/jetbrains/python/console/ConsoleVisitorFilter.java b/python/src/com/jetbrains/python/console/ConsoleVisitorFilter.java
index d54f2011b64a..5ad0850800ae 100644
--- a/python/src/com/jetbrains/python/console/ConsoleVisitorFilter.java
+++ b/python/src/com/jetbrains/python/console/ConsoleVisitorFilter.java
@@ -1,6 +1,8 @@
package com.jetbrains.python.console;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.jetbrains.python.console.completion.PydevConsoleElement;
import com.jetbrains.python.inspections.*;
import com.jetbrains.python.validation.DocStringAnnotator;
import org.jetbrains.annotations.NotNull;
@@ -12,9 +14,9 @@ import org.jetbrains.annotations.NotNull;
*/
public class ConsoleVisitorFilter implements PythonVisitorFilter {
@Override
- public boolean isSupported(@NotNull Class visitorClass, @NotNull PsiElement element) {
+ public boolean isSupported(@NotNull Class visitorClass, @NotNull PsiElement element, PsiFile containingFile) {
//if we're in console
- if (PydevConsoleRunner.isInPydevConsole(element)) {
+ if (element instanceof PydevConsoleElement || containingFile.getCopyableUserData(PydevConsoleRunner.CONSOLE_KEY) != null) {
//inspections
if (visitorClass == PyUnusedLocalInspectionVisitor.class || visitorClass == PyUnboundLocalVariableInspection.Visitor.class ||
visitorClass == PyStatementEffectInspection.class || visitorClass == PySingleQuotedDocstringInspection.class ||
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
index 1a7ac4d2be55..af8984e5464c 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
@@ -476,8 +476,15 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
XBreakpoint> breakpoint = null;
if (threadInfo.isStopOnBreakpoint()) {
final PySourcePosition position = frames.get(0).getPosition();
+
breakpoint = myRegisteredBreakpoints.get(position);
if (breakpoint == null) {
+ System.out.println("Stopped:" + position.getFile() + ", " + position.getLine());
+ System.out.println("Registered:");
+ for (PySourcePosition s: myRegisteredBreakpoints.keySet()) {
+ System.out.println(s.getFile() + ", " + s.getLine());
+ }
+
myDebugger.removeTempBreakpoint(position.getFile(), position.getLine());
}
}
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
index e2c7c326f935..816e71120b66 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
@@ -165,7 +165,7 @@ public class PyDebugRunner extends GenericProgramRunner {
}
if (ApplicationManager.getApplication().isUnitTestMode()) {
- debugParams.addParameter("--DEBUG_RECORD_SOCKET_READS");
+ debugParams.addParameter("--DEBUG");
}
final String[] debuggerArgs = new String[]{
diff --git a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index d65905543dc3..78758da2a1a5 100644
--- a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -4,13 +4,10 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiReference;
+import com.intellij.psi.*;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -53,21 +50,34 @@ public class PyTypeCheckerInspection extends PyInspection {
}
final PyType argType = entry.getKey().getType(myTypeEvalContext);
final PyType paramType = p.getType(myTypeEvalContext);
- checkTypes(paramType, argType, entry.getKey(), myTypeEvalContext);
+ checkTypes(paramType, argType, entry.getKey(), myTypeEvalContext, true);
}
}
}
@Override
public void visitPyBinaryExpression(PyBinaryExpression node) {
- // TODO: Support operators besides PyBinaryExpression
- final PsiReference ref = node.getReference(PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext));
+ final PsiPolyVariantReference ref = node.getReference(resolveWithoutImplicits());
if (ref != null) {
- final PsiElement resolved = ref.resolve();
- if (resolved instanceof PyFunction) {
- final PyFunction fun = (PyFunction)resolved;
- final PyExpression arg = PyNames.isRightOperatorName(fun.getName()) ? node.getLeftExpression() : node.getRightExpression();
- checkSingleArgumentFunction(fun, arg);
+ final ResolveResult[] results = ref.multiResolve(false);
+ String error = null;
+ PyExpression arg = null;
+ for (ResolveResult result : results) {
+ final PsiElement resolved = result.getElement();
+ if (resolved instanceof PyFunction) {
+ final PyFunction fun = (PyFunction)resolved;
+ arg = PyNames.isRightOperatorName(fun.getName()) ? node.getLeftExpression() : node.getRightExpression();
+ error = checkSingleArgumentFunction(fun, arg, false);
+ if (error == null) {
+ return;
+ }
+ }
+ else {
+ return;
+ }
+ }
+ if (error != null) {
+ registerProblem(arg, error);
}
}
}
@@ -75,16 +85,17 @@ public class PyTypeCheckerInspection extends PyInspection {
@Override
public void visitPySubscriptionExpression(PySubscriptionExpression node) {
// TODO: Support slice PySliceExpressions
- final PsiReference ref = node.getReference(PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext));
+ final PsiReference ref = node.getReference(resolveWithoutImplicits());
if (ref != null) {
final PsiElement resolved = ref.resolve();
if (resolved instanceof PyFunction) {
- checkSingleArgumentFunction((PyFunction)resolved, node.getIndexExpression());
+ checkSingleArgumentFunction((PyFunction)resolved, node.getIndexExpression(), true);
}
}
}
- private void checkSingleArgumentFunction(@NotNull PyFunction fun, @Nullable PyExpression argument) {
+ @Nullable
+ private String checkSingleArgumentFunction(@NotNull PyFunction fun, @Nullable PyExpression argument, boolean registerProblem) {
if (argument != null) {
final PyParameter[] parameters = fun.getParameterList().getParameters();
if (parameters.length == 2) {
@@ -92,22 +103,29 @@ public class PyTypeCheckerInspection extends PyInspection {
if (p != null) {
final PyType argType = argument.getType(myTypeEvalContext);
final PyType paramType = p.getType(myTypeEvalContext);
- checkTypes(paramType, argType, argument, myTypeEvalContext);
+ return checkTypes(paramType, argType, argument, myTypeEvalContext, registerProblem);
}
}
}
+ return null;
}
- private void checkTypes(PyType superType, PyType subType, PsiElement node, TypeEvalContext context) {
+ @Nullable
+ private String checkTypes(PyType superType, PyType subType, PsiElement node, TypeEvalContext context, boolean registerPoblem) {
if (subType != null && superType != null) {
if (!PyTypeChecker.match(superType, subType, context)) {
- registerProblem(node, String.format("Expected type '%s', got '%s' instead",
- PythonDocumentationProvider.getTypeName(superType, context),
- PythonDocumentationProvider.getTypeName(subType, myTypeEvalContext)));
+ final String msg = String.format("Expected type '%s', got '%s' instead",
+ PythonDocumentationProvider.getTypeName(superType, context),
+ PythonDocumentationProvider.getTypeName(subType, myTypeEvalContext));
+ if (registerPoblem) {
+ registerProblem(node, msg);
+ }
+ return msg;
}
}
+ return null;
}
- };
+ }
@Override
public void inspectionFinished(LocalInspectionToolSession session, ProblemsHolder problemsHolder) {
diff --git a/python/src/com/jetbrains/python/inspections/PythonVisitorFilter.java b/python/src/com/jetbrains/python/inspections/PythonVisitorFilter.java
index 88665715bb1c..2d8fea63f09b 100644
--- a/python/src/com/jetbrains/python/inspections/PythonVisitorFilter.java
+++ b/python/src/com/jetbrains/python/inspections/PythonVisitorFilter.java
@@ -2,6 +2,7 @@ package com.jetbrains.python.inspections;
import com.intellij.lang.LanguageExtension;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
@@ -11,8 +12,7 @@ import org.jetbrains.annotations.NotNull;
* check if we should visit element
*/
public interface PythonVisitorFilter {
- public static final LanguageExtension INSTANCE =
- new LanguageExtension("Pythonid.visitorFilter");
+ LanguageExtension INSTANCE = new LanguageExtension("Pythonid.visitorFilter");
- boolean isSupported(@NotNull Class visitorClass, @NotNull PsiElement element);
+ boolean isSupported(@NotNull Class visitorClass, @NotNull PsiElement element, PsiFile containingFile);
}
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 07fc238e551e..7d04e8161f13 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -10,6 +10,7 @@ import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.MessageType;
@@ -498,7 +499,7 @@ public class PyUtil {
return false;
}
return PsiTreeUtil.isAncestor(statement.getLeftHandSideExpression(), element, false);
- }
+ }
public static boolean isDocString(PyExpression expression) {
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(expression, PyDocStringOwner.class);
@@ -783,22 +784,32 @@ public class PyUtil {
return selfName;
}
- @Nullable
- public static VirtualFile findInRoots(Module module, String path) {
- final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
- VirtualFile result = findInRoots(moduleRootManager.getContentRoots(), path);
- if (result == null) {
- result = findInRoots(moduleRootManager.getSourceRoots(), path);
+ @NotNull
+ public static List getSourceRoots(@NotNull PsiElement foothold) {
+ final Module module = ModuleUtil.findModuleForPsiElement(foothold);
+ if (module != null) {
+ return getSourceRoots(module);
}
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ public static List getSourceRoots(@NotNull Module module) {
+ final List result = new ArrayList();
+ final ModuleRootManager manager = ModuleRootManager.getInstance(module);
+ result.addAll(Arrays.asList(manager.getSourceRoots()));
+ result.addAll(Arrays.asList(manager.getContentRoots()));
return result;
}
@Nullable
- public static VirtualFile findInRoots(VirtualFile[] roots, String path) {
- for (VirtualFile root : roots) {
- VirtualFile settingsFile = root.findFileByRelativePath(path);
- if (settingsFile != null) {
- return settingsFile;
+ public static VirtualFile findInRoots(Module module, String path) {
+ if (module != null) {
+ for (VirtualFile root : getSourceRoots(module)) {
+ VirtualFile file = root.findFileByRelativePath(path);
+ if (file != null) {
+ return file;
+ }
}
}
return null;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java
index 6ba49a70928c..8b6efcfde24c 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java
@@ -12,7 +12,6 @@ import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
-import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.inspections.PythonVisitorFilter;
@@ -73,7 +72,7 @@ public class PyBaseElementImpl extends StubBasedPsiElemen
}
public static boolean isAcceptedFor(@NotNull final PsiElement element, @NotNull Class clazz) {
- PsiFile file = PsiTreeUtil.getNonStrictParentOfType(element, PsiFile.class);
+ PsiFile file = element.getContainingFile();
if (file != null) {
Language lang = file.getLanguage();
FileViewProvider vProvider = file.getViewProvider();
@@ -81,7 +80,7 @@ public class PyBaseElementImpl extends StubBasedPsiElemen
lang = vProvider.getBaseLanguage();
}
PythonVisitorFilter filter = PythonVisitorFilter.INSTANCE.forLanguage(lang);
- return filter != null ? filter.isSupported(clazz, element) : true;
+ return filter != null ? filter.isSupported(clazz, element, file) : true;
}
return true;
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
index d6f0f69b750e..b1483b725804 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
@@ -18,6 +18,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.SoftHashMap;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
@@ -56,6 +57,8 @@ public class PyClassImpl extends PyPresentableElementImpl implement
return CachedValuesManager.getManager(getProject()).createCachedValue(new NewStyleCachedValueProvider(), false);
}
};
+
+ private final SoftHashMap myPropertyCache = new SoftHashMap();
@Override
public PyType getType(@NotNull TypeEvalContext context) {
@@ -604,7 +607,16 @@ public class PyClassImpl extends PyPresentableElementImpl implement
@Nullable
@Override
public Property findProperty(@NotNull final String name) {
- return scanProperties(name, null, true);
+ synchronized (myPropertyCache) {
+ if (myPropertyCache.containsKey(name)) {
+ return myPropertyCache.get(name);
+ }
+ }
+ final Property result = scanProperties(name, null, true);
+ synchronized (myPropertyCache) {
+ myPropertyCache.put(name, result);
+ }
+ return result;
}
@Nullable
@@ -1025,6 +1037,9 @@ public class PyClassImpl extends PyPresentableElementImpl implement
if (myInstanceAttributes != null) {
myInstanceAttributes = null;
}
+ synchronized (myPropertyCache) {
+ myPropertyCache.clear();
+ }
}
@NotNull
diff --git a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
index 082ec398f2c7..d5be4db61fac 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyImportElementImpl.java
@@ -43,7 +43,8 @@ public class PyImportElementImpl extends PyBaseElementImpl
@Nullable
public PyReferenceExpression getImportReference() {
- return findChildByClass(PyReferenceExpression.class);
+ final ASTNode node = getNode().findChildByType(PyElementTypes.REFERENCE_EXPRESSION);
+ return node == null ? null : (PyReferenceExpression) node.getPsi();
}
public PyQualifiedName getImportedQName() {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyOperatorReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyOperatorReferenceImpl.java
index e729232123f4..6b738ae75761 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyOperatorReferenceImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyOperatorReferenceImpl.java
@@ -39,20 +39,18 @@ public class PyOperatorReferenceImpl extends PyReferenceImpl {
typeEvalContext.trace("Trying to resolve left operator");
typeEvalContext.traceIndent();
try {
- res = resolveMember(expr.getLeftExpression(), name);
+ res.addAll(resolveMember(expr.getLeftExpression(), name));
}
finally {
typeEvalContext.traceUnindent();
}
- if (res.isEmpty()) {
- typeEvalContext.trace("Trying to resolve right operator");
- typeEvalContext.traceIndent();
- try {
- res = resolveMember(expr.getRightExpression(), leftToRightOperatorName(name));
- }
- finally {
- typeEvalContext.traceUnindent();
- }
+ typeEvalContext.trace("Trying to resolve right operator");
+ typeEvalContext.traceIndent();
+ try {
+ res.addAll(resolveMember(expr.getRightExpression(), leftToRightOperatorName(name)));
+ }
+ finally {
+ typeEvalContext.traceUnindent();
}
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java
index 0d39ea8356fe..d1d758503719 100644
--- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
* @author oleg
*/
public class PyExtractMethodHandler implements RefactoringActionHandler {
-
+ @Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, final DataContext dataContext) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
// select editor text fragment
@@ -35,12 +35,11 @@ public class PyExtractMethodHandler implements RefactoringActionHandler {
invokeOnEditor(project, editor, file);
}
-
+ @Override
public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) {
- // ignore this
}
- private void invokeOnEditor(final Project project, final Editor editor, final PsiFile file) {
+ private static void invokeOnEditor(final Project project, final Editor editor, final PsiFile file) {
CommonRefactoringUtil.checkReadOnlyStatus(project, file);
PsiElement element1 = null;
PsiElement element2 = null;
@@ -112,7 +111,7 @@ public class PyExtractMethodHandler implements RefactoringActionHandler {
}
@Nullable
- private PsiElement[] getStatementsRange(final PsiElement element1, final PsiElement element2) {
+ private static PsiElement[] getStatementsRange(final PsiElement element1, final PsiElement element2) {
final PsiElement parent = PsiTreeUtil.findCommonParent(element1, element2);
if (parent == null) {
return null;
@@ -136,5 +135,4 @@ public class PyExtractMethodHandler implements RefactoringActionHandler {
}
return null;
}
-
}
diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
index bf8c95f91033..6a645a3ac704 100644
--- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
@@ -2,6 +2,7 @@ package com.jetbrains.python.refactoring.extractmethod;
import com.intellij.codeInsight.codeFragment.CodeFragment;
import com.intellij.lang.LanguageNamesValidation;
+import com.intellij.lang.refactoring.NamesValidator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
@@ -45,7 +46,6 @@ import java.util.Map;
* @author oleg
*/
public class PyExtractMethodUtil {
-
public static final String NAME = "extract.method.name";
private PyExtractMethodUtil() {
@@ -71,6 +71,9 @@ public class PyExtractMethodUtil {
// collect statements
final List elementsRange = PyPsiUtils.collectElements(statement1, statement2);
if (elementsRange.isEmpty()) {
+ CommonRefactoringUtil.showErrorHint(project, editor,
+ "Cannot perform refactoring from empty code fragment",
+ RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
return;
}
@@ -108,16 +111,17 @@ public class PyExtractMethodUtil {
builder.append("(").append(createCallArgsString(variableData)).append(")");
PsiElement callElement = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyCallExpression.class, builder.toString());
- //# replace statements with call
+ // Replace statements with call
callElement = replaceElements(elementsRange, callElement);
- // # Set editor
+ // Set editor
setSelectionAndCaret(editor, callElement);
}
});
}
}, "Extract method", null);
- } else {
+ }
+ else {
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -210,8 +214,10 @@ public class PyExtractMethodUtil {
if (fragment.getOutputVariables().isEmpty()) {
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
public void run() {
// Generate method
PyFunction generatedMethod = generateMethodFromExpression(project, methodName, variableData, expression, flags);
@@ -234,7 +240,9 @@ public class PyExtractMethodUtil {
PsiElement callElement = fragment.isReturnInstructionInside() ? returnStatement : returnStatement.getExpression();
// replace statements with call
- callElement = PyPsiUtils.replaceExpression(expression, callElement);
+ if (callElement != null) {
+ callElement = PyPsiUtils.replaceExpression(expression, callElement);
+ }
// Set editor
setSelectionAndCaret(editor, callElement);
@@ -372,15 +380,18 @@ public class PyExtractMethodUtil {
addFakeParameters(builder, variableData);
final PyFunction method = builder.buildFunction(project, LanguageLevel.getDefault());
final PyStatementList statementList = method.getStatementList();
-
+ assert statementList != null;
for (PsiElement element : elementsRange) {
- if (element instanceof PsiWhiteSpace){
+ if (element instanceof PsiWhiteSpace) {
continue;
}
statementList.add(element);
}
// remove last instruction
- statementList.getFirstChild().delete();
+ final PsiElement child = statementList.getFirstChild();
+ if (child != null) {
+ child.delete();
+ }
return method;
}
@@ -406,15 +417,15 @@ public class PyExtractMethodUtil {
final PsiElement element,
final boolean isClassMethod,
final boolean isStaticMethod) {
- final ExtractMethodValidator validator = new PyExtractMethodValidator(element, project);
- if (ApplicationManager.getApplication().isUnitTestMode()){
+ final ExtractMethodValidator validator = new PyExtractMethodValidator(element, project);
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
String name = System.getProperty(NAME);
if (name == null){
name = "foo";
}
final String error = validator.check(name);
if (error != null){
- if (ApplicationManager.getApplication().isUnitTestMode()){
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
throw new CommonRefactoringUtil.RefactoringErrorHintException(error);
}
final StringBuilder builder = new StringBuilder();
@@ -517,7 +528,9 @@ public class PyExtractMethodUtil {
}
public boolean isValidName(final String name) {
- return LanguageNamesValidation.INSTANCE.forLanguage(PythonLanguage.getInstance()).isIdentifier(name, myProject);
+ final NamesValidator validator = LanguageNamesValidation.INSTANCE.forLanguage(PythonLanguage.getInstance());
+ assert validator != null;
+ return validator.isIdentifier(name, myProject);
}
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java
index 3bce02aef7a3..d81877c29a17 100644
--- a/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveFileHandler.java
@@ -1,11 +1,13 @@
package com.jetbrains.python.refactoring.move;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
+import com.jetbrains.python.actions.CreatePackageAction;
import com.jetbrains.python.codeInsight.imports.PyImportOptimizer;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyQualifiedName;
@@ -33,6 +35,16 @@ public class PyMoveFileHandler extends MoveFileHandler {
@Override
public void prepareMovedFile(PsiFile file, PsiDirectory moveDestination, Map oldToNewMap) {
+ if (file != null) {
+ final List roots = PyUtil.getSourceRoots(file);
+ PsiDirectory root = moveDestination;
+ while (root != null && !roots.contains(root.getVirtualFile())) {
+ root = root.getParentDirectory();
+ }
+ if (moveDestination != root && root != null) {
+ CreatePackageAction.createInitPyInHierarchy(moveDestination, root);
+ }
+ }
// TODO: Update relative imports
}
diff --git a/python/src/com/jetbrains/python/sdk/IronPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/IronPythonSdkFlavor.java
index 6598c72b4907..bbb08aae87e9 100644
--- a/python/src/com/jetbrains/python/sdk/IronPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/IronPythonSdkFlavor.java
@@ -49,7 +49,7 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor {
@Override
public String getVersionString(String sdkHome) {
- return "IronPython " + getVersionFromOutput(sdkHome, "-V", "\\w+ ([0-9\\.]+).*", true);
+ return "IronPython " + getVersionFromOutput(sdkHome, "-V", "\\w+ ([0-9\\.]+).*");
}
@Override
diff --git a/python/src/com/jetbrains/python/sdk/JythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/JythonSdkFlavor.java
index a3a7da4e822b..70e5b9624bac 100644
--- a/python/src/com/jetbrains/python/sdk/JythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/JythonSdkFlavor.java
@@ -36,7 +36,7 @@ public class JythonSdkFlavor extends PythonSdkFlavor {
@Override
public String getVersionString(String sdkHome) {
- return getVersionFromOutput(sdkHome, "--version", "(Jython \\S+)( on .*)?", false);
+ return getVersionFromOutput(sdkHome, "--version", "(Jython \\S+)( on .*)?");
}
@Override
diff --git a/python/src/com/jetbrains/python/sdk/PyPySdkFlavor.java b/python/src/com/jetbrains/python/sdk/PyPySdkFlavor.java
index cf5ea8c54919..5f69d18c5ad2 100644
--- a/python/src/com/jetbrains/python/sdk/PyPySdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/PyPySdkFlavor.java
@@ -21,6 +21,6 @@ public class PyPySdkFlavor extends PythonSdkFlavor {
@Override
public String getVersionString(String sdkHome) {
- return getVersionFromOutput(sdkHome, "--version", "\\[(PyPy .+)\\]", true);
+ return getVersionFromOutput(sdkHome, "--version", "\\[(PyPy [^ ]+).*\\]");
}
}
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/PythonSdkFlavor.java
index 7a1be292bb38..5a394f3f3e9d 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkFlavor.java
@@ -80,11 +80,11 @@ public abstract class PythonSdkFlavor {
@Nullable
public String getVersionString(String sdkHome) {
- return getVersionFromOutput(sdkHome, "-V", "(Python \\S+).*", false);
+ return getVersionFromOutput(sdkHome, "-V", "(Python \\S+).*");
}
@Nullable
- protected static String getVersionFromOutput(String sdkHome, String version_opt, String version_regexp, boolean stdout) {
+ protected static String getVersionFromOutput(String sdkHome, String version_opt, String version_regexp) {
Pattern pattern = Pattern.compile(version_regexp);
String run_dir = new File(sdkHome).getParent();
final ProcessOutput process_output = SdkUtil.getProcessOutput(run_dir, new String[]{sdkHome, version_opt});
@@ -97,8 +97,11 @@ public abstract class PythonSdkFlavor {
);
return null;
}
- final List lines = stdout ? process_output.getStdoutLines() : process_output.getStderrLines();
- return SdkUtil.getFirstMatch(lines, pattern);
+ final String result = SdkUtil.getFirstMatch(process_output.getStderrLines(), pattern);
+ if (result != null) {
+ return result;
+ }
+ return SdkUtil.getFirstMatch(process_output.getStdoutLines(), pattern);
}
public Collection getExtraDebugOptions() {
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/namedTuple.py b/python/testData/inspections/PyUnresolvedReferencesInspection/namedTuple.py
index 6be5439959d5..66b7904a60a3 100644
--- a/python/testData/inspections/PyUnresolvedReferencesInspection/namedTuple.py
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/namedTuple.py
@@ -10,3 +10,6 @@ print p.__add__
print p._asdict()
print Point._fields
print p._replace
+
+if isinstance(p, Point):
+ p.x
\ No newline at end of file
diff --git a/python/testData/refactoring/extractmethod/methodInIf.after.py b/python/testData/refactoring/extractmethod/methodInIf.after.py
new file mode 100644
index 000000000000..56a5e579abfa
--- /dev/null
+++ b/python/testData/refactoring/extractmethod/methodInIf.after.py
@@ -0,0 +1,10 @@
+class C:
+ def baz(self, arg_new):
+ self.bar(arg_new)
+
+ def foo(self, option, arg):
+ if option:
+ self.baz(arg)
+
+ def bar(self, arg):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractmethod/methodInIf.before.py b/python/testData/refactoring/extractmethod/methodInIf.before.py
new file mode 100644
index 000000000000..c4011231c895
--- /dev/null
+++ b/python/testData/refactoring/extractmethod/methodInIf.before.py
@@ -0,0 +1,7 @@
+class C:
+ def foo(self, option, arg):
+ if option:
+ self.bar(arg)
+
+ def bar(self, arg):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/move/moduleToNonPackage/after/src/a.py b/python/testData/refactoring/move/moduleToNonPackage/after/src/a.py
new file mode 100644
index 000000000000..6618ac3cb7ca
--- /dev/null
+++ b/python/testData/refactoring/move/moduleToNonPackage/after/src/a.py
@@ -0,0 +1,7 @@
+from nonp3 import m1
+from nonp3.m1 import foo
+
+m1.foo
+m1.bar
+m1
+foo
\ No newline at end of file
diff --git a/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/__init__.py b/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/__init__.py
new file mode 100644
index 000000000000..09ee69e66c3c
--- /dev/null
+++ b/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/__init__.py
@@ -0,0 +1 @@
+__author__ = 'user1'
diff --git a/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/m1.py b/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/m1.py
new file mode 100644
index 000000000000..cb19528f954f
--- /dev/null
+++ b/python/testData/refactoring/move/moduleToNonPackage/after/src/nonp3/m1.py
@@ -0,0 +1,2 @@
+foo = 42
+bar = -1
\ No newline at end of file
diff --git a/python/testData/refactoring/move/moduleToNonPackage/after/src/p1/__init__.py b/python/testData/refactoring/move/moduleToNonPackage/after/src/p1/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/python/testData/refactoring/move/moduleToNonPackage/after/src/p1/p2/__init__.py b/python/testData/refactoring/move/moduleToNonPackage/after/src/p1/p2/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/python/testData/refactoring/move/moduleToNonPackage/before/src/a.py b/python/testData/refactoring/move/moduleToNonPackage/before/src/a.py
new file mode 100644
index 000000000000..89193abbbec7
--- /dev/null
+++ b/python/testData/refactoring/move/moduleToNonPackage/before/src/a.py
@@ -0,0 +1,9 @@
+from p1.p2 import m1
+from p1.p2.m1 import foo
+import p1.p2.m1
+import p1
+
+p1.p2.m1.foo
+m1.bar
+m1
+foo
\ No newline at end of file
diff --git a/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/__init__.py b/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/p2/__init__.py b/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/p2/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/p2/m1.py b/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/p2/m1.py
new file mode 100644
index 000000000000..cb19528f954f
--- /dev/null
+++ b/python/testData/refactoring/move/moduleToNonPackage/before/src/p1/p2/m1.py
@@ -0,0 +1,2 @@
+foo = 42
+bar = -1
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
index 1813b4382728..de00757ce9db 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
@@ -26,7 +26,7 @@ public abstract class PyCommandLineTestCase extends PyTestCase {
protected static int verifyPyDevDParameters(List params) {
params = Lists.newArrayList(params);
- int debugParam = params.remove("--DEBUG_RECORD_SOCKET_READS") ? 1 : 0;
+ int debugParam = params.remove("--DEBUG") ? 1 : 0;
assertEquals(PythonHelpersLocator.getHelperPath("pydev/pydevd.py"), params.get(0));
assertEquals("--client", params.get(1));
assertEquals("--port", params.get(3));
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyExtractMethodTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyExtractMethodTest.java
index dabbf42061bf..2827d4b074de 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyExtractMethodTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyExtractMethodTest.java
@@ -147,4 +147,9 @@ public class PyExtractMethodTest extends LightMarkedTestCase {
public void testStaticMethod() {
doTest("staticmethod.before.py", "baz", "staticmethod.after.py");
}
+
+ // PY-5123
+ public void testMethodInIf() {
+ doTest("methodInIf.before.py", "baz", "methodInIf.after.py");
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java
index 8451e7f720a3..67d03802aadc 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java
@@ -75,6 +75,11 @@ public class PyMoveTest extends PyTestCase {
doMoveFileTest("p1/p2/m1.py", "p1");
}
+ // PY-5168
+ public void testModuleToNonPackage() {
+ doMoveFileTest("p1/p2/m1.py", "nonp3");
+ }
+
private void doMoveFileTest(String fileName, String toDirName) {
Project project = myFixture.getProject();
PsiManager manager = PsiManager.getInstance(project);