[pypy-commit] pypy default: Move patch_sys() from _cffi_backend to pypy_setup_home() calling code

arigo pypy.commits at gmail.com
Wed Nov 9 10:50:54 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r88271:440d820c878f
Date: 2016-11-09 14:58 +0100
http://bitbucket.org/pypy/pypy/changeset/440d820c878f/

Log:	Move patch_sys() from _cffi_backend to pypy_setup_home() calling
	code from app_main.py. This is mostly motivated by py3.5, where
	setting up correctly 'sys.std*' is more involved.

diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -33,7 +33,12 @@
     if w_dict is not None: # for tests
         w_entry_point = space.getitem(w_dict, space.wrap('entry_point'))
         w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
+        w_initstdio = space.getitem(w_dict, space.wrap('initstdio'))
         withjit = space.config.objspace.usemodules.pypyjit
+    else:
+        w_initstdio = space.appexec([], """():
+            return lambda unbuffered: None
+        """)
 
     def entry_point(argv):
         if withjit:
@@ -103,18 +108,23 @@
                       " not found in %s or in any parent directory" % home1)
             return rffi.cast(rffi.INT, 1)
         space.startup()
-        space.appexec([w_path], """(path):
-            import sys
-            sys.path[:] = path
-        """)
-        # import site
+        must_leave = space.threadlocals.try_enter_thread(space)
         try:
-            space.setattr(space.getbuiltinmodule('sys'),
-                          space.wrap('executable'),
-                          space.wrap(home))
-            import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
-                                    space.wrap('__import__'))
-            space.call_function(import_, space.wrap('site'))
+            # initialize sys.{path,executable,stdin,stdout,stderr}
+            # (in unbuffered mode, to avoid troubles) and import site
+            space.appexec([w_path, space.wrap(home), w_initstdio],
+            r"""(path, home, initstdio):
+                import sys
+                sys.path[:] = path
+                sys.executable = home
+                initstdio(unbuffered=True)
+                try:
+                    import site
+                except Exception as e:
+                    sys.stderr.write("'import site' failed:\n")
+                    import traceback
+                    traceback.print_exc()
+            """)
             return rffi.cast(rffi.INT, 0)
         except OperationError as e:
             if verbose:
@@ -122,6 +132,9 @@
                 debug(" operror-type: " + e.w_type.getname(space))
                 debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
             return rffi.cast(rffi.INT, -1)
+        finally:
+            if must_leave:
+                space.threadlocals.leave_thread(space)
 
     @entrypoint_highlevel('main', [rffi.CCHARP], c_name='pypy_execute_source')
     def pypy_execute_source(ll_source):
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
@@ -275,6 +275,10 @@
 def set_fully_buffered_io():
     sys.stdout = sys.__stdout__ = fdopen(1, 'w')
 
+def initstdio(unbuffered=False):
+    if unbuffered:
+        set_unbuffered_io()
+
 # ____________________________________________________________
 # Main entry point
 
diff --git a/pypy/interpreter/test/test_targetpypy.py b/pypy/interpreter/test/test_targetpypy.py
--- a/pypy/interpreter/test/test_targetpypy.py
+++ b/pypy/interpreter/test/test_targetpypy.py
@@ -20,7 +20,7 @@
                                                 space.wrap('modules')),
                                                 space.wrap('xyz')))
     assert x == 3
-    lls = rffi.str2charp("sys")
+    lls = rffi.str2charp("sys   # should give a NameError")
     execute_source(lls)
     lltype.free(lls, flavor='raw')
     # did not crash - the same globals
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -71,7 +71,6 @@
     def startup(self, space):
         from pypy.module._cffi_backend import embedding
         embedding.glob.space = space
-        embedding.glob.patched_sys = False
 
 
 def get_dict_rtld_constants():
diff --git a/pypy/module/_cffi_backend/embedding.py b/pypy/module/_cffi_backend/embedding.py
--- a/pypy/module/_cffi_backend/embedding.py
+++ b/pypy/module/_cffi_backend/embedding.py
@@ -45,25 +45,6 @@
     pass
 glob = Global()
 
-def patch_sys(space):
-    # Annoying: CPython would just use the C-level std{in,out,err} as
-    # configured by the main application, for example in binary mode
-    # on Windows or with buffering turned off.  We can't easily do the
-    # same.  Instead, go for the safest bet (but possibly bad for
-    # performance) and open sys.std{in,out,err} unbuffered.  On
-    # Windows I guess binary mode is a better default choice.
-    #
-    # XXX if needed, we could add support for a flag passed to
-    # pypy_init_embedded_cffi_module().
-    if not glob.patched_sys:
-        space.appexec([], """():
-            import os, sys
-            sys.stdin  = sys.__stdin__  = os.fdopen(0, 'rb', 0)
-            sys.stdout = sys.__stdout__ = os.fdopen(1, 'wb', 0)
-            sys.stderr = sys.__stderr__ = os.fdopen(2, 'wb', 0)
-        """)
-        glob.patched_sys = True
-
 
 def pypy_init_embedded_cffi_module(version, init_struct):
     # called from __init__.py
@@ -76,7 +57,6 @@
         must_leave = False
         try:
             must_leave = space.threadlocals.try_enter_thread(space)
-            patch_sys(space)
             load_embedded_cffi_module(space, version, init_struct)
             res = 0
         except OperationError as operr:


More information about the pypy-commit mailing list