| Viewing file:  auxfuncs.py (22.17 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
#!/usr/bin/env python3"""
 
 Auxiliary functions for f2py2e.
 
 Copyright 1999,2000 Pearu Peterson all rights reserved,
 Pearu Peterson <pearu@ioc.ee>
 Permission to use, modify, and distribute this software is given under the
 terms of the NumPy (BSD style) LICENSE.
 
 
 NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
 $Date: 2005/07/24 19:01:55 $
 Pearu Peterson
 
 """
 import pprint
 import sys
 import types
 from functools import reduce
 
 from . import __version__
 from . import cfuncs
 
 __all__ = [
 'applyrules', 'debugcapi', 'dictappend', 'errmess', 'gentitle',
 'getargs2', 'getcallprotoargument', 'getcallstatement',
 'getfortranname', 'getpymethoddef', 'getrestdoc', 'getusercode',
 'getusercode1', 'hasbody', 'hascallstatement', 'hascommon',
 'hasexternals', 'hasinitvalue', 'hasnote', 'hasresultnote',
 'isallocatable', 'isarray', 'isarrayofstrings',
 'ischaracter', 'ischaracterarray', 'ischaracter_or_characterarray',
 'iscomplex',
 'iscomplexarray', 'iscomplexfunction', 'iscomplexfunction_warn',
 'isdouble', 'isdummyroutine', 'isexternal', 'isfunction',
 'isfunction_wrap', 'isint1', 'isint1array', 'isinteger', 'isintent_aux',
 'isintent_c', 'isintent_callback', 'isintent_copy', 'isintent_dict',
 'isintent_hide', 'isintent_in', 'isintent_inout', 'isintent_inplace',
 'isintent_nothide', 'isintent_out', 'isintent_overwrite', 'islogical',
 'islogicalfunction', 'islong_complex', 'islong_double',
 'islong_doublefunction', 'islong_long', 'islong_longfunction',
 'ismodule', 'ismoduleroutine', 'isoptional', 'isprivate', 'isrequired',
 'isroutine', 'isscalar', 'issigned_long_longarray', 'isstring',
 'isstringarray', 'isstring_or_stringarray', 'isstringfunction',
 'issubroutine',
 'issubroutine_wrap', 'isthreadsafe', 'isunsigned', 'isunsigned_char',
 'isunsigned_chararray', 'isunsigned_long_long',
 'isunsigned_long_longarray', 'isunsigned_short',
 'isunsigned_shortarray', 'l_and', 'l_not', 'l_or', 'outmess',
 'replace', 'show', 'stripcomma', 'throw_error', 'isattr_value'
 ]
 
 
 f2py_version = __version__.version
 
 
 errmess = sys.stderr.write
 show = pprint.pprint
 
 options = {}
 debugoptions = []
 wrapfuncs = 1
 
 
 def outmess(t):
 if options.get('verbose', 1):
 sys.stdout.write(t)
 
 
 def debugcapi(var):
 return 'capi' in debugoptions
 
 
 def _ischaracter(var):
 return 'typespec' in var and var['typespec'] == 'character' and \
 not isexternal(var)
 
 
 def _isstring(var):
 return 'typespec' in var and var['typespec'] == 'character' and \
 not isexternal(var)
 
 
 def ischaracter_or_characterarray(var):
 return _ischaracter(var) and 'charselector' not in var
 
 
 def ischaracter(var):
 return ischaracter_or_characterarray(var) and not isarray(var)
 
 
 def ischaracterarray(var):
 return ischaracter_or_characterarray(var) and isarray(var)
 
 
 def isstring_or_stringarray(var):
 return _ischaracter(var) and 'charselector' in var
 
 
 def isstring(var):
 return isstring_or_stringarray(var) and not isarray(var)
 
 
 def isstringarray(var):
 return isstring_or_stringarray(var) and isarray(var)
 
 
 def isarrayofstrings(var):  # obsolete?
 # leaving out '*' for now so that `character*(*) a(m)` and `character
 # a(m,*)` are treated differently. Luckily `character**` is illegal.
 return isstringarray(var) and var['dimension'][-1] == '(*)'
 
 
 def isarray(var):
 return 'dimension' in var and not isexternal(var)
 
 
 def isscalar(var):
 return not (isarray(var) or isstring(var) or isexternal(var))
 
 
 def iscomplex(var):
 return isscalar(var) and \
 var.get('typespec') in ['complex', 'double complex']
 
 
 def islogical(var):
 return isscalar(var) and var.get('typespec') == 'logical'
 
 
 def isinteger(var):
 return isscalar(var) and var.get('typespec') == 'integer'
 
 
 def isreal(var):
 return isscalar(var) and var.get('typespec') == 'real'
 
 
 def get_kind(var):
 try:
 return var['kindselector']['*']
 except KeyError:
 try:
 return var['kindselector']['kind']
 except KeyError:
 pass
 
 
 def isint1(var):
 return var.get('typespec') == 'integer' \
 and get_kind(var) == '1' and not isarray(var)
 
 
 def islong_long(var):
 if not isscalar(var):
 return 0
 if var.get('typespec') not in ['integer', 'logical']:
 return 0
 return get_kind(var) == '8'
 
 
 def isunsigned_char(var):
 if not isscalar(var):
 return 0
 if var.get('typespec') != 'integer':
 return 0
 return get_kind(var) == '-1'
 
 
 def isunsigned_short(var):
 if not isscalar(var):
 return 0
 if var.get('typespec') != 'integer':
 return 0
 return get_kind(var) == '-2'
 
 
 def isunsigned(var):
 if not isscalar(var):
 return 0
 if var.get('typespec') != 'integer':
 return 0
 return get_kind(var) == '-4'
 
 
 def isunsigned_long_long(var):
 if not isscalar(var):
 return 0
 if var.get('typespec') != 'integer':
 return 0
 return get_kind(var) == '-8'
 
 
 def isdouble(var):
 if not isscalar(var):
 return 0
 if not var.get('typespec') == 'real':
 return 0
 return get_kind(var) == '8'
 
 
 def islong_double(var):
 if not isscalar(var):
 return 0
 if not var.get('typespec') == 'real':
 return 0
 return get_kind(var) == '16'
 
 
 def islong_complex(var):
 if not iscomplex(var):
 return 0
 return get_kind(var) == '32'
 
 
 def iscomplexarray(var):
 return isarray(var) and \
 var.get('typespec') in ['complex', 'double complex']
 
 
 def isint1array(var):
 return isarray(var) and var.get('typespec') == 'integer' \
 and get_kind(var) == '1'
 
 
 def isunsigned_chararray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '-1'
 
 
 def isunsigned_shortarray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '-2'
 
 
 def isunsignedarray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '-4'
 
 
 def isunsigned_long_longarray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '-8'
 
 
 def issigned_chararray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '1'
 
 
 def issigned_shortarray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '2'
 
 
 def issigned_array(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '4'
 
 
 def issigned_long_longarray(var):
 return isarray(var) and var.get('typespec') in ['integer', 'logical']\
 and get_kind(var) == '8'
 
 
 def isallocatable(var):
 return 'attrspec' in var and 'allocatable' in var['attrspec']
 
 
 def ismutable(var):
 return not ('dimension' not in var or isstring(var))
 
 
 def ismoduleroutine(rout):
 return 'modulename' in rout
 
 
 def ismodule(rout):
 return 'block' in rout and 'module' == rout['block']
 
 
 def isfunction(rout):
 return 'block' in rout and 'function' == rout['block']
 
 
 def isfunction_wrap(rout):
 if isintent_c(rout):
 return 0
 return wrapfuncs and isfunction(rout) and (not isexternal(rout))
 
 
 def issubroutine(rout):
 return 'block' in rout and 'subroutine' == rout['block']
 
 
 def issubroutine_wrap(rout):
 if isintent_c(rout):
 return 0
 return issubroutine(rout) and hasassumedshape(rout)
 
 def isattr_value(var):
 return 'value' in var.get('attrspec', [])
 
 
 def hasassumedshape(rout):
 if rout.get('hasassumedshape'):
 return True
 for a in rout['args']:
 for d in rout['vars'].get(a, {}).get('dimension', []):
 if d == ':':
 rout['hasassumedshape'] = True
 return True
 return False
 
 
 def requiresf90wrapper(rout):
 return ismoduleroutine(rout) or hasassumedshape(rout)
 
 
 def isroutine(rout):
 return isfunction(rout) or issubroutine(rout)
 
 
 def islogicalfunction(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return islogical(rout['vars'][a])
 return 0
 
 
 def islong_longfunction(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return islong_long(rout['vars'][a])
 return 0
 
 
 def islong_doublefunction(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return islong_double(rout['vars'][a])
 return 0
 
 
 def iscomplexfunction(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return iscomplex(rout['vars'][a])
 return 0
 
 
 def iscomplexfunction_warn(rout):
 if iscomplexfunction(rout):
 outmess("""\
 **************************************************************
 Warning: code with a function returning complex value
 may not work correctly with your Fortran compiler.
 When using GNU gcc/g77 compilers, codes should work
 correctly for callbacks with:
 f2py -c -DF2PY_CB_RETURNCOMPLEX
 **************************************************************\n""")
 return 1
 return 0
 
 
 def isstringfunction(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return isstring(rout['vars'][a])
 return 0
 
 
 def hasexternals(rout):
 return 'externals' in rout and rout['externals']
 
 
 def isthreadsafe(rout):
 return 'f2pyenhancements' in rout and \
 'threadsafe' in rout['f2pyenhancements']
 
 
 def hasvariables(rout):
 return 'vars' in rout and rout['vars']
 
 
 def isoptional(var):
 return ('attrspec' in var and 'optional' in var['attrspec'] and
 'required' not in var['attrspec']) and isintent_nothide(var)
 
 
 def isexternal(var):
 return 'attrspec' in var and 'external' in var['attrspec']
 
 
 def isrequired(var):
 return not isoptional(var) and isintent_nothide(var)
 
 
 def isintent_in(var):
 if 'intent' not in var:
 return 1
 if 'hide' in var['intent']:
 return 0
 if 'inplace' in var['intent']:
 return 0
 if 'in' in var['intent']:
 return 1
 if 'out' in var['intent']:
 return 0
 if 'inout' in var['intent']:
 return 0
 if 'outin' in var['intent']:
 return 0
 return 1
 
 
 def isintent_inout(var):
 return ('intent' in var and ('inout' in var['intent'] or
 'outin' in var['intent']) and 'in' not in var['intent'] and
 'hide' not in var['intent'] and 'inplace' not in var['intent'])
 
 
 def isintent_out(var):
 return 'out' in var.get('intent', [])
 
 
 def isintent_hide(var):
 return ('intent' in var and ('hide' in var['intent'] or
 ('out' in var['intent'] and 'in' not in var['intent'] and
 (not l_or(isintent_inout, isintent_inplace)(var)))))
 
 
 def isintent_nothide(var):
 return not isintent_hide(var)
 
 
 def isintent_c(var):
 return 'c' in var.get('intent', [])
 
 
 def isintent_cache(var):
 return 'cache' in var.get('intent', [])
 
 
 def isintent_copy(var):
 return 'copy' in var.get('intent', [])
 
 
 def isintent_overwrite(var):
 return 'overwrite' in var.get('intent', [])
 
 
 def isintent_callback(var):
 return 'callback' in var.get('intent', [])
 
 
 def isintent_inplace(var):
 return 'inplace' in var.get('intent', [])
 
 
 def isintent_aux(var):
 return 'aux' in var.get('intent', [])
 
 
 def isintent_aligned4(var):
 return 'aligned4' in var.get('intent', [])
 
 
 def isintent_aligned8(var):
 return 'aligned8' in var.get('intent', [])
 
 
 def isintent_aligned16(var):
 return 'aligned16' in var.get('intent', [])
 
 
 isintent_dict = {isintent_in: 'INTENT_IN', isintent_inout: 'INTENT_INOUT',
 isintent_out: 'INTENT_OUT', isintent_hide: 'INTENT_HIDE',
 isintent_cache: 'INTENT_CACHE',
 isintent_c: 'INTENT_C', isoptional: 'OPTIONAL',
 isintent_inplace: 'INTENT_INPLACE',
 isintent_aligned4: 'INTENT_ALIGNED4',
 isintent_aligned8: 'INTENT_ALIGNED8',
 isintent_aligned16: 'INTENT_ALIGNED16',
 }
 
 
 def isprivate(var):
 return 'attrspec' in var and 'private' in var['attrspec']
 
 
 def hasinitvalue(var):
 return '=' in var
 
 
 def hasinitvalueasstring(var):
 if not hasinitvalue(var):
 return 0
 return var['='][0] in ['"', "'"]
 
 
 def hasnote(var):
 return 'note' in var
 
 
 def hasresultnote(rout):
 if not isfunction(rout):
 return 0
 if 'result' in rout:
 a = rout['result']
 else:
 a = rout['name']
 if a in rout['vars']:
 return hasnote(rout['vars'][a])
 return 0
 
 
 def hascommon(rout):
 return 'common' in rout
 
 
 def containscommon(rout):
 if hascommon(rout):
 return 1
 if hasbody(rout):
 for b in rout['body']:
 if containscommon(b):
 return 1
 return 0
 
 
 def containsmodule(block):
 if ismodule(block):
 return 1
 if not hasbody(block):
 return 0
 for b in block['body']:
 if containsmodule(b):
 return 1
 return 0
 
 
 def hasbody(rout):
 return 'body' in rout
 
 
 def hascallstatement(rout):
 return getcallstatement(rout) is not None
 
 
 def istrue(var):
 return 1
 
 
 def isfalse(var):
 return 0
 
 
 class F2PYError(Exception):
 pass
 
 
 class throw_error:
 
 def __init__(self, mess):
 self.mess = mess
 
 def __call__(self, var):
 mess = '\n\n  var = %s\n  Message: %s\n' % (var, self.mess)
 raise F2PYError(mess)
 
 
 def l_and(*f):
 l1, l2 = 'lambda v', []
 for i in range(len(f)):
 l1 = '%s,f%d=f[%d]' % (l1, i, i)
 l2.append('f%d(v)' % (i))
 return eval('%s:%s' % (l1, ' and '.join(l2)))
 
 
 def l_or(*f):
 l1, l2 = 'lambda v', []
 for i in range(len(f)):
 l1 = '%s,f%d=f[%d]' % (l1, i, i)
 l2.append('f%d(v)' % (i))
 return eval('%s:%s' % (l1, ' or '.join(l2)))
 
 
 def l_not(f):
 return eval('lambda v,f=f:not f(v)')
 
 
 def isdummyroutine(rout):
 try:
 return rout['f2pyenhancements']['fortranname'] == ''
 except KeyError:
 return 0
 
 
 def getfortranname(rout):
 try:
 name = rout['f2pyenhancements']['fortranname']
 if name == '':
 raise KeyError
 if not name:
 errmess('Failed to use fortranname from %s\n' %
 (rout['f2pyenhancements']))
 raise KeyError
 except KeyError:
 name = rout['name']
 return name
 
 
 def getmultilineblock(rout, blockname, comment=1, counter=0):
 try:
 r = rout['f2pyenhancements'].get(blockname)
 except KeyError:
 return
 if not r:
 return
 if counter > 0 and isinstance(r, str):
 return
 if isinstance(r, list):
 if counter >= len(r):
 return
 r = r[counter]
 if r[:3] == "'''":
 if comment:
 r = '\t/* start ' + blockname + \
 ' multiline (' + repr(counter) + ') */\n' + r[3:]
 else:
 r = r[3:]
 if r[-3:] == "'''":
 if comment:
 r = r[:-3] + '\n\t/* end multiline (' + repr(counter) + ')*/'
 else:
 r = r[:-3]
 else:
 errmess("%s multiline block should end with `'''`: %s\n"
 % (blockname, repr(r)))
 return r
 
 
 def getcallstatement(rout):
 return getmultilineblock(rout, 'callstatement')
 
 
 def getcallprotoargument(rout, cb_map={}):
 r = getmultilineblock(rout, 'callprotoargument', comment=0)
 if r:
 return r
 if hascallstatement(rout):
 outmess(
 'warning: callstatement is defined without callprotoargument\n')
 return
 from .capi_maps import getctype
 arg_types, arg_types2 = [], []
 if l_and(isstringfunction, l_not(isfunction_wrap))(rout):
 arg_types.extend(['char*', 'size_t'])
 for n in rout['args']:
 var = rout['vars'][n]
 if isintent_callback(var):
 continue
 if n in cb_map:
 ctype = cb_map[n] + '_typedef'
 else:
 ctype = getctype(var)
 if l_and(isintent_c, l_or(isscalar, iscomplex))(var):
 pass
 elif isstring(var):
 pass
 else:
 if not isattr_value(var):
 ctype = ctype + '*'
 if ((isstring(var)
 or isarrayofstrings(var)  # obsolete?
 or isstringarray(var))):
 arg_types2.append('size_t')
 arg_types.append(ctype)
 
 proto_args = ','.join(arg_types + arg_types2)
 if not proto_args:
 proto_args = 'void'
 return proto_args
 
 
 def getusercode(rout):
 return getmultilineblock(rout, 'usercode')
 
 
 def getusercode1(rout):
 return getmultilineblock(rout, 'usercode', counter=1)
 
 
 def getpymethoddef(rout):
 return getmultilineblock(rout, 'pymethoddef')
 
 
 def getargs(rout):
 sortargs, args = [], []
 if 'args' in rout:
 args = rout['args']
 if 'sortvars' in rout:
 for a in rout['sortvars']:
 if a in args:
 sortargs.append(a)
 for a in args:
 if a not in sortargs:
 sortargs.append(a)
 else:
 sortargs = rout['args']
 return args, sortargs
 
 
 def getargs2(rout):
 sortargs, args = [], rout.get('args', [])
 auxvars = [a for a in rout['vars'].keys() if isintent_aux(rout['vars'][a])
 and a not in args]
 args = auxvars + args
 if 'sortvars' in rout:
 for a in rout['sortvars']:
 if a in args:
 sortargs.append(a)
 for a in args:
 if a not in sortargs:
 sortargs.append(a)
 else:
 sortargs = auxvars + rout['args']
 return args, sortargs
 
 
 def getrestdoc(rout):
 if 'f2pymultilines' not in rout:
 return None
 k = None
 if rout['block'] == 'python module':
 k = rout['block'], rout['name']
 return rout['f2pymultilines'].get(k, None)
 
 
 def gentitle(name):
 ln = (80 - len(name) - 6) // 2
 return '/*%s %s %s*/' % (ln * '*', name, ln * '*')
 
 
 def flatlist(lst):
 if isinstance(lst, list):
 return reduce(lambda x, y, f=flatlist: x + f(y), lst, [])
 return [lst]
 
 
 def stripcomma(s):
 if s and s[-1] == ',':
 return s[:-1]
 return s
 
 
 def replace(str, d, defaultsep=''):
 if isinstance(d, list):
 return [replace(str, _m, defaultsep) for _m in d]
 if isinstance(str, list):
 return [replace(_m, d, defaultsep) for _m in str]
 for k in 2 * list(d.keys()):
 if k == 'separatorsfor':
 continue
 if 'separatorsfor' in d and k in d['separatorsfor']:
 sep = d['separatorsfor'][k]
 else:
 sep = defaultsep
 if isinstance(d[k], list):
 str = str.replace('#%s#' % (k), sep.join(flatlist(d[k])))
 else:
 str = str.replace('#%s#' % (k), d[k])
 return str
 
 
 def dictappend(rd, ar):
 if isinstance(ar, list):
 for a in ar:
 rd = dictappend(rd, a)
 return rd
 for k in ar.keys():
 if k[0] == '_':
 continue
 if k in rd:
 if isinstance(rd[k], str):
 rd[k] = [rd[k]]
 if isinstance(rd[k], list):
 if isinstance(ar[k], list):
 rd[k] = rd[k] + ar[k]
 else:
 rd[k].append(ar[k])
 elif isinstance(rd[k], dict):
 if isinstance(ar[k], dict):
 if k == 'separatorsfor':
 for k1 in ar[k].keys():
 if k1 not in rd[k]:
 rd[k][k1] = ar[k][k1]
 else:
 rd[k] = dictappend(rd[k], ar[k])
 else:
 rd[k] = ar[k]
 return rd
 
 
 def applyrules(rules, d, var={}):
 ret = {}
 if isinstance(rules, list):
 for r in rules:
 rr = applyrules(r, d, var)
 ret = dictappend(ret, rr)
 if '_break' in rr:
 break
 return ret
 if '_check' in rules and (not rules['_check'](var)):
 return ret
 if 'need' in rules:
 res = applyrules({'needs': rules['need']}, d, var)
 if 'needs' in res:
 cfuncs.append_needs(res['needs'])
 
 for k in rules.keys():
 if k == 'separatorsfor':
 ret[k] = rules[k]
 continue
 if isinstance(rules[k], str):
 ret[k] = replace(rules[k], d)
 elif isinstance(rules[k], list):
 ret[k] = []
 for i in rules[k]:
 ar = applyrules({k: i}, d, var)
 if k in ar:
 ret[k].append(ar[k])
 elif k[0] == '_':
 continue
 elif isinstance(rules[k], dict):
 ret[k] = []
 for k1 in rules[k].keys():
 if isinstance(k1, types.FunctionType) and k1(var):
 if isinstance(rules[k][k1], list):
 for i in rules[k][k1]:
 if isinstance(i, dict):
 res = applyrules({'supertext': i}, d, var)
 if 'supertext' in res:
 i = res['supertext']
 else:
 i = ''
 ret[k].append(replace(i, d))
 else:
 i = rules[k][k1]
 if isinstance(i, dict):
 res = applyrules({'supertext': i}, d)
 if 'supertext' in res:
 i = res['supertext']
 else:
 i = ''
 ret[k].append(replace(i, d))
 else:
 errmess('applyrules: ignoring rule %s.\n' % repr(rules[k]))
 if isinstance(ret[k], list):
 if len(ret[k]) == 1:
 ret[k] = ret[k][0]
 if ret[k] == []:
 del ret[k]
 return ret
 
 |