summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/swig/swig_doc.py
diff options
context:
space:
mode:
authorBen Reynwar2010-11-03 20:53:07 -0700
committerBen Reynwar2010-11-03 20:53:07 -0700
commita20c127a9469aeac9ec60bf432c4128c49349f34 (patch)
treef4732c1d9f2b244b80a594a00e8b4ede26f651f0 /gnuradio-core/src/lib/swig/swig_doc.py
parenta310fe30079ea8f484e596d77c5132d3f73b517c (diff)
downloadgnuradio-a20c127a9469aeac9ec60bf432c4128c49349f34.tar.gz
gnuradio-a20c127a9469aeac9ec60bf432c4128c49349f34.tar.bz2
gnuradio-a20c127a9469aeac9ec60bf432c4128c49349f34.zip
Generation of python docstrings from doxygen xml.
swig_doc.i is a swig interface file containing all the docstrings. It is generated using swig_doc.py and included by gnuradio.i. Minor changes to the swig make files have been made so that the generation of swig_doc.i occurs.
Diffstat (limited to 'gnuradio-core/src/lib/swig/swig_doc.py')
-rw-r--r--gnuradio-core/src/lib/swig/swig_doc.py195
1 files changed, 195 insertions, 0 deletions
diff --git a/gnuradio-core/src/lib/swig/swig_doc.py b/gnuradio-core/src/lib/swig/swig_doc.py
new file mode 100644
index 000000000..52989e1bd
--- /dev/null
+++ b/gnuradio-core/src/lib/swig/swig_doc.py
@@ -0,0 +1,195 @@
+"""
+Creates the swig_doc.i SWIG interface file.
+Execute using: python swig_doc.py xml_path outputfilename
+
+The file instructs SWIG to transfer the doxygen comments into the
+python docstrings.
+
+"""
+
+import sys
+
+from gnuradio.utils.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction
+
+
+def py_name(name):
+ bits = name.split('_')
+ return '_'.join(bits[1:])
+
+def make_name(name):
+ bits = name.split('_')
+ return bits[0] + '_make_' + '_'.join(bits[1:])
+
+
+class Block(object):
+ """
+ Checks if doxyxml produced objects correspond to a gnuradio block.
+ """
+
+ @classmethod
+ def includes(cls, item):
+ if not isinstance(item, DoxyClass):
+ return False
+ # Check for a parsing error.
+ if item.error():
+ return False
+ return item.has_member(make_name(item.name()), DoxyFriend)
+
+
+def utoascii(text):
+ """
+ Convert unicode text into ascii and escape quotes.
+ """
+ if text is None:
+ return ''
+ out = text.encode('ascii', 'replace')
+ out = out.replace('"', '\\"')
+ return out
+
+
+def combine_descriptions(obj):
+ """
+ Combines the brief and detailed descriptions of an object together.
+ """
+ description = []
+ bd = obj.brief_description
+ dd = obj.detailed_description
+ if bd:
+ description.append(bd)
+ if dd:
+ description.append(dd)
+ return utoascii('\n\n'.join(description))
+
+
+entry_templ = '%feature("docstring") {name} "{docstring}"'
+def make_entry(obj, name=None, templ="{description}", description=None):
+ """
+ Create a docstring entry for a swig interface file.
+
+ obj - a doxyxml object from which documentation will be extracted.
+ name - the name of the C object (defaults to obj.name())
+ templ - an optional template for the docstring containing only one
+ variable named 'description'.
+ description - if this optional variable is set then it's value is
+ used as the description instead of extracting it from obj.
+ """
+ if name is None:
+ name=obj.name()
+ if description is None:
+ description = combine_descriptions(obj)
+ docstring = templ.format(description=description)
+ if not docstring:
+ return ''
+ return entry_templ.format(
+ name=name,
+ docstring=docstring,
+ )
+
+
+def make_func_entry(func, name=None, description=None, params=None):
+ """
+ Create a function docstring entry for a swig interface file.
+
+ func - a doxyxml object from which documentation will be extracted.
+ name - the name of the C object (defaults to func.name())
+ description - if this optional variable is set then it's value is
+ used as the description instead of extracting it from func.
+ params - a parameter list that overrides using func.params.
+ """
+ if params is None:
+ params = func.params
+ params = [prm.declname for prm in params]
+ if params:
+ sig = "Params: (%s)" % ", ".join(params)
+ else:
+ sig = "Params: (NONE)"
+ templ = "{description}\n\n" + sig
+ return make_entry(func, name=name, templ=utoascii(templ), description=description)
+
+
+def make_class_entry(klass):
+ """
+ Create a class docstring for a swig interface file.
+ """
+ output = []
+ output.append(make_entry(klass))
+ for func in klass.in_category(DoxyFunction):
+ name = klass.name() + '::' + func.name()
+ output.append(make_func_entry(func, name=name))
+ return "\n\n".join(output)
+
+
+def make_block_entry(block):
+ """
+ Create class and function docstrings of a gnuradio block for a
+ swig interface file.
+ """
+ output = []
+ # Get creator function
+ make_func = di.get_member(make_name(block.name()))
+ output.append(make_class_entry(block))
+ creator = block.get_member(block.name())
+ make_func_desc = "Creates a {name} block.\n\n{block_desc}"
+ description = make_func_desc.format(
+ block_desc = combine_descriptions(block),
+ name = py_name(block.name()),
+ )
+ output.append(make_func_entry(make_func, description=description, params=creator.params))
+ return "\n\n".join(output)
+
+
+# Parse command line options and set up doxyxml.
+err_msg = "Execute using: python swig_doc.py xml_path outputfilename"
+if len(sys.argv) != 3:
+ raise StandardError(err_msg)
+xml_path = sys.argv[1]
+swigdocfilename = sys.argv[2]
+swig_doc = file(swigdocfilename, 'w')
+di = DoxyIndex(xml_path)
+
+output = []
+
+# gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined!
+# This is presumably a bug in SWIG.
+msg_q = di.get_member(u'gr_msg_queue')
+insert_tail = msg_q.get_member(u'insert_tail')
+delete_head = msg_q.get_member(u'delete_head')
+output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail'))
+output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head'))
+
+# Create docstrings for the blocks.
+blocks = di.in_category(Block)
+make_funcs = set([])
+for block in blocks:
+ try:
+ make_func = di.get_member(make_name(block.name()))
+ make_funcs.add(make_func.name())
+ output.append(make_block_entry(block))
+ except block.ParsingError:
+ print('Parsing error for block %s' % block.name())
+
+# Create docstrings for functions
+# Don't include the make functions since they have already been dealt with.
+funcs = [f for f in di.in_category(DoxyFunction) if f.name() not in make_funcs]
+for f in funcs:
+ try:
+ output.append(make_func_entry(f))
+ except f.ParsingError:
+ print('Parsing error for function %s' % f.name())
+
+# Create docstrings for classes
+block_names = [block.name() for block in blocks]
+klasses = [k for k in di.in_category(DoxyClass) if k.name() not in block_names]
+for k in klasses:
+ try:
+ output.append(make_class_entry(k))
+ except k.ParsingError:
+ print('Parsing error for class %s' % k.name())
+
+# Docstrings are not created for anything that is not a function or a class.
+# If this excludes anything important please add it here.
+
+output = "\n\n".join(output)
+
+swig_doc.write(output)
+swig_doc.close()