[pypy-svn] r48996 - in pypy/branch/windows48396/pypy/translator/goal: . test2

tismer at codespeak.net tismer at codespeak.net
Fri Nov 23 19:05:18 CET 2007


Author: tismer
Date: Fri Nov 23 19:05:18 2007
New Revision: 48996

Added:
   pypy/branch/windows48396/pypy/translator/goal/nanos.py   (contents, props changed)
   pypy/branch/windows48396/pypy/translator/goal/test2/test_nanos.py   (contents, props changed)
Modified:
   pypy/branch/windows48396/pypy/translator/goal/app_main.py
   pypy/branch/windows48396/pypy/translator/goal/targetpypystandalone.py
Log:
a final solution to the import problem in app_main.py
Actually quite elegant and minimal

Modified: pypy/branch/windows48396/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/branch/windows48396/pypy/translator/goal/app_main.py	(original)
+++ pypy/branch/windows48396/pypy/translator/goal/app_main.py	Fri Nov 23 19:05:18 2007
@@ -144,64 +144,27 @@
 # ____________________________________________________________
 # Main entry point
 
-# faking os, until we really are able to import it from source
-"""
-Why reload_os ?
----------------
-
-When pypy is starting, the builtin modules are there, but os.path
-is a Python module. The current startup code depends on os.py,
-which had the side effect that os.py got frozen into the binary.
-
-Os.py is a wrapper for system specific built-in modules and tries
-to unify the interface. One problem is os.environ which looks
-very differently per os.
-Access to os.environ is not possible on Windows, due to caching
-problems. We solve that by passing the PATH envirnment setting
-in from a low-level interface.
-
-As an intermediate hack, the os.path functions are used until
-os.py can be imported. The module is then re-imported. This
-intermediate, since it will still leave os.environ unusable.
-(the last version solved that by hairy import tricks)
-
-The next version will avoid early import of os, alltogether.
-"""
+# see nanos.py for explainment why we do not import os here
+# CAUTION!
+# remember to update nanos.py if you are using more functions
+# from os or os.path!
+# Running test/test_nanos.py might be helpful as well.
 
 def we_are_translated():
-    # this function does not exist on app-level.
-    # Don't confuse it with
-    # from pypy.rlib.objectmodel import we_are_translated
-    # which I did.
+    # app-level, very different from pypy.rlib.objectmodel.we_are_translated
     return hasattr(sys, 'pypy_translation_info')
 
-class reload_os:
-    def __init__(self):
-        self.pre_import = sys.modules.keys()
-
-    def reload(self):
-        # re-load modules instead of using the pre-compiled ones
-        # note that this gives trouble if we are not translated,
-        # since some exithandler in threading.py complains
-        if we_are_translated():
-            for mod in sys.modules.keys():
-                if mod not in self.pre_import:
-                    del sys.modules[mod]
-        global os
-        import os
-        
-reload_os = reload_os()
-import os
-
-AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d'
-
 if 'nt' in sys.builtin_module_names:
     IS_WINDOWS = True
     DRIVE_LETTER_SEP = ':'
 else:
     IS_WINDOWS = False
 
-def entry_point(executable, argv, path):
+def entry_point(executable, argv, nanos):
+    # a substituted os if we are translated
+    global os
+    os = nanos
+    AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d'
     # find the full path to the executable, assuming that if there is no '/'
     # in the provided one then we must look along the $PATH
     if we_are_translated() and IS_WINDOWS and not executable.lower().endswith('.exe'):
@@ -209,8 +172,7 @@
     if os.sep in executable or (IS_WINDOWS and DRIVE_LETTER_SEP in executable):
         pass    # the path is already more than just an executable name
     else:
-        # path = os.getenv('PATH')
-        # we avoid getenv
+        path = os.getenv('PATH')
         if path:
             for dir in path.split(os.pathsep):
                 fn = os.path.join(dir, executable)
@@ -238,8 +200,6 @@
         sys.path = newpath      # found!
         break
     
-    reload_os.reload() # from now on use a fresh import
-    
     go_interactive = False
     run_command = False
     import_site = True
@@ -441,6 +401,7 @@
 
 
 if __name__ == '__main__':
+    import os
     import autopath
     # obscure! try removing the following line, see how it crashes, and
     # guess why...
@@ -459,5 +420,5 @@
     from pypy.module.sys.version import PYPY_VERSION
     sys.pypy_version_info = PYPY_VERSION
     sys.pypy_initial_path = pypy_initial_path
-    sys.exit(entry_point(sys.argv[0], sys.argv[1:], os.getenv("PATH")))
+    sys.exit(entry_point(sys.argv[0], sys.argv[1:], os))
     #sys.exit(entry_point('app_main.py', sys.argv[1:]))

Added: pypy/branch/windows48396/pypy/translator/goal/nanos.py
==============================================================================
--- (empty file)
+++ pypy/branch/windows48396/pypy/translator/goal/nanos.py	Fri Nov 23 19:05:18 2007
@@ -0,0 +1,53 @@
+"""
+Not An os or Nano os :-)
+
+Implementation of a few methods needed for starting up
+PyPy in app_main without importing os there.
+
+At startup time, app_main wants to find out about itself,
+sys.executable, the path to its library etc.
+This is done the easiest using os.py, but since this
+is a python module, we have a recurrence problem.
+
+Importing it at compile time would work, partially,
+but the way os is initialized will cause os.getenv
+to malfunction, due to caching problems.
+
+The solution taken here implements a minimal os using
+app-level code that is created at compile-time. Only
+the few needed functions are implemented in a tiny os module
+that contains a tiny path module.
+
+os.getenv got a direct implementation to overcome the caching
+problem.
+
+Please adjust the applevel code below, if you need to support
+more from os and os.path.
+"""
+
+from pypy.interpreter.gateway import applevel, ObjSpace, W_Root, interp2app
+import os
+
+app_os_path = applevel(r'''
+    from os.path import dirname, join, abspath, isfile, islink
+''', filename=__file__)
+
+app_os = applevel(r'''
+    from os import sep, pathsep
+    try:
+        from os import readlink
+    except ImportError:
+        pass
+''', filename=__file__)
+
+def getenv(space, w_name):
+    name = space.str_w(w_name)
+    return space.wrap(os.environ.get(name))
+getenv_w = interp2app(getenv, unwrap_spec=[ObjSpace, W_Root])
+
+def setup_nanos(space):
+    w_os = space.wrap(app_os.buildmodule(space, 'os'))
+    w_os_path = space.wrap(app_os_path.buildmodule(space, 'path'))
+    space.setattr(w_os, space.wrap('path'), w_os_path)
+    space.setattr(w_os, space.wrap('getenv'), space.wrap(getenv_w))
+    return w_os

Modified: pypy/branch/windows48396/pypy/translator/goal/targetpypystandalone.py
==============================================================================
--- pypy/branch/windows48396/pypy/translator/goal/targetpypystandalone.py	(original)
+++ pypy/branch/windows48396/pypy/translator/goal/targetpypystandalone.py	Fri Nov 23 19:05:18 2007
@@ -8,6 +8,7 @@
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy
 from pypy.config.config import Config, to_optparse, make_dict, SUPPRESS_USAGE
 from pypy.tool.option import make_objspace
+from pypy.translator.goal.nanos import setup_nanos
 
 thisdir = py.magic.autopath().dirpath()
 
@@ -26,6 +27,7 @@
     w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
     w_call_finish_gateway = space.wrap(gateway.interp2app(call_finish))
     w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
+    w_os = setup_nanos(space)
 
     def entry_point(argv):
         #debug("entry point starting") 
@@ -43,9 +45,7 @@
                 space.call_function(w_run_toplevel, w_call_startup_gateway)
                 w_executable = space.wrap(argv[0])
                 w_argv = space.newlist([space.wrap(s) for s in argv[1:]])
-                # we avoid using app-level environ due to the weird initialization of os
-                w_path = space.wrap(os.environ.get("PATH"))
-                w_exitcode = space.call_function(w_entry_point, w_executable, w_argv, w_path)
+                w_exitcode = space.call_function(w_entry_point, w_executable, w_argv, w_os)
                 exitcode = space.int_w(w_exitcode)
                 # try to pull it all in
             ##    from pypy.interpreter import main, interactive, error

Added: pypy/branch/windows48396/pypy/translator/goal/test2/test_nanos.py
==============================================================================
--- (empty file)
+++ pypy/branch/windows48396/pypy/translator/goal/test2/test_nanos.py	Fri Nov 23 19:05:18 2007
@@ -0,0 +1,20 @@
+"""
+Tests for the entry point of pypy-c, whether nanos.py is supplying
+the needed names for app_main.py.
+"""
+import os
+
+from pypy.translator.goal import app_main
+this_dir = os.path.dirname(app_main.__file__)
+
+from pypy.objspace.std import Space
+from pypy.translator.goal.targetpypystandalone import create_entry_point
+
+def test_nanos():
+    space = Space()
+    # manually imports app_main.py
+    filename = os.path.join(this_dir, 'app_main.py')
+    w_dict = space.newdict()
+    space.exec_(open(filename).read(), w_dict, w_dict)
+    entry_point = create_entry_point(space, w_dict)
+    entry_point(['', '-c', 'print 42'])



More information about the Pypy-commit mailing list