Example #1
0
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
Example #2
0
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