diff options
Diffstat (limited to 'numpy/f2py/lib/wrapper_base.py')
-rw-r--r-- | numpy/f2py/lib/wrapper_base.py | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/numpy/f2py/lib/wrapper_base.py b/numpy/f2py/lib/wrapper_base.py new file mode 100644 index 000000000..3164e817f --- /dev/null +++ b/numpy/f2py/lib/wrapper_base.py @@ -0,0 +1,178 @@ +import os +import sys +import re + +__all__ = ['WrapperBase','WrapperCPPMacro','WrapperCCode'] + +class WrapperBase: + + def __init__(self): + self.srcdir = os.path.join(os.path.dirname(__file__),'src') + return + def warning(self, message): + print >> sys.stderr, message + def info(self, message): + print >> sys.stderr, message + + def get_resource_content(self, name, ext): + if name.startswith('pyobj_to_'): + try: + return self.generate_pyobj_to_ctype_c(name[9:]) + except NotImplementedError: + pass + elif name.startswith('pyobj_from_'): + try: + return self.generate_pyobj_from_ctype_c(name[11:]) + except NotImplementedError: + pass + generator_mth_name = 'generate_' + name + ext.replace('.','_') + generator_mth = getattr(self, generator_mth_name, lambda : None) + body = generator_mth() + if body is not None: + return body + fn = os.path.join(self.srcdir,name+ext) + if os.path.isfile(fn): + f = open(fn,'r') + body = f.read() + f.close() + return body + self.warning('No such file: %r' % (fn)) + return + + def get_dependencies(self, code): + l = [] + for uses in re.findall(r'(?<=depends:)([,\w\s.]+)', code, re.I): + for use in uses.split(','): + use = use.strip() + if not use: continue + l.append(use) + return l + + def resolve_dependencies(self, parent, body): + assert isinstance(body, str),type(body) + for d in self.get_dependencies(body): + if d.endswith('.cpp'): + WrapperCPPMacro(parent, d[:-4]) + elif d.endswith('.c'): + WrapperCCode(parent, d[:-2]) + else: + self.warning('Unknown dependence: %r.' % (d)) + return + + def apply_attributes(self, template): + """ + Apply instance attributes to template string. + + Replace rules for attributes: + _list - will be joined with newline + _clist - _list will be joined with comma + _elist - _list will be joined + ..+.. - attributes will be added + [..] - will be evaluated + """ + replace_names = set(re.findall(r'[ ]*%\(.*?\)s', template)) + d = {} + for name in replace_names: + tab = ' ' * (len(name)-len(name.lstrip())) + name = name.lstrip()[2:-2] + names = name.split('+') + joinsymbol = '\n' + attrs = None + for n in names: + realname = n.strip() + if n.endswith('_clist'): + joinsymbol = ', ' + realname = realname[:-6] + '_list' + elif n.endswith('_elist'): + joinsymbol = '' + realname = realname[:-6] + '_list' + realname_lower = realname.lower() + parent = getattr(self,'parent',None) + if hasattr(self, realname): + attr = getattr(self, realname) + elif hasattr(self, realname_lower): + attr = getattr(self, realname_lower).upper() + elif hasattr(parent, realname): + attr = getattr(parent, realname) + elif hasattr(parent, realname_lower): + attr = getattr(parent, realname_lower).upper() + elif realname.startswith('['): + attr = eval(realname) + else: + self.warning('Undefined %r attribute: %r' % (self.__class__.__name__, realname)) + continue + if attrs is None: + attrs = attr + else: + attrs += attr + if isinstance(attrs, list): + attrs = joinsymbol.join(attrs) + d[name] = str(attrs).replace('\n','\n'+tab) + return template % d + + def apply_templates(self, child): + for n in self.list_names: + l = getattr(self,n + '_list') + c = child.apply_attributes(getattr(child, n+'_template','')) + if c: + l.append(c) + return + +class WrapperCPPMacro(WrapperBase): + """ + CPP macros + """ + def __init__(self, parent, name): + WrapperBase.__init__(self) + defined = parent.defined_cpp_code + if name in defined: + return + defined.append(name) + + body = self.get_resource_content(name,'.cpp') + if body is None: + self.warning('Failed to get CPP macro %r content.' % (name)) + return + self.resolve_dependencies(parent, body) + parent.header_list.append(body) + return + +class WrapperCCode(WrapperBase): + """ + C code + """ + def __init__(self, parent, name): + WrapperBase.__init__(self) + defined = parent.defined_c_code + if name in defined: + return + defined.append(name) + + body = self.get_resource_content(name,'.c') + if body is None: + self.warning('Failed to get C code %r content.' % (name)) + return + if isinstance(body, dict): + for k,v in body.items(): + self.resolve_dependencies(parent, v) + for k,v in body.items(): + l = getattr(parent,k+'_list') + l.append(v) + else: + self.resolve_dependencies(parent, body) + parent.c_code_list.append(body) + return + + def generate_pyobj_to_ctype_c(self, ctype): + from generate_pyobj_tofrom_funcs import pyobj_to_npy_scalar, pyobj_to_f2py_string + if ctype.startswith('npy_'): + return pyobj_to_npy_scalar(ctype) + elif ctype.startswith('f2py_string'): + return pyobj_to_f2py_string(ctype) + raise NotImplementedError,`ctype` + + def generate_pyobj_from_ctype_c(self, ctype): + from generate_pyobj_tofrom_funcs import pyobj_from_npy_scalar + if ctype.startswith('npy_'): + return pyobj_from_npy_scalar(ctype) + raise NotImplementedError,`ctype` |