[pypy-svn] r18791 - in pypy/dist/pypy/rpython: . module module/test

arigo at codespeak.net arigo at codespeak.net
Thu Oct 20 13:18:27 CEST 2005


Author: arigo
Date: Thu Oct 20 13:18:26 2005
New Revision: 18791

Modified:
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/module/ll_os.py
   pypy/dist/pypy/rpython/module/support.py
   pypy/dist/pypy/rpython/module/test/test_ll_os.py
   pypy/dist/pypy/rpython/ros.py
   pypy/dist/pypy/rpython/rspecialcase.py
Log:
* RPythonic helpers to implement os.listdir(): the C-ish functions
  ros.opendir(), readdir(), closedir().
  
* support for external types that are externally-managed pointers
  (used here for the DIR* pointer).  This means that closedir()
  must be called explicitely from RPython!



Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Thu Oct 20 13:18:26 2005
@@ -80,6 +80,11 @@
         exttypeinfo = s_opaqueptr.ll_ptrtype.TO._exttypeinfo
         return annmodel.SomeExternalObject(exttypeinfo.typ)
 
+    def override__to_opaque_object(pol, s_value):
+        assert isinstance(s_value, annmodel.SomeExternalObject)
+        exttypeinfo = extfunctable.typetable[s_value.knowntype]
+        return annmodel.SomePtr(lltype.Ptr(exttypeinfo.get_lltype()))
+
 
 def annotate_lowlevel_helper(annotator, ll_function, args_s):
     saved = annotator.policy, annotator.added_blocks

Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Thu Oct 20 13:18:26 2005
@@ -28,11 +28,12 @@
 
 
 class ExtTypeInfo:
-    def __init__(self, typ, tag, methods):
+    def __init__(self, typ, tag, methods, needs_container=True):
         self.typ = typ
         self.tag = tag
         self._TYPE = None
         self.methods = methods     # {'name': ExtFuncInfo()}
+        self.needs_container = needs_container
 
     def get_annotation(self, methodname):
         return self.methods[methodname].annotation
@@ -51,8 +52,11 @@
             from pypy.rpython import lltype
             OPAQUE = lltype.OpaqueType(self.tag)
             OPAQUE._exttypeinfo = self
-            STRUCT = lltype.GcStruct(self.tag, ('obj', OPAQUE))
-            self._TYPE = STRUCT
+            if self.needs_container:
+                STRUCT = lltype.GcStruct(self.tag, ('obj', OPAQUE))
+                self._TYPE = STRUCT
+            else:
+                self._TYPE = OPAQUE
         return self._TYPE
 
 
@@ -87,7 +91,7 @@
     return info
 
 typetable = {}
-def declaretype(typ, tag, **methodsdecl):
+def declaretype1(typ, tag, methodsdecl, needs_container):
     assert isinstance(typ, type)
     methods = {}
     for name, args in methodsdecl.items():
@@ -99,12 +103,18 @@
         else:
             func = None   # failed (typical for old-style C types), ignore it
         methods[name] = declare(func, *args)
-    info = ExtTypeInfo(typ, tag, methods)
+    info = ExtTypeInfo(typ, tag, methods, needs_container)
     typetable[typ] = info
     for callback in table_callbacks:
         callback()
     return info
 
+def declaretype(typ, tag, **methodsdecl):
+    return declaretype1(typ, tag, methodsdecl, needs_container=True)
+
+def declareptrtype(typ, tag, **methodsdecl):
+    return declaretype1(typ, tag, methodsdecl, needs_container=False)
+
 # _____________________________________________________________
 
 
@@ -204,6 +214,10 @@
 from pypy.rpython import ros
 declare(ros.putenv, noneannotation, 'll_os/putenv')
 declare(ros.environ, strnullannotation, 'll_os/environ')
+declare(ros.opendir, ros.DIR, 'll_os/opendir')
+declareptrtype(ros.DIR, "DIR",
+               readdir = (strnullannotation, 'll_os/readdir'),
+               closedir = (noneannotation,   'll_os/closedir'))
 
 # ___________________________________________________________
 # stackless

Modified: pypy/dist/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_os.py	(original)
+++ pypy/dist/pypy/rpython/module/ll_os.py	Thu Oct 20 13:18:26 2005
@@ -17,6 +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.module.support import to_opaque_object, from_opaque_object
 from pypy.rpython import ros
 
 def ll_os_open(fname, flag, mode):
@@ -147,3 +148,22 @@
 def ll_os_environ(idx):
     return ros.environ(idx)
 ll_os_environ.suggested_primitive = True
+
+# ____________________________________________________________
+# opendir/readdir
+
+def ll_os_opendir(dirname):
+    dir = ros.opendir(from_rstr(dirname))
+    return to_opaque_object(dir)
+ll_os_opendir.suggested_primitive = True
+
+def ll_os_readdir(opaquedir):
+    dir = from_opaque_object(opaquedir)
+    nextentry = dir.readdir()
+    return to_rstr(nextentry)
+ll_os_readdir.suggested_primitive = True
+
+def ll_os_closedir(opaquedir):
+    dir = from_opaque_object(opaquedir)
+    dir.closedir()
+ll_os_closedir.suggested_primitive = True

Modified: pypy/dist/pypy/rpython/module/support.py
==============================================================================
--- pypy/dist/pypy/rpython/module/support.py	(original)
+++ pypy/dist/pypy/rpython/module/support.py	Thu Oct 20 13:18:26 2005
@@ -6,13 +6,18 @@
 
 # utility conversion functions
 def to_rstr(s):
+    if s is None:
+        return lltype.nullptr(STR)
     p = malloc(STR, len(s))
     for i in range(len(s)):
         p.chars[i] = s[i]
     return p
 
 def from_rstr(rs):
-    return ''.join([rs.chars[i] for i in range(len(rs.chars))])
+    if not rs:   # null pointer
+        return None
+    else:
+        return ''.join([rs.chars[i] for i in range(len(rs.chars))])
 
 def ll_strcpy(dstchars, srcchars, n):
     i = 0
@@ -29,3 +34,10 @@
     "NOT_RPYTHON"
     return opaqueptr._obj.externalobj
 from_opaque_object._annspecialcase_ = "override:from_opaque_object"
+
+def to_opaque_object(value):
+    "NOT_RPYTHON"
+    exttypeinfo = extfunctable.typetable[value.__class__]
+    return lltype.opaqueptr(exttypeinfo.get_lltype(), 'opaque',
+                            externalobj=value)
+to_opaque_object._annspecialcase_ = "override:to_opaque_object"

Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py
==============================================================================
--- pypy/dist/pypy/rpython/module/test/test_ll_os.py	(original)
+++ pypy/dist/pypy/rpython/module/test/test_ll_os.py	Thu Oct 20 13:18:26 2005
@@ -80,3 +80,24 @@
     assert res
     chan.close()
 
+def test_opendir_readdir():
+    dirname = str(udir)
+    rsdirname = to_rstr(dirname)
+    result = []
+    DIR = ll_os_opendir(rsdirname)
+    try:
+        while True:
+            nextentry = ll_os_readdir(DIR)
+            if not nextentry:   # null pointer check
+                break
+            result.append(from_rstr(nextentry))
+    finally:
+        ll_os_closedir(DIR)
+    assert '.' in result
+    assert '..' in result
+    result.remove('.')
+    result.remove('..')
+    result.sort()
+    compared_with = os.listdir(dirname)
+    compared_with.sort()
+    assert result == compared_with

Modified: pypy/dist/pypy/rpython/ros.py
==============================================================================
--- pypy/dist/pypy/rpython/ros.py	(original)
+++ pypy/dist/pypy/rpython/ros.py	Thu Oct 20 13:18:26 2005
@@ -15,3 +15,23 @@
     # we simulate the environ list
     if idx < len(_initial_items):
         return '%s=%s' % _initial_items[idx]
+
+
+class DIR(object):
+    # a simulated DIR structure from C, i.e. a directory opened by
+    # opendir() from which we can enumerate the entries with readdir().
+    # Like readdir(), this version does not hide the '.' and '..' entries.
+    def __init__(self, dirname):
+        self._entries = iter(['.', '..'] + os.listdir(dirname))
+
+    def readdir(self):
+        try:
+            return self._entries.next()
+        except StopIteration:
+            return None
+
+    def closedir(self):
+        pass
+
+def opendir(dirname):
+    return DIR(dirname)

Modified: pypy/dist/pypy/rpython/rspecialcase.py
==============================================================================
--- pypy/dist/pypy/rpython/rspecialcase.py	(original)
+++ pypy/dist/pypy/rpython/rspecialcase.py	Thu Oct 20 13:18:26 2005
@@ -40,3 +40,7 @@
 def rtype_override_from_opaque_object(hop, clsdef):
     return hop.genop('from_opaque_object_should_never_be_seen_by_the_backend',
                      [], resulttype=hop.r_result)
+
+def rtype_override_to_opaque_object(hop, clsdef):
+    return hop.genop('to_opaque_object_should_never_be_seen_by_the_backend',
+                     [], resulttype=hop.r_result)



More information about the Pypy-commit mailing list