[pypy-svn] r48247 - pypy/dist/pypy/translator/goal
tismer at codespeak.net
tismer at codespeak.net
Fri Nov 2 06:08:01 CET 2007
Author: tismer
Date: Fri Nov 2 06:08:00 2007
New Revision: 48247
Modified:
pypy/dist/pypy/translator/goal/app_main.py
Log:
this is still not completely correct, but way better than before.
Nobody will believe that I hacked a week on this, already, because it cannot
be debugged without compilation...
Modified: pypy/dist/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/dist/pypy/translator/goal/app_main.py (original)
+++ pypy/dist/pypy/translator/goal/app_main.py Fri Nov 2 06:08:00 2007
@@ -16,14 +16,14 @@
--info print translation information about this PyPy executable
"""
-import sys, os
+import sys
DEBUG = False # dump exceptions before calling the except hook
originalexcepthook = sys.__excepthook__
def run_toplevel(f, *fargs, **fkwds):
- """Calls f() and handle all OperationErrors.
+ """Calls f() and handles all OperationErrors.
Intended use is to run the main program or one interactive statement.
run_protected() handles details like forwarding exceptions to
sys.excepthook(), catching SystemExit, printing a newline after
@@ -144,16 +144,120 @@
# ____________________________________________________________
# Main entry point
+# faking os, until we really are able to import it from source
+"""
+Why fake_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.
+Due to the way os.py initializes its environ variable on Windows,
+it s hard to get a correct os.getenv that uses the actual environment
+variables. In order to fix that without modifying os.py, we need to
+re-import it several times, before and after compilation.
+
+When compiling the source, we first create a fake_os class instance.
+fake_os contains all of os, when compiling.reduction seems to be not
+appropriate, since lots of other modules are sucked in, at the same time.
+A complete reduction is possible, but would require much more work.
+
+In the course of creating fake_os, we import the real os. We keep a record
+of which modules were imported, before.
+
+During start of the entry_point, we call os.setup().
+This repeats an import of the specific parts in os.name.
+Depending of the underlying os, this might or might not
+cause a redefinition of certain os variables, but this happens
+exactly like in os.py's initialization.
+We then capture the variable environ, which may or may not come from the
+specific os.
+After that, we re-initialize our dict to what is expected in standard
+os. The effect of all this magic is that we have captured the environ
+cariable, again, and we now can redefine os.getenv to use this fresh
+variable, being accurate and not frozen.
+
+At this point, we finally can compute the location of our import.
+
+As a side effect, the involved modules are re-imported, although they had
+been compiled in, so PyPy behaves really conformant, making all .py
+modules changeable, again.
+"""
+
+from pypy.rlib.objectmodel import we_are_translated
+
+class fake_os:
+ def __init__(self):
+ import sys
+ self.pre_import = sys.modules.keys()
+ import os
+ self.os = os
+ # make ourselves a clone of os
+ self.__dict__.update(self.os.__dict__)
+
+ def setup(self):
+ # we now repeat the os-specific initialization, which
+ # must be done before importing os, since os hides
+ # variables after initialization.
+ specifics = __import__(self.os.name)
+ self.__dict__.update(specifics.__dict__)
+ # depending on the os, we now might or might not have
+ # a new environ variable. However, we can now
+ # repeat the environ initialisation from os.py
+ environ = self.os._Environ(self.environ)
+ # to be safe, reset our dict to be like os
+ self.__dict__.update(self.os.__dict__)
+ # but now we insert the fresh environ
+ self.environ = environ
+ del self.getenv
+ # use our method, instead of the os's one's
+ assert self.getenv
+
+ def teardown(self):
+ for mod in sys.modules.keys():
+ if mod not in self.pre_import:
+ del sys.modules[mod]
+ global os
+ import os
+
+ def getenv(self, key, default=None):
+ """Get an environment variable, return None if it doesn't exist.
+ The optional second argument can specify an alternate default."""
+ return self.environ.get(key, default)
+
+os = fake_os()
+
AUTOSUBPATH = 'share' + os.sep + 'pypy-%d.%d'
+# hack to determine if we are on windows. Maybe there is a better way...
+DRIVE_LETTER_SEP = ''
+try:
+ here = os.getcwd()
+ try:
+ os.chdir('C:')
+ DRIVE_LETTER_SEP = ':'
+ finally:
+ os.chdir(here)
+except os.OSError:
+ DRIVE_LETTER_SEP = None
+IS_WINDOWS = DRIVE_LETTER_SEP is not None
+# XXX extend here
+
def entry_point(executable, argv):
# 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 os.sep not in executable:
+ os.setup() # this is the faked one
+ if os.sep not in executable and DRIVE_LETTER_SEP not in executable:
path = os.getenv('PATH')
if path:
for dir in path.split(os.pathsep):
fn = os.path.join(dir, executable)
+ if we_are_translated and IS_WINDOWS and not fn.lower().endswith('.exe'):
+ fn += '.exe'
if os.path.isfile(fn):
executable = fn
break
@@ -177,7 +281,9 @@
continue
sys.path = newpath # found!
break
-
+
+ os.teardown() # from now on this is the real one
+
go_interactive = False
run_command = False
import_site = True
More information about the Pypy-commit
mailing list