File: GenerateDoc.py

package info (click to toggle)
simpleitk 1.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 75,056 kB
  • sloc: cpp: 25,403; python: 3,060; sh: 1,131; ansic: 369; java: 260; cs: 215; makefile: 51; ruby: 47; tcl: 22
file content (240 lines) | stat: -rwxr-xr-x 6,655 bytes parent folder | download
1
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
75
76
77
78
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#!/usr/bin/env python

from __future__ import print_function
import os, sys, io, json, re
import xml.etree.ElementTree as ET
from collections import OrderedDict


#
#  This script updates the documentation of a SimpleITK class in its
#  JSON file.  The documentation is pulled from the correpsonding ITK
#  class XML file.  The SimpleITKClass.json file is modified in place.
#
#  The script is a re-write of the GenerateDocumentation.groovy script in python.
#
#  usage: GenerateDoc.py <SimpleITKClass.json> <Path/To/ITK-build/With/Doxygen>
#

if len(sys.argv) != 3:
    print("usage: GenerateDoc.py <SimpleITKClass.json> <Path/To/ITK-build/With/Doxygen>\n")

sitk_json = sys.argv[1]
itk_path  = sys.argv[2]

blue_text = "\033[0;34m"
end_color = "\033[0m"

# Load the JSON file
with open(sitk_json, "r") as fp:
  json_obj = json.load(fp, object_pairs_hook=OrderedDict)

#print(json.dumps(json_obj, indent=1))


itk_name = ''
if 'itk_name' in json_obj:
  itk_name = json_obj['itk_name']

name = ''
if 'name' in json_obj:
  name = json_obj['name']

template_code_filename = ''
if 'template_code_filename' in json_obj:
  template_code_filename = json_obj['template_code_filename']

  XMLFileOptions = ["classitk_1_1" + itk_name + ".xml",
                    "classitk_1_1" + name + template_code_filename + ".xml",
                    "classitk_1_1" + name + ".xml"]
#print( XMLFileOptions )


# Find the XML file
XMLFile = None
for xf in XMLFileOptions:
  xname = itk_path + '/' + xf
  if os.path.isfile(xname):
    try:
      XMLFile = io.open(xname, "r")
      print("xml file: ", xname)
    except:
      XMLFile = None
      print("no xml file: ", xname)

if not XMLFile:
  print( "Tried to read a file for " + name)
  print(XMLFileOptions)
  sys.exit ( 1 )


# Load the XML file
tree = ET.parse(XMLFile)
root = tree.getroot()


#
# traverse an XML subtree to produced a formated description string
#
def traverseXML( xml_node, depth=0, Debug=False ):
  result = ""
  prefix = { 'listitem' : "\\li ",
             'itemizedlist' : "\n",
             'computeroutput' : " ",
             'programlisting' : "\\code\n"}
  postfix = { 'para' : "\n\n",
              'title' : "\n",
              'computeroutput' : " ",
              'ref' : " ",
              'ulink' : " ",
              'codeline' : "\n",
              'programlisting' : "\\endcode\n",
              'sp' : " "}
  if Debug:
    print( "\nNode: ", xml_node )
    for i in range(depth):
      sys.stdout.write("  ")
    print( xml_node.tag, ": ", xml_node.attrib, xml_node.text)

  # handle simplesection nodes (particularly See nodes)
  if xml_node.tag == 'simplesect':
    if xml_node.attrib['kind'] == 'see':
      for child in xml_node:
        child_desc = traverseXML( child, depth+1 )
        if (len(child_desc)):
          result = result + "\\see " + child_desc + "\n"
          if Debug:
            print("See result: ", repr(result))
      return result
    else:
      result = result + "\\" + xml_node.attrib['kind'] + " "

  # iterate through the children
  for child in xml_node:
    if Debug:
      print ("Child: ", child, child.text)
    result = result + traverseXML(child, depth+1 )

  text = xml_node.text

  # handle formula nodes
  if xml_node.tag == 'formula':
    if Debug:
      print(blue_text, "\nFormula", end_color)
      print(text)
    text = text.replace("\[", " \\f[", 1)
    text = text.replace( "\\]", "\\f] " )
    text = text.replace( "$", "\\f$" ) +  " "
    if Debug:
      print(text)


  # add the prefix and postfixes
  if xml_node.tag in prefix:
    result = prefix[xml_node.tag] + result
  if text != None:
    result = text + result
  if xml_node.tag in postfix:
    result = result + postfix[xml_node.tag]
  if xml_node.tail:
    result = result + xml_node.tail

  # finished
  if Debug:
    for i in range(depth):
      sys.stdout.write("  ")
    print ("result: ", repr(result))

  return result


# Call the recursive XML traversal function, then clean up some white space
def formatDescription( xml_node ):
  result = traverseXML( xml_node )
  result = result.replace("\n\n\n", "\n\n")
  result = re.sub( ' +', ' ', result)
  result = result.strip()
  return result


# Class brief description
briefdesc = root.find( './compounddef/briefdescription' )
# Class detailed description
detaileddesc = root.find( './compounddef/detaileddescription' )



#
# Set the class detailed description in the JSON to the formated text from the XML tree
#
json_obj['detaileddescription'] = formatDescription(detaileddesc)
print ( blue_text, "\nDetailed description\n", end_color, repr(json_obj['detaileddescription']) )

#
# Set the class brief description in the JSON to the formated text from the XML tree
#
json_obj['briefdescription'] = formatDescription(briefdesc)
print ( blue_text, "\nBrief description\n", end_color, repr(json_obj['briefdescription']) )


#
# Build a dict of class member functions in the XML
#
member_dict = {}
print ( blue_text, "\nBuilding XML member function dict\n", end_color )
for m in root.findall("./compounddef/sectiondef/memberdef[@kind='function']"):
  name_node = m.find("./name")
  if name_node != None:
    print (name_node.text, " : ", repr(m))
    member_dict[name_node.text] = m


#
# Loop through the class members and measurements in the JSON
#
print ( blue_text, "\nJSON class members and measurements\n", end_color )
obj_list = []

# Create a list of members and measurements
if 'members' in json_obj:
  obj_list = obj_list + json_obj['members']
if 'measurements' in json_obj:
  obj_list = obj_list + json_obj['measurements']


for m in obj_list:
  name = m['name']
  print( blue_text, name, end_color )

  # Iterate through the possible prefixes
  for prefix in [ "", "Set", "Get" ]:
    funcname = prefix+name

    if funcname in member_dict:
      # find the item in the XML that corresponds to the JSON member function
      m_xml = member_dict[funcname]
      print (funcname, repr(m_xml))

      # pull the brief and detailed descriptions from the XML to the JSON
      for dtype in ['briefdescription', 'detaileddescription']:
          desc_prefix = dtype + prefix
          print( "Setting", desc_prefix )
          desc_node = m_xml.find("./"+dtype)
          if desc_node != None:
            m[desc_prefix] = formatDescription( desc_node )
            print( "  ", m[desc_prefix] )
          else:
            print ("./"+dtype+ " not found in the XML")


#
# We done.  Write out the results.
#
backup_flag = False
if backup_flag:
  os.rename(sitk_json, sitk_json+".BAK")

fp = file(sitk_json, "w")
json.dump(json_obj, fp, indent=2, separators=(',', ' : '))
print ( "", file=fp )
fp.close()