buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/directives/desc.py
author wbernard
Wed, 23 Dec 2009 19:29:07 +0200
changeset 179 d8ac696cc51f
permissions -rw-r--r--
helium_7.0-r14027
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     1
# -*- coding: utf-8 -*-
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
    sphinx.directives.desc
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
    ~~~~~~~~~~~~~~~~~~~~~~
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
    :copyright: 2007-2008 by Georg Brandl.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
    :license: BSD.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
import re
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
import string
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
from docutils import nodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
from docutils.parsers.rst import directives
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
from sphinx import addnodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
from sphinx.util import ws_re
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
# ------ information units ---------------------------------------------------------
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
def desc_index_text(desctype, module, name, add_modules):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
    if desctype == 'function':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
        if not module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
            return _('%s() (built-in function)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
        return _('%s() (in module %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
    elif desctype == 'data':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
        if not module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
            return _('%s (built-in variable)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
        return _('%s (in module %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
    elif desctype == 'class':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
        if not module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
            return _('%s (built-in class)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
        return _('%s (class in %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
    elif desctype == 'exception':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
        return name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
    elif desctype == 'method':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
            clsname, methname = name.rsplit('.', 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
        except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
            if module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
                return _('%s() (in module %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
                return '%s()' % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
        if module and add_modules:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
            return _('%s() (%s.%s method)') % (methname, module, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
            return _('%s() (%s method)') % (methname, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
    elif desctype == 'staticmethod':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
            clsname, methname = name.rsplit('.', 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
        except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
            if module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
                return _('%s() (in module %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
                return '%s()' % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
        if module and add_modules:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
            return _('%s() (%s.%s static method)') % (methname, module, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
            return _('%s() (%s static method)') % (methname, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
    elif desctype == 'attribute':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
            clsname, attrname = name.rsplit('.', 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
        except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
            if module:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
                return _('%s (in module %s)') % (name, module)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
                return name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
        if module and add_modules:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
            return _('%s (%s.%s attribute)') % (attrname, module, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
            return _('%s (%s attribute)') % (attrname, clsname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
    elif desctype == 'cfunction':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
        return _('%s (C function)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
    elif desctype == 'cmember':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
        return _('%s (C member)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
    elif desctype == 'cmacro':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
        return _('%s (C macro)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
    elif desctype == 'ctype':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
        return _('%s (C type)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
    elif desctype == 'cvar':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
        return _('%s (C variable)') % name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
        raise ValueError('unhandled descenv: %s' % desctype)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
# ------ make field lists (like :param foo:) in desc bodies prettier
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
_ = lambda x: x  # make gettext extraction in constants possible
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
doc_fields_with_arg = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
    'param': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
    'parameter': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
    'arg': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
    'argument': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
    'keyword': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
    'kwarg': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
    'kwparam': '%param',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
    'type': '%type',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
    'raises': _('Raises'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
    'raise': 'Raises',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
    'exception': 'Raises',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
    'except': 'Raises',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
    'var': _('Variable'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
    'ivar': 'Variable',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
    'cvar': 'Variable',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
    'returns': _('Returns'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
    'return': 'Returns',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
doc_fields_without_arg = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
    'returns': 'Returns',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
    'return': 'Returns',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
    'rtype': _('Return type'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
del _
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
def _is_only_paragraph(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
    # determine if the node only contains one paragraph (and system messages)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
    if len(node) == 0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
        return False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
    elif len(node) > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
        for subnode in node[1:]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
            if not isinstance(subnode, nodes.system_message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
                return False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
    if isinstance(node[0], nodes.paragraph):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
        return True
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
    return False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
def handle_doc_fields(node, env):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
    # don't traverse, only handle field lists that are immediate children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
    for child in node.children:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
        if not isinstance(child, nodes.field_list):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
            continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        params = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
        param_nodes = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        param_types = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        new_list = nodes.field_list()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        for field in child:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
            fname, fbody = field
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
                typ, obj = fname.astext().split(None, 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
                typdesc = _(doc_fields_with_arg[typ])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
                if _is_only_paragraph(fbody):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
                    children = fbody.children[0].children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
                    children = fbody.children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
                if typdesc == '%param':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
                    if not params:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
                        pfield = nodes.field()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
                        pfield += nodes.field_name('', _('Parameters'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
                        pfield += nodes.field_body()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
                        params = nodes.bullet_list()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
                        pfield[1] += params
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
                        new_list += pfield
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
                    dlitem = nodes.list_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
                    dlpar = nodes.paragraph()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
                    dlpar += nodes.emphasis(obj, obj)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
                    dlpar += nodes.Text(' -- ', ' -- ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
                    dlpar += children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
                    param_nodes[obj] = dlpar
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
                    dlitem += dlpar
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
                    params += dlitem
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
                elif typdesc == '%type':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
                    typenodes = fbody.children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
                    if _is_only_paragraph(fbody):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
                        typenodes = [nodes.Text(' (')] + \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
                                    typenodes[0].children + [nodes.Text(')')]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
                    param_types[obj] = typenodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
                    fieldname = typdesc + ' '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
                    nfield = nodes.field()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
                    nfieldname = nodes.field_name(fieldname, fieldname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
                    nfield += nfieldname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
                    node = nfieldname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
                    if typ in doc_fields_with_linked_arg:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
                        node = addnodes.pending_xref(obj, reftype='obj',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
                                                     refcaption=False,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
                                                     reftarget=obj,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
                                                     modname=env.currmodule,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
                                                     classname=env.currclass)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
                        nfieldname += node
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
                    node += nodes.Text(obj, obj)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
                    nfield += nodes.field_body()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
                    nfield[1] += fbody.children
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
                    new_list += nfield
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
            except (KeyError, ValueError):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
                fnametext = fname.astext()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
                try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
                    typ = _(doc_fields_without_arg[fnametext])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
                except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
                    # at least capitalize the field name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
                    typ = fnametext.capitalize()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
                fname[0] = nodes.Text(typ)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
                new_list += field
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
        for param, type in param_types.iteritems():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
            if param in param_nodes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
                param_nodes[param][1:1] = type
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
        child.replace_self(new_list)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
# ------ functions to parse a Python or C signature and create desc_* nodes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
py_sig_re = re.compile(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
    r'''^ ([\w.]*\.)?            # class name(s)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
          (\w+)  \s*             # thing name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
          (?: \((.*)\)           # optional arguments
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
          (\s* -> \s* .*)? )? $  # optional return annotation
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
          ''', re.VERBOSE)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
py_paramlist_re = re.compile(r'([\[\],])')  # split at '[', ']' and ','
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
def parse_py_signature(signode, sig, desctype, module, env):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
    Transform a python signature into RST nodes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
    Return (fully qualified name of the thing, classname if any).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
    If inside a class, the current class name is handled intelligently:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
    * it is stripped from the displayed name if present
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
    * it is added to the full name (return value) if not present
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
    m = py_sig_re.match(sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
    if m is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
        raise ValueError
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
    classname, name, arglist, retann = m.groups()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
    if retann:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
        retann = u' \N{RIGHTWARDS ARROW} ' + retann.strip()[2:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
    if env.currclass:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
        add_module = False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
        if classname and classname.startswith(env.currclass):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
            fullname = classname + name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
            # class name is given again in the signature
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
            classname = classname[len(env.currclass):].lstrip('.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
        elif classname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
            # class name is given in the signature, but different
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
            # (shouldn't happen)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
            fullname = env.currclass + '.' + classname + name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
            # class name is not given in the signature
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
            fullname = env.currclass + '.' + name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
        add_module = True
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
        fullname = classname and classname + name or name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
    if desctype == 'staticmethod':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
        signode += addnodes.desc_annotation('static ', 'static ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
    if classname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
        signode += addnodes.desc_addname(classname, classname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
    # exceptions are a special case, since they are documented in the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
    # 'exceptions' module.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
    elif add_module and env.config.add_module_names and \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
           module and module != 'exceptions':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
        nodetext = module + '.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
        signode += addnodes.desc_addname(nodetext, nodetext)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
    signode += addnodes.desc_name(name, name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
    if not arglist:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
        if desctype in ('function', 'method', 'staticmethod'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
            # for callables, add an empty parameter list
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
            signode += addnodes.desc_parameterlist()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
        if retann:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
            signode += addnodes.desc_type(retann, retann)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
        return fullname, classname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
    signode += addnodes.desc_parameterlist()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
    stack = [signode[-1]]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
    for token in py_paramlist_re.split(arglist):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
        if token == '[':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
            opt = addnodes.desc_optional()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
            stack[-1] += opt
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
            stack.append(opt)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
        elif token == ']':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
                stack.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
            except IndexError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
                raise ValueError
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
        elif not token or token == ',' or token.isspace():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
            pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
            token = token.strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
            stack[-1] += addnodes.desc_parameter(token, token)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
    if len(stack) != 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
        raise ValueError
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
    if retann:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
        signode += addnodes.desc_type(retann, retann)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
    return fullname, classname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
c_sig_re = re.compile(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
    r'''^([^(]*?)          # return type
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
        ([\w:]+)  \s*      # thing name (colon allowed for C++ class names)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
        (?: \((.*)\) )?    # optionally arguments
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
        (\s+const)? $      # const specifier
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
    ''', re.VERBOSE)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
c_funcptr_sig_re = re.compile(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
    r'''^([^(]+?)          # return type
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
        (\( [^()]+ \)) \s* # name in parentheses
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
        \( (.*) \)         # arguments
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
        (\s+const)? $      # const specifier
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
    ''', re.VERBOSE)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
c_funcptr_name_re = re.compile(r'^\(\s*\*\s*(.*?)\s*\)$')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
# RE to split at word boundaries
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
wsplit_re = re.compile(r'(\W+)')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
# These C types aren't described in the reference, so don't try to create
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
# a cross-reference to them
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
def parse_c_type(node, ctype):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
    # add cross-ref nodes for all words
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
    for part in filter(None, wsplit_re.split(ctype)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
        tnode = nodes.Text(part, part)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
        if part[0] in string.letters+'_' and part not in stopwords:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
            pnode = addnodes.pending_xref(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
                '', reftype='ctype', reftarget=part, modname=None, classname=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
            pnode += tnode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
            node += pnode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
            node += tnode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
def parse_c_signature(signode, sig, desctype):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
    """Transform a C (or C++) signature into RST nodes."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
    # first try the function pointer signature regex, it's more specific
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
    m = c_funcptr_sig_re.match(sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
    if m is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
        m = c_sig_re.match(sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
    if m is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
        raise ValueError('no match')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
    rettype, name, arglist, const = m.groups()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
    signode += addnodes.desc_type('', '')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
    parse_c_type(signode[-1], rettype)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
        classname, funcname = name.split('::', 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
        classname += '::'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
        signode += addnodes.desc_addname(classname, classname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
        signode += addnodes.desc_name(funcname, funcname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
        # name (the full name) is still both parts
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
    except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
        signode += addnodes.desc_name(name, name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
    # clean up parentheses from canonical name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
    m = c_funcptr_name_re.match(name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
    if m:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
        name = m.group(1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
    if not arglist:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
        if desctype == 'cfunction':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
            # for functions, add an empty parameter list
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
            signode += addnodes.desc_parameterlist()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
        return name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
    paramlist = addnodes.desc_parameterlist()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
    arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
    # this messes up function pointer types, but not too badly ;)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
    args = arglist.split(',')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
    for arg in args:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
        arg = arg.strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
        param = addnodes.desc_parameter('', '', noemph=True)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   368
            ctype, argname = arg.rsplit(' ', 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   369
        except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   370
            # no argument name given, only the type
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   371
            parse_c_type(param, arg)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   372
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   373
            parse_c_type(param, ctype)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   374
            param += nodes.emphasis(' '+argname, ' '+argname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   375
        paramlist += param
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   376
    signode += paramlist
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   377
    if const:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   378
        signode += addnodes.desc_addname(const, const)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   379
    return name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   380
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   381
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   382
option_desc_re = re.compile(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   383
    r'((?:/|-|--)[-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   384
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   385
def parse_option_desc(signode, sig):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   386
    """Transform an option description into RST nodes."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   387
    count = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   388
    firstname = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   389
    for m in option_desc_re.finditer(sig):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   390
        optname, args = m.groups()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   391
        if count:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   392
            signode += addnodes.desc_addname(', ', ', ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   393
        signode += addnodes.desc_name(optname, optname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   394
        signode += addnodes.desc_addname(args, args)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   395
        if not count:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   396
            firstname = optname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   397
        count += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   398
    if not firstname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   399
        raise ValueError
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   400
    return firstname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   401
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   402
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   403
strip_backslash_re = re.compile(r'\\(?=[^\\])')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   404
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   405
def desc_directive(desctype, arguments, options, content, lineno,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   406
                   content_offset, block_text, state, state_machine):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   407
    env = state.document.settings.env
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   408
    inode = addnodes.index(entries=[])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   409
    node = addnodes.desc()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   410
    node['desctype'] = desctype
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   411
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   412
    noindex = ('noindex' in options)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   413
    node['noindex'] = noindex
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   414
    # remove backslashes to support (dummy) escapes; helps Vim's highlighting
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   415
    signatures = map(lambda s: strip_backslash_re.sub('', s.strip()),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   416
                     arguments[0].split('\n'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   417
    names = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   418
    clsname = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   419
    module = options.get('module', env.currmodule)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   420
    for i, sig in enumerate(signatures):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   421
        # add a signature node for each signature in the current unit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   422
        # and add a reference target for it
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   423
        sig = sig.strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   424
        signode = addnodes.desc_signature(sig, '')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   425
        signode['first'] = False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   426
        node.append(signode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   427
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   428
            if desctype in ('function', 'data', 'class', 'exception',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   429
                            'method', 'staticmethod', 'attribute'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   430
                name, clsname = parse_py_signature(signode, sig, desctype, module, env)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   431
            elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   432
                name = parse_c_signature(signode, sig, desctype)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   433
            elif desctype == 'cmdoption':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   434
                optname = parse_option_desc(signode, sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   435
                if not noindex:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   436
                    targetname = optname.replace('/', '-')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   437
                    if env.currprogram:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   438
                        targetname = '-' + env.currprogram + targetname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   439
                    targetname = 'cmdoption' + targetname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   440
                    signode['ids'].append(targetname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   441
                    state.document.note_explicit_target(signode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   442
                    inode['entries'].append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   443
                        ('pair', _('%scommand line option; %s') %
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   444
                         ((env.currprogram and env.currprogram + ' ' or ''), sig),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   445
                         targetname, targetname))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   446
                    env.note_progoption(optname, targetname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   447
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   448
            elif desctype == 'describe':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   449
                signode.clear()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   450
                signode += addnodes.desc_name(sig, sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   451
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   452
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   453
                # another registered generic x-ref directive
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   454
                rolename, indextemplate, parse_node = additional_xref_types[desctype]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   455
                if parse_node:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   456
                    fullname = parse_node(env, sig, signode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   457
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   458
                    signode.clear()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   459
                    signode += addnodes.desc_name(sig, sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   460
                    # normalize whitespace like xfileref_role does
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   461
                    fullname = ws_re.sub('', sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   462
                if not noindex:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   463
                    targetname = '%s-%s' % (rolename, fullname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   464
                    signode['ids'].append(targetname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   465
                    state.document.note_explicit_target(signode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   466
                    if indextemplate:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   467
                        indexentry = _(indextemplate) % (fullname,)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   468
                        indextype = 'single'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   469
                        colon = indexentry.find(':')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   470
                        if colon != -1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   471
                            indextype = indexentry[:colon].strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   472
                            indexentry = indexentry[colon+1:].strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   473
                        inode['entries'].append((indextype, indexentry,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   474
                                                 targetname, targetname))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   475
                    env.note_reftarget(rolename, fullname, targetname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   476
                # don't use object indexing below
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   477
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   478
        except ValueError, err:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   479
            # signature parsing failed
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   480
            signode.clear()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   481
            signode += addnodes.desc_name(sig, sig)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   482
            continue             # we don't want an index entry here
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   483
        # only add target and index entry if this is the first description of the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   484
        # function name in this desc block
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   485
        if not noindex and name not in names:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   486
            fullname = (module and module + '.' or '') + name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   487
            # note target
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   488
            if fullname not in state.document.ids:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   489
                signode['names'].append(fullname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   490
                signode['ids'].append(fullname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   491
                signode['first'] = (not names)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   492
                state.document.note_explicit_target(signode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   493
                env.note_descref(fullname, desctype, lineno)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   494
            names.append(name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   495
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   496
            indextext = desc_index_text(desctype, module, name,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   497
                                        env.config.add_module_names)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   498
            inode['entries'].append(('single', indextext, fullname, fullname))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   499
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   500
    subnode = addnodes.desc_content()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   501
    # needed for automatic qualification of members
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   502
    clsname_set = False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   503
    if desctype in ('class', 'exception') and names:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   504
        env.currclass = names[0]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   505
        clsname_set = True
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   506
    elif desctype in ('method', 'staticmethod', 'attribute') and \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   507
             clsname and not env.currclass:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   508
        env.currclass = clsname.strip('.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   509
        clsname_set = True
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   510
    # needed for association of version{added,changed} directives
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   511
    if names:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   512
        env.currdesc = names[0]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   513
    state.nested_parse(content, content_offset, subnode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   514
    handle_doc_fields(subnode, env)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   515
    if clsname_set:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   516
        env.currclass = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   517
    env.currdesc = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   518
    node.append(subnode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   519
    return [inode, node]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   520
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   521
desc_directive.content = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   522
desc_directive.arguments = (1, 0, 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   523
desc_directive.options = {'noindex': directives.flag,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   524
                          'module': directives.unchanged}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   525
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   526
desctypes = [
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   527
    # the Python ones
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   528
    'function',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   529
    'data',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   530
    'class',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   531
    'method',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   532
    'staticmethod',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   533
    'attribute',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   534
    'exception',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   535
    # the C ones
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   536
    'cfunction',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   537
    'cmember',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   538
    'cmacro',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   539
    'ctype',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   540
    'cvar',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   541
    # for command line options
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   542
    'cmdoption',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   543
    # the generic one
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   544
    'describe',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   545
    'envvar',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   546
]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   547
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   548
for _name in desctypes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   549
    directives.register_directive(_name, desc_directive)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   550
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   551
_ = lambda x: x
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   552
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   553
# Generic cross-reference types; they can be registered in the application;
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   554
# the directives are either desc_directive or target_directive
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   555
additional_xref_types = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   556
    # directive name: (role name, index text, function to parse the desc node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   557
    'envvar': ('envvar', _('environment variable; %s'), None),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   558
}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   559
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   560
del _
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   561
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   562
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   563
# ------ target --------------------------------------------------------------------
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   564
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   565
def target_directive(targettype, arguments, options, content, lineno,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   566
                     content_offset, block_text, state, state_machine):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   567
    """Generic target for user-defined cross-reference types."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   568
    env = state.document.settings.env
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   569
    rolename, indextemplate, foo = additional_xref_types[targettype]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   570
    # normalize whitespace in fullname like xfileref_role does
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   571
    fullname = ws_re.sub('', arguments[0].strip())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   572
    targetname = '%s-%s' % (rolename, fullname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   573
    node = nodes.target('', '', ids=[targetname])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   574
    state.document.note_explicit_target(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   575
    ret = [node]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   576
    if indextemplate:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   577
        indexentry = indextemplate % (fullname,)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   578
        indextype = 'single'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   579
        colon = indexentry.find(':')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   580
        if colon != -1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   581
            indextype = indexentry[:colon].strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   582
            indexentry = indexentry[colon+1:].strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   583
        inode = addnodes.index(entries=[(indextype, indexentry, targetname, targetname)])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   584
        ret.insert(0, inode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   585
    env.note_reftarget(rolename, fullname, targetname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   586
    return ret
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   587
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   588
target_directive.content = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   589
target_directive.arguments = (1, 0, 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   590
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   591
# note, the target directive is not registered here, it is used by the application
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   592
# when registering additional xref types