Newer
Older
#!/usr/bin/env python
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""Script that will grab doxygen strings from a
.cpp file and stuff them in the corresponding
.sip file under a %Docstring tag"""
import os
import sys
from optparse import OptionParser
#----------------------------------------------------------
def findInSubdirectory(filename, subdirectory=''):
if subdirectory:
path = subdirectory
else:
path = os.getcwd()
for root, dirs, names in os.walk(path):
if filename in names:
return os.path.join(root, filename)
raise 'File not found'
def find_cpp_file(basedir, classname):
return findInSubdirectory(classname + ".cpp", basedir)
#----------------------------------------------------------
def grab_doxygen(cppfile, method):
"""Grab the DOXYGEN documentation string from a .cpp file
cppfile :: full path to the .cpp file
method :: method definition to look for
"""
lines = open(cppfile, 'r').read().split('\n')
#print method
out = []
for i in range(len(lines)):
line = lines[i].strip()
if line.startswith(method):
# Go backwards above the class to grab the doxygen
for j in range(i-1, -1, -1):
out.insert(0, lines[j])
# Stop when you reach the start of the comment "/**"
if lines[j].strip().startswith('/**'):
break
# OK return the lines
return out
print "WARNING: Could not find method %s" % method
return None
#----------------------------------------------------------
def doxygen_to_docstring(doxygen, method):
""" Takes an array of DOXYGEN lines, and converts
them to a more pleasing python docstring format
@param doxygen :: list of strings contaning the doxygen
@param method :: method declaration string """
out = []
if doxygen is None:
return out
out.append("%Docstring")
out.append(method)
out.append('-' * len(method))
for line in doxygen:
line = line.strip()
if line.startswith("/**"): line = line[3:]
if line.endswith("*/"): line = line[:-2]
if line.startswith("*"): line = line[1:]
# Make the text indented by 4 spaces
line = " " + line
out.append(line)
out.append("%End")
out.append("")
return out
#----------------------------------------------------------
def process_sip(filename):
""" Reads an input .sip file and finds methods from
classes. Retrieves doxygen and adds them as
docstrings """
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
root = os.path.split(os.path.abspath(filename))[0]
# Read and split into a buncha lines
lines = open(filename, 'r').read().split('\n')
i = 0
classname = ''
classcpp = ''
outlines = []
for i in range(len(lines)):
# Copy to output
outlines.append(lines[i])
line = lines[i].strip()
if line.startswith("class "):
classname = line[6:].strip()
n = classname.find(':')
if n > 0: classname = classname[0:n].strip()
# Now, we look for the .cpp file
classcpp = find_cpp_file(root, classname)
print "Found class '%s' at %s" % (classname, classcpp)
if classname != "":
# We are within a real class
if line.endswith(";"):
# Within a function declaration
n = line.find(')')
if n > 0:
method = line[0:n+1]
n = method.find(' ')
# Make the string like this:
# "void ClassName::method(arguments)"
method = method[0:n+1] + classname + "::" + method[n+1:]
# Now extract the doxygen
doxygen = grab_doxygen(classcpp, method)
# Convert to a docstring
docstring = doxygen_to_docstring(doxygen, method)
# And add to the output
outlines += docstring
# Give back the generated lines
return outlines
#----------------------------------------------------------
if __name__=="__main__":
parser = OptionParser(description=
"""Automatically adds Docstring directives to an input .sip file.
REQUIREMENTS:
- All method declarations in the sip file must be on one line.
- The cpp file must be = to ClassName.cpp
- The method declaration must match exactly the sip entry.
- The Doxygen must be just before the method in the .cpp file.
""")
parser.add_option('-i', metavar='SIPFILE', dest="sipfile",
help='The .sip input file')
parser.add_option('-o', metavar='OUTPUTFILE', dest="outputfile",
help='The name of the output file')
(options, args) = parser.parse_args()
if options.sipfile is None:
raise Exception("Must specify an input file with -i !")
if options.outputfile is None:
raise Exception("Must specify an output file with -o !")
print "---- Reading from %s ---- " % options.sipfile
out = process_sip(options.sipfile)
if not (options.outputfile is None):
print "---- Writing to %s ---- " % options.outputfile
f = open(options.outputfile, 'w')
f.write('\n'.join(out))
f.close()