diff -r 300e2bbd413c Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py Wed Jul 11 09:17:54 2012 +0200 +++ b/Lib/idlelib/PyShell.py Wed Jul 11 12:11:02 2012 +0300 @@ -1,6 +1,7 @@ #! /usr/bin/env python3 import getopt +import io import os import os.path import re @@ -410,7 +411,8 @@ except socket.timeout as err: self.display_no_subprocess_error() return None - self.rpcclt.register("stdin", self.tkconsole) + self.rpcclt.register("console", self.tkconsole) + self.rpcclt.register("stdin", self.tkconsole.stdin) self.rpcclt.register("stdout", self.tkconsole.stdout) self.rpcclt.register("stderr", self.tkconsole.stderr) self.rpcclt.register("flist", self.tkconsole.flist) @@ -854,13 +856,14 @@ self.save_stderr = sys.stderr self.save_stdin = sys.stdin from idlelib import IOBinding - self.stdout = PseudoFile(self, "stdout", IOBinding.encoding) - self.stderr = PseudoFile(self, "stderr", IOBinding.encoding) - self.console = PseudoFile(self, "console", IOBinding.encoding) + self.stdout = OutputPseudoFile(self, "stdout", IOBinding.encoding) + self.stderr = OutputPseudoFile(self, "stderr", IOBinding.encoding) + self.console = OutputPseudoFile(self, "console", IOBinding.encoding) + self.stdin = InputPseudoFile(self, "stdin", IOBinding.encoding) if not use_subprocess: sys.stdout = self.stdout sys.stderr = self.stderr - sys.stdin = self + sys.stdin = self.stdin try: # page help() text to shell. import pydoc # import must be done here to capture i/o rebinding. @@ -1250,28 +1253,68 @@ if not use_subprocess: raise KeyboardInterrupt -class PseudoFile(object): +class PseudoFile(io.TextIOBase): def __init__(self, shell, tags, encoding=None): self.shell = shell self.tags = tags - self.encoding = encoding + self._encoding = encoding + + @property + def encoding(self): + return self._encoding + + def isatty(self): + return True + + def close(self): + return self.shell.close() + + +class InputPseudoFile(PseudoFile): + + _line_buffer = '' + + def readable(self): + return True + + def read(self, n=-1): + if n is None: + n = -1 + result = self._line_buffer + self._line_buffer = '' + if n < 0: + while True: + line = self.readline() + if not line: break + result += line + else: + while len(result) < n: + line = self.readline() + if not line: break + result += line + self._line_buffer = result[n:] + result = result[:n] + return result + + def readline(self): + if self._line_buffer: + line = self._line_buffer + self._line_buffer = '' + return line + return self.shell.readline() + + +class OutputPseudoFile(PseudoFile): + + def writable(self): + return True def write(self, s): if not isinstance(s, str): raise TypeError('must be str, not ' + type(s).__name__) self.shell.write(s, self.tags) - def writelines(self, lines): - for line in lines: - self.write(line) - - def flush(self): - pass - - def isatty(self): - return True - usage_msg = """\ diff -r 300e2bbd413c Lib/idlelib/run.py --- a/Lib/idlelib/run.py Wed Jul 11 09:17:54 2012 +0200 +++ b/Lib/idlelib/run.py Wed Jul 11 12:11:02 2012 +0300 @@ -258,29 +258,15 @@ quitting = True thread.interrupt_main() -class _RPCFile(io.TextIOBase): - """Wrapper class for the RPC proxy to typecheck arguments - that may not support pickling. The base class is there only - to support type tests; all implementations come from the remote - object.""" - - def __init__(self, rpc): - super.__setattr__(self, 'rpc', rpc) - - def __getattribute__(self, name): - # When accessing the 'rpc' attribute, or 'write', use ours - if name in ('rpc', 'write'): - return io.TextIOBase.__getattribute__(self, name) - # Else only look into the remote object only - return getattr(self.rpc, name) - - def __setattr__(self, name, value): - return setattr(self.rpc, name, value) - - def write(self, s): +def _checked_text_writer(writer): + # Wrap the RPC proxy to typecheck arguments that may not support pickling. + oldwrite = writer.write + def write(s): if not isinstance(s, str): raise TypeError('must be str, not ' + type(s).__name__) - return self.rpc.write(s) + return oldwrite(s) + writer.write = write + return writer class MyHandler(rpc.RPCHandler): @@ -288,9 +274,10 @@ """Override base method""" executive = Executive(self) self.register("exec", executive) - sys.stdin = self.console = self.get_remote_proxy("stdin") - sys.stdout = _RPCFile(self.get_remote_proxy("stdout")) - sys.stderr = _RPCFile(self.get_remote_proxy("stderr")) + sys.stdin = self.get_remote_proxy("stdin") + sys.stdout = _checked_text_writer(self.get_remote_proxy("stdout")) + sys.stderr = _checked_text_writer(self.get_remote_proxy("stderr")) + self.console = _checked_text_writer(self.get_remote_proxy("console")) sys.displayhook = rpc.displayhook # page help() text to shell. import pydoc # import must be done here to capture i/o binding