Author: Ronan Lamy <ronan.l...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit