24 Defines a decorator to trace all function calling with arguments and results
25 and count number of calls and time spent
28 def wrapper(*args, **kwargs):
30 logger = logging.getLogger()
31 if logger.isEnabledFor(logging.DEBUG):
32 callstr = func.__name__ + \
33 '(' +
', '.join([str(a)
for a
in args] +
34 [k +
'=' + str(v)
for (k, v)
in kwargs.items()]) +
')'
35 logging.debug(
'%s --> ...', callstr)
40 if logger.isEnabledFor(logging.INFO):
46 result = func(*args, **kwargs)
51 if func.__name__
not in debugStats:
52 debugStats[func.__name__] = dict(nb=0, totalTime=0)
53 debugStats[func.__name__][
'nb'] += 1
54 duration = time.time() - t0
55 debugStats[func.__name__][
'totalTime'] += duration
56 debugStats[func.__name__][
'min'] = \
57 min(duration, debugStats[func.__name__].get(
'min', duration))
58 debugStats[func.__name__][
'max'] = \
59 max(duration, debugStats[func.__name__].get(
'max', duration))
62 if callstr
is not None:
64 logging.debug(
'%s --> %s', callstr, str(result))
72 Defines a decorator that prevent this method to be executed in parallel on several files
75 def wrapper(self, *args, **kwargs):
76 if self.NO_PARALLEL_LOCK
is not None:
78 with self.NO_PARALLEL_LOCK:
84 if self.SHARED_TREE
is not None:
85 self.tree.copyFromOtherTree(self.SHARED_TREE)
86 result = func(self, *args, **kwargs)
87 if self.SHARED_TREE
is not None:
88 self.tree.copyToOtherTree(self.SHARED_TREE)
91 return func(self, *args, **kwargs)
109 Print statistics on methods and function usage
111 logger = logging.getLogger()
112 if logger.isEnabledFor(logging.INFO):
113 def _print(name, nb, vmin, vmax, mean):
114 print(
'| ' + name.ljust(30) +
'| ' + str(nb).ljust(14) +
'| ' +
115 str(vmin).ljust(23) +
'| ' + str(vmax).ljust(23) +
'| ' +
116 str(mean).ljust(23) +
'|')
117 _print(
'Name of the function',
'# of calls',
'Min (s)',
'Max (s)',
'Total (s)')
118 for funcName, values
in debugStats.items():
119 _print(funcName, values[
'nb'], values[
'min'], values[
'max'], values[
'totalTime'])
131def fortran2xml(fortranSource, parserOptions=None, wrapH=False):
133 :param fortranSource: a string containing a fortran source code
135 :param parserOptions: dictionnary holding the parser options
136 :param wrapH: if True, content of .h file is put in a .F90 file (to force
137 fxtran to recognize it as free form) inside a module (to
138 enable the reading of files containing only a code part)
139 :returns: (includesRemoved, xml) where includesRemoved indicates if an include
140 was replaced by fxtran and xml is an ET xml document
143 ET.register_namespace(
'f', NAMESPACE)
146 if parserOptions
is None:
148 parserOptions = pyfortool.PYFT.DEFAULT_FXTRAN_OPTIONS
153 with tempfile.NamedTemporaryFile(buffering=0, suffix=
'.F90')
as file:
154 if os.path.exists(fortranSource):
158 filename = fortranSource
159 if wrapH
and filename.endswith(
'.h'):
162 with open(fortranSource,
'r', encoding=
'utf-8')
as src:
167 firstLine = [line
for line
in content.split(
'\n')
168 if not (re.search(
r'^[\t ]*!', line)
or
169 re.search(
r'^[\t ]*$', line))][0]
170 fisrtLine = firstLine.upper().split()
171 if not (
'SUBROUTINE' in fisrtLine
or 'FUNCTION' in firstLine):
174 content =
'MODULE FOO\n' + content +
'\nEND MODULE FOO'
175 file.write(content.encode(
'UTF8'))
178 file.write(fortranSource.encode(
'UTF-8'))
179 xml = pyfxtran.run(filename, [
'-o',
'-'] + parserOptions)
180 xml = ET.fromstring(xml, parser=ET.XMLParser(encoding=
'UTF-8'))
182 xml.find(
'./{*}file').attrib[
'name'] = fortranSource
184 file = xml.find(
'./{*}file')
185 programUnit = file.find(
'./{*}program-unit')
187 for node
in programUnit[1:-1]:
190 node.tail = node.tail[:-1]
191 file.remove(programUnit)
194 if len(set([
'-no-include',
'-noinclude']).intersection(parserOptions)) == 0:
201 includeStmts = xml.findall(
'.//{*}include')
202 for includeStmt
in includeStmts:
203 par = [p
for p
in xml.iter()
if includeStmt
in p][0]
204 par.remove(includeStmt)
207 mainfile = xml.find(
'./{*}file')
208 for file
in mainfile.findall(
'.//{*}file'):
209 par = [p
for p
in xml.iter()
if file
in p][0]
210 index = list(par).index(file)
211 if file.tail
is not None:
212 file[-1].tail = file.tail
if file[-1].tail
is None else (file[-1].tail + file.tail)
213 for node
in file[::-1]:
214 par.insert(index, node)
217 return includesDone, xml