def funccpppxd(desc, exception_type='+'): """Generates a cpp_*.pxd Cython header snippet for exposing a C/C++ function to other Cython wrappers based off of a dictionary description. Parameters ---------- desc : dict Function description dictonary. exception_type : str, optional Cython exception annotation. Set to None when exceptions should not be included. Returns ------- cimport_tups : set of tuples Set of Cython cimport tuples for cpp_*.pxd header file. cpppxd : str Cython cpp_*.pxd header file as in-memory string. """ d = {} copy_from_desc = ['name', 'namespace', 'header_filename'] for key in copy_from_desc: d[key] = desc[key] inc = set(['c']) cimport_tups = set() flines = [] estr = str() if exception_type is None else ' except {0}'.format(exception_type) funcitems = sorted(expand_default_args(desc['signatures'].items())) for fkey, frtn in funcitems: fname, fargs = fkey[0], fkey[1:] if fname.startswith('_'): continue # private argfill = ", ".join([cython_ctype(a[1]) for a in fargs]) for a in fargs: cython_cimport_tuples(a[1], cimport_tups, inc) line = "{0}({1}){2}".format(fname, argfill, estr) rtype = cython_ctype(frtn) cython_cimport_tuples(frtn, cimport_tups, inc) line = rtype + " " + line if line not in flines: flines.append(line) d['functions_block'] = indent(flines, 4) d['extra'] = desc.get('extra', {}).get('cpppxd', '') cpppxd = _cpppxd_func_template.format(**d) if 'cpppxd_filename' not in desc: desc['cpppxd_filename'] = 'cpp_{0}.pxd'.format(d['name'].lower()) return cimport_tups, cpppxd
def classcpppxd(desc, exception_type='+'): """Generates a cpp_*.pxd Cython header snippet for exposing a C/C++ class or struct to other Cython wrappers based off of a dictionary description of the class or struct. Parameters ---------- desc : dict Class description dictonary. exception_type : str, optional Cython exception annotation. Set to None when exceptions should not be included. Returns ------- cimport_tups : set of tuples Set of Cython cimport tuples for cpp_*.pxd header file. cpppxd : str Cython cpp_*.pxd header file as in-memory string. """ pars = ', '.join([cython_ctype(p) for p in desc['parents'] or ()]) d = {'parents': pars if 0 == len(pars) else '('+pars+')'} copy_from_desc = ['name', 'namespace', 'header_filename'] for key in copy_from_desc: d[key] = desc[key] inc = set(['c']) cimport_tups = set() for parent in desc['parents'] or (): cython_cimport_tuples(parent, cimport_tups, inc) alines = [] attritems = sorted(desc['attrs'].items()) for aname, atype in attritems: if aname.startswith('_'): continue alines.append("{0} {1}".format(cython_ctype(atype), aname)) cython_cimport_tuples(atype, cimport_tups, inc) d['attrs_block'] = indent(alines, 8) mlines = [] clines = [] estr = str() if exception_type is None else ' except {0}'.format(exception_type) methitems = sorted(expand_default_args(desc['methods'].items())) for mkey, mrtn in methitems: mname, margs = mkey[0], mkey[1:] if mname.startswith('_') or mname.startswith('~'): continue # private or destructor argfill = ", ".join([cython_ctype(a[1]) for a in margs]) for a in margs: cython_cimport_tuples(a[1], cimport_tups, inc) line = "{0}({1}){2}".format(mname, argfill, estr) if mrtn is None: # this must be a constructor if line not in clines: clines.append(line) else: # this is a normal method rtype = cython_ctype(mrtn) cython_cimport_tuples(mrtn, cimport_tups, inc) line = rtype + " " + line if line not in mlines: mlines.append(line) d['methods_block'] = indent(mlines, 8) d['constructors_block'] = indent(clines, 8) d['extra'] = desc.get('extra', {}).get('cpppxd', '') cpppxd = _cpppxd_class_template.format(**d) if 'cpppxd_filename' not in desc: desc['cpppxd_filename'] = 'cpp_{0}.pxd'.format(d['name'].lower()) return cimport_tups, cpppxd