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`
|