Skip to content

Instantly share code, notes, and snippets.

@josef-pkt
Last active December 22, 2015 05:49
Show Gist options
  • Save josef-pkt/6426618 to your computer and use it in GitHub Desktop.
Save josef-pkt/6426618 to your computer and use it in GitHub Desktop.
parsing Fortran docstrings
# -*- coding: utf-8 -*-
"""Parsing the Fortran files to create raw docstrings
Created on Tue Sep 03 10:11:10 2013
Author: Josef Perktold
open problems
cumnor.f doesn't define segment headers besides "Function"
"""
import os
from collections import defaultdict
import textwrap
def reformat(s):
# remove duplicate spaces
for i in range(6):
s = s.replace(' ', ' ')
return textwrap.fill(s, 66)
template_arg = '''\
%s : array_like
%s
'''
template = '''\
%(signature)s
%(short)s
%(long)s
Parameters
----------
%(Parameters)s
Returns
-------
%(Returns)s
Notes
-----
%(Notes)s
'''
def fdocstring(filepath):
lines = file(filepath).readlines()
header = lines[0].strip()
description = []
# get docstring at beginning of file
section = 0
for line in lines[2:]:
#if line == sep:
if line.startswith('C********'):
section += 1
continue
if section == 0:
description.append(line[1:])
# get separate segments in docstring
segments = defaultdict(list)
section = 'start'
for line in description[1:]:
if len(line.strip()) == 0:
continue
if ' Function' in line:
section = 'func'
elif ' Arguments' in line:
section = 'args'
elif ' Method' in line:
section = 'method'
elif ' Variables' in line:
section = 'ignore'
segments[section].append(line[1:].strip(' '))
# for debugging
print_seg = False
if print_seg:
for seg in segments:
print '\n'
print seg
print ''.join(segments[seg])
# process Arguments
import re
expr_in = re.compile('(.*)-->(.*)')
expr_out = re.compile('(.*)<--(.*)')
expr_inout = re.compile('(.*)<.*-->(.*)')
argsli = []
argdesc = []
inout = ''
argname = ''
for line in segments['args']:
if len(line.strip()) == 0:
continue
if '<-->' in line or '< -->' in line:
# need to check this first or it will be captured by -->
# '< -->' is typo in cdff.f
#TODO: in or out or both ? depends on case
argsli.append((inout, argname, '\n'.join(argdesc)))
inout = 'inout'
res = expr_inout.match(line).groups()
argname = res[0].strip().lower()
argdesc = [' '*4 + res[1].strip(' ')]
elif '-->' in line:
argsli.append((inout, argname, '\n'.join(argdesc)))
inout = 'in'
res = expr_in.match(line).groups()
argname = res[0].strip().lower()
argdesc = [' '*4 + res[1].strip(' ')]
elif '<--' in line:
argsli.append((inout, argname, '\n'.join(argdesc)))
inout = 'out'
res = expr_out.match(line).groups()
argname = res[0].strip().lower()
argdesc = [' '*4 + res[1].strip(' ')]
else:
# don't add comment about return precision
if not 'PREC' in line:
argdesc.append(' '*4 + line.strip())
argsli.append((inout, argname, '\n'.join(argdesc))) # finish last args
del argsli[0] # remove initialization, could be cleaned up
# build docstring
docstring = {}
docstring['signature'] = header.split(' ')[1].replace(',', ', ')
if len(segments['start']) > 1:
docstring['short'] = reformat(''.join(segments['start'][1:]))
else:
docstring['short'] = ''
docstring['long'] = reformat(''.join(segments['func'][1:]))
docstring['Notes'] = reformat(''.join(segments['method'][1:]))
docstring['Parameters'] = ''
docstring['Returns'] = ''
for i in argsli:
if i[0] == 'in':
# string concatenation but short loop
docstring['Parameters'] += template_arg % i[1:]# + '\n'
elif i[0] == 'out':
# string concatenation but short loop
docstring['Returns'] += template_arg % i[1:]# + '\n'
elif i[0] == 'inout':
# string concatenation but short loop
docstring['Parameters'] += template_arg % i[1:]# + '\n'
docstring['Returns'] += template_arg % i[1:]# + '\n'
return template % docstring
root = r'<path to\scipy\scipy\special\cdflib'
names = ['cumchn.f', 'cumtnc.f']
#names = [os.path.join(root, ffile) for ffile in names]
use_glob = True
if use_glob:
import glob
names = glob.glob(root+'/c*.f')
for ffile in names:
fn = os.path.join(root, ffile) #redundant for glob with full path
print '#################'
print fdocstring(fn)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment