Author: Ronan Lamy <[email protected]>
Branch:
Changeset: r89478:11109e66a206
Date: 2017-01-10 18:46 +0000
http://bitbucket.org/pypy/pypy/changeset/11109e66a206/
Log: Merged in api_func-refactor (pull request #505)
Refactor ApiFunction
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -329,66 +329,19 @@
wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
return wrapper
-DEFAULT_HEADER = 'pypy_decl.h'
-def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
- gil=None, result_borrowed=False, result_is_ll=False):
- """
- Declares a function to be exported.
- - `argtypes`, `restype` are lltypes and describe the function signature.
- - `error` is the value returned when an applevel exception is raised. The
- special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
- exception into a wrapped SystemError. Unwrapped exceptions also cause a
- SytemError.
- - `header` is the header file to export the function in, Set to None to get
- a C function pointer, but not exported by the API headers.
- - set `gil` to "acquire", "release" or "around" to acquire the GIL,
- release the GIL, or both
- """
- if isinstance(restype, lltype.Typedef):
- real_restype = restype.OF
- else:
- real_restype = restype
-
- if error is _NOT_SPECIFIED:
- if isinstance(real_restype, lltype.Ptr):
- error = lltype.nullptr(real_restype.TO)
- elif real_restype is lltype.Void:
- error = CANNOT_FAIL
- if type(error) is int:
- error = rffi.cast(real_restype, error)
- expect_integer = (isinstance(real_restype, lltype.Primitive) and
- rffi.cast(restype, 0) == 0)
-
- def decorate(func):
- func._always_inline_ = 'try'
- func_name = func.func_name
- if header is not None:
- c_name = None
- if func_name in FUNCTIONS_BY_HEADER[header]:
- raise ValueError("%s already registered" % func_name)
- else:
- c_name = func_name
- api_function = ApiFunction(argtypes, restype, func, error,
- c_name=c_name, gil=gil,
- result_borrowed=result_borrowed,
- result_is_ll=result_is_ll)
- func.api_func = api_function
-
- if error is _NOT_SPECIFIED:
- raise ValueError("function %s has no return value for exceptions"
- % func)
- names = api_function.argnames
- types_names_enum_ui = unrolling_iterable(enumerate(
- zip(api_function.argtypes,
- [tp_name.startswith("w_") for tp_name in names])))
+ def get_unwrapper(self):
+ names = self.argnames
+ argtypesw = zip(self.argtypes,
+ [_name.startswith("w_") for _name in self.argnames])
+ types_names_enum_ui = unrolling_iterable(enumerate(argtypesw))
@specialize.ll()
def unwrapper(space, *args):
- from pypy.module.cpyext.pyobject import Py_DecRef, is_pyobj
+ from pypy.module.cpyext.pyobject import is_pyobj
from pypy.module.cpyext.pyobject import from_ref, as_pyobj
newargs = ()
keepalives = ()
- assert len(args) == len(api_function.argtypes)
+ assert len(args) == len(self.argtypes)
for i, (ARG, is_wrapped) in types_names_enum_ui:
input_arg = args[i]
if is_PyObject(ARG) and not is_wrapped:
@@ -413,31 +366,79 @@
arg = from_ref(space, input_arg)
else:
arg = input_arg
-
- ## ZZZ: for is_pyobj:
- ## try:
- ## arg = from_ref(space,
- ## rffi.cast(PyObject, input_arg))
- ## except TypeError, e:
- ## err = oefmt(space.w_TypeError,
- ## "could not cast arg to PyObject")
- ## if not catch_exception:
- ## raise err
- ## state = space.fromcache(State)
- ## state.set_exception(err)
- ## if is_PyObject(restype):
- ## return None
- ## else:
- ## return api_function.error_value
else:
# arg is not declared as PyObject, no magic
arg = input_arg
newargs += (arg, )
try:
- return func(space, *newargs)
+ return self.callable(space, *newargs)
finally:
keepalive_until_here(*keepalives)
+ return unwrapper
+ def get_c_restype(self, c_writer):
+ return c_writer.gettype(self.restype).replace('@', '').strip()
+
+ def get_c_args(self, c_writer):
+ args = []
+ for i, argtype in enumerate(self.argtypes):
+ if argtype is CONST_STRING:
+ arg = 'const char *@'
+ elif argtype is CONST_STRINGP:
+ arg = 'const char **@'
+ elif argtype is CONST_WSTRING:
+ arg = 'const wchar_t *@'
+ else:
+ arg = c_writer.gettype(argtype)
+ arg = arg.replace('@', 'arg%d' % (i,)).strip()
+ args.append(arg)
+ args = ', '.join(args) or "void"
+ return args
+
+ def get_api_decl(self, name, c_writer):
+ restype = self.get_c_restype(c_writer)
+ args = self.get_c_args(c_writer)
+ return "PyAPI_FUNC({restype}) {name}({args});".format(**locals())
+
+ def get_ptr_decl(self, name, c_writer):
+ restype = self.get_c_restype(c_writer)
+ args = self.get_c_args(c_writer)
+ return "{restype} (*{name})({args});".format(**locals())
+
+ def get_ctypes_impl(self, name, c_writer):
+ restype = self.get_c_restype(c_writer)
+ args = self.get_c_args(c_writer)
+ callargs = ', '.join('arg%d' % (i,)
+ for i in range(len(self.argtypes)))
+ if self.restype is lltype.Void:
+ body = "{ _pypyAPI.%s(%s); }" % (name, callargs)
+ else:
+ body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
+ return '%s %s(%s)\n%s' % (restype, name, args, body)
+
+
+DEFAULT_HEADER = 'pypy_decl.h'
+def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
+ gil=None, result_borrowed=False, result_is_ll=False):
+ """
+ Declares a function to be exported.
+ - `argtypes`, `restype` are lltypes and describe the function signature.
+ - `error` is the value returned when an applevel exception is raised. The
+ special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
+ exception into a wrapped SystemError. Unwrapped exceptions also cause a
+ SytemError.
+ - `header` is the header file to export the function in.
+ - set `gil` to "acquire", "release" or "around" to acquire the GIL,
+ release the GIL, or both
+ """
+ assert header is not None
+ def decorate(func):
+ if func.__name__ in FUNCTIONS_BY_HEADER[header]:
+ raise ValueError("%s already registered" % func.__name__)
+ api_function = _create_api_func(
+ func, argtypes, restype, error, gil=gil,
+ result_borrowed=result_borrowed, result_is_ll=result_is_ll)
+ unwrapper = api_function.get_unwrapper()
unwrapper.func = func
unwrapper.api_func = api_function
@@ -449,25 +450,64 @@
try:
res = unwrapper(space, *args)
except OperationError as e:
- if not hasattr(api_function, "error_value"):
+ if not hasattr(unwrapper.api_func, "error_value"):
raise
state = space.fromcache(State)
state.set_exception(e)
if is_PyObject(restype):
return None
else:
- return api_function.error_value
+ return unwrapper.api_func.error_value
got_integer = isinstance(res, (int, long, float))
+ if isinstance(restype, lltype.Typedef):
+ real_restype = restype.OF
+ else:
+ real_restype = restype
+ expect_integer = (isinstance(real_restype, lltype.Primitive) and
+ rffi.cast(restype, 0) == 0)
assert got_integer == expect_integer, (
'got %r not integer' % (res,))
return res
if header is not None:
- FUNCTIONS_BY_HEADER[header][func_name] = api_function
- INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests
- return unwrapper # used in 'normal' RPython code.
+ FUNCTIONS_BY_HEADER[header][func.__name__] = api_function
+ INTERPLEVEL_API[func.__name__] = unwrapper_catch # used in tests
+ return unwrapper
return decorate
+def slot_function(argtypes, restype, error=_NOT_SPECIFIED):
+ def decorate(func):
+ c_name = func.__name__
+ api_function = _create_api_func(func, argtypes, restype, error, c_name)
+ unwrapper = api_function.get_unwrapper()
+ unwrapper.func = func
+ unwrapper.api_func = api_function
+ return unwrapper
+ return decorate
+
+
+def _create_api_func(
+ func, argtypes, restype, error=_NOT_SPECIFIED, c_name=None,
+ gil=None, result_borrowed=False, result_is_ll=False):
+ if isinstance(restype, lltype.Typedef):
+ real_restype = restype.OF
+ else:
+ real_restype = restype
+
+ if error is _NOT_SPECIFIED:
+ if isinstance(real_restype, lltype.Ptr):
+ error = lltype.nullptr(real_restype.TO)
+ elif real_restype is lltype.Void:
+ error = CANNOT_FAIL
+ if type(error) is int:
+ error = rffi.cast(real_restype, error)
+
+ func._always_inline_ = 'try'
+ return ApiFunction(
+ argtypes, restype, func, error, c_name=c_name, gil=gil,
+ result_borrowed=result_borrowed, result_is_ll=result_is_ll)
+
+
def cpython_struct(name, fields, forward=None, level=1):
configname = name.replace(' ', '__')
if level == 1:
@@ -978,23 +1018,6 @@
for func in BOOTSTRAP_FUNCTIONS:
func(space)
-def c_function_signature(db, func):
- restype = db.gettype(func.restype).replace('@', '').strip()
- args = []
- for i, argtype in enumerate(func.argtypes):
- if argtype is CONST_STRING:
- arg = 'const char *@'
- elif argtype is CONST_STRINGP:
- arg = 'const char **@'
- elif argtype is CONST_WSTRING:
- arg = 'const wchar_t *@'
- else:
- arg = db.gettype(argtype)
- arg = arg.replace('@', 'arg%d' % (i,)).strip()
- args.append(arg)
- args = ', '.join(args) or "void"
- return restype, args
-
#_____________________________________________________
# Build the bridge DLL, Allow extension DLLs to call
# back into Pypy space functions
@@ -1014,15 +1037,8 @@
structindex = {}
for header, header_functions in FUNCTIONS_BY_HEADER.iteritems():
for name, func in header_functions.iteritems():
- restype, args = c_function_signature(db, func)
- callargs = ', '.join('arg%d' % (i,)
- for i in range(len(func.argtypes)))
- if func.restype is lltype.Void:
- body = "{ _pypyAPI.%s(%s); }" % (name, callargs)
- else:
- body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
- functions.append('%s %s(%s)\n%s' % (restype, name, args, body))
- members.append('%s (*%s)(%s);' % (restype, name, args))
+ functions.append(func.get_ctypes_impl(name, db))
+ members.append(func.get_ptr_decl(name, db))
structindex[name] = len(structindex)
structmembers = '\n'.join(members)
struct_declaration_code = """\
@@ -1217,8 +1233,7 @@
for name, func in sorted(header_functions.iteritems()):
_name = mangle_name(prefix, name)
header.append("#define %s %s" % (name, _name))
- restype, args = c_function_signature(db, func)
- header.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args))
+ header.append(func.get_api_decl(name, db))
for name, (typ, expr) in GLOBALS.iteritems():
if '#' in name:
diff --git a/pypy/module/cpyext/bufferobject.py
b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -2,7 +2,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.interpreter.error import oefmt
from pypy.module.cpyext.api import (
- cpython_api, Py_ssize_t, cpython_struct, bootstrap_function,
+ cpython_api, Py_ssize_t, cpython_struct, bootstrap_function, slot_function,
PyObjectFields, PyObject)
from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef, make_ref
from pypy.module.array.interp_array import ArrayBuffer
@@ -72,7 +72,7 @@
"Don't know how to realize a buffer")
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def buffer_dealloc(space, py_obj):
py_buf = rffi.cast(PyBufferObject, py_obj)
if py_buf.c_b_base:
diff --git a/pypy/module/cpyext/bytesobject.py
b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -2,7 +2,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
- PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL)
+ PyVarObjectFields, Py_ssize_t, CONST_STRING, CANNOT_FAIL, slot_function)
from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
@@ -25,14 +25,14 @@
##
## In the PyBytesObject returned, the ob_sval buffer may be modified as
## long as the freshly allocated PyBytesObject is not "forced" via a call
-## to any of the more sophisticated C-API functions.
+## to any of the more sophisticated C-API functions.
##
## Care has been taken in implementing the functions below, so that
-## if they are called with a non-forced PyBytesObject, they will not
+## if they are called with a non-forced PyBytesObject, they will not
## unintentionally force the creation of a RPython object. As long as only
these
## are used, the ob_sval buffer is still modifiable:
-##
-## PyBytes_AsString / PyString_AsString
+##
+## PyBytes_AsString / PyString_AsString
## PyBytes_AS_STRING / PyString_AS_STRING
## PyBytes_AsStringAndSize / PyString_AsStringAndSize
## PyBytes_Size / PyString_Size
@@ -40,7 +40,7 @@
## _PyBytes_Resize / _PyString_Resize (raises if called with a forced object)
##
## - There could be an (expensive!) check in from_ref() that the buffer still
-## corresponds to the pypy gc-managed string,
+## corresponds to the pypy gc-managed string,
##
PyBytesObjectStruct = lltype.ForwardReference()
@@ -105,7 +105,7 @@
track_reference(space, py_obj, w_obj)
return w_obj
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def bytes_dealloc(space, py_obj):
"""Frees allocated PyBytesObject resources.
"""
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -6,8 +6,8 @@
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, build_type_checkers, Py_ssize_t,
Py_ssize_tP, CONST_STRING, PyObjectFields, cpython_struct,
- bootstrap_function)
-from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj,
+ bootstrap_function, slot_function)
+from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj,
make_typedescr, track_reference, create_ref, from_ref, decref,
Py_IncRef)
from pypy.module.cpyext.object import _dealloc
@@ -36,7 +36,7 @@
py_dict.c__tmpkeys = lltype.nullptr(PyObject.TO)
# Problems: if this dict is a typedict, we may have unbound GetSetProperty
# functions in the dict. The corresponding PyGetSetDescrObject must be
- # bound to a class, but the actual w_type will be unavailable later on.
+ # bound to a class, but the actual w_type will be unavailable later on.
# Solution: use the w_userdata argument when assigning a PyTypeObject's
# tp_dict slot to pass a w_type in, and force creation of the pair here
if not space.is_w(w_userdata, space.gettypefor(GetSetProperty)):
@@ -55,7 +55,7 @@
w_obj = space.newdict()
track_reference(space, py_obj, w_obj)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def dict_dealloc(space, py_obj):
py_dict = rffi.cast(PyDictObject, py_obj)
decref(space, py_dict.c__tmpkeys)
@@ -287,7 +287,7 @@
if space not in _frozendict_cache:
_frozendict_cache[space] = _make_frozendict(space)
return _frozendict_cache[space]
-
+
_frozendict_cache = {}
def _make_frozendict(space):
return space.appexec([], '''():
diff --git a/pypy/module/cpyext/frameobject.py
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, bootstrap_function, PyObjectFields, cpython_struct,
- CANNOT_FAIL)
+ CANNOT_FAIL, slot_function)
from pypy.module.cpyext.pyobject import (
PyObject, Py_DecRef, make_ref, from_ref, track_reference,
make_typedescr, get_typedescr)
@@ -39,7 +39,7 @@
py_frame.c_f_locals = make_ref(space, frame.get_w_locals())
rffi.setintfield(py_frame, 'c_f_lineno', frame.getorcreatedebug().f_lineno)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def frame_dealloc(space, py_obj):
py_frame = rffi.cast(PyFrameObject, py_obj)
py_code = rffi.cast(PyObject, py_frame.c_f_code)
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -1,7 +1,8 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t,
- cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
+ cpython_api, bootstrap_function, cpython_struct, build_type_checkers,
+ slot_function)
from pypy.module.cpyext.pyobject import (
PyObject, make_ref, from_ref, Py_DecRef, make_typedescr)
from rpython.rlib.unroll import unrolling_iterable
@@ -56,7 +57,7 @@
assert isinstance(w_obj, Function)
py_func.c_func_name = make_ref(space, space.wrap(w_obj.name))
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def function_dealloc(space, py_obj):
py_func = rffi.cast(PyFunctionObject, py_obj)
Py_DecRef(space, py_func.c_func_name)
@@ -75,7 +76,7 @@
rffi.setintfield(py_code, 'c_co_flags', co_flags)
rffi.setintfield(py_code, 'c_co_argcount', w_obj.co_argcount)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def code_dealloc(space, py_obj):
py_code = rffi.cast(PyCodeObject, py_obj)
Py_DecRef(space, py_code.c_co_name)
diff --git a/pypy/module/cpyext/memoryobject.py
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,9 +1,9 @@
-from pypy.module.cpyext.api import (cpython_api, Py_buffer, CANNOT_FAIL,
- Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers,
- Py_ssize_tP, PyObjectFields, cpython_struct,
- bootstrap_function, Py_bufferP)
-from pypy.module.cpyext.pyobject import (PyObject, make_ref, as_pyobj, incref,
- decref, from_ref, make_typedescr)
+from pypy.module.cpyext.api import (
+ cpython_api, Py_buffer, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS,
+ build_type_checkers, Py_ssize_tP, PyObjectFields, cpython_struct,
+ bootstrap_function, Py_bufferP, slot_function)
+from pypy.module.cpyext.pyobject import (
+ PyObject, make_ref, as_pyobj, incref, decref, from_ref, make_typedescr)
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.rarithmetic import widen
from pypy.objspace.std.memoryobject import W_MemoryView
@@ -60,7 +60,7 @@
"""
raise oefmt(space.w_NotImplementedError, "cannot call this yet")
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def memory_dealloc(space, py_obj):
mem_obj = rffi.cast(PyMemoryViewObject, py_obj)
if mem_obj.c_view.c_obj:
diff --git a/pypy/module/cpyext/methodobject.py
b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -11,7 +11,7 @@
CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O,
METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function,
build_type_checkers, cpython_api, cpython_struct, generic_cpy_call,
- PyTypeObjectPtr)
+ PyTypeObjectPtr, slot_function)
from pypy.module.cpyext.pyobject import (
Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr)
@@ -51,7 +51,7 @@
py_func.c_m_self = make_ref(space, w_obj.w_self)
py_func.c_m_module = make_ref(space, w_obj.w_module)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def cfunction_dealloc(space, py_obj):
py_func = rffi.cast(PyCFunctionObject, py_obj)
Py_DecRef(space, py_func.c_m_self)
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
- PyVarObject, Py_buffer, size_t,
+ PyVarObject, Py_buffer, size_t, slot_function,
Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite)
from pypy.module.cpyext.pyobject import (
@@ -54,7 +54,7 @@
w_obj = PyObject_InitVar(space, py_objvar, type, itemcount)
return py_obj
-@cpython_api([PyObject], lltype.Void)
+@slot_function([PyObject], lltype.Void)
def PyObject_dealloc(space, obj):
return _dealloc(space, obj)
@@ -511,7 +511,7 @@
@cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
def PyBuffer_Release(space, view):
"""
- Release the buffer view. This should be called when the buffer is
+ Release the buffer view. This should be called when the buffer is
no longer being used as it may free memory from it
"""
Py_DecRef(space, view.c_obj)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -87,7 +87,7 @@
alloc : allocate and basic initialization of a raw PyObject
attach : Function called to tie a raw structure to a pypy object
realize : Function called to create a pypy object from a raw struct
- dealloc : a cpython_api(header=None), similar to PyObject_dealloc
+ dealloc : a @slot_function(), similar to PyObject_dealloc
"""
tp_basestruct = kw.pop('basestruct', PyObject.TO)
diff --git a/pypy/module/cpyext/pytraceback.py
b/pypy/module/cpyext/pytraceback.py
--- a/pypy/module/cpyext/pytraceback.py
+++ b/pypy/module/cpyext/pytraceback.py
@@ -1,7 +1,8 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t,
- cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
+ cpython_api, bootstrap_function, cpython_struct, build_type_checkers,
+ slot_function)
from pypy.module.cpyext.pyobject import (
PyObject, make_ref, from_ref, Py_DecRef, make_typedescr)
from pypy.module.cpyext.frameobject import PyFrameObject
@@ -40,7 +41,7 @@
rffi.setintfield(py_traceback, 'c_tb_lasti', traceback.lasti)
rffi.setintfield(py_traceback, 'c_tb_lineno',traceback.get_lineno())
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def traceback_dealloc(space, py_obj):
py_traceback = rffi.cast(PyTracebackObject, py_obj)
Py_DecRef(space, rffi.cast(PyObject, py_traceback.c_tb_next))
diff --git a/pypy/module/cpyext/sliceobject.py
b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
- CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, PyObjectFields)
+ CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, PyObjectFields, slot_function)
from pypy.module.cpyext.pyobject import (
Py_DecRef, PyObject, make_ref, make_typedescr)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
@@ -36,7 +36,7 @@
py_slice.c_stop = make_ref(space, w_obj.w_stop)
py_slice.c_step = make_ref(space, w_obj.w_step)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def slice_dealloc(space, py_obj):
"""Frees allocated PyBytesObject resources.
"""
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -6,7 +6,7 @@
from rpython.rlib.rarithmetic import widen
from rpython.rlib import rgc # Force registration of gc.collect
from pypy.module.cpyext.api import (
- cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES,
+ slot_function, generic_cpy_call, PyObject, Py_ssize_t,
Py_TPFLAGS_CHECKTYPES,
pypy_decl, Py_buffer, Py_bufferP)
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
@@ -64,7 +64,7 @@
@not_rpython
def llslot(space, func):
- return llhelper(func.api_func.functype, func.api_func.get_wrapper(space))
+ return func.api_func.get_llhelper(space)
@register_flow_sc(llslot)
def sc_llslot(ctx, v_space, v_func):
@@ -521,9 +521,6 @@
def build_slot_tp_function(space, typedef, name):
w_type = space.gettypeobject(typedef)
- header = pypy_decl
- if not (name.startswith('Py') or name.startswith('_Py')):
- header = None
handled = False
# unary functions
for tp_name, attr in [('tp_as_number.c_nb_int', '__int__'),
@@ -545,7 +542,7 @@
if slot_fn is None:
return
- @cpython_api([PyObject], PyObject, header=header)
+ @slot_function([PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'),
typedef.name))
def slot_func(space, w_self):
return space.call_function(slot_fn, w_self)
@@ -571,7 +568,7 @@
if slot_fn is None:
return
- @cpython_api([PyObject, PyObject], PyObject, header=header)
+ @slot_function([PyObject, PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'),
typedef.name))
def slot_func(space, w_self, w_arg):
return space.call_function(slot_fn, w_self, w_arg)
@@ -588,7 +585,7 @@
if slot_fn is None:
return
- @cpython_api([PyObject, Py_ssize_t], PyObject, header=header)
+ @slot_function([PyObject, Py_ssize_t], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'),
typedef.name))
def slot_func(space, w_self, arg):
return space.call_function(slot_fn, w_self, space.wrap(arg))
@@ -602,7 +599,7 @@
if slot_fn is None:
return
- @cpython_api([PyObject, PyObject, PyObject], PyObject,
header=header)
+ @slot_function([PyObject, PyObject, PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'),
typedef.name))
def slot_func(space, w_self, w_arg1, w_arg2):
return space.call_function(slot_fn, w_self, w_arg1, w_arg2)
@@ -616,8 +613,8 @@
if setattr_fn is None:
return
- @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real,
- error=-1, header=header)
+ @slot_function([PyObject, PyObject, PyObject], rffi.INT_real,
+ error=-1)
@func_renamer("cpyext_tp_setattro_%s" % (typedef.name,))
def slot_tp_setattro(space, w_self, w_name, w_value):
if w_value is not None:
@@ -631,7 +628,7 @@
if getattr_fn is None:
return
- @cpython_api([PyObject, PyObject], PyObject, header=header)
+ @slot_function([PyObject, PyObject], PyObject)
@func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
def slot_tp_getattro(space, w_self, w_name):
return space.call_function(getattr_fn, w_self, w_name)
@@ -641,7 +638,7 @@
if call_fn is None:
return
- @cpython_api([PyObject, PyObject, PyObject], PyObject, header=header)
+ @slot_function([PyObject, PyObject, PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
def slot_tp_call(space, w_self, w_args, w_kwds):
args = Arguments(space, [w_self],
@@ -654,7 +651,7 @@
if iternext_fn is None:
return
- @cpython_api([PyObject], PyObject, header=header)
+ @slot_function([PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
def slot_tp_iternext(space, w_self):
try:
@@ -670,8 +667,7 @@
if init_fn is None:
return
- @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1,
- header=header)
+ @slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
def slot_tp_init(space, w_self, w_args, w_kwds):
args = Arguments(space, [w_self],
@@ -684,7 +680,7 @@
if new_fn is None:
return
- @cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject,
header=None)
+ @slot_function([PyTypeObjectPtr, PyObject, PyObject], PyObject)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
def slot_tp_new(space, w_self, w_args, w_kwds):
args = Arguments(space, [w_self],
@@ -695,8 +691,8 @@
buff_fn = w_type.getdictvalue(space, '__buffer__')
if buff_fn is None:
return
- @cpython_api([PyObject, Py_bufferP, rffi.INT_real],
- rffi.INT_real, header=None, error=-1)
+ @slot_function([PyObject, Py_bufferP, rffi.INT_real],
+ rffi.INT_real, error=-1)
@func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
def buff_w(space, w_self, view, flags):
args = Arguments(space, [space.newint(flags)])
diff --git a/pypy/module/cpyext/test/test_api.py
b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -89,10 +89,10 @@
def test_typedef(self, space):
from rpython.translator.c.database import LowLevelDatabase
db = LowLevelDatabase()
- assert (api.c_function_signature(db, PyPy_TypedefTest1.api_func)
- == ('Py_ssize_t', 'Py_ssize_t arg0'))
- assert (api.c_function_signature(db, PyPy_TypedefTest2.api_func)
- == ('Py_ssize_t *', 'Py_ssize_t *arg0'))
+ assert PyPy_TypedefTest1.api_func.get_c_restype(db) == 'Py_ssize_t'
+ assert PyPy_TypedefTest1.api_func.get_c_args(db) == 'Py_ssize_t arg0'
+ assert PyPy_TypedefTest2.api_func.get_c_restype(db) == 'Py_ssize_t *'
+ assert PyPy_TypedefTest2.api_func.get_c_args(db) == 'Py_ssize_t *arg0'
PyPy_TypedefTest1(space, 0)
ppos = lltype.malloc(api.Py_ssize_tP.TO, 1, flavor='raw')
diff --git a/pypy/module/cpyext/test/test_translate.py
b/pypy/module/cpyext/test/test_translate.py
--- a/pypy/module/cpyext/test/test_translate.py
+++ b/pypy/module/cpyext/test/test_translate.py
@@ -1,6 +1,6 @@
from rpython.translator.c.test.test_genc import compile
import pypy.module.cpyext.api
-from pypy.module.cpyext.api import cpython_api
+from pypy.module.cpyext.api import slot_function
from rpython.rtyper.annlowlevel import llhelper
from rpython.rtyper.lltypesystem import lltype
from rpython.rlib.objectmodel import specialize
@@ -19,7 +19,7 @@
@specialize.memo()
def get_tp_function(space, typedef):
- @cpython_api([], lltype.Signed, error=-1, header=None)
+ @slot_function([], lltype.Signed, error=-1)
def slot_tp_function(space):
return typedef.value
diff --git a/pypy/module/cpyext/tupleobject.py
b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -1,11 +1,11 @@
from pypy.interpreter.error import oefmt
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.debug import fatalerror_notb
-from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
- build_type_checkers, PyVarObjectFields,
- cpython_struct, bootstrap_function)
-from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
- make_ref, from_ref, decref, incref, pyobj_has_w_obj,
+from pypy.module.cpyext.api import (
+ cpython_api, Py_ssize_t, build_type_checkers,
+ PyVarObjectFields, cpython_struct, bootstrap_function, slot_function)
+from pypy.module.cpyext.pyobject import (
+ PyObject, PyObjectP, make_ref, from_ref, decref, incref,
track_reference, make_typedescr, get_typedescr)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.objspace.std.tupleobject import W_TupleObject
@@ -74,7 +74,7 @@
if py_tup.c_ob_size < length:
raise oefmt(space.w_ValueError,
"tuple_attach called on object with ob_size %d but trying to store
%d",
- py_tup.c_ob_size, length)
+ py_tup.c_ob_size, length)
i = 0
try:
while i < length:
@@ -113,7 +113,7 @@
track_reference(space, py_obj, w_obj)
return w_obj
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def tuple_dealloc(space, py_obj):
"""Frees allocated PyTupleObject resources.
"""
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -2,21 +2,20 @@
from rpython.rlib import jit
from rpython.rlib.objectmodel import specialize
-from rpython.rlib.rstring import rsplit
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.interpreter.baseobjspace import W_Root, DescrMismatch
from pypy.interpreter.error import oefmt
-from pypy.interpreter.typedef import (GetSetProperty, TypeDef,
- interp_attrproperty, interp_attrproperty, interp2app)
+from pypy.interpreter.typedef import (
+ GetSetProperty, TypeDef, interp_attrproperty, interp2app)
from pypy.module.__builtin__.abstractinst import abstract_issubclass_w
from pypy.module.cpyext import structmemberdefs
from pypy.module.cpyext.api import (
cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
- generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
+ slot_function, generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
- Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, StaticObjectBuilder,
- PyObjectFields, Py_TPFLAGS_BASETYPE, PyTypeObject, PyTypeObjectPtr,
+ Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers,
+ PyObjectFields, PyTypeObject, PyTypeObjectPtr,
Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_CHECKTYPES,
Py_TPFLAGS_HAVE_INPLACEOPS)
from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject,
@@ -346,7 +345,7 @@
if pto.c_tp_new:
add_tp_new_wrapper(space, dict_w, pto)
-@cpython_api([PyObject, PyObject, PyObject], PyObject, header=None)
+@slot_function([PyObject, PyObject, PyObject], PyObject)
def tp_new_wrapper(space, self, w_args, w_kwds):
self_pytype = rffi.cast(PyTypeObjectPtr, self)
tp_new = self_pytype.c_tp_new
@@ -507,7 +506,7 @@
realize=type_realize,
dealloc=type_dealloc)
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def subtype_dealloc(space, obj):
pto = obj.c_ob_type
base = pto
@@ -522,15 +521,13 @@
# hopefully this does not clash with the memory model assumed in
# extension modules
-@cpython_api([PyObject, Py_ssize_tP], lltype.Signed, header=None,
- error=CANNOT_FAIL)
+@slot_function([PyObject, Py_ssize_tP], lltype.Signed, error=CANNOT_FAIL)
def bf_segcount(space, w_obj, ref):
if ref:
ref[0] = space.len_w(w_obj)
return 1
-@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed, error=-1)
def bf_getreadbuffer(space, w_buf, segment, ref):
from rpython.rlib.buffer import StringBuffer
if segment != 0:
@@ -543,13 +540,11 @@
ref[0] = address
return len(buf)
-@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed, error=-1)
def bf_getcharbuffer(space, w_buf, segment, ref):
return bf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, ref))
-@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed, error=-1)
def bf_getwritebuffer(space, w_buf, segment, ref):
if segment != 0:
raise oefmt(space.w_SystemError,
@@ -558,8 +553,7 @@
ref[0] = buf.get_raw_address()
return len(buf)
-@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed, error=-1)
def str_getreadbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.bytesobject import PyString_AsString
if segment != 0:
@@ -571,11 +565,10 @@
Py_DecRef(space, pyref)
return space.len_w(w_str)
-@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed, error=-1)
def unicode_getreadbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.unicodeobject import (
- PyUnicode_AS_UNICODE, PyUnicode_GET_DATA_SIZE)
+ PyUnicode_AS_UNICODE, PyUnicode_GET_DATA_SIZE)
if segment != 0:
raise oefmt(space.w_SystemError,
"accessing non-existent unicode segment")
@@ -585,13 +578,11 @@
Py_DecRef(space, pyref)
return PyUnicode_GET_DATA_SIZE(space, w_str)
-@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed, error=-1)
def str_getcharbuffer(space, w_buf, segment, ref):
return str_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP,
ref))
-@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed, error=-1)
def buf_getreadbuffer(space, pyref, segment, ref):
from pypy.module.cpyext.bufferobject import PyBufferObject
if segment != 0:
@@ -601,8 +592,7 @@
ref[0] = py_buf.c_b_ptr
return py_buf.c_b_size
-@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
- header=None, error=-1)
+@slot_function([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed, error=-1)
def buf_getcharbuffer(space, w_buf, segment, ref):
return buf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP,
ref))
@@ -642,7 +632,7 @@
pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
pto.c_tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def type_dealloc(space, obj):
from pypy.module.cpyext.object import _dealloc
obj_pto = rffi.cast(PyTypeObjectPtr, obj)
diff --git a/pypy/module/cpyext/unicodeobject.py
b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -4,7 +4,7 @@
from pypy.module.cpyext.api import (
CANNOT_FAIL, Py_ssize_t, build_type_checkers, cpython_api,
bootstrap_function, PyObjectFields, cpython_struct, CONST_STRING,
- CONST_WSTRING)
+ CONST_WSTRING, slot_function)
from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
@@ -84,7 +84,7 @@
track_reference(space, py_obj, w_obj)
return w_obj
-@cpython_api([PyObject], lltype.Void, header=None)
+@slot_function([PyObject], lltype.Void)
def unicode_dealloc(space, py_obj):
py_unicode = rffi.cast(PyUnicodeObject, py_obj)
Py_DecRef(space, py_unicode.c_defenc)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit