def genpxd(desc): """Generates a ``*pxd`` Cython header file for exposing C/C++ data to other Cython wrappers based off of a dictionary description. Parameters ---------- desc : dict Class description dictonary. Returns ------- pxd : str Cython ``*.pxd`` header file as in-memory string. """ if 'pxd_filename' not in desc: desc['pxd_filename'] = '{0}.pxd'.format(desc['name'].lower()) pars = ', '.join([cython_cytype(p) for p in desc['parents'] or ()]) d = {'parents': pars if 0 == len(pars) else '('+pars+')'} copy_from_desc = ['name',] for key in copy_from_desc: d[key] = desc[key] cimport_tups = set() for parent in desc['parents'] or (): cython_cimport_tuples(parent, cimport_tups, set(['cy'])) from_cpppxd = desc['cpppxd_filename'].rsplit('.', 1)[0] # This is taken care of in main! #register_class(desc['name'], cython_cimport=from_cpppxd, # cython_c_type="{0}.{1}".format(from_cpppxd, desc['name']),) d['name_type'] = cython_ctype(desc['name']) cython_cimport_tuples(desc['name'], cimport_tups, set(['c'])) parentless_body = ['cdef void * _inst', 'cdef public bint _free_inst'] body = parentless_body if desc['parents'] is None else [] attritems = sorted(desc['attrs'].items()) for aname, atype in attritems: if aname.startswith('_'): continue # skip private _, _, cachename, iscached = cython_c2py(aname, atype, cache_prefix=None) if iscached: cython_cimport_tuples(atype, cimport_tups) cyt = cython_cytype(atype) decl = "cdef public {0} {1}".format(cyt, cachename) body.append(decl) d['cimports'] = "\n".join(sorted(cython_cimports(cimport_tups))) d['body'] = indent(body or ['pass']) d['extra'] = desc.get('extra', {}).get('pxd', '') pxd = _pxd_template.format(**d) return pxd
def _gen_property_get(name, t, cached_names=None, inst_name="self._inst"): """This generates a Cython property getter for a variable of a given name and type.""" lines = ['def __get__(self):'] decl, body, rtn, iscached = cython_c2py(name, t, inst_name=inst_name) if decl is not None: lines += indent(decl, join=False) if body is not None: lines += indent(body, join=False) if iscached and cached_names is not None: cached_names.append(rtn) lines += indent("return {0}".format(rtn), join=False) return lines
def _gen_method(name, name_mangled, args, rtn, doc=None, inst_name="self._inst"): argfill = ", ".join(['self'] + [a[0] for a in args if 2 == len(a)] + \ ["{0}={1}".format(a[0], a[2]) for a in args if 3 == len(a)]) lines = ['def {0}({1}):'.format(name_mangled, argfill)] lines += [] if doc is None else indent('\"\"\"{0}\"\"\"'.format(doc), join=False) decls = [] argbodies = [] argrtns = {} for a in args: adecl, abody, artn = cython_py2c(a[0], a[1]) if adecl is not None: decls += indent(adecl, join=False) if abody is not None: argbodies += indent(abody, join=False) argrtns[a[0]] = artn rtype = cython_ctype(rtn) hasrtn = rtype not in set(['None', None, 'NULL', 'void']) argvals = ', '.join([argrtns[a[0]] for a in args]) fcall = '{0}.{1}({2})'.format(inst_name, name, argvals) if hasrtn: fcdecl, fcbody, fcrtn, fccached = cython_c2py('rtnval', rtn, cached=False) decls += indent("cdef {0} {1}".format(rtype, 'rtnval'), join=False) func_call = indent('rtnval = {0}'.format(fcall), join=False) if fcdecl is not None: decls += indent(fcdecl, join=False) if fcbody is not None: func_call += indent(fcbody, join=False) func_rtn = indent("return {0}".format(fcrtn), join=False) else: func_call = indent(fcall, join=False) func_rtn = [] lines += decls lines += argbodies lines += func_call lines += func_rtn lines += ['', ""] return lines
def check_cython_c2py(name, t, inst_name, exp): #import pprint; pprint.pprint(ts.refined_types) obs = ts.cython_c2py(name, t, inst_name=inst_name) assert_equal(obs, exp)