[issue15318] IDLE - sys.stdin is writeable

Serhiy Storchaka report at bugs.python.org
Wed Jul 11 11:35:16 CEST 2012


Serhiy Storchaka <storchaka at gmail.com> added the comment:

Added getvar method to PyShell.console.

----------
Added file: http://bugs.python.org/file26354/idle_stdstreams-3.patch

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue15318>
_______________________________________
-------------- next part --------------
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:33:10 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,15 @@
         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.console.getvar = self.getvar
+        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 +1254,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:33:10 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


More information about the Python-bugs-list mailing list