root/releases/pkgcore/0.2.8/build_docs.py @ marienz%2540gentoo.org-20070304140903-2gwfq2wo3qbp1q9e

Revision marienz%2540gentoo.org-20070304140903-2gwfq2wo3qbp1q9e, 8.4 kB (checked in by Marien Zwart <marienz@…>, 21 months ago)

Fix up manpage categories.

  • Property executable set to True
Line 
1#!/usr/bin/env python
2
3
4"""Script for rebuilding our documentation."""
5
6
7import sys
8import os.path
9import optparse
10
11from docutils import nodes, core
12from docutils.parsers import rst
13import docutils.utils
14
15sys.path.append('man')
16import manpage
17
18from pkgcore.util import modules
19
20# (limited) support for trac wiki links.
21# This is copied and hacked up from rst.py in the trac source.
22
23def trac_get_reference(rawtext, link, text):
24    if not link.startswith('rst:'):
25        return None
26    target = link.split(':', 1)[1]
27    reference = nodes.reference(rawtext, text or target)
28    reference['refuri'] = target
29    return reference
30
31def trac(name, arguments, options, content, lineno,
32         content_offset, block_text, state, state_machine):
33    """Inserts a `reference` node into the document
34    for a given `TracLink`_, based on the content
35    of the arguments.
36
37    Usage::
38
39      .. trac:: target [text]
40
41    ``target`` may be any `TracLink`_, provided it doesn't
42    embed a space character (e.g. wiki:"..." notation won't work).
43
44    ``[text]`` is optional.  If not given, ``target`` is
45    used as the reference text.
46
47    .. _TracLink: http://trac.edgewall.org/wiki/TracLinks
48    """
49    link = arguments[0]
50    if len(arguments) == 2:
51        text = arguments[1]
52    else:
53        text = None
54    reference = trac_get_reference(block_text, link, text)
55    if reference:
56        p = nodes.paragraph()
57        p += reference
58        return p
59    # didn't find a match (invalid TracLink),
60    # report a warning
61    warning = state_machine.reporter.warning(
62            '%s is not a valid TracLink' % (arguments[0]),
63            nodes.literal_block(block_text, block_text),
64            line=lineno)
65    return [warning]
66
67def trac_role(name, rawtext, text, lineno, inliner, options={},
68              content=[]):
69    args  = text.split(" ",1)
70    link = args[0]
71    if len(args)==2:
72        text = args[1]
73    else:
74        text = None
75    reference = trac_get_reference(rawtext, link, text)
76    if reference:
77        return [reference], []
78    warning = nodes.warning(None, nodes.literal_block(text,
79        'WARNING: %s is not a valid TracLink' % rawtext))
80    return warning, []
81
82# 1 required arg, 1 optional arg, spaces allowed in last arg
83trac.arguments = (1, 1, True)
84trac.options = None
85trac.content = False
86rst.directives.register_directive('trac', trac)
87rst.roles.register_local_role('trac', trac_role)
88
89
90class HelpFormatter(optparse.HelpFormatter):
91
92    """Hack to "format" optparse help as a docutils tree.
93
94    Normally the methods return strings that are glued together. This
95    one builds a docutils tree as its "result" attribute and returns
96    empty strings.
97    """
98
99    def __init__(self, state):
100        optparse.HelpFormatter.__init__(
101            self, indent_increment=0, max_help_position=24, width=80,
102            short_first=0)
103        self.result = nodes.paragraph()
104        self.current = nodes.option_list()
105        self.result += self.current
106        self._state = state
107
108    def format_heading(self, heading):
109        section = nodes.section()
110        self.result += section
111        section += nodes.title(text=heading)
112        self.current = nodes.option_list()
113        section += self.current
114        return ''
115
116    def format_option(self, option):
117        item = nodes.option_list_item()
118        group = nodes.option_group()
119        item.append(group)
120        for opt_string in self.option_strings[option]:
121            opt_node = nodes.option()
122            opt_node.append(nodes.option_string(text=opt_string))
123            if option.takes_value():
124                metavar = option.metavar or option.dest
125                opt_node.append(nodes.option_argument(text=metavar))
126            group.append(opt_node)
127        if option.long_help:
128            desc = nodes.description()
129            par = nodes.paragraph()
130            helpnodes, messages = self._state.inline_text(option.long_help, 0)
131            par.extend(helpnodes)
132            # XXX I have no idea if this makes sense and triggering it
133            # without making rst2man explode is nontrivial.
134            par.extend(messages)
135            desc.append(par)
136            group.append(desc)
137        elif option.help:
138            desc = nodes.description()
139            par = nodes.paragraph(text=option.help)
140            desc.append(par)
141            group.append(desc)
142        self.current.append(item)
143        return ''
144
145    def format_option_strings(self, option):
146        return option._short_opts + option._long_opts
147
148def script_options(name, arguments, options, content, lineno,
149                   content_offset, block_text, state, state_machine):
150    assert len(arguments) == 1, arguments
151    assert not options, options
152    parserclass = modules.load_attribute(arguments[0])
153    optionparser = parserclass()
154    formatter = HelpFormatter(state)
155    optionparser.format_help(formatter)
156    return formatter.result
157
158# 1 argument, no optional arguments, no spaces in the argument.
159script_options.arguments = (1, 0, False)
160# No options.
161script_options.options = None
162# No content used.
163script_options.content = False
164
165rst.directives.register_directive('pkgcore_script_options', script_options)
166
167
168def process_docs(directory, force, do_parent=False):
169    """Generate the table of contents and html files."""
170    print 'processing %s' % (directory,)
171    # Dirs first so we pick up their contents when generating ours.
172    for child in os.listdir(directory):
173        target = os.path.join(directory, child)
174        if os.path.isdir(target):
175            process_docs(target, force, True)
176    # Write the table of contents .rst file while processing files.
177    indexpath = os.path.join(directory, 'index.rst')
178    out = open(indexpath, 'w')
179    try:
180        out.write('===================\n')
181        out.write(' Table of contents\n')
182        out.write('===================\n')
183        out.write('\n')
184        if do_parent:
185            out.write('- `../ <../index.html>`_\n')
186        for entry in sorted(os.listdir(directory)):
187            original = os.path.join(directory, entry)
188            if entry == 'index.rst':
189                continue
190            if entry.lower().endswith('.rst'):
191                base = entry[:-4]
192                target = os.path.join(directory, base) + '.html'
193                out.write('- `%s <%s.html>`_\n' % (base, base))
194                # Check if we need to reprocess.
195                if force or not os.path.exists(target) or (
196                    os.path.getmtime(target) < os.path.getmtime(original)):
197                    print 'writing %s' % (target,)
198                    core.publish_file(source_path=original,
199                                      destination_path=target,
200                                      writer_name='html')
201                else:
202                    print 'up to date: %s' % (target,)
203            elif (os.path.isdir(original) and
204                  os.path.exists(os.path.join(original, 'index.rst'))):
205                out.write('- `%s/ <%s/index.html>`_\n' % (entry, entry))
206    finally:
207        out.close()
208    # And convert the index.
209    # (Guess we could keep its rst only in memory but who knows, someone
210    # might want to read it!)
211    core.publish_file(source_path=indexpath,
212                      destination_path=os.path.join(directory, 'index.html'),
213                      writer_name='html')
214
215
216def process_man(directory, force, debug):
217    """Generate manpages."""
218    print 'processing %s' % (directory,)
219    debug_loc = None
220    for entry in os.listdir(directory):
221        original = os.path.join(directory, entry)
222        if entry.lower().endswith('rst'):
223            base = entry[:-4]
224            target = os.path.join(directory, base)
225            if debug:
226                debug_loc = os.path.join(directory, base) + '.doctree'
227            if force or not os.path.exists(target) or (
228                os.path.getmtime(target) < os.path.getmtime(original)):
229                print 'writing %s' % (target,)
230                core.publish_file(source_path=original,
231                                  destination_path=target,
232                                  writer=manpage.Writer(debug_loc))
233            else:
234                print 'up to date: %s' % (target,)
235
236
237if __name__ == '__main__':
238    print 'checking documentation, use --force to force rebuild'
239    print
240    force = '--force' in sys.argv
241    debug = '--debug' in sys.argv
242    for directory in ['dev-notes', 'doc']:
243        process_docs(os.path.join(os.path.dirname(__file__), directory), force)
244    process_man(os.path.join(os.path.dirname(__file__), 'man'), force, debug)
Note: See TracBrowser for help on using the browser.