[pypy-svn] r27379 - pypy/dist/pypy/module/select

ac at codespeak.net ac at codespeak.net
Thu May 18 00:20:42 CEST 2006


Author: ac
Date: Thu May 18 00:20:42 2006
New Revision: 27379

Added:
   pypy/dist/pypy/module/select/   (props changed)
   pypy/dist/pypy/module/select/__init__.py   (contents, props changed)
   pypy/dist/pypy/module/select/app_select.py   (contents, props changed)
   pypy/dist/pypy/module/select/conftest.py   (contents, props changed)
   pypy/dist/pypy/module/select/ctypes_select.py   (contents, props changed)
   pypy/dist/pypy/module/select/interp_select.py   (contents, props changed)
Log:
First cut at select module, but cheating.
select is implemented by using poll.



Added: pypy/dist/pypy/module/select/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/__init__.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,21 @@
+# Package initialisation
+from pypy.interpreter.mixedmodule import MixedModule
+import sys
+
+class Module(MixedModule):
+    appleveldefs = {
+        'error': 'app_select.error',
+        'select': 'app_select.select',
+    }
+
+    interpleveldefs = {
+        'poll'  :  'interp_select.poll',
+    }
+
+    def buildloaders(cls):
+        from pypy.module.select import ctypes_select as _c 
+        for constant, value in _c.constants.iteritems():
+            Module.interpleveldefs[constant] = "space.wrap(%r)" % value
+        super(Module, cls).buildloaders()
+    buildloaders = classmethod(buildloaders)
+

Added: pypy/dist/pypy/module/select/app_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/app_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,48 @@
+class error(Exception):
+    pass
+
+def as_fd(f):
+    if not isinstance(f, (int, long)):
+        try:
+            fileno = f.fileno
+        except AttributeError:
+            raise TypeError("argument must be an int, or have a fileno() method.")
+        f = f.fileno()
+        if not isinstance(f, (int, long)):
+            raise TypeError("fileno() returned a non-integer")
+    fd = int(f)
+    if fd < 0 or isinstance(fd, long):
+        raise ValueError("file descriptor cannot be a negative integer (%i)"%fd)
+    return fd
+
+def select(iwtd, owtd, ewtd, timeout=None):
+    from select import poll, POLLIN, POLLOUT, POLLPRI
+    fddict = {}
+    polldict = {}
+    fd = 0
+    for f in iwtd + owtd + ewtd:
+        fddict[id(f)] = as_fd(f)
+    for f in iwtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLIN
+    for f in owtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLOUT
+    for f in ewtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLPRI
+
+    p = poll()
+    for fd, mask in polldict.iteritems():
+        p.register(fd, mask)
+    if timeout is not None:
+        ret = dict(p.poll(int(timeout * 1000)))
+    else:
+        ret = dict(p.poll())
+
+    iretd = [ f for f in iwtd if ret.get(fddict[id(f)], 0) & POLLIN]
+    oretd = [ f for f in owtd if ret.get(fddict[id(f)], 0) & POLLOUT]
+    eretd = [ f for f in ewtd if ret.get(fddict[id(f)], 0) & POLLPRI]
+
+    return iretd, oretd, eretd
+    

Added: pypy/dist/pypy/module/select/conftest.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/conftest.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,10 @@
+import py
+
+class Directory(py.test.collect.Directory):
+
+    def run(self):
+        try:
+            import ctypes
+        except ImportError:
+            py.test.skip("these tests need ctypes installed")
+        return super(Directory, self).run()

Added: pypy/dist/pypy/module/select/ctypes_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/ctypes_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,37 @@
+from pypy.rpython.rctypes.tool import ctypes_platform
+from ctypes import *
+from pypy.rpython.rctypes.tool import util      # ctypes.util from 0.9.9.6
+
+includes = ('sys/poll.h',
+            'sys/select.h',
+            )
+constant_names = '''POLLIN POLLPRI POLLOUT POLLERR POLLHUP POLLNVAL
+    POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG'''.split()
+
+class CConfig:
+    _header_ = ''.join(['#include <%s>\n' % filename for filename in includes])
+    locals().update(map(lambda name: (name, ctypes_platform.DefinedConstantInteger(name)), constant_names))
+    nfds_t = ctypes_platform.SimpleType('nfds_t')
+    pollfd = ctypes_platform.Struct('struct pollfd',
+                                    [('fd', c_int),
+                                     ('events', c_short),
+                                     ('revents', c_short)])
+    
+globals().update(ctypes_platform.configure(CConfig))
+constants = {}
+for name in constant_names:
+    value = globals()[name]
+    if value is not None:
+        constants[name] = value
+        
+dllname = util.find_library('c')
+assert dllname is not None
+libc = cdll.LoadLibrary(dllname)
+
+poll = libc.poll
+poll.argtypes = [POINTER(pollfd), nfds_t, c_int]
+poll.restype = c_int
+
+strerror = libc.strerror
+strerror.argtypes = [c_int]
+strerror.restype = c_char_p

Added: pypy/dist/pypy/module/select/interp_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/interp_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,96 @@
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.gateway import W_Root, ObjSpace, interp2app
+from pypy.module.select import ctypes_select as _c
+from pypy.rpython.rctypes.aerrno import geterrno
+from pypy.interpreter.error import OperationError
+
+defaultevents = _c.POLLIN | _c.POLLOUT | _c.POLLPRI
+
+def poll(space):
+    return Poll()
+
+def as_fd_w(space, w_fd):
+    if not space.is_true(space.isinstance(w_fd, space.w_int)):
+        try:
+            w_fileno = space.getattr(w_fd, space.wrap('fileno'))
+        except OperationError, e:
+            if e.match(space, space.w_AttributeError):
+                raise OperationError(space.w_TypeError,
+                                     space.wrap("argument must be an int, or have a fileno() method."))
+            raise
+        w_fd = space.call_function(w_fileno)
+        if not space.is_true(space.isinstance(w_fd, space.w_int)):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap('filneo() return a non-integer'))
+        
+    fd = space.int_w(w_fd)
+    if fd < 0:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("file descriptor cannot be a negative integer (%d)"%fd))
+    return fd
+
+class Poll(Wrappable):
+    def __init__(self):
+        self.fddict = {}
+
+    def register(self, space, w_fd, events=defaultevents):
+        fd = as_fd_w(space, w_fd)
+        self.fddict[fd] = events
+    register.unwrap_spec = ['self', ObjSpace, W_Root, int]
+
+    def unregister(self, space, w_fd):
+        fd = as_fd_w(space, w_fd)
+        try:
+            del self.fddict[fd]
+        except KeyError:
+            raise OperationError(space.w_KeyError,
+                                 space.wrap(fd))
+    unregister.unwrap_spec = ['self', ObjSpace, W_Root]
+
+    def poll(self, space, w_timeout=None):
+        if space.is_w(w_timeout, space.w_None):
+            timeout = -1
+        else:
+            timeout = space.int_w(w_timeout)
+            
+        numfd = len(self.fddict)
+        buf = _c.create_string_buffer(_c.sizeof(_c.pollfd) * numfd)
+        pollfds = _c.cast(buf, _c.POINTER(_c.pollfd))
+        i = 0
+        for fd, events in self.fddict.iteritems():
+            pollfds[i].fd = fd
+            pollfds[i].events = events
+            i += 1
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
+        ret = _c.poll(pollfds, numfd, timeout)
+        if GIL is not None: GIL.acquire(True)
+
+        if ret < 0:
+            errno = geterrno()
+            w_module = space.getbuiltinmodule('select')
+            w_errortype = space.getattr(w_module, space.wrap('error'))
+            message = _c.strerror(errno)
+            raise OperationError(w_errortype,
+                                 space.newtuple([space.wrap(errno),
+                                                 space.wrap(message)]))
+        
+        retval_w = []
+        for i in range(numfd):
+            pollfd = pollfds[i]
+            if pollfd.revents:
+                retval_w.append(space.newtuple([space.wrap(pollfd.fd),
+                                                space.wrap(pollfd.revents)]))
+        return space.newlist(retval_w)
+    poll.unwrap_spec = ['self', ObjSpace, W_Root]
+
+pollmethods = {}
+for methodname in 'register unregister poll'.split():
+    method = getattr(Poll, methodname)
+    assert hasattr(method,'unwrap_spec'), methodname
+    assert method.im_func.func_code.co_argcount == len(method.unwrap_spec), methodname
+    pollmethods[methodname] = interp2app(method, unwrap_spec=method.unwrap_spec)
+Poll.typedef = TypeDef('select.poll', **pollmethods)



More information about the Pypy-commit mailing list