summaryrefslogtreecommitdiffstats
path: root/Doc/tools/sphinxext/pyspecific.py
blob: be6f78dfa005cae7b545f75dfc65f13cec1ec0cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# -*- coding: utf-8 -*-
"""
    pyspecific.py
    ~~~~~~~~~~~~~

    Sphinx extension with Python doc-specific markup.

    :copyright: 2008, 2009 by Georg Brandl.
    :license: Python license.
"""

ISSUE_URI = 'http://bugs.python.org/issue%s'

from docutils import nodes, utils

# monkey-patch reST parser to disable alphabetic and roman enumerated lists
from docutils.parsers.rst.states import Body
Body.enum.converters['loweralpha'] = \
    Body.enum.converters['upperalpha'] = \
    Body.enum.converters['lowerroman'] = \
    Body.enum.converters['upperroman'] = lambda x: None


def issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
    issue = utils.unescape(text)
    text = 'issue ' + issue
    refnode = nodes.reference(text, text, refuri=ISSUE_URI % issue)
    return [refnode], []


# Support for building "topic help" for pydoc

pydoc_topic_labels = [
    'assert', 'assignment', 'atom-identifiers', 'atom-literals',
    'attribute-access', 'attribute-references', 'augassign', 'binary',
    'bitwise', 'bltin-code-objects', 'bltin-ellipsis-object',
    'bltin-file-objects', 'bltin-null-object', 'bltin-type-objects', 'booleans',
    'break', 'callable-types', 'calls', 'class', 'coercion-rules',
    'comparisons', 'compound', 'context-managers', 'continue', 'conversions',
    'customization', 'debugger', 'del', 'dict', 'dynamic-features', 'else',
    'exceptions', 'exec', 'execmodel', 'exprlists', 'floating', 'for',
    'formatstrings', 'function', 'global', 'id-classes', 'identifiers', 'if',
    'imaginary', 'import', 'in', 'integers', 'lambda', 'lists', 'naming',
    'numbers', 'numeric-types', 'objects', 'operator-summary', 'pass', 'power',
    'print', 'raise', 'return', 'sequence-methods', 'sequence-types',
    'shifting', 'slicings', 'specialattrs', 'specialnames',
    'string-conversions', 'string-methods', 'strings', 'subscriptions', 'truth',
    'try', 'types', 'typesfunctions', 'typesmapping', 'typesmethods',
    'typesmodules', 'typesseq', 'typesseq-mutable', 'unary', 'while', 'with',
    'yield'
]

from os import path
from time import asctime
from pprint import pformat
from docutils.io import StringOutput
from docutils.utils import new_document

try:
    from sphinx.builders import Builder
except ImportError:
    # using Sphinx < 0.6, which has a different package layout
    from sphinx.builder import Builder
    # monkey-patch toctree directive to accept (and ignore) the :numbered: flag
    from sphinx.directives.other import toctree_directive
    toctree_directive.options['numbered'] = toctree_directive.options['glob']

try:
    from sphinx.writers.text import TextWriter
except ImportError:
    from sphinx.textwriter import TextWriter


class PydocTopicsBuilder(Builder):
    name = 'pydoc-topics'

    def init(self):
        self.topics = {}

    def get_outdated_docs(self):
        return 'all pydoc topics'

    def get_target_uri(self, docname, typ=None):
        return ''  # no URIs

    def write(self, *ignored):
        writer = TextWriter(self)
        for label in self.status_iterator(pydoc_topic_labels, 'building topics... '):
            if label not in self.env.labels:
                self.warn('label %r not in documentation' % label)
                continue
            docname, labelid, sectname = self.env.labels[label]
            doctree = self.env.get_and_resolve_doctree(docname, self)
            document = new_document('<section node>')
            document.append(doctree.ids[labelid])
            destination = StringOutput(encoding='utf-8')
            writer.write(document, destination)
            self.topics[label] = writer.output

    def finish(self):
        f = open(path.join(self.outdir, 'pydoc_topics.py'), 'w')
        try:
            f.write('# Autogenerated by Sphinx on %s\n' % asctime())
            f.write('topics = ' + pformat(self.topics) + '\n')
        finally:
            f.close()

# Support for checking for suspicious markup

import suspicious

# Support for documenting Opcodes

import re
from sphinx import addnodes

opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)\s*\((.*)\)')

def parse_opcode_signature(env, sig, signode):
    """Transform an opcode signature into RST nodes."""
    m = opcode_sig_re.match(sig)
    if m is None:
        raise ValueError
    opname, arglist = m.groups()
    signode += addnodes.desc_name(opname, opname)
    paramlist = addnodes.desc_parameterlist()
    signode += paramlist
    paramlist += addnodes.desc_parameter(arglist, arglist)
    return opname.strip()


def setup(app):
    app.add_role('issue', issue_role)
    app.add_builder(PydocTopicsBuilder)
    app.add_builder(suspicious.CheckSuspiciousMarkupBuilder)
    app.add_description_unit('opcode', 'opcode', '%s (opcode)',
                             parse_opcode_signature)