[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