[pypy-svn] r30960 - in pypy/dist/pypy/translator: . cli cli/src cli/test

antocuni at codespeak.net antocuni at codespeak.net
Thu Aug 3 17:43:56 CEST 2006


Author: antocuni
Date: Thu Aug  3 17:43:33 2006
New Revision: 30960

Modified:
   pypy/dist/pypy/translator/cli/src/ll_os.cs
   pypy/dist/pypy/translator/cli/support.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_builtin.py
   pypy/dist/pypy/translator/driver.py
Log:
some of the flags in the os module such as os.O_CREAT & co. are simply
different depending on the platform: this means that the same rpython
program can be different depending on the platform it is *compiled*
on. Moreover, these values are passed to external functions
implemented in pypylib.dll, which has no chance to know the original
meaning of the flags.

We really don't want this because .NET executables should be portable
between windows and Mono: to solve, we patch some of the attributes of
the os module to have the same value as in Windows just before the
annotation, then we restore the original values when the compilation
has been completed.

This could be dangerous if "real" python code (instead of rpython
code) tries to access such attributes when they are patched, but as
far as now tests are still passing, so I hope not have broken anything.

This is only a short-term hack, the long term solution will be to
refactor the I/O model of pypy.



Modified: pypy/dist/pypy/translator/cli/src/ll_os.cs
==============================================================================
--- pypy/dist/pypy/translator/cli/src/ll_os.cs	(original)
+++ pypy/dist/pypy/translator/cli/src/ll_os.cs	Thu Aug  3 17:43:33 2006
@@ -126,13 +126,19 @@
     {
         private static Dictionary<int, IFile> FileDescriptors;
         private static int fdcount;
-        private const int O_RDONLY = 0;
-        private const int O_WRONLY = 1;
-        private const int O_RDWR = 2;
-        private const int O_CREAT = 64;
-        private const int O_TRUNC = 512;
-        private const int O_APPEND = 1024;
-        private const int O_BINARY = 32768;
+        
+        // NB: these values are those used by Windows and they differs
+        // from the Unix ones; the os module is patched with these
+        // values before flowgraphing to make sure we get the very
+        // same values on each platform we do the compilation.
+        private const int O_RDONLY = 0x0000;
+        private const int O_WRONLY = 0x0001;
+        private const int O_RDWR   = 0x0002;
+        private const int O_APPEND = 0x0008;
+        private const int O_CREAT  = 0x0100;
+        private const int O_TRUNC  = 0x0200;
+        private const int O_TEXT   = 0x4000;
+        private const int O_BINARY = 0x8000;
 
         private const int S_IFMT = 61440;
         private const int S_IFDIR = 16384;

Modified: pypy/dist/pypy/translator/cli/support.py
==============================================================================
--- pypy/dist/pypy/translator/cli/support.py	(original)
+++ pypy/dist/pypy/translator/cli/support.py	Thu Aug  3 17:43:33 2006
@@ -46,3 +46,34 @@
             label = ', '.join([str(item) for item in key])
             f.write('%s: %d\n' % (label, self.counters[key]))
         f.close()
+
+NT_OS = dict(
+    O_RDONLY = 0x0000,
+    O_WRONLY = 0x0001,
+    O_RDWR   = 0x0002,
+    O_APPEND = 0x0008,
+    O_CREAT  = 0x0100,
+    O_TRUNC  = 0x0200,
+    O_TEXT   = 0x4000,
+    O_BINARY = 0x8000
+    )
+
+def patch_os(defs=None):
+    """
+    Modify the value of some attributes of the os module to be sure
+    they are the same on every platform pypy is compiled on. Returns a
+    dictionary containing the original values that can be passed to
+    patch_os to rollback to the original values.
+    """
+    
+    import os
+    if defs is None:
+        defs = NT_OS
+    olddefs = {}
+    for name, value in defs.iteritems():
+        try:
+            olddefs[name] = getattr(os, name)
+        except AttributeError:
+            pass
+        setattr(os, name, value)
+    return olddefs

Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py	Thu Aug  3 17:43:33 2006
@@ -18,6 +18,7 @@
 from pypy.translator.cli.database import LowLevelDatabase
 from pypy.translator.cli.sdk import SDK
 from pypy.translator.cli.entrypoint import BaseEntryPoint
+from pypy.translator.cli.support import patch_os
 
 FLOAT_PRECISION = 8
 
@@ -112,9 +113,11 @@
 
 
 def compile_function(func, annotation=[], graph=None):
+    olddefs = patch_os() # patch the values of some attributes of the os module
     gen = _build_gen(func, annotation, graph)
     gen.generate_source()
     exe_name = gen.build_exe()
+    patch_os(olddefs) # restore original values
     return CliFunctionWrapper(exe_name)
 
 def _build_gen(func, annotation, graph=None):

Modified: pypy/dist/pypy/translator/cli/test/test_builtin.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_builtin.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_builtin.py	Thu Aug  3 17:43:33 2006
@@ -17,15 +17,28 @@
     test_os_path_exists = skip_os
     test_os_isdir = skip_os
 
+    def test_patch_os(self):
+        from pypy.translator.cli.support import patch_os, NT_OS
+        original_O_CREAT = os.O_CREAT
+        olddefs = patch_os()
+        assert os.O_CREAT == NT_OS['O_CREAT']
+        patch_os(olddefs)
+        assert os.O_CREAT == original_O_CREAT
+
+    def test_os_flags(self):
+        from pypy.translator.cli.support import NT_OS
+        def fn():
+            return os.O_CREAT
+        assert self.interpret(fn, []) == NT_OS['O_CREAT']
+
     def test_os_read(self):
         BaseTestRbuiltin.test_os_read(self)
 
     def test_os_read_binary_crlf(self):
         tmpfile = str(udir.udir.join("os_read_test"))
         def fn(flag):
-            from pypy.module.__builtin__.importing import BIN_READMASK
             if flag:
-                fd = os.open(tmpfile, BIN_READMASK, 0666)
+                fd = os.open(tmpfile, os.O_RDONLY|os.O_BINARY, 0666)
             else:
                 fd = os.open(tmpfile, os.O_RDONLY, 0666)
             res = os.read(fd, 4096)
@@ -51,18 +64,15 @@
         pass
 
     def test_os_open_write(self):
-        skip_win()
         tmpdir = str(udir.udir.join("os_write_test"))
         def fn():
-            fd = os.open(tmpdir, os.O_WRONLY|os.O_CREAT, 0777)            
+            fd = os.open(tmpdir, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0777)            
             os.write(fd, "hello world")
             os.close(fd)
         self.interpret(fn, [])
         assert file(tmpdir).read() == 'hello world'
 
     def test_os_write_magic(self):
-        from pypy.module.__builtin__.importing import BIN_WRITEMASK
-        skip_win()
         MAGIC = 62061 | (ord('\r')<<16) | (ord('\n')<<24)
         tmpfile = str(udir.udir.join("os_write_test"))
         def long2str(x):
@@ -75,11 +85,11 @@
             d = x & 0xff
             return chr(a) + chr(b) + chr(c) + chr(d)
         def fn(magic):
-            fd = os.open(tmpfile, BIN_WRITEMASK, 0777)
+            fd = os.open(tmpfile, os.O_BINARY|os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0777)
             os.write(fd, long2str(magic))
             os.close(fd)
         self.interpret(fn, [MAGIC])
-        contents = file(tmpfile).read()
+        contents = file(tmpfile, 'rb').read()
         assert contents == long2str(MAGIC)
 
     def test_os_stat(self):

Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Thu Aug  3 17:43:33 2006
@@ -199,7 +199,19 @@
             self.done[goal] = True
         return res
 
-    def task_annotate(self):  
+    def task_annotate(self):
+        # XXX: this should be a separate task, but I don't know how to
+        # specify a task to be executed before annotation only if the
+        # backend is 'cli'
+
+        # patch some attributes of the os module to make sure they
+        # have the same value on every platform.
+        backend, ts = self.get_backend_and_type_system()
+        if backend == 'cli':
+            from pypy.translator.cli.support import patch_os
+            self.old_os_defs = patch_os()
+        # end of XXX
+        
         # includes annotation and annotatation simplifications
         translator = self.translator
         policy = self.policy
@@ -482,9 +494,13 @@
                              'Generating CLI source')
 
     def task_compile_cli(self):
+        from pypy.translator.cli.support import patch_os
         from pypy.translator.cli.test.runtest import CliFunctionWrapper
         filename = self.gen.build_exe()
         self.c_entryp = CliFunctionWrapper(filename)
+        # restore original os values
+        patch_os(self.old_os_defs)
+        
         self.log.info("Compiled %s" % filename)
     task_compile_cli = taskdef(task_compile_cli, ['source_cli'],
                               'Compiling CLI source')



More information about the Pypy-commit mailing list