mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-18 00:20:54 +07:00
140 lines
5.4 KiB
Python
140 lines
5.4 KiB
Python
import sys
|
|
|
|
|
|
# =======================================================================================================================
|
|
# BaseStdIn
|
|
# =======================================================================================================================
|
|
class BaseStdIn:
|
|
def __init__(self, original_stdin=sys.stdin, *args, **kwargs):
|
|
try:
|
|
self.encoding = sys.stdin.encoding
|
|
except:
|
|
# Not sure if it's available in all Python versions...
|
|
pass
|
|
self.original_stdin = original_stdin
|
|
|
|
def readline(self, *args, **kwargs):
|
|
# sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything
|
|
# This could happen if the user had done input('enter number).<-- upon entering this, that message would appear,
|
|
# which is not something we want.
|
|
return '\n'
|
|
|
|
def write(self, *args, **kwargs):
|
|
pass # not available StdIn (but it can be expected to be in the stream interface)
|
|
|
|
def flush(self, *args, **kwargs):
|
|
pass # not available StdIn (but it can be expected to be in the stream interface)
|
|
|
|
def read(self, *args, **kwargs):
|
|
# in the interactive interpreter, a read and a readline are the same.
|
|
return self.readline()
|
|
|
|
def close(self, *args, **kwargs):
|
|
pass # expected in StdIn
|
|
|
|
def __iter__(self):
|
|
# BaseStdIn would not be considered as Iterable in Python 3 without explicit `__iter__` implementation
|
|
self.iter = self.original_stdin.__iter__()
|
|
return self
|
|
|
|
def __next__(self):
|
|
return self.iter.__next__()
|
|
|
|
def __getattr__(self, item):
|
|
# it's called if the attribute wasn't found
|
|
if hasattr(self.original_stdin, item):
|
|
return getattr(self.original_stdin, item)
|
|
raise AttributeError("%s has no attribute %s" % (self.original_stdin, item))
|
|
|
|
|
|
# =======================================================================================================================
|
|
# StdIn
|
|
# =======================================================================================================================
|
|
class StdIn(BaseStdIn):
|
|
'''
|
|
Object to be added to stdin (to emulate it as non-blocking while the next line arrives)
|
|
'''
|
|
|
|
def __init__(self, interpreter, rpc_client, original_stdin=sys.stdin):
|
|
BaseStdIn.__init__(self, original_stdin)
|
|
self.interpreter = interpreter
|
|
self.rpc_client = rpc_client
|
|
|
|
def readline(self, *args, **kwargs):
|
|
return self.request_input()
|
|
|
|
def request_input(self):
|
|
from pydev_console.pydev_protocol import KeyboardInterruptException
|
|
|
|
# Ok, callback into the client to get the new input
|
|
try:
|
|
requested_input = self.rpc_client.requestInput()
|
|
if not requested_input:
|
|
return '\n' # Yes, a readline must return something (otherwise we can get an EOFError on the input() call).
|
|
return requested_input
|
|
except KeyboardInterrupt:
|
|
raise # Let KeyboardInterrupt go through -- #PyDev-816: Interrupting infinite loop in the Interactive Console
|
|
except KeyboardInterruptException:
|
|
# this exception is explicitly declared in `requestInput()` method of `PythonConsoleFrontendService` Thrift service
|
|
# it is thrown on the IDE side and transferred by Thrift library as the response to `requestInput()` method
|
|
raise
|
|
except:
|
|
return '\n'
|
|
|
|
def close(self, *args, **kwargs):
|
|
pass # expected in StdIn
|
|
|
|
def __iter__(self):
|
|
return self
|
|
|
|
def __next__(self):
|
|
return self.request_input()
|
|
|
|
#=======================================================================================================================
|
|
# DebugConsoleStdIn
|
|
#=======================================================================================================================
|
|
class DebugConsoleStdIn(BaseStdIn):
|
|
'''
|
|
Object to be added to stdin (to emulate it as non-blocking while the next line arrives)
|
|
'''
|
|
|
|
def __init__(self, dbg, original_stdin):
|
|
BaseStdIn.__init__(self, original_stdin)
|
|
self.debugger = dbg
|
|
|
|
def __pydev_run_command(self, is_started):
|
|
try:
|
|
cmd = self.debugger.cmd_factory.make_input_requested_message(is_started)
|
|
self.debugger.writer.add_command(cmd)
|
|
except Exception:
|
|
import traceback
|
|
traceback.print_exc()
|
|
return '\n'
|
|
|
|
def readline(self, *args, **kwargs):
|
|
# Notify Java side about input and call original function
|
|
self.__pydev_run_command(True)
|
|
result = self.original_stdin.readline(*args, **kwargs)
|
|
self.__pydev_run_command(False)
|
|
return result
|
|
|
|
def __iter__(self):
|
|
self.iter = self.original_stdin.__iter__()
|
|
return self
|
|
|
|
def __next__(self):
|
|
# Notify Java side about input and call original function
|
|
self.__pydev_run_command(True)
|
|
released = False
|
|
if self.debugger._main_lock.is_acquired_by_current_thread():
|
|
# release main lock while waiting for input to process internal commands and handle interrupt() request
|
|
self.debugger._main_lock.release()
|
|
released = True
|
|
try:
|
|
result = self.iter.__next__()
|
|
finally:
|
|
self.__pydev_run_command(False)
|
|
if released:
|
|
self.debugger._main_lock.acquire()
|
|
return result
|