[pypy-svn] r72743 - in pypy/branch/cpython-extension/pypy: module/cpyext module/cpyext/include module/cpyext/test objspace/std
afa at codespeak.net
afa at codespeak.net
Wed Mar 24 18:55:34 CET 2010
Author: afa
Date: Wed Mar 24 18:55:32 2010
New Revision: 72743
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/api.py
pypy/branch/cpython-extension/pypy/module/cpyext/floatobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/include/pyerrors.h
pypy/branch/cpython-extension/pypy/module/cpyext/object.py
pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/conftest.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_floatobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py
pypy/branch/cpython-extension/pypy/objspace/std/fake.py
Log:
more progress:
- add a way to specify the value returned when RPython raises an exception
- greatly simplify tests for the regular part of the C API: call it directly from interp-level.
- Add support for PyErr_Clear() and PyErr_Occurred()
- fix attribute access of FakedInstance objects, very useful in tests!
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py Wed Mar 24 18:55:32 2010
@@ -43,14 +43,17 @@
setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
globals().update(rffi_platform.configure(CConfig_constants))
+_NOT_SPECIFIED = object()
class ApiFunction:
- def __init__(self, argtypes, restype, callable, borrowed):
+ def __init__(self, argtypes, restype, callable, borrowed, error):
self.argtypes = argtypes
self.restype = restype
self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
self.callable = callable
self.borrowed = borrowed
+ if error is not _NOT_SPECIFIED:
+ self.error_value = error
# extract the signature from the (CPython-level) code object
from pypy.interpreter import pycode
@@ -60,11 +63,12 @@
self.argnames = argnames[1:]
assert len(self.argnames) == len(self.argtypes)
+def cpython_api(argtypes, restype, borrowed=False, error=_NOT_SPECIFIED):
+ if restype is PyObject and error is _NOT_SPECIFIED:
+ error = None
-def cpython_api(argtypes, restype, borrowed=False):
def decorate(func):
- api_function = ApiFunction(argtypes, restype, func, borrowed)
- FUNCTIONS[func.func_name] = api_function
+ api_function = ApiFunction(argtypes, restype, func, borrowed, error)
def unwrapper(space, *args):
"NOT_RPYTHON: XXX unsure"
@@ -82,6 +86,14 @@
newargs.append(arg)
try:
return func(space, *newargs)
+ except OperationError, e:
+ if not hasattr(api_function, "error_value"):
+ raise
+ state = space.fromcache(State)
+ e.normalize_exception(space)
+ state.exc_type = e.w_type
+ state.exc_value = e.get_w_value(space)
+ return api_function.error_value
finally:
from pypy.module.cpyext.macros import Py_DECREF
for arg in to_decref:
@@ -89,6 +101,8 @@
func.api_func = api_function
unwrapper.api_func = api_function
+ FUNCTIONS[func.func_name] = api_function
+ INTERPLEVEL_API[func.func_name] = unwrapper
return unwrapper
return decorate
@@ -105,6 +119,7 @@
TYPES[configname] = forward
return forward
+INTERPLEVEL_API = {}
FUNCTIONS = {}
FUNCTIONS_C = {}
TYPES = {}
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/floatobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/floatobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/floatobject.py Wed Mar 24 18:55:32 2010
@@ -5,6 +5,6 @@
def PyFloat_FromDouble(space, value):
return space.wrap(value)
- at cpython_api([PyObject], lltype.Float)
+ at cpython_api([PyObject], lltype.Float, error=-1)
def PyFloat_AsDouble(space, w_obj):
return space.float_w(space.float(w_obj))
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/include/pyerrors.h
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/include/pyerrors.h (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/pyerrors.h Wed Mar 24 18:55:32 2010
@@ -9,6 +9,8 @@
PyAPI_DATA(PyObject *) PyExc_Exception;
void PyErr_SetString(PyObject *, char *);
+PyObject * PyErr_Occurred(void);
+void PyErr_Clear(PyObject *, char *);
#ifdef __cplusplus
}
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/object.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/object.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/object.py Wed Mar 24 18:55:32 2010
@@ -26,11 +26,11 @@
obj_voidp = rffi.cast(rffi.VOIDP_real, obj)
generic_cpy_call(space, pto.c_tp_free, obj_voidp)
- at cpython_api([PyObject], rffi.INT_real)
+ at cpython_api([PyObject], rffi.INT_real, error=-1)
def PyObject_IsTrue(space, w_obj):
return space.is_true(w_obj)
- at cpython_api([PyObject], rffi.INT_real)
+ at cpython_api([PyObject], rffi.INT_real, error=-1)
def PyObject_Not(space, w_obj):
return not space.is_true(w_obj)
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/pyerrors.py Wed Mar 24 18:55:32 2010
@@ -1,7 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.api import cpython_api, PyObject, make_ref
-
+from pypy.module.cpyext.state import State
@cpython_api([PyObject, rffi.CCHARP], lltype.Void)
def PyErr_SetString(space, w_type, message_ptr):
@@ -9,6 +9,16 @@
w_obj = space.call_function(w_type, space.wrap(message))
raise OperationError(w_type, w_obj)
+ at cpython_api([], PyObject)
+def PyErr_Occurred(space):
+ state = space.fromcache(State)
+ return state.exc_value
+
+ at cpython_api([], lltype.Void)
+def PyErr_Clear(space):
+ state = space.fromcache(State)
+ state.exc_type = None
+ state.exc_value = None
@cpython_api([], lltype.Void)
def PyErr_BadInternalCall(space):
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/conftest.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/conftest.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/conftest.py Wed Mar 24 18:55:32 2010
@@ -6,3 +6,7 @@
if option.runappdirect:
py.test.skip("cannot be run by py.test -A")
return super(Directory, self).collect()
+
+def pytest_funcarg__api(request):
+ return request.cls.api
+
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py Wed Mar 24 18:55:32 2010
@@ -54,6 +54,18 @@
standalone=False)
return str(soname)
+class BaseApiTest:
+ def setup_class(cls):
+ class CAPI:
+ def __getattr__(self, name):
+ return getattr(cls.space, name)
+ cls.api = CAPI()
+ CAPI.__dict__.update(api.INTERPLEVEL_API)
+
+ def teardown_method(self, func):
+ state = self.space.fromcache(State)
+ assert state.exc_value is None
+
class AppTestCpythonExtensionBase:
def setup_class(cls):
cls.space = gettestobjspace(usemodules=['cpyext'])
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_floatobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_floatobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_floatobject.py Wed Mar 24 18:55:32 2010
@@ -1,22 +1,9 @@
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_cpyext import BaseApiTest
-import py
-import sys
+class TestFloatObject(BaseApiTest):
+ def test_floatobject(self, space, api):
+ assert space.unwrap(api.PyFloat_FromDouble(3.14)) == 3.14
+ assert api.PyFloat_AsDouble(space.wrap(23.45)) == 23.45
-class AppTestFloatObject(AppTestCpythonExtensionBase):
- def test_floatobject(self):
- module = self.import_extension('foo', [
- ("FromDouble", "METH_NOARGS",
- """
- return PyFloat_FromDouble(3.14);
- """),
- ("AsDouble", "METH_NOARGS",
- """
- PyObject* obj = PyFloat_FromDouble(23.45);
- double d = PyFloat_AsDouble(obj);
- Py_DECREF(obj);
- return PyFloat_FromDouble(d);
- """),
- ])
- assert module.FromDouble() == 3.14
- assert module.AsDouble() == 23.45
+ assert api.PyFloat_AsDouble(space.w_None) == -1
+ api.PyErr_Clear()
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_object.py Wed Mar 24 18:55:32 2010
@@ -1,66 +1,40 @@
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.test.test_cpyext import BaseApiTest
-import py
-import sys
+class TestObject(BaseApiTest):
+ def test_IsTrue(self, space, api):
+ assert api.PyObject_IsTrue(space.wrap(1.0)) == 1
+ assert api.PyObject_IsTrue(space.wrap(False)) == 0
+ assert api.PyObject_IsTrue(space.wrap(0)) == 0
+
+ def test_Not(self, space, api):
+ assert api.PyObject_Not(space.wrap(False)) == 1
+ assert api.PyObject_Not(space.wrap(0)) == 1
+ assert api.PyObject_Not(space.wrap(True)) == 0
+ assert api.PyObject_Not(space.wrap(3.14)) == 0
+
+ def test_exception(self, space, api):
+ class C:
+ def __nonzero__(self):
+ raise ValueError
+
+ assert api.PyObject_IsTrue(space.wrap(C())) == -1
+ assert api.PyObject_Not(space.wrap(C())) == -1
+ api.PyErr_Clear()
+
+ def test_HasAttr(self, space, api):
+ hasattr_ = lambda w_obj, name: api.PyObject_HasAttr(w_obj,
+ space.wrap(name))
+ assert hasattr_(space.wrap(''), '__len__')
+ assert hasattr_(space.w_int, '__eq__')
+ assert not hasattr_(space.w_int, 'nonexistingattr')
-
-class AppTestObject(AppTestCpythonExtensionBase):
- def test_IsTrue(self):
- module = self.import_extension('foo', [
- ("is_true", "METH_VARARGS",
- """
- PyObject* arg = PyTuple_GetItem(args, 0);
- return PyBool_FromLong(PyObject_IsTrue(arg));
- """),
- ])
- assert module.is_true(True)
- assert module.is_true(1.0)
- assert not module.is_true(False)
- assert not module.is_true(0)
-
- def test_Not(self):
- module = self.import_extension('foo', [
- ("not_", "METH_VARARGS",
- """
- PyObject* arg = PyTuple_GetItem(args, 0);
- return PyBool_FromLong(PyObject_Not(arg));
- """),
- ])
- assert module.not_(False)
- assert module.not_(0)
- assert not module.not_(True)
- assert not module.not_(3.14)
-
- def test_HasAttr(self):
- module = self.import_extension('foo', [
- ("hasattr", "METH_VARARGS",
- """
- PyObject* obj = PyTuple_GetItem(args, 0);
- PyObject* name = PyTuple_GetItem(args, 1);
- return PyBool_FromLong(PyObject_HasAttr(obj, name));
- """),
- ])
- assert module.hasattr('', '__len__')
- assert module.hasattr(int, '__eq__')
- assert not module.hasattr(int, 'nonexistingattr')
-
- def test_SetAttr(self):
- module = self.import_extension('foo', [
- ("setattr", "METH_VARARGS",
- """
- PyObject* obj = PyTuple_GetItem(args, 0);
- PyObject* name = PyTuple_GetItem(args, 1);
- PyObject* value = PyTuple_GetItem(args, 2);
- PyObject_SetAttr(obj, name, value);
- Py_INCREF(Py_None);
- return Py_None;
- """),
- ])
+ def test_SetAttr(self, space, api):
class X:
pass
x = X()
- module.setattr(x, 'test', 5)
- assert hasattr(x, 'test')
+ api.PyObject_SetAttr(space.wrap(x), space.wrap('test'), space.wrap(5))
+ assert not api.PyErr_Occurred()
assert x.test == 5
- module.setattr(x, 'test', 10)
+ assert api.PyObject_HasAttr(space.wrap(x), space.wrap('test'))
+ api.PyObject_SetAttr(space.wrap(x), space.wrap('test'), space.wrap(10))
assert x.test == 10
Modified: pypy/branch/cpython-extension/pypy/objspace/std/fake.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/objspace/std/fake.py (original)
+++ pypy/branch/cpython-extension/pypy/objspace/std/fake.py Wed Mar 24 18:55:32 2010
@@ -114,6 +114,9 @@
cpy_type.__name__, base, **kw)
def __init__(w_self, space, val):
w_self.val = val
+ w_self.space = space
+ def getdict(w_self):
+ return w_self.space.wrap(w_self.val.__dict__)
def unwrap(w_self, space):
return w_self.val
W_Fake.__name__ = 'W_Fake%s'%(cpy_type.__name__.capitalize())
More information about the Pypy-commit
mailing list