[pypy-svn] r16692 - in pypy/release/0.7.x/pypy: module/posix rpython rpython/module rpython/module/test translator/c translator/c/src translator/c/test

tismer at codespeak.net tismer at codespeak.net
Fri Aug 26 21:23:21 CEST 2005


Author: tismer
Date: Fri Aug 26 21:23:15 2005
New Revision: 16692

Added:
   pypy/release/0.7.x/pypy/rpython/ros.py   (contents, props changed)
Modified:
   pypy/release/0.7.x/pypy/module/posix/__init__.py
   pypy/release/0.7.x/pypy/module/posix/interp_posix.py
   pypy/release/0.7.x/pypy/rpython/extfunctable.py
   pypy/release/0.7.x/pypy/rpython/module/ll_os.py
   pypy/release/0.7.x/pypy/rpython/module/test/test_ll_os.py
   pypy/release/0.7.x/pypy/translator/c/extfunc.py
   pypy/release/0.7.x/pypy/translator/c/src/ll_os.h
   pypy/release/0.7.x/pypy/translator/c/test/test_extfunc.py
Log:
added putenv and environ to os.
That was particularly interesting,
because we have to keep the putenv arguments
alive, like CPython does.

Modified: pypy/release/0.7.x/pypy/module/posix/__init__.py
==============================================================================
--- pypy/release/0.7.x/pypy/module/posix/__init__.py	(original)
+++ pypy/release/0.7.x/pypy/module/posix/__init__.py	Fri Aug 26 21:23:15 2005
@@ -31,9 +31,12 @@
     'chdir'     : 'interp_posix.chdir',
     'mkdir'     : 'interp_posix.mkdir',
     'rmdir'     : 'interp_posix.rmdir',
+    'environ'   : 'interp_posix.get(space).w_environ'
     }
     if hasattr(os, 'ftruncate'):
         interpleveldefs['ftruncate'] = 'interp_posix.ftruncate'
+    if hasattr(os, 'putenv'):
+        interpleveldefs['putenv'] = 'interp_posix.putenv'
 
 
 for constant in dir(os):

Modified: pypy/release/0.7.x/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/release/0.7.x/pypy/module/posix/interp_posix.py	(original)
+++ pypy/release/0.7.x/pypy/module/posix/interp_posix.py	Fri Aug 26 21:23:15 2005
@@ -1,5 +1,6 @@
 from pypy.interpreter.baseobjspace import ObjSpace
 from pypy.rpython.rarithmetic import intmask
+from pypy.rpython import ros
 from pypy.interpreter.error import OperationError
 
 import os
@@ -77,7 +78,7 @@
     lst = [st[0], st[1], st[2], st[3], st[4],
            st[5], st[6], st[7], st[8], st[9]]
     w_tuple = space.newtuple([space.wrap(intmask(x)) for x in lst])
-    w_stat_result = space.getattr(space.getbuiltinmodule('posix'),
+    w_stat_result = space.getattr(space.getbuiltinmodule(os.name),
                                   space.wrap('stat_result'))
     return space.call_function(w_stat_result, w_tuple)
 
@@ -178,3 +179,43 @@
     except OSError, e: 
         raise wrap_oserror(space, e) 
 rmdir.unwrap_spec = [ObjSpace, str]
+
+
+# this is a particular case, because we need to supply
+# the storage for the environment variables, at least
+# for some OSes.
+
+class State:
+    def __init__(self, space): 
+        self.posix_putenv_garbage = {}
+        self.w_environ = space.newdict([])
+        _convertenviron(space, self.w_environ)
+def get(space): 
+    return space.fromcache(State) 
+
+def _convertenviron(space, w_env):
+    idx = 0
+    while 1:
+        s = ros.environ(idx)
+        if s is None:
+            break
+        p = s.find('=');
+        if p >= 0:
+            assert p >= 0
+            key = s[:p]
+            value = s[p+1:]
+            space.setitem(w_env, space.wrap(key), space.wrap(value))
+        idx += 1
+
+def putenv(space, name, value):
+    """putenv(key, value)
+
+Change or add an environment variable."""
+    txt = '%s=%s' % name, value
+    ros.putenv(txt)
+    # Install the first arg and newstr in posix_putenv_garbage;
+    # this will cause previous value to be collected.  This has to
+    # happen after the real putenv() call because the old value
+    # was still accessible until then.
+    get(space).posix_putenv_garbage[name] = txt
+putenv.unwrap_spec = [ObjSpace, str, str]

Modified: pypy/release/0.7.x/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/release/0.7.x/pypy/rpython/extfunctable.py	(original)
+++ pypy/release/0.7.x/pypy/rpython/extfunctable.py	Fri Aug 26 21:23:15 2005
@@ -128,6 +128,10 @@
     from pypy.annotation.model import SomeTuple, SomeFloat
     return SomeTuple((SomeFloat(), SomeFloat()))
 
+def strnullannotation(*args):
+    from pypy.annotation.model import SomeString
+    return SomeString(can_be_None=True)
+
 # external function declarations
 declare(os.open     , int           , 'll_os/open')
 declare(os.read     , str           , 'll_os/read')
@@ -193,6 +197,12 @@
 declare(rarithmetic.formatd, str, 'll_strtod/formatd')
 
 # ___________________________________________________________
+# special helpers for os with no equivalent
+from pypy.rpython import ros
+declare(ros.putenv,  noneannotation, 'll_os/putenv')
+declare(ros.environ, strnullannotation, 'll_os/environ')
+
+# ___________________________________________________________
 # the exceptions that can be implicitely raised by some operations
 standardexceptions = {
     TypeError        : True,

Modified: pypy/release/0.7.x/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/release/0.7.x/pypy/rpython/module/ll_os.py	(original)
+++ pypy/release/0.7.x/pypy/rpython/module/ll_os.py	Fri Aug 26 21:23:15 2005
@@ -17,7 +17,7 @@
 from pypy.rpython.rstr import STR
 from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc
 from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy
-
+from pypy.rpython import ros
 
 def ll_os_open(fname, flag, mode):
     return os.open(from_rstr(fname), flag, mode)
@@ -133,3 +133,13 @@
 def ll_os_rmdir(path):
     os.rmdir(from_rstr(path))
 ll_os_rmdir.suggested_primitive = True
+
+# this function is not really the os thing, but the internal one.
+def ll_os_putenv(name_eq_value):
+    ros.putenv(from_rstr(name_eq_value))
+ll_os_putenv.suggested_primitive = True
+
+# get the initial environment as a string list
+def ll_os_environ(idx):
+    return ros.environ(idx)
+ll_os_environ.suggested_primitive = True

Modified: pypy/release/0.7.x/pypy/rpython/module/test/test_ll_os.py
==============================================================================
--- pypy/release/0.7.x/pypy/rpython/module/test/test_ll_os.py	(original)
+++ pypy/release/0.7.x/pypy/rpython/module/test/test_ll_os.py	Fri Aug 26 21:23:15 2005
@@ -35,3 +35,20 @@
     assert data == 0
     assert file(filename).read().strip() == '2'
     os.unlink(filename)
+
+def test_putenv():
+    filename = str(udir.join('test_putenv.txt'))
+    arg = to_rstr('abcdefgh=12345678')
+    ll_os_putenv(arg)
+    cmd = '''python -c "import os; print os.environ['abcdefgh']" > %s''' % filename
+    os.system(cmd)
+    assert file(filename).read().strip() == '12345678'
+    os.unlink(filename)
+
+def test_environ():
+    count = 0
+    while 1:
+        if not ll_os_environ(count):
+            break
+        count += 1
+    assert count == len(os.environ.keys())

Added: pypy/release/0.7.x/pypy/rpython/ros.py
==============================================================================
--- (empty file)
+++ pypy/release/0.7.x/pypy/rpython/ros.py	Fri Aug 26 21:23:15 2005
@@ -0,0 +1,17 @@
+"""
+Helper file for Python equivalents of os specific calls.
+"""
+
+import os
+
+def putenv(name_eq_value):
+    # we fake it with the real one
+    name, value = name_eq_value.split('=', 1)
+    os.putenv(name, value)
+
+_initial_items = os.environ.items()
+
+def environ(idx):
+    # we simulate the environ list
+    if idx < len(_initial_items):
+        return '%s=%s' % _initial_items[idx]

Modified: pypy/release/0.7.x/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/release/0.7.x/pypy/translator/c/extfunc.py	(original)
+++ pypy/release/0.7.x/pypy/translator/c/extfunc.py	Fri Aug 26 21:23:15 2005
@@ -27,6 +27,8 @@
     ll_os  .ll_os_chdir:   'LL_os_chdir',
     ll_os  .ll_os_mkdir:   'LL_os_mkdir',
     ll_os  .ll_os_rmdir:   'LL_os_rmdir',
+    ll_os  .ll_os_putenv:  'LL_os_putenv',
+    ll_os  .ll_os_environ: 'LL_os_environ',
     ll_time.ll_time_clock: 'LL_time_clock',
     ll_time.ll_time_sleep: 'LL_time_sleep',
     ll_time.ll_time_time:  'LL_time_time',

Modified: pypy/release/0.7.x/pypy/translator/c/src/ll_os.h
==============================================================================
--- pypy/release/0.7.x/pypy/translator/c/src/ll_os.h	(original)
+++ pypy/release/0.7.x/pypy/translator/c/src/ll_os.h	Fri Aug 26 21:23:15 2005
@@ -201,3 +201,43 @@
 	RPYTHON_RAISE_OSERROR(errno);
     }
 }
+
+#ifdef HAVE_PUTENV
+
+/* note that this doesn't map to os.putenv, it is the name=value
+ * version of C. See ros.py for the fake implementation.
+ * Note that we are responsible to keep the
+ * value alive. This is done in interp_posix.py
+ */
+void LL_os_putenv(RPyString * name_eq_value) {
+    int error = putenv(RPyString_AsString(name_eq_value));
+    if (error != 0) {
+	RPYTHON_RAISE_OSERROR(errno);
+    }
+}
+#endif
+
+/* Return a dictionary corresponding to the POSIX environment table */
+/*** actually, we create a sring list here and do the rest in posix */
+#ifdef WITH_NEXT_FRAMEWORK
+/* On Darwin/MacOSX a shared library or framework has no access to
+** environ directly, we must obtain it with _NSGetEnviron().
+*/
+#include <crt_externs.h>
+static char **environ;
+#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
+extern char **environ;
+#endif /* !_MSC_VER */
+
+RPyString* LL_os_environ(int idx) {
+    RPyString *rs = NULL;
+    char *s;
+#ifdef WITH_NEXT_FRAMEWORK
+    if (environ == NULL)
+	environ = *_NSGetEnviron();
+#endif
+    if (environ != NULL && (s = environ[idx]) != NULL) {
+	rs = RPyString_FromString(s);
+    }
+    return rs;
+}
\ No newline at end of file

Modified: pypy/release/0.7.x/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/release/0.7.x/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/release/0.7.x/pypy/translator/c/test/test_extfunc.py	Fri Aug 26 21:23:15 2005
@@ -4,6 +4,7 @@
 from pypy.tool.udir import udir
 from pypy.translator.c.test.test_genc import compile
 from pypy.translator.c.extfunc import EXTERNALS
+from pypy.rpython import ros
 
 def test_all_suggested_primitives():
     for modulename in ['ll_math', 'll_os', 'll_os_path', 'll_time']:
@@ -423,3 +424,28 @@
     f1(dirname, True)
     assert not os.path.exists(dirname)
 
+def test_putenv():
+    def put(s):
+        ros.putenv(s)
+    func = compile(put, [str])
+    filename = str(udir.join('test_putenv.txt'))
+    func('abcdefgh=12345678')
+    cmd = '''python -c "import os; print os.environ['abcdefgh']" > %s''' % filename
+    os.system(cmd)
+    assert file(filename).read().strip() == '12345678'
+    os.unlink(filename)
+
+def test_environ():
+    def env(idx):
+        # need to as if the result is NULL, or we crash
+        ret = ros.environ(idx)
+        if ret is None:
+            return False
+        return ret
+    func = compile(env, [int])
+    count = 0
+    while 1:
+        if not func(count):
+            break
+        count += 1
+    assert count == len(os.environ.keys())



More information about the Pypy-commit mailing list