Execute multi-line code fragments by runsrouce with 'exec' option instead of one line by one (PY-10769).

This commit is contained in:
Dmitry Trofimov
2013-11-18 17:33:40 +01:00
parent 04d706e0b2
commit cbabd0bb04
8 changed files with 111 additions and 142 deletions
+28 -13
View File
@@ -132,6 +132,11 @@ class StdIn(BaseStdIn):
return '\n'
class ExecCode:
def __init__(self, code, is_single_line=True):
self.code = code
self.is_single_line = is_single_line
#=======================================================================================================================
# BaseInterpreterInterface
#=======================================================================================================================
@@ -142,20 +147,14 @@ class BaseInterpreterInterface:
self.exec_queue = _queue.Queue(0)
self.buffer = []
def needMore(self, buffer, line):
if not buffer:
buffer = []
buffer.append(line)
source = "\n".join(buffer)
def needMoreForCode(self, source):
if hasattr(self.interpreter, 'is_complete'):
return not self.interpreter.is_complete(source)
try:
code = self.interpreter.compile(source, "<input>", "single")
code = self.interpreter.compile(source, "<input>", "exec")
except (OverflowError, SyntaxError, ValueError):
# Case 1
return False
if code is None:
# Case 2
return True
@@ -163,8 +162,16 @@ class BaseInterpreterInterface:
# Case 3
return False
def needMore(self, buffer, line):
if not buffer:
buffer = []
buffer.append(line)
source = "\n".join(buffer)
return self.needMoreForCode(source)
def addExec(self, line):
def addExec(self, command):
original_in = sys.stdin
try:
help = None
@@ -203,7 +210,7 @@ class BaseInterpreterInterface:
try:
self.startExec()
more = self.doAddExec(line)
more = self.doAddExec(command)
self.finishExec()
finally:
if help is not None:
@@ -229,7 +236,7 @@ class BaseInterpreterInterface:
return more, need_input
def doAddExec(self, line):
def doAddExec(self, command):
'''
Subclasses should override.
@@ -309,14 +316,22 @@ class BaseInterpreterInterface:
def execLine(self, line):
try:
#buffer = self.interpreter.buffer[:]
self.exec_queue.put(line)
self.exec_queue.put(ExecCode(line, True))
return self.needMore(self.buffer, line)
except:
traceback.print_exc()
return False
def execMultipleLines(self, lines):
try:
self.exec_queue.put(ExecCode(lines, False))
return self.needMoreForCode(lines)
except:
traceback.print_exc()
return False
def interrupt(self):
try:
if self.interruptable:
@@ -39,14 +39,14 @@ class InterpreterInterface(BaseInterpreterInterface):
def get_greeting_msg(self):
return self.interpreter.get_greeting_msg()
def doAddExec(self, line):
def doAddExec(self, command):
self.notify_about_magic()
if (line.rstrip().endswith('??')):
if (command.rstrip().endswith('??')):
print('IPython-->')
try:
res = bool(self.interpreter.addExec(line))
res = bool(self.interpreter.addExec(command))
finally:
if (line.rstrip().endswith('??')):
if (command.rstrip().endswith('??')):
print('<--IPython')
return res
+20 -51
View File
@@ -10,7 +10,6 @@ import os
import sys
from pydevd_constants import USE_LIB_COPY
from pydevd_utils import *
if USE_LIB_COPY:
import _pydev_threading as threading
@@ -72,56 +71,25 @@ try:
except ImportError:
import _pydev_xmlrpclib as xmlrpclib
try:
class ExecState:
FIRST_CALL = True
PYDEV_CONSOLE_RUN_IN_UI = False #Defines if we should run commands in the UI thread.
from org.python.pydev.core.uiutils import RunInUiThread #@UnresolvedImport
from java.lang import Runnable #@UnresolvedImport
class Command:
def __init__(self, interpreter, command):
"""
:type command: object
:type interpreter: InteractiveConsole
"""
self.interpreter = interpreter
self.command = command
self.more = None
class Command(Runnable):
def __init__(self, interpreter, line):
self.interpreter = interpreter
self.line = line
def run(self):
if ExecState.FIRST_CALL:
ExecState.FIRST_CALL = False
sys.stdout.write('\nYou are now in a console within Eclipse.\nUse it with care as it can halt the VM.\n')
sys.stdout.write(
'Typing a line with "PYDEV_CONSOLE_TOGGLE_RUN_IN_UI"\nwill start executing all the commands in the UI thread.\n\n')
if self.line == 'PYDEV_CONSOLE_TOGGLE_RUN_IN_UI':
ExecState.PYDEV_CONSOLE_RUN_IN_UI = not ExecState.PYDEV_CONSOLE_RUN_IN_UI
if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
sys.stdout.write(
'Running commands in UI mode. WARNING: using sys.stdin (i.e.: calling raw_input()) WILL HALT ECLIPSE.\n')
else:
sys.stdout.write('No longer running commands in UI mode.\n')
self.more = False
else:
self.more = self.interpreter.push(self.line)
def Sync(runnable):
if ExecState.PYDEV_CONSOLE_RUN_IN_UI:
return RunInUiThread.sync(runnable)
def run(self):
if self.command.is_single_line:
self.more = self.interpreter.push(self.command.code)
else:
return runnable.run()
self.more = self.interpreter.runsource(self.command.code, '<input>', 'exec')
except:
#If things are not there, define a way in which there's no 'real' sync, only the default execution.
class Command:
def __init__(self, interpreter, line):
self.interpreter = interpreter
self.line = line
def run(self):
self.more = self.interpreter.push(self.line)
def Sync(runnable):
runnable.run()
def Sync(runnable):
runnable.run()
try:
try:
@@ -152,8 +120,8 @@ class InterpreterInterface(BaseInterpreterInterface):
self._input_error_printed = False
def doAddExec(self, line):
command = Command(self.interpreter, line)
def doAddExec(self, command):
command = Command(self.interpreter, command)
Sync(command)
return command.more
@@ -185,11 +153,11 @@ def process_exec_queue(interpreter):
while 1:
try:
try:
line = interpreter.exec_queue.get(block=True, timeout=0.05)
command = interpreter.exec_queue.get(block=True, timeout=0.05)
except _queue.Empty:
continue
if not interpreter.addExec(line): #TODO: think about locks here
if not interpreter.addExec(command): #TODO: think about locks here
interpreter.buffer = []
except KeyboardInterrupt:
interpreter.buffer = []
@@ -274,6 +242,7 @@ def start_server(host, port, interpreter):
raise
server.register_function(interpreter.execLine)
server.register_function(interpreter.execMultipleLines)
server.register_function(interpreter.getCompletions)
server.register_function(interpreter.getFrame)
server.register_function(interpreter.getVariable)