2 Copyright 2008 Free Software Foundation, Inc.
3 This file is part of GNU Radio
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 ##@package grc_gnuradio.utils.extract_docs
20 #Extract documentation from the gnuradio doxygen files.
23 from grc_gnuradio.Constants import *
24 from lxml import etree
27 DOXYGEN_NAME_XPATH = '/doxygen/compounddef/compoundname'
28 DOXYGEN_BRIEFDESC_GR_XPATH = '/doxygen/compounddef/briefdescription'
29 DOXYGEN_DETAILDESC_GR_XPATH = '/doxygen/compounddef/detaileddescription'
30 DOXYGEN_BRIEFDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/briefdescription'
31 DOXYGEN_DETAILDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/detaileddescription'
35 Recursivly pull the text out of an xml tree.
36 @param xml the xml tree
40 if not len(xml): return text
41 return ''.join([text] + map(extract_txt, xml))
43 def is_match(key, file):
45 Is the block key a match for the given file name?
47 @param file the xml file name
48 @return true if matches
50 if not file.endswith('.xml'): return False
51 file = file.replace('.xml', '') #remove file ext
52 file = file.replace('__', '_') #doxygen xml files have 2 underscores
53 if key.startswith('gr_'):
54 if not file.startswith('classgr_'): return False
55 key = key.replace('gr_', 'classgr_')
56 elif key.startswith('trellis_'):
57 if not file.startswith('classtrellis_'): return False
58 key = key.replace('trellis_', 'classtrellis_')
59 elif key.startswith('blks2_'):
60 if not file.startswith('classgnuradio_'): return False
61 if 'blks2' not in file: return False
62 file = file.replace('_1_1', '_') #weird blks2 doxygen syntax
63 key = key.replace('blks2_', '')
65 for k, f in zip(*map(reversed, map(lambda x: x.split('_'), [key, file]))):
68 if len(ks) == 2 and f.startswith(ks[0]) and f.endswith(ks[1]): continue
69 if len(ks) > 2 and all(ki in ('x', fi) for ki, fi in zip(k, f)): continue
75 Extract the documentation from the doxygen generated xml files.
76 If multiple files match, combine the docs.
77 @param key the block key
78 @return a string with documentation
80 #get potential xml file matches for the key
81 if os.path.exists(DOCS_DIR) and os.path.isdir(DOCS_DIR):
82 matches = filter(lambda f: is_match(key, f), os.listdir(DOCS_DIR))
83 else: matches = list()
88 xml_file = DOCS_DIR + '/' + match
89 xml = etree.parse(xml_file)
91 comp_name = extract_txt(xml.xpath(DOXYGEN_NAME_XPATH)[0]).strip('\n')
92 comp_name = ' --- ' + comp_name + ' --- '
93 if key.startswith('gr_') or key.startswith('trellis_'):
94 brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_GR_XPATH)[0]).strip('\n')
95 detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_GR_XPATH)[0]).strip('\n')
96 elif key.startswith('blks2_'):
97 brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_BLKS2_XPATH)[0]).strip('\n')
98 detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_BLKS2_XPATH)[0]).strip('\n')
103 doc_strs.append('\n'.join([comp_name, brief_desc, detailed_desc]).strip('\n'))
104 except IndexError: pass #bad format
105 return '\n\n'.join(doc_strs)
107 if __name__ == '__main__':
109 print extract(sys.argv[1])