[pypy-svn] r45677 - in pypy/branch/pypy-more-rtti-inprogress: rpython rpython/module translator/c/test

arigo at codespeak.net arigo at codespeak.net
Wed Aug 15 14:29:34 CEST 2007


Author: arigo
Date: Wed Aug 15 14:29:32 2007
New Revision: 45677

Modified:
   pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py
   pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py
Log:
Support for  del os.environ[name]


Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/controllerentry.py	Wed Aug 15 14:29:32 2007
@@ -117,6 +117,13 @@
         from pypy.rpython.rcontrollerentry import rtypedelegate
         return rtypedelegate(self.setitem, hop)
 
+    def ctrl_delitem(self, s_obj, s_key):
+        return delegate(self.delitem, s_obj, s_key)
+
+    def rtype_delitem(self, hop):
+        from pypy.rpython.rcontrollerentry import rtypedelegate
+        return rtypedelegate(self.delitem, hop)
+
     def ctrl_is_true(self, s_obj):
         return delegate(self.is_true, s_obj)
 
@@ -237,6 +244,9 @@
     def setitem((s_cin, s_key), s_value):
         s_cin.controller.ctrl_setitem(s_cin.s_real_obj, s_key, s_value)
 
+    def delitem((s_cin, s_key)):
+        s_cin.controller.ctrl_delitem(s_cin.s_real_obj, s_key)
+
 
 class __extend__(pairtype(SomeControlledInstance, SomeControlledInstance)):
 

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/module/ll_os_environ.py	Wed Aug 15 14:29:32 2007
@@ -22,6 +22,10 @@
         # in the RPython program, 'os.environ[key] = value' is redirected here
         r_putenv(key, value)
 
+    def delitem(self, obj, key):
+        # in the RPython program, 'del os.environ[key]' is redirected here
+        r_unsetenv(key)
+
     def get_keys(self, obj):
         # 'os.environ.keys' is redirected here - note that it's the getattr
         # that arrives here, not the actual method call!
@@ -70,6 +74,7 @@
     l_string = rffi.str2charp('%s=%s' % (name, value))
     error = os_putenv(l_string)
     if error:
+        rffi.free_charp(l_string)
         raise OSError(rffi.get_errno(), "os_putenv failed")
     # keep 'l_string' alive - we know that the C library needs it
     # until the next call to putenv() with the same 'name'.
@@ -83,6 +88,34 @@
                    llimpl=putenv_lltypeimpl)
 
 # ____________________________________________________________
+
+def r_unsetenv(name):
+    # default implementation for platforms without a real unsetenv()
+    r_putenv(name, '')
+
+if hasattr(__import__(os.name), 'unsetenv'):
+
+    os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT)
+
+    def unsetenv_lltypeimpl(name):
+        l_name = rffi.str2charp(name)
+        error = os_unsetenv(l_name)
+        rffi.free_charp(l_name)
+        if error:
+            raise OSError(rffi.get_errno(), "os_unsetenv failed")
+        try:
+            l_oldstring = envkeepalive.byname[name]
+        except KeyError:
+            pass
+        else:
+            del envkeepalive.byname[name]
+            rffi.free_charp(l_oldstring)
+
+    _register_external(r_unsetenv, [str], annmodel.s_None,
+                       export_name='ll_os.ll_os_unsetenv',
+                       llimpl=unsetenv_lltypeimpl)
+
+# ____________________________________________________________
 # Access to the 'environ' external variable
 
 if os.name.startswith('darwin'):

Modified: pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rpython/rcontrollerentry.py	Wed Aug 15 14:29:32 2007
@@ -40,6 +40,9 @@
     def rtype_setitem((r_controlled, r_key), hop):
         return r_controlled.controller.rtype_setitem(hop)
 
+    def rtype_delitem((r_controlled, r_key), hop):
+        return r_controlled.controller.rtype_delitem(hop)
+
 
 def rtypedelegate(callable, hop, revealargs=[0], revealresult=False):
     bk = hop.rtyper.annotator.bookkeeper

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/test/test_extfunc.py	Wed Aug 15 14:29:32 2007
@@ -701,9 +701,44 @@
         os.environ[s] = t5
     func = compile(fn, [str, str, str, str, str, str])
     func('PYPY_TEST_DICTLIKE_ENVIRON', 'a', 'b', 'c', 'FOOBAR', '42',
-         expected_extra_mallocs = (1, 2, 3, 4))   # at least one, less than 5
+         expected_extra_mallocs = (2, 3, 4))   # at least two, less than 5
     assert _real_getenv('PYPY_TEST_DICTLIKE_ENVIRON') == '42'
 
+def test_dictlike_environ_delitem():
+    def fn(s1, s2, s3, s4, s5):
+        for n in range(10):
+            os.environ[s1] = 't1'
+            os.environ[s2] = 't2'
+            os.environ[s3] = 't3'
+            os.environ[s4] = 't4'
+            os.environ[s5] = 't5'
+            del os.environ[s3]
+            del os.environ[s1]
+            del os.environ[s2]
+            del os.environ[s4]
+            # os.environ[s5] stays
+    func = compile(fn, [str, str, str, str, str])
+    if hasattr(__import__(os.name), 'unsetenv'):
+        expected_extra_mallocs = range(2, 10)
+        # at least 2, less than 10: memory for s1, s2, s3, s4 should be freed
+        # (each kept-alive entry counts as two: the RPython string used as
+        # key in 'envkeepalive.byname' and the raw-allocated char* as value)
+    else:
+        expected_extra_mallocs = range(10, 18)
+        # at least 10, less than 18: memory for the initial s1, s2, s3, s4
+        # should be freed, but replaced by new buffers for empty strings
+    func('PYPY_TEST_DICTLIKE_ENVDEL1',
+         'PYPY_TEST_DICTLIKE_ENVDEL_X',
+         'PYPY_TEST_DICTLIKE_ENVDELFOO',
+         'PYPY_TEST_DICTLIKE_ENVDELBAR',
+         'PYPY_TEST_DICTLIKE_ENVDEL5',
+         expected_extra_mallocs = expected_extra_mallocs)
+    assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL1')
+    assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL_X')
+    assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDELFOO')
+    assert not _real_getenv('PYPY_TEST_DICTLIKE_ENVDELBAR')
+    assert _real_getenv('PYPY_TEST_DICTLIKE_ENVDEL5') == 't5'
+
 def test_dictlike_environ_keys():
     def fn():
         return '\x00'.join(os.environ.keys())



More information about the Pypy-commit mailing list