Hi,

  I noticed that doxyxml helper scripts in gr-howto-write-a-block need
to be updated, in order to be in sync with those in the main tree.
I needed to update doxyxml mainly for having block parameters
documentation.  Please see the attached patch.

  Regards,

-- Julien Olivain.
diff --git a/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py b/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
index 0132ab8..304109a 100644
--- a/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
+++ b/gr-howto-write-a-block/docs/doxygen/doxyxml/doxyindex.py
@@ -1,23 +1,23 @@
 #
 # Copyright 2010 Free Software Foundation, Inc.
-#
+# 
 # This file is part of GNU Radio
-#
+# 
 # GNU Radio is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 3, or (at your option)
 # any later version.
-#
+# 
 # GNU Radio is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-#
+# 
 # You should have received a copy of the GNU General Public License
 # along with GNU Radio; see the file COPYING.  If not, write to
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
-#
+# 
 """
 Classes providing more user-friendly interfaces to the doxygen xml
 docs than the generated classes provide.
@@ -40,7 +40,7 @@ class DoxyIndex(Base):
         if self._parsed:
             return
         super(DoxyIndex, self)._parse()
-        self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))
+        self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))      
         for mem in self._root.compound:
             converted = self.convert_mem(mem)
             # For files we want the contents to be accessible directly
@@ -78,7 +78,24 @@ class DoxyCompMem(Base):
         bd = description(getattr(parse_data, 'briefdescription', None))
         dd = description(getattr(parse_data, 'detaileddescription', None))
         self._data['brief_description'] = bd
-        self._data['detailed_description'] = dd
+        self._data['detailed_description'] = dd        
+
+    def set_parameters(self, data):
+        vs = [ddc.value for ddc in data.detaileddescription.content_]
+        pls = []
+        for v in vs:
+            if hasattr(v, 'parameterlist'):
+                pls += v.parameterlist
+        pis = []
+        for pl in pls:
+            pis += pl.parameteritem
+        dpis = []
+        for pi in pis:
+            dpi = DoxyParameterItem(pi)
+            dpi._parse()
+            dpis.append(dpi)
+        self._data['params'] = dpis
+
 
 class DoxyCompound(DoxyCompMem):
     pass
@@ -86,7 +103,6 @@ class DoxyCompound(DoxyCompMem):
 class DoxyMember(DoxyCompMem):
     pass
 
-
 class DoxyFunction(DoxyMember):
 
     __module__ = "gnuradio.utils.doxyxml"
@@ -98,10 +114,13 @@ class DoxyFunction(DoxyMember):
             return
         super(DoxyFunction, self)._parse()
         self.set_descriptions(self._parse_data)
-        self._data['params'] = []
-        prms = self._parse_data.param
-        for prm in prms:
-            self._data['params'].append(DoxyParam(prm))
+        self.set_parameters(self._parse_data)
+        if not self._data['params']:
+            # If the params weren't set by a comment then just grab the names.
+            self._data['params'] = []
+            prms = self._parse_data.param
+            for prm in prms:
+                self._data['params'].append(DoxyParam(prm))
 
     brief_description = property(lambda self: self.data()['brief_description'])
     detailed_description = property(lambda self: self.data()['detailed_description'])
@@ -111,7 +130,7 @@ Base.mem_classes.append(DoxyFunction)
 
 
 class DoxyParam(DoxyMember):
-
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     def _parse(self):
@@ -121,16 +140,46 @@ class DoxyParam(DoxyMember):
         self.set_descriptions(self._parse_data)
         self._data['declname'] = self._parse_data.declname
 
+    @property
+    def description(self):
+        descriptions = []
+        if self.brief_description:
+            descriptions.append(self.brief_description)
+        if self.detailed_description:
+            descriptions.append(self.detailed_description)
+        return '\n\n'.join(descriptions)
+
     brief_description = property(lambda self: self.data()['brief_description'])
     detailed_description = property(lambda self: self.data()['detailed_description'])
-    declname = property(lambda self: self.data()['declname'])
+    name = property(lambda self: self.data()['declname'])
 
-class DoxyClass(DoxyCompound):
+class DoxyParameterItem(DoxyMember):
+    """A different representation of a parameter in Doxygen."""
+
+    def _parse(self):
+        if self._parsed:
+            return
+        super(DoxyParameterItem, self)._parse()
+        names = []
+        for nl in self._parse_data.parameternamelist:
+            for pn in nl.parametername:
+                names.append(description(pn))
+        # Just take first name
+        self._data['name'] = names[0]
+        # Get description
+        pd = description(self._parse_data.get_parameterdescription())
+        self._data['description'] = pd
+
+    description = property(lambda self: self.data()['description'])
+    name = property(lambda self: self.data()['name'])
 
+
+class DoxyClass(DoxyCompound):
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     kind = 'class'
-
+    
     def _parse(self):
         if self._parsed:
             return
@@ -139,22 +188,24 @@ class DoxyClass(DoxyCompound):
         if self._error:
             return
         self.set_descriptions(self._retrieved_data.compounddef)
+        self.set_parameters(self._retrieved_data.compounddef)
         # Sectiondef.kind tells about whether private or public.
         # We just ignore this for now.
         self.process_memberdefs()
 
     brief_description = property(lambda self: self.data()['brief_description'])
     detailed_description = property(lambda self: self.data()['detailed_description'])
+    params = property(lambda self: self.data()['params'])
 
 Base.mem_classes.append(DoxyClass)
-
+        
 
 class DoxyFile(DoxyCompound):
-
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     kind = 'file'
-
+    
     def _parse(self):
         if self._parsed:
             return
@@ -164,7 +215,7 @@ class DoxyFile(DoxyCompound):
         if self._error:
             return
         self.process_memberdefs()
-
+        
     brief_description = property(lambda self: self.data()['brief_description'])
     detailed_description = property(lambda self: self.data()['detailed_description'])
 
@@ -172,16 +223,16 @@ Base.mem_classes.append(DoxyFile)
 
 
 class DoxyNamespace(DoxyCompound):
-
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     kind = 'namespace'
-
+    
 Base.mem_classes.append(DoxyNamespace)
 
 
 class DoxyGroup(DoxyCompound):
-
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     kind = 'group'
@@ -209,7 +260,7 @@ class DoxyGroup(DoxyCompound):
         self.process_memberdefs()
 
     title = property(lambda self: self.data()['title'])
-
+        
 
 Base.mem_classes.append(DoxyGroup)
 
@@ -224,7 +275,7 @@ Base.mem_classes.append(DoxyFriend)
 
 
 class DoxyOther(Base):
-
+    
     __module__ = "gnuradio.utils.doxyxml"
 
     kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 'dir', 'page'])
@@ -232,6 +283,6 @@ class DoxyOther(Base):
     @classmethod
     def can_parse(cls, obj):
         return obj.kind in cls.kinds
-
+    
 Base.mem_classes.append(DoxyOther)
 
diff --git a/gr-howto-write-a-block/docs/doxygen/swig_doc.py b/gr-howto-write-a-block/docs/doxygen/swig_doc.py
index 4e1ce2e..f24608b 100644
--- a/gr-howto-write-a-block/docs/doxygen/swig_doc.py
+++ b/gr-howto-write-a-block/docs/doxygen/swig_doc.py
@@ -1,23 +1,23 @@
 #
-# Copyright 2010,2011 Free Software Foundation, Inc.
-#
+# Copyright 2010-2012 Free Software Foundation, Inc.
+# 
 # This file is part of GNU Radio
-#
+# 
 # GNU Radio is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 3, or (at your option)
 # any later version.
-#
+# 
 # GNU Radio is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
-#
+# 
 # You should have received a copy of the GNU General Public License
 # along with GNU Radio; see the file COPYING.  If not, write to
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
-#
+# 
 """
 Creates the swig_doc.i SWIG interface file.
 Execute using: python swig_doc.py xml_path outputfilename
@@ -27,13 +27,10 @@ python docstrings.
 
 """
 
-import sys
-
-try:
-    from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
-except ImportError:
-    from gnuradio.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
+import sys, time
 
+from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile
+from doxyxml import DoxyOther, base
 
 def py_name(name):
     bits = name.split('_')
@@ -56,8 +53,29 @@ class Block(object):
         # Check for a parsing error.
         if item.error():
             return False
-        return item.has_member(make_name(item.name()), DoxyFriend)
-
+        friendname = make_name(item.name())
+        is_a_block = item.has_member(friendname, DoxyFriend)
+        # But now sometimes the make function isn't a friend so check again.
+        if not is_a_block:
+            is_a_block = di.has_member(friendname, DoxyFunction)
+        return is_a_block
+
+class Block2(object):
+    """
+    Checks if doxyxml produced objects correspond to a new style
+    gnuradio block.
+    """
+    
+    @classmethod
+    def includes(cls, item):
+        if not isinstance(item, DoxyClass):
+            return False
+        # Check for a parsing error.
+        if item.error():
+            return False
+        is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther)
+        return is_a_block2
+        
 
 def utoascii(text):
     """
@@ -82,13 +100,19 @@ def combine_descriptions(obj):
     if dd:
         description.append(dd)
     return utoascii('\n\n'.join(description)).strip()
-
+    
+def format_params(parameteritems):
+    output = ['Args:']
+    template = '    {0} : {1}'
+    for pi in parameteritems:
+        output.append(template.format(pi.name, pi.description))
+    return '\n'.join(output)
 
 entry_templ = '%feature("docstring") {name} "{docstring}"'
-def make_entry(obj, name=None, templ="{description}", description=None):
+def make_entry(obj, name=None, templ="{description}", description=None, params=[]):
     """
     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
@@ -102,6 +126,9 @@ def make_entry(obj, name=None, templ="{description}", description=None):
         return ''
     if description is None:
         description = combine_descriptions(obj)
+    if params:
+        description += '\n\n'
+        description += utoascii(format_params(params))
     docstring = templ.format(description=description)
     if not docstring:
         return ''
@@ -121,27 +148,31 @@ def make_func_entry(func, name=None, description=None, params=None):
             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, description=None):
+    #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)
+    return make_entry(func, name=name, description=description, params=params)
+
+
+def make_class_entry(klass, description=None, ignored_methods=[], params=None):
     """
     Create a class docstring for a swig interface file.
     """
+    if params is None:
+        params = klass.params
     output = []
-    output.append(make_entry(klass, description=description))
+    output.append(make_entry(klass, description=description, params=params))
     for func in klass.in_category(DoxyFunction):
-        name = klass.name() + '::' + func.name()
-        output.append(make_func_entry(func, name=name))
+        if func.name() not in ignored_methods:
+            name = klass.name() + '::' + func.name()
+            output.append(make_func_entry(func, name=name))
     return "\n\n".join(output)
 
 
@@ -175,18 +206,38 @@ def make_block_entry(di, block):
     # the make function.
     output = []
     output.append(make_class_entry(block, description=super_description))
-    creator = block.get_member(block.name(), DoxyFunction)
     output.append(make_func_entry(make_func, description=super_description,
-                                  params=creator.params))
+                                  params=block.params))
     return "\n\n".join(output)
 
+def make_block2_entry(di, block):
+    """
+    Create class and function docstrings of a new style gnuradio block for a
+    swig interface file.
+    """
+    descriptions = []
+    # For new style blocks all the relevant documentation should be
+    # associated with the 'make' method.
+    make_func = block.get_member('make', DoxyFunction)
+    description = combine_descriptions(make_func)
+    # Associate the combined description with the class and
+    # the make function.
+    output = []
+    #output.append(make_class_entry(
+    #        block, description=description,
+    #        ignored_methods=['make'], params=make_func.params))
+    makename = block.name() + '::make'
+    output.append(make_func_entry(
+            make_func, name=makename, description=description,
+            params=make_func.params))
+    return "\n\n".join(output)
 
 def make_swig_interface_file(di, swigdocfilename, custom_output=None):
-
+    
     output = ["""
 /*
  * This file was automatically generated using swig_doc.py.
- *
+ * 
  * Any changes to it will be lost next time it is regenerated.
  */
 """]
@@ -196,32 +247,52 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None):
 
     # Create docstrings for the blocks.
     blocks = di.in_category(Block)
+    blocks2 = di.in_category(Block2)
+
     make_funcs = set([])
     for block in blocks:
         try:
             make_func = di.get_member(make_name(block.name()), DoxyFunction)
-            make_funcs.add(make_func.name())
-            output.append(make_block_entry(di, block))
+            # Don't want to risk writing to output twice.
+            if make_func.name() not in make_funcs:
+                make_funcs.add(make_func.name())
+                output.append(make_block_entry(di, block))
+        except block.ParsingError:
+            sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
+            raise
+
+    for block in blocks2:
+        try:
+            make_func = block.get_member('make', DoxyFunction)
+            make_func_name = block.name() +'::make'
+            # Don't want to risk writing to output twice.
+            if make_func_name not in make_funcs:
+                make_funcs.add(make_func_name)
+                output.append(make_block2_entry(di, block))
         except block.ParsingError:
-            print('Parsing error for block %s' % block.name())
+            sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
+            raise
 
     # 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]
+    funcs = [f for f in di.in_category(DoxyFunction) 
+             if f.name() not in make_funcs and not f.name().startswith('std::')]
     for f in funcs:
         try:
             output.append(make_func_entry(f))
         except f.ParsingError:
-            print('Parsing error for function %s' % f.name())
+            sys.stderr.write('Parsing error for function {0}\n'.format(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]
+    block_names += [block.name() for block in blocks2]
+    klasses = [k for k in di.in_category(DoxyClass)
+               if k.name() not in block_names and not k.name().startswith('std::')]
     for k in klasses:
         try:
             output.append(make_class_entry(k))
         except k.ParsingError:
-            print('Parsing error for class %s' % k.name())
+            sys.stderr.write('Parsing error for class {0}\n'.format(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.
_______________________________________________
Patch-gnuradio mailing list
Patch-gnuradio@gnu.org
https://lists.gnu.org/mailman/listinfo/patch-gnuradio

Reply via email to