Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
logging.debug('marking private symbol ' + node.name)
self.mod.private_symbols.append(node.name)
else:
# symbol should be marked as public if it's not already
if node.name not in self.mod.public_symbols:
logging.debug('marking public symbol ' + node.name)
self.mod.public_symbols.append(node.name)
else:
raise ValueError('bad default access %s for module %s' %
(self.mod.default_access, self.mod.name))
return node # no need to recurse further
class PrivateSymbolsRemover(FortranTransformer):
"""
Transform a tree by removing private symbols.
"""
def __init__(self):
self.mod = None
def visit_Module(self, mod):
# keep track of the current module
self.mod = mod
self.generic_visit(mod)
self.mod = None
def visit(self, node):
if self.mod is None:
return self.generic_visit(node)
def fix_argument_attributes(node):
"""
Walk over all procedures in the tree starting at `node` and
fix the argument attributes.
"""
for mod, sub, arguments in walk_procedures(node):
for arg in arguments:
if not hasattr(arg, 'type'):
arg.type = 'callback'
arg.value = ''
arg.attributes.append('callback')
return node
class LowerCaseConverter(FortranTransformer):
"""
Subclass of FortranTransformer which converts program, module,
procedure, interface, type and declaration names and attributes to
lower case. Original names are preserved in the *orig_name*
attribute.
"""
def visit_Program(self, node):
node.orig_name = node.name
node.name = node.name.lower()
return self.generic_visit(node)
def visit_Module(self, node):
node.orig_name = node.name
node.name = node.name.lower()
node.default_access = node.default_access.lower()
node.default_access = 'public'
if 'private' in node.attributes:
node.default_access = 'private'
node = self.generic_visit(node)
self.type = None
return node
def visit_Element(self, node):
if self.type is not None:
self.update_access(node, self.mod, self.type.default_access, in_type=True)
else:
self.update_access(node, self.mod, self.mod.default_access)
return node
class PrivateSymbolsRemover(ft.FortranTransformer):
"""
Transform a tree by removing private symbols
"""
def __init__(self):
self.mod = None
def visit_Module(self, mod):
# keep track of the current module
self.mod = mod
mod = self.generic_visit(mod)
self.mod = None
return mod
def visit_Procedure(self, node):
if self.mod is None:
node.orig_name = node.name
node.name = node.name.lower()
node.type = node.type.lower()
node.attributes = [a.lower() for a in node.attributes]
return self.generic_visit(node)
def strip_type(t):
"""Return type name from type declaration"""
t = t.replace(' ', '') # remove blanks
if t.startswith('type('):
t = t[t.index('(') + 1:t.index(')')]
if t.startswith('class('):
t = t[t.index('(') + 1:t.index(')')]
return t.lower()
class AccessUpdater(FortranTransformer):
"""Visit module contents and update public_symbols and
private_symbols lists to be consistent with (i) default module
access; (ii) public and private statements at module level;
(iii) public and private attibutes."""
def __init__(self):
self.mod = None
def visit_Module(self, mod):
# keep track of the current module
self.mod = mod
self.generic_visit(mod)
self.mod = None
def visit(self, node):
if self.mod is None:
def remove_private_symbols(node):
"""
Walk the tree starting at *node*, removing all private symbols.
This function first applies the AccessUpdater transformer to
ensure module *public_symbols* and *private_symbols* are up to
date with *default_access* and individual `public` and `private`
attributes.
"""
node = AccessUpdater().visit(node)
node = PrivateSymbolsRemover().visit(node)
return node
class UnwrappablesRemover(ft.FortranTransformer):
def __init__(self, callbacks, types, constructors, destructors, remove_optional_arguments):
self.callbacks = callbacks
self.types = types
self.constructors = constructors
self.destructors = destructors
self.remove_optional_arguments = remove_optional_arguments
def visit_Interface(self, node):
# don't wrap operator overloading routines
if node.name.startswith('operator('):
return None
return self.generic_visit(node)
def visit_Procedure(self, node):
# special case: keep all constructors and destructors, although
def collapse_single_interfaces(tree):
"""Collapse interfaces which contain only a single procedure."""
class _InterfaceCollapser(ft.FortranTransformer):
"""Replace interfaces with only one procedure by that procedure"""
def visit_Interface(self, node):
if len(node.procedures) == 1:
proc = node.procedures[0]
proc.doc = node.doc + proc.doc
logging.debug('collapsing single-component interface %s' % proc.name)
return proc
else:
return node
class _ProcedureRelocator(ft.FortranTransformer):
"""Filter interfaces and procedures into correct lists"""
def visit_Type(self, node):
logging.debug('visiting %r' % node)
if 'intent(out)' not in arg.attributes:
dummy_arg.f2py_line = ('!f2py intent(hide), depend(%s) :: %s = shape(%s,%d)' %
(arg.name, dummy_arg.name, arg.name, i))
new_dummy_args.append(dummy_arg)
new_ds.append(dummy_arg.name)
n_dummy += 1
if new_dummy_args != []:
logging.debug('adding dummy arguments %r to %s' % (new_dummy_args, node.name))
arg.attributes = ([attr for attr in arg.attributes if not attr.startswith('dimension')] +
['dimension(%s)' % ','.join(new_ds)])
node.arguments.extend(new_dummy_args)
class MethodFinder(ft.FortranTransformer):
def __init__(self, types, constructor_names, destructor_names, short_names,
move_methods, shorten_routine_names=True, modules_for_type=None):
self.types = types
self.constructor_names = constructor_names
self.destructor_names = destructor_names
self.short_names = short_names
self.move_methods = move_methods
self.shorten_routine_names = shorten_routine_names
self.modules_for_type = modules_for_type
def visit_Interface(self, node):
new_procs = []
for proc in node.procedures:
if isinstance(proc, ft.Procedure):
new_proc = self.visit_Procedure(proc, interface=node)
if new_proc is not None:
class ReorderOptionalArgumentsPython(ft.FortranVisitor):
"""
Move optional arguments after non-optional arguments:
in Fortran they can come in any order, but in Python
optional arguments must come at the end of argument list.
"""
def visit_Procedure(self, node):
non_optional = [arg for arg in node.arguments if 'optional' not in arg.attributes]
optional = [arg for arg in node.arguments if 'optional' in arg.attributes]
node.arguments = non_optional + optional
return node
class OnlyAndSkip(ft.FortranTransformer):
"""
This class does the job of removing nodes from the tree
which are not necessary to write wrappers for (given user-supplied
values for only and skip).
Currently it takes a list of subroutines and a list of modules to write
wrappers for. If empty, it does all of them.
"""
def __init__(self, kept_subs, kept_mods):
self.kept_subs = kept_subs
self.kept_mods = kept_mods
def visit_Procedure(self, node):
if len(self.kept_subs) > 0:
if node not in self.kept_subs:
[ft.Argument(name='this', # self.prefix + 'this' would probably be safer
filename=node.filename,
doc=['Object to be destructed'],
lineno=node.lineno,
attributes=['intent(inout)'],
type='type(%s)' % node.name)],
node.uses,
['destructor', 'skip_call'],
mod_name=node.mod_name,
type_name=node.name)
new_node.method_name = '__del__'
node.procedures.append(new_node)
return tree
class FunctionToSubroutineConverter(ft.FortranTransformer):
"""Convert all functions to subroutines, with return value as an
intent(out) argument after the last non-optional argument"""
def visit_Function(self, node):
# insert ret_val after last non-optional argument
arguments = node.arguments[:]
i = 0
for i, arg in enumerate(arguments):
if 'optional' in arg.attributes:
break
arguments.insert(i, node.ret_val)
arguments[i].name = 'ret_' + arguments[i].name
arguments[i].attributes.append('intent(out)')
new_node = ft.Subroutine(node.name,
node.doc,
node.lineno,
arguments,
node.uses,
node.attributes,
mod_name=node.mod_name)
if hasattr(node, 'call_name'):
new_node.call_name = node.call_name
if hasattr(node, 'type'):
new_node.type = node.type
new_node.orig_name = node.orig_name
new_node.orig_node = node # keep a reference to the original node
return new_node
class IntentOutToReturnValues(ft.FortranTransformer):
"""
Convert all Subroutine and Function intent(out) arguments to return values
"""
def visit_Procedure(self, node):
if 'constructor' in node.attributes:
node.arguments[0].attributes = set_intent(node.arguments[0].attributes,
'intent(out)')
ret_val = []
ret_val_doc = None
if isinstance(node, ft.Function) and node.ret_val is not None:
ret_val.append(node.ret_val)
if node.ret_val_doc is not None:
ret_val_doc = node.ret_val_doc