[pypy-svn] r45428 - in pypy/dist/pypy/rpython: . module module/test test
fijal at codespeak.net
fijal at codespeak.net
Sun Jul 29 16:34:45 CEST 2007
Author: fijal
Date: Sun Jul 29 16:34:42 2007
New Revision: 45428
Added:
pypy/dist/pypy/rpython/test/test_extfuncregister.py (contents, props changed)
Modified:
pypy/dist/pypy/rpython/extfunc.py
pypy/dist/pypy/rpython/extfuncregistry.py
pypy/dist/pypy/rpython/module/ll_os.py
pypy/dist/pypy/rpython/module/ll_termios.py
pypy/dist/pypy/rpython/module/test/test_ll_os.py
pypy/dist/pypy/rpython/module/test/test_posix.py
pypy/dist/pypy/rpython/test/test_extfunc.py
Log:
(intermediate checkin) New, better way of lazily evaluating registering
externals. Not sure if this is an ultimate solution, but seems at least
like a better one.
Will break js code, will fix it later.
Modified: pypy/dist/pypy/rpython/extfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunc.py (original)
+++ pypy/dist/pypy/rpython/extfunc.py Sun Jul 29 16:34:42 2007
@@ -6,19 +6,56 @@
import py, sys
-def lazy_register(func, register_func):
+def lazy_register(func_or_list, register_func):
""" Lazily register external function. Will create a function,
which explodes when llinterpd/translated, but does not explode
earlier
"""
+ if isinstance(func_or_list, list):
+ funcs = func_or_list
+ else:
+ funcs = [func_or_list]
try:
- register_func()
+ return register_func()
except:
exc, exc_inst, tb = sys.exc_info()
- class ExtRaisingEntry(ExtRegistryEntry):
- _about_ = func
- def compute_result_annotation(self, *args_s):
- raise exc, exc_inst, tb
+ for func in funcs:
+ class ExtRaisingEntry(ExtRegistryEntry):
+ _about_ = func
+ def compute_result_annotation(self, *args_s):
+ raise exc, exc_inst, tb
+
+def registering(func):
+ def decorator(method):
+ method._registering_func = func
+ return method
+ return decorator
+
+class LazyRegisteringMeta(type):
+ def __new__(self, _name, _type, _vars):
+ retval = type.__new__(self, _name, _type, _vars)
+ allfuncs = []
+ for varname in _vars:
+ attr = getattr(retval, varname)
+ f = getattr(attr, '_registering_func', None)
+ if f:
+ allfuncs.append(f)
+ instance = lazy_register(allfuncs, retval)
+ if instance is not None:
+ for varname in _vars:
+ attr = getattr(instance, varname)
+ f = getattr(attr, '_registering_func', None)
+ if f:
+ lazy_register(f, attr)
+ retval.instance = instance
+ # override __init__ to avoid confusion
+ def raising(self):
+ raise TypeError("Cannot call __init__ directly, use cls.instance to access singleton")
+ retval.__init__ = raising
+ return retval
+
+class BaseLazyRegistering(object):
+ __metaclass__ = LazyRegisteringMeta
class genericcallable(object):
""" A way to specify the callable annotation, but deferred until
@@ -75,10 +112,10 @@
hop.exception_is_here()
return hop.genop('direct_call', vlist, r_result)
-def register_external(function, args, result=None, export_name=None,
- llimpl=None, ooimpl=None,
- llfakeimpl=None, oofakeimpl=None,
- annotation_hook=None):
+def _register_external(function, args, result=None, export_name=None,
+ llimpl=None, ooimpl=None,
+ llfakeimpl=None, oofakeimpl=None,
+ annotation_hook=None):
"""
function: the RPython function that will be rendered as an external function (e.g.: math.floor)
args: a list containing the annotation of the arguments
@@ -113,6 +150,8 @@
else:
FunEntry.__name__ = function.func_name
+BaseLazyRegistering.register = staticmethod(_register_external)
+
def is_external(func):
if hasattr(func, 'value'):
func = func.value
Modified: pypy/dist/pypy/rpython/extfuncregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/extfuncregistry.py (original)
+++ pypy/dist/pypy/rpython/extfuncregistry.py Sun Jul 29 16:34:42 2007
@@ -1,7 +1,7 @@
# this registry use the new interface for external functions
# all the above declarations in extfunctable should be moved here at some point.
-from extfunc import register_external
+from extfunc import _register_external
# ___________________________
# math functions
@@ -24,7 +24,7 @@
'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'
]
for name in simple_math_functions:
- register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name)
+ _register_external(getattr(math, name), [float], float, "ll_math.ll_math_%s" % name)
def frexp_hook():
from pypy.rpython.extfunctable import record_call
@@ -52,9 +52,9 @@
func = getattr(math, name)
llfake = getattr(ll_math, 'll_math_%s' % name, None)
oofake = getattr(oo_math, 'll_math_%s' % name, None)
- register_external(func, args, res, 'll_math.ll_math_%s' % name,
- llfakeimpl=llfake, oofakeimpl=oofake,
- annotation_hook = hook)
+ _register_external(func, args, res, 'll_math.ll_math_%s' % name,
+ llfakeimpl=llfake, oofakeimpl=oofake,
+ annotation_hook = hook)
# ___________________________
@@ -81,4 +81,4 @@
for name, args, res in path_functions:
func = getattr(os.path, name)
llimpl = func_with_new_name(func, name)
- register_external(func, args, res, 'll_os_path.ll_%s' % name, llimpl=llimpl)
+ _register_external(func, args, res, 'll_os_path.ll_%s' % name, llimpl=llimpl)
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 Sun Jul 29 16:34:42 2007
@@ -12,328 +12,340 @@
from pypy.rlib.rarithmetic import r_longlong
from pypy.tool.staticmethods import ClassMethods
import stat
-from pypy.rpython.extfunc import ExtFuncEntry, register_external
+from pypy.rpython.extfunc import BaseLazyRegistering, registering
from pypy.annotation.model import SomeString, SomeInteger, s_ImpossibleValue, \
s_None
from pypy.rpython.lltypesystem import rffi
from pypy.rpython.lltypesystem.rffi import platform
from pypy.rpython.lltypesystem import lltype
-# a simple, yet usefull factory
-def register_os_function_returning_int(fun, name, **kwds):
- c_func = rffi.llexternal(name, [], rffi.INT, **kwds)
- def c_func_lltypeimpl():
- res = c_func()
- if res == -1:
- raise OSError(rffi.c_errno, "%s failed" % name)
- return res
- c_func_lltypeimpl.func_name = name + '_llimpl'
+class RegisterOs(BaseLazyRegistering):
+ def __init__(self):
+ self.getuid_incl = ['unistd.h', 'sys/types.h']
+
+ # a simple, yet usefull factory
+ def register_os_function_returning_int(self, fun, name, **kwds):
+ c_func = rffi.llexternal(name, [], rffi.INT, **kwds)
+ def c_func_lltypeimpl():
+ res = c_func()
+ if res == -1:
+ raise OSError(rffi.c_errno, "%s failed" % name)
+ return res
+ c_func_lltypeimpl.func_name = name + '_llimpl'
- register_external(fun, [], int, llimpl=c_func_lltypeimpl,
+ self.register(fun, [], int, llimpl=c_func_lltypeimpl,
export_name='ll_os.ll_os_' + name)
-# ------------------------------- os.execv ------------------------------
-
-if hasattr(os, 'execv'):
-
- os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP],
- rffi.INT)
-
- def execv_lltypeimpl(path, args):
- l_path = rffi.str2charp(path)
- l_args = rffi.liststr2charpp(args)
- os_execv(l_path, l_args)
- rffi.free_charpp(l_args)
- rffi.free_charp(l_path)
- raise OSError(rffi.c_errno, "execv failed")
-
- register_external(os.execv, [str, [str]], s_ImpossibleValue, llimpl=
- execv_lltypeimpl, export_name="ll_os.ll_os_execv")
-
-# ------------------------------- os.dup --------------------------------
-
-os_dup = rffi.llexternal('dup', [rffi.INT], rffi.INT)
+ if hasattr(os, 'execv'):
+ @registering(os.execv)
+ def register_os_execv(self):
+ os_execv = rffi.llexternal('execv', [rffi.CCHARP, rffi.CCHARPP],
+ rffi.INT)
+
+ def execv_lltypeimpl(path, args):
+ l_path = rffi.str2charp(path)
+ l_args = rffi.liststr2charpp(args)
+ os_execv(l_path, l_args)
+ rffi.free_charpp(l_args)
+ rffi.free_charp(l_path)
+ raise OSError(rffi.c_errno, "execv failed")
+
+ self.register(os.execv, [str, [str]], s_ImpossibleValue, llimpl=
+ execv_lltypeimpl, export_name="ll_os.ll_os_execv")
+
+ @registering(os.dup)
+ def register_os_dup(self):
+ os_dup = rffi.llexternal('dup', [rffi.INT], rffi.INT)
+
+ def dup_lltypeimpl(fd):
+ newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
+ if newfd == -1:
+ raise OSError(rffi.c_errno, "dup failed")
+ return newfd
+
+ self.register(os.dup, [int], int, llimpl=dup_lltypeimpl,
+ export_name="ll_os.ll_os_dup", oofakeimpl=os.dup)
+
+ @registering(os.dup2)
+ def register_os_dup2(self):
+ os_dup2 = rffi.llexternal('dup2', [rffi.INT, rffi.INT], rffi.INT)
-def dup_lltypeimpl(fd):
- newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
- if newfd == -1:
- raise OSError(rffi.c_errno, "dup failed")
- return newfd
-register_external(os.dup, [int], int, llimpl=dup_lltypeimpl,
- export_name="ll_os.ll_os_dup", oofakeimpl=os.dup)
-
-# ------------------------------- os.dup2 -------------------------------
+ def dup2_lltypeimpl(fd, newfd):
+ error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
+ rffi.cast(rffi.INT, newfd)))
+ if error == -1:
+ raise OSError(rffi.c_errno, "dup2 failed")
-os_dup2 = rffi.llexternal('dup2', [rffi.INT, rffi.INT], rffi.INT)
+ self.register(os.dup2, [int, int], s_None, llimpl=dup2_lltypeimpl,
+ export_name="ll_os.ll_os_dup2")
-def dup2_lltypeimpl(fd, newfd):
- error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
- rffi.cast(rffi.INT, newfd)))
- if error == -1:
- raise OSError(rffi.c_errno, "dup2 failed")
-register_external(os.dup2, [int, int], s_None, llimpl=dup2_lltypeimpl,
- export_name="ll_os.ll_os_dup2")
-
-# ------------------------------- os.utime ------------------------------
-
-TIME_T = rffi.INT # XXX do the right thing
-UTIMEBUFP = rffi.CStruct('utimbuf', ('actime', TIME_T),
- ('modtime', TIME_T))
-
-# XXX sys/types.h is not portable at all
-ros_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP], rffi.INT,
- includes=['utime.h', 'sys/types.h'])
-
-def utime_null_lltypeimpl(path):
- l_path = rffi.str2charp(path)
- error = rffi.cast(lltype.Signed, ros_utime(l_path,
- lltype.nullptr(UTIMEBUFP.TO)))
- rffi.free_charp(l_path)
- if error == -1:
- raise OSError(rffi.c_errno, "utime_null failed")
-register_external(ros.utime_null, [str], s_None, "ll_os.utime_null",
- llimpl=utime_null_lltypeimpl)
-
-def utime_tuple_lltypeimpl(path, tp):
- # XXX right now they're all ints, might change in future
- # XXX does not use utimes, even when available
- l_path = rffi.str2charp(path)
- l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw')
- actime, modtime = tp
- l_utimebuf.c_actime, l_utimebuf.c_modtime = int(actime), int(modtime)
- error = rffi.cast(lltype.Signed, ros_utime(l_path, l_utimebuf))
- rffi.free_charp(l_path)
- lltype.free(l_utimebuf, flavor='raw')
- if error == -1:
- raise OSError(rffi.c_errno, "utime_tuple failed")
-register_external(ros.utime_tuple, [str, (float, float)], s_None, "ll_os.utime_tuple",
- llimpl=utime_tuple_lltypeimpl)
-
-# ------------------------------- os.setsid -----------------------------
-
-if hasattr(os, 'setsid'):
- os_setsid = rffi.llexternal('setsid', [], rffi.PID_T,
- includes=['unistd.h'])
-
- def setsid_lltypeimpl():
- result = rffi.cast(lltype.Signed, os_setsid())
- if result == -1:
- raise OSError(rffi.c_errno, "os_setsid failed")
- return result
-
- register_external(os.setsid, [], int, export_name="ll_os.ll_os_setsid",
- llimpl=setsid_lltypeimpl)
-
-# ------------------------------- os.uname ------------------------------
-
-if False and hasattr(os, 'uname'): # make it more portable
- lgt = platform.intdefined('_UTSNAME_LENGTH', includes=['sys/utsname.h'])
- UTCHARP = lltype.FixedSizeArray(lltype.Char, lgt)
- fields = [('sysname', UTCHARP),
- ('nodename', UTCHARP),
- ('release', UTCHARP),
- ('version', UTCHARP),
- ('machine', UTCHARP),
- ('domainname', UTCHARP)]
- UTSNAMEP = rffi.CStruct('utsname', *fields)
+ @registering(os.utime)
+ def register_os_utime(self):
+ TIME_T = rffi.INT # XXX do the right thing
+ UTIMEBUFP = rffi.CStruct('utimbuf', ('actime', TIME_T),
+ ('modtime', TIME_T))
+
+ # XXX sys/types.h is not portable at all
+ ros_utime = rffi.llexternal('utime', [rffi.CCHARP, UTIMEBUFP],
+ rffi.INT,
+ includes=['utime.h', 'sys/types.h'])
+
+ def utime_null_lltypeimpl(path):
+ l_path = rffi.str2charp(path)
+ error = rffi.cast(lltype.Signed, ros_utime(l_path,
+ lltype.nullptr(UTIMEBUFP.TO)))
+ rffi.free_charp(l_path)
+ if error == -1:
+ raise OSError(rffi.c_errno, "utime_null failed")
+
+ self.register(ros.utime_null, [str], s_None, "ll_os.utime_null",
+ llimpl=utime_null_lltypeimpl)
+
+ def utime_tuple_lltypeimpl(path, tp):
+ # XXX right now they're all ints, might change in future
+ # XXX does not use utimes, even when available
+ l_path = rffi.str2charp(path)
+ l_utimebuf = lltype.malloc(UTIMEBUFP.TO, flavor='raw')
+ actime, modtime = tp
+ l_utimebuf.c_actime, l_utimebuf.c_modtime = int(actime), int(modtime)
+ error = rffi.cast(lltype.Signed, ros_utime(l_path, l_utimebuf))
+ rffi.free_charp(l_path)
+ lltype.free(l_utimebuf, flavor='raw')
+ if error == -1:
+ raise OSError(rffi.c_errno, "utime_tuple failed")
+
+ self.register(ros.utime_tuple, [str, (float, float)], s_None,
+ "ll_os.utime_tuple",
+ llimpl=utime_tuple_lltypeimpl)
+
+ if hasattr(os, 'setsid'):
+ @registering(os.setsid)
+ def register_os_setsid(self):
+ os_setsid = rffi.llexternal('setsid', [], rffi.PID_T,
+ includes=['unistd.h'])
+
+ def setsid_lltypeimpl():
+ result = rffi.cast(lltype.Signed, os_setsid())
+ if result == -1:
+ raise OSError(rffi.c_errno, "os_setsid failed")
+ return result
+
+ self.register(os.setsid, [], int, export_name="ll_os.ll_os_setsid",
+ llimpl=setsid_lltypeimpl)
+
+ if False and hasattr(os, 'uname'): # make it more portable
+ @registering(os.uname)
+ def register_os_uname(self):
+ lgt = platform.intdefined('_UTSNAME_LENGTH',
+ includes=['sys/utsname.h'])
+ UTCHARP = lltype.FixedSizeArray(lltype.Char, lgt)
+ fields = [('sysname', UTCHARP),
+ ('nodename', UTCHARP),
+ ('release', UTCHARP),
+ ('version', UTCHARP),
+ ('machine', UTCHARP),
+ ('domainname', UTCHARP)]
+ UTSNAMEP = rffi.CStruct('utsname', *fields)
- os_uname = rffi.llexternal('uname', [UTSNAMEP], rffi.INT,
- includes=['sys/utsname.h'])
+ os_uname = rffi.llexternal('uname', [UTSNAMEP], rffi.INT,
+ includes=['sys/utsname.h'])
- def utcharp2str(cp):
- l = []
- i = 0
- while cp[i] != '\x00' and i < lgt:
- l.append(cp[i])
- i += 1
- return "".join(l)
-
- def uname_lltypeimpl():
- l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw')
- result = os_uname(l_utsbuf)
- if result == -1:
- raise OSError(rffi.c_errno, "os_uname failed")
- fields = [l_utsbuf.c_sysname, l_utsbuf.c_nodename,
- l_utsbuf.c_release, l_utsbuf.c_version, l_utsbuf.c_machine]
- l = [utcharp2str(i) for i in fields]
- retval = (l[0], l[1], l[2], l[3], l[4])
- lltype.free(l_utsbuf, flavor='raw')
- return retval
-
- register_external(os.uname, [], (str, str, str, str, str),
- "ll_os.ll_uname", llimpl=uname_lltypeimpl)
-
-# ------------------------------- os.getuid/geteuid ---------------------
-
-getuid_incl = ['unistd.h', 'sys/types.h']
-register_os_function_returning_int(os.getuid, 'getuid',
- includes=getuid_incl)
-register_os_function_returning_int(os.geteuid, 'geteuid',
- includes=getuid_incl)
-
-# ------------------------------- os.open -------------------------------
-
-if os.name == 'nt':
- mode_t = rffi.INT
-else:
- mode_t = rffi.MODE_T
-
-os_open = rffi.llexternal('open', [rffi.CCHARP, rffi.INT, mode_t],
- rffi.INT)
-
-def os_open_lltypeimpl(path, flags, mode):
- l_path = rffi.str2charp(path)
- result = rffi.cast(lltype.Signed, os_open(l_path,
- rffi.cast(rffi.INT, flags),
- rffi.cast(mode_t, mode)))
- rffi.free_charp(l_path)
- if result == -1:
- raise OSError(rffi.c_errno, "os_open failed")
- return result
+ def utcharp2str(cp):
+ l = []
+ i = 0
+ while cp[i] != '\x00' and i < lgt:
+ l.append(cp[i])
+ i += 1
+ return "".join(l)
+
+ def uname_lltypeimpl():
+ l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw')
+ result = os_uname(l_utsbuf)
+ if result == -1:
+ raise OSError(rffi.c_errno, "os_uname failed")
+ fields = [l_utsbuf.c_sysname, l_utsbuf.c_nodename,
+ l_utsbuf.c_release, l_utsbuf.c_version,
+ l_utsbuf.c_machine]
+ l = [utcharp2str(i) for i in fields]
+ retval = (l[0], l[1], l[2], l[3], l[4])
+ lltype.free(l_utsbuf, flavor='raw')
+ return retval
+
+ self.register(os.uname, [], (str, str, str, str, str),
+ "ll_os.ll_uname", llimpl=uname_lltypeimpl)
+
+ @registering(os.getuid)
+ def register_os_getuid(self):
+ self.register_os_function_returning_int(os.getuid, 'getuid',
+ includes=self.getuid_incl)
+
+ @registering(os.geteuid)
+ def register_os_geteuid(self):
+ self.register_os_function_returning_int(os.geteuid, 'geteuid',
+ includes=self.getuid_incl)
+
+ @registering(os.open)
+ def register_os_open(self):
+ if os.name == 'nt':
+ mode_t = rffi.INT
+ else:
+ mode_t = rffi.MODE_T
+ os_open = rffi.llexternal('open', [rffi.CCHARP, rffi.INT, mode_t],
+ rffi.INT)
+
+ def os_open_lltypeimpl(path, flags, mode):
+ l_path = rffi.str2charp(path)
+ result = rffi.cast(lltype.Signed, os_open(l_path,
+ rffi.cast(rffi.INT, flags),
+ rffi.cast(mode_t, mode)))
+ rffi.free_charp(l_path)
+ if result == -1:
+ raise OSError(rffi.c_errno, "os_open failed")
+ return result
-def os_open_oofakeimpl(o_path, flags, mode):
- return os.open(o_path._str, flags, mode)
+ def os_open_oofakeimpl(o_path, flags, mode):
+ return os.open(o_path._str, flags, mode)
-register_external(os.open, [str, int, int], int, "ll_os.ll_os_open",
- llimpl=os_open_lltypeimpl, oofakeimpl=os_open_oofakeimpl)
+ self.register(os.open, [str, int, int], int, "ll_os.ll_os_open",
+ llimpl=os_open_lltypeimpl, oofakeimpl=os_open_oofakeimpl)
# ------------------------------- os.read -------------------------------
-os_read = rffi.llexternal('read', [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
- rffi.SIZE_T)
-
-def os_read_lltypeimpl(fd, count):
- if count < 0:
- raise OSError(errno.EINVAL, None)
- inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw')
- try:
- got = rffi.cast(lltype.Signed, os_read(rffi.cast(rffi.INT, fd),
- inbuf,
- rffi.cast(rffi.SIZE_T, count)))
- if got < 0:
- raise OSError(rffi.c_errno, "os_read failed")
- # XXX too many copies of the data!
- l = [inbuf[i] for i in range(got)]
- finally:
- lltype.free(inbuf, flavor='raw')
- return ''.join(l)
-
-def os_read_oofakeimpl(fd, count):
- return OOSupport.to_rstr(os.read(fd, count))
-
-register_external(os.read, [int, int], str, "ll_os.ll_os_read",
- llimpl=os_read_lltypeimpl, oofakeimpl=os_read_oofakeimpl)
-
-# '--sandbox' support
-def os_read_marshal_input(msg, fd, buf, size):
- msg.packnum(rffi.cast(lltype.Signed, fd))
- msg.packsize_t(size)
-def os_read_unmarshal_output(msg, fd, buf, size):
- data = msg.nextstring()
- if len(data) > rffi.cast(lltype.Signed, size):
- raise OverflowError
- for i in range(len(data)):
- buf[i] = data[i]
- return rffi.cast(rffi.SIZE_T, len(data))
-os_read._obj._marshal_input = os_read_marshal_input
-os_read._obj._unmarshal_output = os_read_unmarshal_output
-
-# ------------------------------- os.write ------------------------------
-
-os_write = rffi.llexternal('write', [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
- rffi.SIZE_T)
-
-def os_write_lltypeimpl(fd, data):
- count = len(data)
- outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw')
- try:
- for i in range(count):
- outbuf[i] = data[i]
- written = rffi.cast(lltype.Signed, os_write(rffi.cast(rffi.INT, fd),
- outbuf,
- rffi.cast(rffi.SIZE_T, count)))
- if written < 0:
- raise OSError(rffi.c_errno, "os_write failed")
- finally:
- lltype.free(outbuf, flavor='raw')
- return written
-
-def os_write_oofakeimpl(fd, data):
- return os.write(fd, OOSupport.from_rstr(data))
-
-register_external(os.write, [int, str], SomeInteger(nonneg=True)
- , "ll_os.ll_os_write",
- llimpl=os_write_lltypeimpl, oofakeimpl=os_write_oofakeimpl)
-
-# '--sandbox' support
-def os_write_marshal_input(msg, fd, buf, size):
- msg.packnum(rffi.cast(lltype.Signed, fd))
- msg.packbuf(buf, 0, rffi.cast(lltype.Signed, size))
-os_write._obj._marshal_input = os_write_marshal_input
-
-# ------------------------------- os.close ------------------------------
-
-os_close = rffi.llexternal('close', [rffi.INT], rffi.INT)
-
-def close_lltypeimpl(fd):
- error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
- if error == -1:
- raise OSError(rffi.c_errno, "close failed")
-
-register_external(os.close, [int], s_None, llimpl=close_lltypeimpl,
- export_name="ll_os.ll_os_close", oofakeimpl=os.close)
-
-# ------------------------------- os.* ----------------------------------
-
-w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
- 'WIFSIGNALED', 'WIFEXITED', 'WEXITSTATUS',
- 'WSTOPSIG', 'WTERMSIG']
-# last 3 are returning int
-w_star_returning_int = dict.fromkeys(w_star[-3:])
-
-def declare_new_w_star(name):
- """ stupid workaround for the python late-binding
- 'feature'
- """
- def fake(status):
- return int(getattr(os, name)(status))
- fake.func_name = 'fake_' + name
-
-
- os_c_func = rffi.llexternal(name, [lltype.Signed],
- lltype.Signed, _callable=fake,
- includes=["sys/wait.h", "sys/types.h"])
+ @registering(os.read)
+ def register_os_read(self):
+ os_read = rffi.llexternal('read', [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
+ rffi.SIZE_T)
+
+ def os_read_lltypeimpl(fd, count):
+ if count < 0:
+ raise OSError(errno.EINVAL, None)
+ inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw')
+ try:
+ got = rffi.cast(lltype.Signed, os_read(rffi.cast(rffi.INT, fd),
+ inbuf, rffi.cast(rffi.SIZE_T, count)))
+ if got < 0:
+ raise OSError(rffi.c_errno, "os_read failed")
+ # XXX too many copies of the data!
+ l = [inbuf[i] for i in range(got)]
+ finally:
+ lltype.free(inbuf, flavor='raw')
+ return ''.join(l)
+
+ def os_read_oofakeimpl(fd, count):
+ return OOSupport.to_rstr(os.read(fd, count))
+
+ self.register(os.read, [int, int], str, "ll_os.ll_os_read",
+ llimpl=os_read_lltypeimpl, oofakeimpl=os_read_oofakeimpl)
+
+ # '--sandbox' support
+ def os_read_marshal_input(msg, fd, buf, size):
+ msg.packnum(rffi.cast(lltype.Signed, fd))
+ msg.packsize_t(size)
+ def os_read_unmarshal_output(msg, fd, buf, size):
+ data = msg.nextstring()
+ if len(data) > rffi.cast(lltype.Signed, size):
+ raise OverflowError
+ for i in range(len(data)):
+ buf[i] = data[i]
+ return rffi.cast(rffi.SIZE_T, len(data))
+ os_read._obj._marshal_input = os_read_marshal_input
+ os_read._obj._unmarshal_output = os_read_unmarshal_output
+
+ @registering(os.write)
+ def register_os_write(self):
+ os_write = rffi.llexternal('write', [rffi.INT, rffi.VOIDP,
+ rffi.SIZE_T], rffi.SIZE_T)
+
+ def os_write_lltypeimpl(fd, data):
+ count = len(data)
+ outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw')
+ try:
+ for i in range(count):
+ outbuf[i] = data[i]
+ written = rffi.cast(lltype.Signed, os_write(
+ rffi.cast(rffi.INT, fd),
+ outbuf, rffi.cast(rffi.SIZE_T, count)))
+ if written < 0:
+ raise OSError(rffi.c_errno, "os_write failed")
+ finally:
+ lltype.free(outbuf, flavor='raw')
+ return written
+
+ def os_write_oofakeimpl(fd, data):
+ return os.write(fd, OOSupport.from_rstr(data))
+
+ self.register(os.write, [int, str], SomeInteger(nonneg=True),
+ "ll_os.ll_os_write", llimpl=os_write_lltypeimpl,
+ oofakeimpl=os_write_oofakeimpl)
+
+ # '--sandbox' support
+ def os_write_marshal_input(msg, fd, buf, size):
+ msg.packnum(rffi.cast(lltype.Signed, fd))
+ msg.packbuf(buf, 0, rffi.cast(lltype.Signed, size))
+ os_write._obj._marshal_input = os_write_marshal_input
+
+ @registering(os.close)
+ def register_os_close(self):
+ os_close = rffi.llexternal('close', [rffi.INT], rffi.INT)
+
+ def close_lltypeimpl(fd):
+ error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
+ if error == -1:
+ raise OSError(rffi.c_errno, "close failed")
+
+ self.register(os.close, [int], s_None, llimpl=close_lltypeimpl,
+ export_name="ll_os.ll_os_close", oofakeimpl=os.close)
+
+ # ------------------------------- os.W* ---------------------------------
+
+ w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
+ 'WIFSIGNALED', 'WIFEXITED', 'WEXITSTATUS',
+ 'WSTOPSIG', 'WTERMSIG']
+ # last 3 are returning int
+ w_star_returning_int = dict.fromkeys(w_star[-3:])
+
+ def declare_new_w_star(self, name):
+ """ stupid workaround for the python late-binding
+ 'feature'
+ """
+ def fake(status):
+ return int(getattr(os, name)(status))
+ fake.func_name = 'fake_' + name
+
+ os_c_func = rffi.llexternal(name, [lltype.Signed],
+ lltype.Signed, _callable=fake,
+ includes=["sys/wait.h", "sys/types.h"])
- if name in w_star_returning_int:
- def lltypeimpl(status):
- return os_c_func(status)
- resulttype = int
- else:
- def lltypeimpl(status):
- return bool(os_c_func(status))
- resulttype = bool
- lltypeimpl.func_name = name + '_lltypeimpl'
- register_external(getattr(os, name), [int], resulttype, "ll_os."+name,
+ if name in self.w_star_returning_int:
+ def lltypeimpl(status):
+ return os_c_func(status)
+ resulttype = int
+ else:
+ def lltypeimpl(status):
+ return bool(os_c_func(status))
+ resulttype = bool
+ lltypeimpl.func_name = name + '_lltypeimpl'
+ self.register(getattr(os, name), [int], resulttype, "ll_os."+name,
llimpl=lltypeimpl)
+ for name in w_star:
+ if hasattr(os, name):
+ locals()['register_w_' + name] = registering(getattr(os, name))(
+ lambda self, xname=name : self.declare_new_w_star(xname))
+
+ if hasattr(os, 'ttyname'):
+ @registering(os.ttyname)
+ def register_os_ttyname(self):
+ os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP)
+
+ def ttyname_lltypeimpl(fd):
+ l_name = os_ttyname(fd)
+ if not l_name:
+ raise OSError(rffi.c_errno, "ttyname raised")
+ return rffi.charp2str(l_name)
-for name in w_star:
- if hasattr(os, name):
- declare_new_w_star(name)
-
-# ------------------------------- os.ttyname ----------------------------
-
-if hasattr(os, 'ttyname'):
- os_ttyname = rffi.llexternal('ttyname', [lltype.Signed], rffi.CCHARP)
-
- def ttyname_lltypeimpl(fd):
- l_name = os_ttyname(fd)
- if not l_name:
- raise OSError(rffi.c_errno, "ttyname raised")
- return rffi.charp2str(l_name)
-
- register_external(os.ttyname, [int], str, "ll_os.ttyname",
- llimpl=ttyname_lltypeimpl)
+ self.register(os.ttyname, [int], str, "ll_os.ttyname",
+ llimpl=ttyname_lltypeimpl)
class BaseOS:
__metaclass__ = ClassMethods
Modified: pypy/dist/pypy/rpython/module/ll_termios.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_termios.py (original)
+++ pypy/dist/pypy/rpython/module/ll_termios.py Sun Jul 29 16:34:42 2007
@@ -8,18 +8,19 @@
import termios
from pypy.rpython.lltypesystem import rffi
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.extfunc import register_external
+from pypy.rpython.extfunc import lazy_register, _register_external
from pypy.rlib.rarithmetic import intmask
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.annotation import model as annmodel
from pypy.rpython import rclass
from pypy.rlib import rtermios
+from pypy.rpython.lltypesystem.rffi import platform
+
+includes = ['termios.h', 'unistd.h']
-# XXX is this portable? well.. not at all, ideally
-# I would like to have NCCS = CLaterConstant(NCCS)
TCFLAG_T = rffi.UINT
CC_T = rffi.UCHAR
-NCCS = 32
+NCCS = platform.intdefined('NCCS', includes=includes)
SPEED_T = rffi.UINT
INT = rffi.INT
@@ -28,8 +29,6 @@
termios.error.__init__ = termios_error_init
-includes = ['termios.h', 'unistd.h']
-
TERMIOSP = rffi.CStruct('termios', ('c_iflag', TCFLAG_T), ('c_oflag', TCFLAG_T),
('c_cflag', TCFLAG_T), ('c_lflag', TCFLAG_T),
('c_cc', lltype.FixedSizeArray(CC_T, NCCS)))
@@ -37,7 +36,6 @@
def c_external(name, args, result):
return rffi.llexternal(name, args, result, includes=includes)
-c_tcgetattr = c_external('tcgetattr', [INT, TERMIOSP], INT)
c_tcsetattr = c_external('tcsetattr', [INT, INT, TERMIOSP], INT)
c_cfgetispeed = c_external('cfgetispeed', [TERMIOSP], SPEED_T)
c_cfgetospeed = c_external('cfgetospeed', [TERMIOSP], SPEED_T)
@@ -52,6 +50,8 @@
# def __init__(self, num, msg):
# self.args = (num, msg)
+c_tcgetattr = c_external('tcgetattr', [INT, TERMIOSP], INT)
+
def tcgetattr_llimpl(fd):
c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
error = c_tcgetattr(fd, c_struct)
@@ -68,8 +68,8 @@
finally:
lltype.free(c_struct, flavor='raw')
-register_external(rtermios.tcgetattr, [int], (int, int, int, int, int, int, [str]),
- llimpl=tcgetattr_llimpl, export_name='termios.tcgetattr')
+_register_external(rtermios.tcgetattr, [int], (int, int, int, int, int, int, [str]),
+ llimpl=tcgetattr_llimpl, export_name='termios.tcgetattr')
def tcsetattr_llimpl(fd, when, attributes):
c_struct = lltype.malloc(TERMIOSP.TO, flavor='raw')
@@ -91,7 +91,7 @@
lltype.free(c_struct, flavor='raw')
r_uint = rffi.r_uint
-register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint,
+_register_external(rtermios.tcsetattr, [int, int, (r_uint, r_uint, r_uint,
r_uint, r_uint, r_uint, [str])], llimpl=tcsetattr_llimpl,
export_name='termios.tcsetattr')
@@ -101,7 +101,7 @@
error = c_tcsendbreak(fd, duration)
if error == -1:
raise termios.error(error, 'tcsendbreak failed')
-register_external(termios.tcsendbreak, [int, int],
+_register_external(termios.tcsendbreak, [int, int],
llimpl=tcsendbreak_llimpl,
export_name='termios.tcsendbreak')
@@ -109,19 +109,19 @@
error = c_tcdrain(fd)
if error == -1:
raise termios.error(error, 'tcdrain failed')
-register_external(termios.tcdrain, [int], llimpl=tcdrain_llimpl,
+_register_external(termios.tcdrain, [int], llimpl=tcdrain_llimpl,
export_name='termios.tcdrain')
def tcflush_llimpl(fd, queue_selector):
error = c_tcflush(fd, queue_selector)
if error == -1:
raise termios.error(error, 'tcflush failed')
-register_external(termios.tcflush, [int, int], llimpl=tcflush_llimpl,
+_register_external(termios.tcflush, [int, int], llimpl=tcflush_llimpl,
export_name='termios.tcflush')
def tcflow_llimpl(fd, action):
error = c_tcflow(fd, action)
if error == -1:
raise termios.error(error, 'tcflow failed')
-register_external(termios.tcflow, [int, int], llimpl=tcflow_llimpl,
+_register_external(termios.tcflow, [int, int], llimpl=tcflow_llimpl,
export_name='termios.tcflow')
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 Sun Jul 29 16:34:42 2007
@@ -104,8 +104,8 @@
assert result == compared_with
def test_os_wstar():
- from pypy.rpython.module.ll_os import w_star
- for name in w_star:
+ from pypy.rpython.module.ll_os import RegisterOs
+ for name in RegisterOs.w_star:
def fun(s):
return getattr(os, name)(s)
Modified: pypy/dist/pypy/rpython/module/test/test_posix.py
==============================================================================
--- pypy/dist/pypy/rpython/module/test/test_posix.py (original)
+++ pypy/dist/pypy/rpython/module/test/test_posix.py Sun Jul 29 16:34:42 2007
@@ -108,7 +108,7 @@
del BaseTestPosix.test_ftruncate
class TestLLtype(BaseTestPosix, LLRtypeMixin):
- if hasattr(os, 'uname'):
+ if False and hasattr(os, 'uname'):
def test_os_uname(self):
for num in range(5):
def fun():
Modified: pypy/dist/pypy/rpython/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_extfunc.py (original)
+++ pypy/dist/pypy/rpython/test/test_extfunc.py Sun Jul 29 16:34:42 2007
@@ -1,5 +1,5 @@
-from pypy.rpython.extfunc import ExtFuncEntry, register_external,\
+from pypy.rpython.extfunc import ExtFuncEntry, _register_external,\
is_external, lazy_register
from pypy.annotation import model as annmodel
from pypy.annotation.annrpython import RPythonAnnotator
@@ -79,7 +79,7 @@
def dd():
pass
-register_external(dd, [int], int)
+_register_external(dd, [int], int)
def test_register_external_signature():
def f():
@@ -98,7 +98,7 @@
an argument so that register_external's behavior for tuple-taking functions
can be verified.
"""
-register_external(function_with_tuple_arg, [(int,)], int)
+_register_external(function_with_tuple_arg, [(int,)], int)
def test_register_external_tuple_args():
"""
@@ -118,11 +118,11 @@
def function_with_list():
pass
-register_external(function_with_list, [[int]], int)
+_register_external(function_with_list, [[int]], int)
def function_returning_list():
pass
-register_external(function_returning_list, [], [int])
+_register_external(function_returning_list, [], [int])
def test_register_external_return_goes_back():
"""
@@ -141,7 +141,7 @@
def function_withspecialcase(arg):
return repr(arg)
-register_external(function_withspecialcase, args=None, result=str)
+_register_external(function_withspecialcase, args=None, result=str)
def test_register_external_specialcase():
def f():
@@ -153,19 +153,3 @@
a = RPythonAnnotator(policy=policy)
s = a.build_types(f, [])
assert isinstance(s, annmodel.SomeString)
-
-def test_lazy_register():
- def f():
- return 3
-
- def g():
- return f()
-
- def reg_func():
- 1/0
-
- lazy_register(f, reg_func)
-
- from pypy.rpython.test.test_llinterp import interpret
-
- interpret(g, [])
Added: pypy/dist/pypy/rpython/test/test_extfuncregister.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/test_extfuncregister.py Sun Jul 29 16:34:42 2007
@@ -0,0 +1,73 @@
+
+""" A small test suite for discovering whether lazy registration
+of register_external functions work as intendet
+"""
+
+import py
+from pypy.rpython.extfunc import lazy_register, BaseLazyRegistering, \
+ registering
+from pypy.rpython.test.test_llinterp import interpret
+
+def test_lazy_register():
+ def f():
+ return 3
+
+ def g():
+ return f()
+
+ def reg_func():
+ 1/0
+
+ lazy_register(f, reg_func)
+
+ py.test.raises(ZeroDivisionError, interpret, g, [])
+
+def test_lazy_register_class_raising():
+ def f():
+ return 3
+
+ def g():
+ return 3
+
+ class LazyRegister(BaseLazyRegistering):
+ def __init__(self):
+ self.stuff = 8
+ self.x = []
+
+ @registering(f)
+ def register_f(self):
+ self.x.append(1)
+ 1/0
+
+ @registering(g)
+ def register_g(self):
+ self.x.append(2)
+ self.register(g, [], int, llimpl=lambda : self.stuff)
+
+ py.test.raises(TypeError, "LazyRegister()")
+ assert LazyRegister.instance.x == [1, 2]
+ py.test.raises(ZeroDivisionError, interpret, lambda : f(), [])
+ assert interpret(lambda : g(), []) == 8
+
+def test_lazy_register_raising_init():
+ def f():
+ return 3
+
+ def g():
+ return 3
+
+ class LazyRegister(BaseLazyRegistering):
+ def __init__(self):
+ 1/0
+
+ @registering(f)
+ def register_f(self):
+ pass
+
+ @registering(g)
+ def register_g(self):
+ pass
+
+ py.test.raises(ZeroDivisionError, interpret, lambda : f(), [])
+ py.test.raises(ZeroDivisionError, interpret, lambda : g(), [])
+
More information about the Pypy-commit
mailing list