[pypy-commit] pypy py3.3: Implement preliminary stderr printer and use it in app_main.py.

mjacob noreply at buildbot.pypy.org
Wed Aug 26 18:06:52 CEST 2015


Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.3
Changeset: r79232:54b7b89a7172
Date: 2015-08-26 18:06 +0200
http://bitbucket.org/pypy/pypy/changeset/54b7b89a7172/

Log:	Implement preliminary stderr printer and use it in app_main.py.

	This is needed because during initialization of stderr imports can
	happen. If the interpreter is run in verbose mode importlib prints
	to stderr, resulting in an AttributeError.

diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -43,9 +43,10 @@
 """
 
 try:
-    from __pypy__ import hidden_applevel
+    from __pypy__ import hidden_applevel, StdErrPrinter
 except ImportError:
     hidden_applevel = lambda f: f
+    StdErrPrinter = None
 try:
     from _ast import PyCF_ACCEPT_NULL_BYTES
 except ImportError:
@@ -266,6 +267,9 @@
     if hasattr(sys, 'stdin'):
         return # already initialized
 
+    if StdErrPrinter is not None:
+        sys.stderr = sys.__stderr__ = StdErrPrinter(2)
+
     if 1:  # keep indentation
         if encoding and ':' in encoding:
             encoding, errors = encoding.split(':', 1)
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -87,6 +87,7 @@
         'save_module_content_for_future_reload':
                           'interp_magic.save_module_content_for_future_reload',
         'normalize_exc'             : 'interp_magic.normalize_exc',
+        'StdErrPrinter'             : 'interp_stderrprinter.W_StdErrPrinter',
     }
 
     submodules = {
diff --git a/pypy/module/__pypy__/interp_stderrprinter.py b/pypy/module/__pypy__/interp_stderrprinter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/interp_stderrprinter.py
@@ -0,0 +1,70 @@
+import errno, os
+
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import wrap_oserror
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import GetSetProperty, TypeDef
+
+
+class W_StdErrPrinter(W_Root):
+    @staticmethod
+    @unwrap_spec(fd='c_int')
+    def descr_new(space, w_subtype, fd):
+        return W_StdErrPrinter(fd)
+
+    def __init__(self, fd):
+        self.fd = fd
+
+    def descr_repr(self, space):
+        addrstring = unicode(self.getaddrstring(space))
+        return space.wrap(u"<StdErrPrinter(fd=%d) object at 0x%s>" %
+                          (self.fd, addrstring))
+
+    def descr_noop(self, space):
+        pass
+
+    def descr_fileno(self, space):
+        return space.wrap(self.fd)
+
+    def descr_isatty(self, space):
+        try:
+            res = os.isatty(self.fd)
+        except OSError, e:
+            raise wrap_oserror(space, e)
+        return space.wrap(res)
+
+    def descr_write(self, space, w_data):
+        # Encode to UTF-8.
+        data = space.identifier_w(w_data)
+
+        try:
+            n = os.write(self.fd, data)
+        except OSError, e:
+            if e.errno == errno.EAGAIN:
+                return space.w_None
+            raise wrap_oserror(space, e)
+        return space.wrap(n)
+
+    def descr_get_closed(self, space):
+        return space.wrap(False)
+
+    def descr_get_encoding(self, space):
+        return space.w_None
+
+    def descr_get_mode(self, space):
+        return space.wrap(u'w')
+
+
+W_StdErrPrinter.typedef = TypeDef("StdErrPrinter",
+    __new__ = interp2app(W_StdErrPrinter.descr_new),
+    __repr__ = interp2app(W_StdErrPrinter.descr_repr),
+    close = interp2app(W_StdErrPrinter.descr_noop),
+    flush = interp2app(W_StdErrPrinter.descr_noop),
+    fileno = interp2app(W_StdErrPrinter.descr_fileno),
+    isatty = interp2app(W_StdErrPrinter.descr_isatty),
+    write = interp2app(W_StdErrPrinter.descr_write),
+
+    closed = GetSetProperty(W_StdErrPrinter.descr_get_closed),
+    encoding = GetSetProperty(W_StdErrPrinter.descr_get_encoding),
+    mode = GetSetProperty(W_StdErrPrinter.descr_get_mode),
+)
diff --git a/pypy/module/__pypy__/test/test_stderrprinter.py b/pypy/module/__pypy__/test/test_stderrprinter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/test/test_stderrprinter.py
@@ -0,0 +1,16 @@
+def app_test_stderrprinter():
+    from __pypy__ import StdErrPrinter
+
+    p = StdErrPrinter(2)
+    assert repr(p).startswith("<StdErrPrinter(fd=2) object at")
+
+    p.close()  # this should be a no-op
+    p.flush()  # this should be a no-op
+    assert p.fileno() == 2
+    assert p.isatty()
+    assert p.write('foo') == 3
+    raises(TypeError, p.write, b'foo')
+
+    assert not p.closed
+    assert p.encoding is None
+    assert p.mode == 'w'


More information about the pypy-commit mailing list