def format_doc_string(node): """ Generate Python docstring from Fortran docstring and call signature """ def _format_line_no(lineno): """ Format Fortran source code line numbers FIXME could link to source repository (e.g. github) """ if isinstance(lineno, slice): return 'lines %d-%d' % (lineno.start, lineno.stop - 1) else: return 'line %d' % lineno doc = [format_call_signature(node), ''] doc.append('') doc.append('Defined at %s %s' % (node.filename, _format_line_no(node.lineno))) if isinstance(node, ft.Procedure): # For procedures, write parameters and return values in numpydoc format doc.append('') # Input parameters for i, arg in enumerate(node.arguments): pytype = ft.f2py_type(arg.type, arg.attributes) if i == 0: doc.append("Parameters") doc.append("----------") doc.append("%s : %s" % (arg.name, pytype)) if arg.doc: for d in arg.doc: doc.append("\t%s" % d) doc.append("") if isinstance(node, ft.Function): for i, arg in enumerate(node.ret_val): pytype = ft.f2py_type(arg.type, arg.attributes) if i == 0: doc.append("") doc.append("Returns") doc.append("-------") doc.append("%s : %s" % (arg.name, pytype)) if arg.doc: for d in arg.doc: doc.append("\t%s" % d) doc.append("") elif isinstance(node, ft.Interface): # for interfaces, list the components doc.append('') doc.append('Overloaded interface containing the following procedures:') for proc in node.procedures: doc.append(' %s' % (hasattr(proc, 'method_name') and proc.method_name or proc.name)) doc += [''] + node.doc[:] # incoming docstring from Fortran source return '\n'.join(['"""'] + doc + ['"""'])
def format_call_signature(node): if isinstance(node, ft.Procedure): sig = '' if isinstance(node, ft.Function): sig += ', '.join(ret_val.py_name for ret_val in node.ret_val) sig += ' = ' if 'constructor' in node.attributes: sig += node.type_name.title() elif 'destructor' in node.attributes: return 'Destructor for class %s' % node.type_name.title() else: if hasattr(node, 'method_name'): sig += node.method_name else: sig += node.name sig += '(' had_optional = False for i, arg in enumerate(node.arguments): if not had_optional and 'optional' in arg.attributes: sig += '[' had_optional = True if i != 0: sig += ', ' sig += arg.py_name if had_optional: sig += ']' sig += ')' return sig elif isinstance(node, ft.Module): return 'Module %s' % node.name elif isinstance(node, ft.Element): return ('Element %s ftype=%s pytype=%s' % (node.name, node.type, ft.f2py_type(node.type))) else: return str(node)
def format_call_signature(node): if isinstance(node, ft.Procedure): sig = '' if isinstance(node, ft.Function): sig += ', '.join(ret_val.py_name for ret_val in node.ret_val) sig += ' = ' if 'constructor' in node.attributes: sig += node.type_name.title() elif 'destructor' in node.attributes: return 'Destructor for class %s' % node.type_name.title() else: if hasattr(node, 'method_name'): sig += node.method_name else: sig += node.name sig += '(' had_optional = False for i, arg in enumerate(node.arguments): if not had_optional and 'optional' in arg.attributes: sig += '[' had_optional = True if i != 0: sig += ', ' sig += arg.py_name if had_optional: sig += ']' sig += ')' rex = re.compile(r'\s+') # collapse multiple whitespace sig = rex.sub(' ', sig) return sig elif isinstance(node, ft.Module): return 'Module %s' % node.name elif isinstance(node, ft.Element): return ('Element %s ftype=%s pytype=%s' % (node.name, node.type, ft.f2py_type(node.type))) elif isinstance(node, ft.Interface): if hasattr(node, 'method_name'): name = node.method_name else: name = node.name return '%s(*args, **kwargs)' % name else: return str(node)