2
# Copyright 2010,2011 Free Software Foundation, Inc.
4
# This file is part of GNU Radio
6
# GNU Radio is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3, or (at your option)
11
# GNU Radio is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with GNU Radio; see the file COPYING. If not, write to
18
# the Free Software Foundation, Inc., 51 Franklin Street,
19
# Boston, MA 02110-1301, USA.
22
Creates the swig_doc.i SWIG interface file.
23
Execute using: python swig_doc.py xml_path outputfilename
25
The file instructs SWIG to transfer the doxygen comments into the
33
from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
35
from gnuradio.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
39
bits = name.split('_')
40
return '_'.join(bits[1:])
43
bits = name.split('_')
44
return bits[0] + '_make_' + '_'.join(bits[1:])
49
Checks if doxyxml produced objects correspond to a gnuradio block.
53
def includes(cls, item):
54
if not isinstance(item, DoxyClass):
56
# Check for a parsing error.
59
return item.has_member(make_name(item.name()), DoxyFriend)
64
Convert unicode text into ascii and escape quotes.
68
out = text.encode('ascii', 'replace')
69
out = out.replace('"', '\\"')
73
def combine_descriptions(obj):
75
Combines the brief and detailed descriptions of an object together.
78
bd = obj.brief_description.strip()
79
dd = obj.detailed_description.strip()
81
description.append(bd)
83
description.append(dd)
84
return utoascii('\n\n'.join(description)).strip()
87
entry_templ = '%feature("docstring") {name} "{docstring}"'
88
def make_entry(obj, name=None, templ="{description}", description=None):
90
Create a docstring entry for a swig interface file.
92
obj - a doxyxml object from which documentation will be extracted.
93
name - the name of the C object (defaults to obj.name())
94
templ - an optional template for the docstring containing only one
95
variable named 'description'.
96
description - if this optional variable is set then it's value is
97
used as the description instead of extracting it from obj.
101
if description is None:
102
description = combine_descriptions(obj)
103
docstring = templ.format(description=description)
106
return entry_templ.format(
112
def make_func_entry(func, name=None, description=None, params=None):
114
Create a function docstring entry for a swig interface file.
116
func - a doxyxml object from which documentation will be extracted.
117
name - the name of the C object (defaults to func.name())
118
description - if this optional variable is set then it's value is
119
used as the description instead of extracting it from func.
120
params - a parameter list that overrides using func.params.
124
params = [prm.declname for prm in params]
126
sig = "Params: (%s)" % ", ".join(params)
128
sig = "Params: (NONE)"
129
templ = "{description}\n\n" + sig
130
return make_entry(func, name=name, templ=utoascii(templ),
131
description=description)
134
def make_class_entry(klass, description=None):
136
Create a class docstring for a swig interface file.
139
output.append(make_entry(klass, description=description))
140
for func in klass.in_category(DoxyFunction):
141
name = klass.name() + '::' + func.name()
142
output.append(make_func_entry(func, name=name))
143
return "\n\n".join(output)
146
def make_block_entry(di, block):
148
Create class and function docstrings of a gnuradio block for a
152
# Get the documentation associated with the class.
153
class_desc = combine_descriptions(block)
155
descriptions.append(class_desc)
156
# Get the documentation associated with the make function
157
make_func = di.get_member(make_name(block.name()), DoxyFunction)
158
make_func_desc = combine_descriptions(make_func)
160
descriptions.append(make_func_desc)
161
# Get the documentation associated with the file
163
block_file = di.get_member(block.name() + ".h", DoxyFile)
164
file_desc = combine_descriptions(block_file)
166
descriptions.append(file_desc)
167
except base.Base.NoSuchMember:
168
# Don't worry if we can't find a matching file.
170
# And join them all together to make a super duper description.
171
super_description = "\n\n".join(descriptions)
172
# Associate the combined description with the class and
175
output.append(make_class_entry(block, description=super_description))
176
creator = block.get_member(block.name(), DoxyFunction)
177
output.append(make_func_entry(make_func, description=super_description,
178
params=creator.params))
179
return "\n\n".join(output)
182
def make_swig_interface_file(di, swigdocfilename, custom_output=None):
186
* This file was automatically generated using swig_doc.py.
188
* Any changes to it will be lost next time it is regenerated.
192
if custom_output is not None:
193
output.append(custom_output)
195
# Create docstrings for the blocks.
199
blocks = di.in_category(Block)
202
# May not be built just yet; sleep and try again
203
sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format(
208
# if we've given it three tries, give up and raise an error
209
sys.stderr.write("XML parsing error with file {0}. giving up.\n".format(
218
make_func = di.get_member(make_name(block.name()), DoxyFunction)
219
make_funcs.add(make_func.name())
220
output.append(make_block_entry(di, block))
221
except block.ParsingError:
222
sys.stderr.write('Parsing error for block {0}'.format(block.name()))
224
# Create docstrings for functions
225
# Don't include the make functions since they have already been dealt with.
226
funcs = [f for f in di.in_category(DoxyFunction) if f.name() not in make_funcs]
229
output.append(make_func_entry(f))
230
except f.ParsingError:
231
sys.stderr.write('Parsing error for function {0}'.format(f.name()))
233
# Create docstrings for classes
234
block_names = [block.name() for block in blocks]
235
klasses = [k for k in di.in_category(DoxyClass) if k.name() not in block_names]
238
output.append(make_class_entry(k))
239
except k.ParsingError:
240
sys.stderr.write('Parsing error for class {0}'.format(k.name()))
242
# Docstrings are not created for anything that is not a function or a class.
243
# If this excludes anything important please add it here.
245
output = "\n\n".join(output)
247
swig_doc = file(swigdocfilename, 'w')
248
swig_doc.write(output)
251
if __name__ == "__main__":
252
# Parse command line options and set up doxyxml.
253
err_msg = "Execute using: python swig_doc.py xml_path outputfilename"
254
if len(sys.argv) != 3:
255
raise StandardError(err_msg)
256
xml_path = sys.argv[1]
257
swigdocfilename = sys.argv[2]
258
di = DoxyIndex(xml_path)
260
# gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined!
261
# This is presumably a bug in SWIG.
262
#msg_q = di.get_member(u'gr_msg_queue', DoxyClass)
263
#insert_tail = msg_q.get_member(u'insert_tail', DoxyFunction)
264
#delete_head = msg_q.get_member(u'delete_head', DoxyFunction)
266
#output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail'))
267
#output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head'))
268
custom_output = "\n\n".join(output)
270
# Generate the docstrings interface file.
271
# If parsing error on NoSuchMember, try again by rereading everything.
272
# Give up after 3 tries.
276
make_swig_interface_file(di, swigdocfilename, custom_output=custom_output)
277
except base.Base.NoSuchMember:
279
# May not be built just yet; sleep and try again
280
sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format(
285
# if we've given it three tries, give up and raise an error
286
sys.stderr.write("XML parsing error with file {0}. giving up.\n".format(