1#
2# Copyright 2010 Free Software Foundation, Inc.
3#
4# This file is part of GNU Radio
5#
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)
9# any later version.
10#
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.
15#
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.
20#
21"""
22Classes providing more user-friendly interfaces to the doxygen xml
23docs than the generated classes provide.
24"""
25
26import os
27
28from generated import index
29from base import Base
30from text import description
31
32class DoxyIndex(Base):
33    """
34    Parses a doxygen xml directory.
35    """
36
37    __module__ = "gnuradio.utils.doxyxml"
38
39    def _parse(self):
40        if self._parsed:
41            return
42        super(DoxyIndex, self)._parse()
43        self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))
44        for mem in self._root.compound:
45            converted = self.convert_mem(mem)
46            # For files and namespaces we want the contents to be
47            # accessible directly from the parent rather than having
48            # to go through the file object.
49            if self.get_cls(mem) == DoxyFile:
50                if mem.name.endswith('.h'):
51                    self._members += converted.members()
52                    self._members.append(converted)
53            elif self.get_cls(mem) == DoxyNamespace:
54                self._members += converted.members()
55                self._members.append(converted)
56            else:
57                self._members.append(converted)
58
59
60def generate_swig_doc_i(self):
61    """
62    %feature("docstring") gr_make_align_on_samplenumbers_ss::align_state "
63    Wraps the C++: gr_align_on_samplenumbers_ss::align_state";
64    """
65    pass
66
67
68class DoxyCompMem(Base):
69
70
71    kind = None
72
73    def __init__(self, *args, **kwargs):
74        super(DoxyCompMem, self).__init__(*args, **kwargs)
75
76    @classmethod
77    def can_parse(cls, obj):
78        return obj.kind == cls.kind
79
80    def set_descriptions(self, parse_data):
81        bd = description(getattr(parse_data, 'briefdescription', None))
82        dd = description(getattr(parse_data, 'detaileddescription', None))
83        self._data['brief_description'] = bd
84        self._data['detailed_description'] = dd
85
86    def set_parameters(self, data):
87        vs = [ddc.value for ddc in data.detaileddescription.content_]
88        pls = []
89        for v in vs:
90            if hasattr(v, 'parameterlist'):
91                pls += v.parameterlist
92        pis = []
93        for pl in pls:
94            pis += pl.parameteritem
95        dpis = []
96        for pi in pis:
97            dpi = DoxyParameterItem(pi)
98            dpi._parse()
99            dpis.append(dpi)
100        self._data['params'] = dpis
101
102
103class DoxyCompound(DoxyCompMem):
104    pass
105
106class DoxyMember(DoxyCompMem):
107    pass
108
109class DoxyFunction(DoxyMember):
110
111    __module__ = "gnuradio.utils.doxyxml"
112
113    kind = 'function'
114
115    def _parse(self):
116        if self._parsed:
117            return
118        super(DoxyFunction, self)._parse()
119        self.set_descriptions(self._parse_data)
120        self.set_parameters(self._parse_data)
121        if not self._data['params']:
122            # If the params weren't set by a comment then just grab the names.
123            self._data['params'] = []
124            prms = self._parse_data.param
125            for prm in prms:
126                self._data['params'].append(DoxyParam(prm))
127
128    brief_description = property(lambda self: self.data()['brief_description'])
129    detailed_description = property(lambda self: self.data()['detailed_description'])
130    params = property(lambda self: self.data()['params'])
131
132Base.mem_classes.append(DoxyFunction)
133
134
135class DoxyParam(DoxyMember):
136
137    __module__ = "gnuradio.utils.doxyxml"
138
139    def _parse(self):
140        if self._parsed:
141            return
142        super(DoxyParam, self)._parse()
143        self.set_descriptions(self._parse_data)
144        self._data['declname'] = self._parse_data.declname
145
146    @property
147    def description(self):
148        descriptions = []
149        if self.brief_description:
150            descriptions.append(self.brief_description)
151        if self.detailed_description:
152            descriptions.append(self.detailed_description)
153        return '\n\n'.join(descriptions)
154
155    brief_description = property(lambda self: self.data()['brief_description'])
156    detailed_description = property(lambda self: self.data()['detailed_description'])
157    name = property(lambda self: self.data()['declname'])
158
159class DoxyParameterItem(DoxyMember):
160    """A different representation of a parameter in Doxygen."""
161
162    def _parse(self):
163        if self._parsed:
164            return
165        super(DoxyParameterItem, self)._parse()
166        names = []
167        for nl in self._parse_data.parameternamelist:
168            for pn in nl.parametername:
169                names.append(description(pn))
170        # Just take first name
171        self._data['name'] = names[0]
172        # Get description
173        pd = description(self._parse_data.get_parameterdescription())
174        self._data['description'] = pd
175
176    description = property(lambda self: self.data()['description'])
177    name = property(lambda self: self.data()['name'])
178
179
180class DoxyClass(DoxyCompound):
181
182    __module__ = "gnuradio.utils.doxyxml"
183
184    kind = 'class'
185
186    def _parse(self):
187        if self._parsed:
188            return
189        super(DoxyClass, self)._parse()
190        self.retrieve_data()
191        if self._error:
192            return
193        self.set_descriptions(self._retrieved_data.compounddef)
194        self.set_parameters(self._retrieved_data.compounddef)
195        # Sectiondef.kind tells about whether private or public.
196        # We just ignore this for now.
197        self.process_memberdefs()
198
199    brief_description = property(lambda self: self.data()['brief_description'])
200    detailed_description = property(lambda self: self.data()['detailed_description'])
201    params = property(lambda self: self.data()['params'])
202
203Base.mem_classes.append(DoxyClass)
204
205
206class DoxyFile(DoxyCompound):
207
208    __module__ = "gnuradio.utils.doxyxml"
209
210    kind = 'file'
211
212    def _parse(self):
213        if self._parsed:
214            return
215        super(DoxyFile, self)._parse()
216        self.retrieve_data()
217        self.set_descriptions(self._retrieved_data.compounddef)
218        if self._error:
219            return
220        self.process_memberdefs()
221
222    brief_description = property(lambda self: self.data()['brief_description'])
223    detailed_description = property(lambda self: self.data()['detailed_description'])
224
225Base.mem_classes.append(DoxyFile)
226
227
228class DoxyNamespace(DoxyCompound):
229
230    __module__ = "gnuradio.utils.doxyxml"
231
232    kind = 'namespace'
233
234    def _parse(self):
235        if self._parsed:
236            return
237        super(DoxyNamespace, self)._parse()
238        self.retrieve_data()
239        self.set_descriptions(self._retrieved_data.compounddef)
240        if self._error:
241            return
242        self.process_memberdefs()
243
244Base.mem_classes.append(DoxyNamespace)
245
246
247class DoxyGroup(DoxyCompound):
248
249    __module__ = "gnuradio.utils.doxyxml"
250
251    kind = 'group'
252
253    def _parse(self):
254        if self._parsed:
255            return
256        super(DoxyGroup, self)._parse()
257        self.retrieve_data()
258        if self._error:
259            return
260        cdef = self._retrieved_data.compounddef
261        self._data['title'] = description(cdef.title)
262        # Process inner groups
263        grps = cdef.innergroup
264        for grp in grps:
265            converted = DoxyGroup.from_refid(grp.refid, top=self.top)
266            self._members.append(converted)
267        # Process inner classes
268        klasses = cdef.innerclass
269        for kls in klasses:
270            converted = DoxyClass.from_refid(kls.refid, top=self.top)
271            self._members.append(converted)
272        # Process normal members
273        self.process_memberdefs()
274
275    title = property(lambda self: self.data()['title'])
276
277
278Base.mem_classes.append(DoxyGroup)
279
280
281class DoxyFriend(DoxyMember):
282
283    __module__ = "gnuradio.utils.doxyxml"
284
285    kind = 'friend'
286
287Base.mem_classes.append(DoxyFriend)
288
289
290class DoxyOther(Base):
291
292    __module__ = "gnuradio.utils.doxyxml"
293
294    kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum',
295                 'dir', 'page', 'signal', 'slot', 'property'])
296
297    @classmethod
298    def can_parse(cls, obj):
299        return obj.kind in cls.kinds
300
301Base.mem_classes.append(DoxyOther)
302