from __future__ import division, print_function import os import genapi import numpy_api from genapi import \ TypeApi, GlobalVarApi, FunctionApi, BoolValuesApi h_template = r""" #ifdef _UMATHMODULE extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type; %s #else #if defined(PY_UFUNC_UNIQUE_SYMBOL) #define PyUFunc_API PY_UFUNC_UNIQUE_SYMBOL #endif #if defined(NO_IMPORT) || defined(NO_IMPORT_UFUNC) extern void **PyUFunc_API; #else #if defined(PY_UFUNC_UNIQUE_SYMBOL) void **PyUFunc_API; #else static void **PyUFunc_API=NULL; #endif #endif %s static NPY_INLINE int _import_umath(void) { PyObject *numpy = PyImport_ImportModule("numpy.core.umath"); PyObject *c_api = NULL; if (numpy == NULL) { PyErr_SetString(PyExc_ImportError, "numpy.core.umath failed to import"); return -1; } c_api = PyObject_GetAttrString(numpy, "_UFUNC_API"); Py_DECREF(numpy); if (c_api == NULL) { PyErr_SetString(PyExc_AttributeError, "_UFUNC_API not found"); return -1; } #if PY_VERSION_HEX >= 0x03000000 if (!PyCapsule_CheckExact(c_api)) { PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCapsule object"); Py_DECREF(c_api); return -1; } PyUFunc_API = (void **)PyCapsule_GetPointer(c_api, NULL); #else if (!PyCObject_Check(c_api)) { PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCObject object"); Py_DECREF(c_api); return -1; } PyUFunc_API = (void **)PyCObject_AsVoidPtr(c_api); #endif Py_DECREF(c_api); if (PyUFunc_API == NULL) { PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer"); return -1; } return 0; } #if PY_VERSION_HEX >= 0x03000000 #define NUMPY_IMPORT_UMATH_RETVAL NULL #else #define NUMPY_IMPORT_UMATH_RETVAL #endif #define import_umath() \ do {\ UFUNC_NOFPE\ if (_import_umath() < 0) {\ PyErr_Print();\ PyErr_SetString(PyExc_ImportError,\ "numpy.core.umath failed to import");\ return NUMPY_IMPORT_UMATH_RETVAL;\ }\ } while(0) #define import_umath1(ret) \ do {\ UFUNC_NOFPE\ if (_import_umath() < 0) {\ PyErr_Print();\ PyErr_SetString(PyExc_ImportError,\ "numpy.core.umath failed to import");\ return ret;\ }\ } while(0) #define import_umath2(ret, msg) \ do {\ UFUNC_NOFPE\ if (_import_umath() < 0) {\ PyErr_Print();\ PyErr_SetString(PyExc_ImportError, msg);\ return ret;\ }\ } while(0) #define import_ufunc() \ do {\ UFUNC_NOFPE\ if (_import_umath() < 0) {\ PyErr_Print();\ PyErr_SetString(PyExc_ImportError,\ "numpy.core.umath failed to import");\ }\ } while(0) #endif """ c_template = r""" /* These pointers will be stored in the C-object for use in other extension modules */ void *PyUFunc_API[] = { %s }; """ def generate_api(output_dir, force=False): basename = 'ufunc_api' h_file = os.path.join(output_dir, '__%s.h' % basename) c_file = os.path.join(output_dir, '__%s.c' % basename) d_file = os.path.join(output_dir, '%s.txt' % basename) targets = (h_file, c_file, d_file) sources = ['ufunc_api_order.txt'] if (not force and not genapi.should_rebuild(targets, sources + [__file__])): return targets else: do_generate_api(targets, sources) return targets def do_generate_api(targets, sources): header_file = targets[0] c_file = targets[1] doc_file = targets[2] ufunc_api_index = genapi.merge_api_dicts(( numpy_api.ufunc_funcs_api, numpy_api.ufunc_types_api)) genapi.check_api_dict(ufunc_api_index) ufunc_api_list = genapi.get_api_functions('UFUNC_API', numpy_api.ufunc_funcs_api) # Create dict name -> *Api instance ufunc_api_dict = {} api_name = 'PyUFunc_API' for f in ufunc_api_list: name = f.name index = ufunc_api_index[name][0] annotations = ufunc_api_index[name][1:] ufunc_api_dict[name] = FunctionApi(f.name, index, annotations, f.return_type, f.args, api_name) for name, val in numpy_api.ufunc_types_api.items(): index = val[0] ufunc_api_dict[name] = TypeApi(name, index, 'PyTypeObject', api_name) # set up object API module_list = [] extension_list = [] init_list = [] for name, index in genapi.order_dict(ufunc_api_index): api_item = ufunc_api_dict[name] extension_list.append(api_item.define_from_array_api_string()) init_list.append(api_item.array_api_define()) module_list.append(api_item.internal_define()) # Write to header s = h_template % ('\n'.join(module_list), '\n'.join(extension_list)) genapi.write_file(header_file, s) # Write to c-code s = c_template % ',\n'.join(init_list) genapi.write_file(c_file, s) # Write to documentation s = ''' ================= NumPy Ufunc C-API ================= ''' for func in ufunc_api_list: s += func.to_ReST() s += '\n\n' genapi.write_file(doc_file, s) return targets