~ubuntu-branches/ubuntu/trusty/gnuradio/trusty-updates

« back to all changes in this revision

Viewing changes to .pc/0007-docs-another-hack-to-check-for-errors-and-retry-when.patch/docs/doxygen/swig_doc.py

  • Committer: Package Import Robot
  • Author(s): A. Maitland Bottoms
  • Date: 2012-03-16 20:30:18 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20120316203018-o9cvujkbn563d8ou
Tags: 3.5.2.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Copyright 2010,2011 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
 
"""
22
 
Creates the swig_doc.i SWIG interface file.
23
 
Execute using: python swig_doc.py xml_path outputfilename
24
 
 
25
 
The file instructs SWIG to transfer the doxygen comments into the
26
 
python docstrings.
27
 
 
28
 
"""
29
 
 
30
 
import sys, time
31
 
 
32
 
try:
33
 
    from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
34
 
except ImportError:
35
 
    from gnuradio.doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base
36
 
 
37
 
 
38
 
def py_name(name):
39
 
    bits = name.split('_')
40
 
    return '_'.join(bits[1:])
41
 
 
42
 
def make_name(name):
43
 
    bits = name.split('_')
44
 
    return bits[0] + '_make_' + '_'.join(bits[1:])
45
 
 
46
 
 
47
 
class Block(object):
48
 
    """
49
 
    Checks if doxyxml produced objects correspond to a gnuradio block.
50
 
    """
51
 
 
52
 
    @classmethod
53
 
    def includes(cls, item):
54
 
        if not isinstance(item, DoxyClass):
55
 
            return False
56
 
        # Check for a parsing error.
57
 
        if item.error():
58
 
            return False
59
 
        return item.has_member(make_name(item.name()), DoxyFriend)
60
 
 
61
 
 
62
 
def utoascii(text):
63
 
    """
64
 
    Convert unicode text into ascii and escape quotes.
65
 
    """
66
 
    if text is None:
67
 
        return ''
68
 
    out = text.encode('ascii', 'replace')
69
 
    out = out.replace('"', '\\"')
70
 
    return out
71
 
 
72
 
 
73
 
def combine_descriptions(obj):
74
 
    """
75
 
    Combines the brief and detailed descriptions of an object together.
76
 
    """
77
 
    description = []
78
 
    bd = obj.brief_description.strip()
79
 
    dd = obj.detailed_description.strip()
80
 
    if bd:
81
 
        description.append(bd)
82
 
    if dd:
83
 
        description.append(dd)
84
 
    return utoascii('\n\n'.join(description)).strip()
85
 
    
86
 
 
87
 
entry_templ = '%feature("docstring") {name} "{docstring}"'
88
 
def make_entry(obj, name=None, templ="{description}", description=None):
89
 
    """
90
 
    Create a docstring entry for a swig interface file.
91
 
    
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.
98
 
    """
99
 
    if name is None:
100
 
        name=obj.name()
101
 
    if description is None:
102
 
        description = combine_descriptions(obj)
103
 
    docstring = templ.format(description=description)
104
 
    if not docstring:
105
 
        return ''
106
 
    return entry_templ.format(
107
 
        name=name,
108
 
        docstring=docstring,
109
 
        )
110
 
 
111
 
 
112
 
def make_func_entry(func, name=None, description=None, params=None):
113
 
    """
114
 
    Create a function docstring entry for a swig interface file.
115
 
 
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.
121
 
    """
122
 
    if params is None:
123
 
        params = func.params
124
 
    params = [prm.declname for prm in params]
125
 
    if params:
126
 
        sig = "Params: (%s)" % ", ".join(params)
127
 
    else:
128
 
        sig = "Params: (NONE)"
129
 
    templ = "{description}\n\n" + sig
130
 
    return make_entry(func, name=name, templ=utoascii(templ),
131
 
                      description=description)
132
 
 
133
 
 
134
 
def make_class_entry(klass, description=None):
135
 
    """
136
 
    Create a class docstring for a swig interface file.
137
 
    """
138
 
    output = []
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)
144
 
 
145
 
 
146
 
def make_block_entry(di, block):
147
 
    """
148
 
    Create class and function docstrings of a gnuradio block for a
149
 
    swig interface file.
150
 
    """
151
 
    descriptions = []
152
 
    # Get the documentation associated with the class.
153
 
    class_desc = combine_descriptions(block)
154
 
    if class_desc:
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)
159
 
    if make_func_desc:
160
 
        descriptions.append(make_func_desc)
161
 
    # Get the documentation associated with the file
162
 
    try:
163
 
        block_file = di.get_member(block.name() + ".h", DoxyFile)
164
 
        file_desc = combine_descriptions(block_file)
165
 
        if file_desc:
166
 
            descriptions.append(file_desc)
167
 
    except base.Base.NoSuchMember:
168
 
        # Don't worry if we can't find a matching file.
169
 
        pass
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
173
 
    # the make function.
174
 
    output = []
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)
180
 
 
181
 
 
182
 
def make_swig_interface_file(di, swigdocfilename, custom_output=None):
183
 
    
184
 
    output = ["""
185
 
/*
186
 
 * This file was automatically generated using swig_doc.py.
187
 
 * 
188
 
 * Any changes to it will be lost next time it is regenerated.
189
 
 */
190
 
"""]
191
 
 
192
 
    if custom_output is not None:
193
 
        output.append(custom_output)
194
 
 
195
 
    # Create docstrings for the blocks.
196
 
    tries = 0
197
 
    while(1):
198
 
        try:
199
 
            blocks = di.in_category(Block)
200
 
        except:
201
 
            if(tries < 3):
202
 
                # May not be built just yet; sleep and try again
203
 
                sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format(
204
 
                        swigdocfilename))
205
 
                time.sleep(1)
206
 
                tries += 1
207
 
            else:
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(
210
 
                        swigdocfilename))
211
 
                raise
212
 
        else:
213
 
            break
214
 
 
215
 
    make_funcs = set([])
216
 
    for block in blocks:
217
 
        try:
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()))
223
 
 
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]
227
 
    for f in funcs:
228
 
        try:
229
 
            output.append(make_func_entry(f))
230
 
        except f.ParsingError:
231
 
            sys.stderr.write('Parsing error for function {0}'.format(f.name()))
232
 
 
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]
236
 
    for k in klasses:
237
 
        try:
238
 
            output.append(make_class_entry(k))
239
 
        except k.ParsingError:
240
 
            sys.stderr.write('Parsing error for class {0}'.format(k.name()))
241
 
 
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.
244
 
 
245
 
    output = "\n\n".join(output)
246
 
 
247
 
    swig_doc = file(swigdocfilename, 'w')
248
 
    swig_doc.write(output)
249
 
    swig_doc.close()
250
 
 
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)
259
 
 
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)
265
 
    output = []
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)
269
 
 
270
 
    # Generate the docstrings interface file.
271
 
    # If parsing error on NoSuchMember, try again by rereading everything.
272
 
    # Give up after 3 tries.
273
 
    tries = 0
274
 
    while(1):
275
 
        try:
276
 
            make_swig_interface_file(di, swigdocfilename, custom_output=custom_output)
277
 
        except base.Base.NoSuchMember:
278
 
            if(tries < 3):
279
 
                # May not be built just yet; sleep and try again
280
 
                sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format(
281
 
                        swigdocfilename))
282
 
                time.sleep(1)
283
 
                tries += 1
284
 
            else:
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(
287
 
                        swigdocfilename))
288
 
                raise
289
 
        else:
290
 
            break
291