def make_field(self, types, domain, items, env=None):
     fieldname = nodes.field_name('', self.label)
     listnode = self.list_type()
     if len(items) == 1 and self.can_collapse:
         return Field.make_field(self, types, domain, items[0])
     for fieldarg, content in items:
         par = nodes.paragraph()
         par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong)
         listnode += nodes.list_item('', par)
     fieldbody = nodes.field_body('', listnode)
     return nodes.field('', fieldname, fieldbody)
Esempio n. 2
0
 def make_field(self, types, domain, items):
     fieldname = nodes.field_name('', self.label)
     if len(items) == 1 and self.can_collapse:
         return Field.make_field(self, types, domain, items[0])
     bodynode = nodes.paragraph()
     for i, (fieldarg, content) in enumerate(items):
         bodynode += nodes.Text(', ') if i else None
         bodynode += self.make_xref(self.bodyrolename, domain,
                                    content[0].astext(), nodes.Text)
     fieldbody = nodes.field_body('', bodynode)
     return nodes.field('', fieldname, fieldbody)
Esempio n. 3
0
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type('confval',
                        'confval',
                        objname='configuration value',
                        indextemplate='pair: %s; configuration value',
                        doc_field_types=[
                            PyField('type',
                                    label=_('Type'),
                                    has_arg=False,
                                    names=('type', ),
                                    bodyrolename='class'),
                            Field(
                                'default',
                                label=_('Default'),
                                has_arg=False,
                                names=('default', ),
                            ),
                        ])
Esempio n. 4
0
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type("confval",
                        "confval",
                        objname="configuration value",
                        indextemplate="pair: %s; configuration value",
                        doc_field_types=[
                            PyField("type",
                                    label=_("Type"),
                                    has_arg=False,
                                    names=("type", ),
                                    bodyrolename="class"),
                            Field(
                                "default",
                                label=_("Default"),
                                has_arg=False,
                                names=("default", ),
                            ),
                        ])
Esempio n. 5
0
def setup(app: Sphinx) -> None:
    """Register the :dir: role.

    This is just a shortcut to curb the cognitive dissonance
    when saying :file:`directory/`.
    """
    app.add_role("dir", DirRole())
    app.add_object_type(
        "confval",
        "confval",
        objname="configuration parameter",
        doc_field_types=[
            Field(
                "default",
                label="default",
                has_arg=True,
                names=("default", ),
                bodyrolename="class",
            )
        ],
    )
Esempio n. 6
0
def setup(app) -> Dict[str, Any]:
    app.add_config_value('ceph_confval_imports',
                         default=[],
                         rebuild='html',
                         types=[str])
    app.add_config_value('ceph_confval_mgr_module_path',
                         default=[],
                         rebuild='html',
                         types=[str])
    app.add_config_value('ceph_confval_mgr_python_path',
                         default=[],
                         rebuild='',
                         types=[str])
    app.add_object_type(
        'confsec',
        'confsec',
        objname='configuration section',
        indextemplate='pair: %s; configuration section',
        doc_field_types=[
            Field(
                'example',
                label=_('Example'),
                has_arg=False,
            )]
    )
    app.add_object_type(
        'confval',
        'confval',
        objname='configuration option',
    )
    app.add_directive_to_domain('std', 'mgr_module', CephModule)
    app.add_directive_to_domain('std', 'confval', CephOption, override=True)
    app.connect('env-purge-doc', _reset_ref_context)

    return {
        'version': 'builtin',
        'parallel_read_safe': True,
        'parallel_write_safe': True,
    }
Esempio n. 7
0
class ReFORMStatement(ReFORMMarkup):
    """
    Description of a reFORM statement.
    """
    doc_field_types = [
        TypedField('parameter',
                   label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
    ]

    def handle_signature(self, sig, signode):
        name = sig.strip()
        nameid = name.split()[0]
        desc_name = name
        signode += addnodes.desc_name(nameid, desc_name)
        return nameid
Esempio n. 8
0
def setup(app):
    from sphinx.util.docfields import Field, TypedField

    increase_python_stack()

    # the :ghci-cmd: directive used in ghci.rst
    app.add_object_type('ghci-cmd', 'ghci-cmd',
                        parse_node=parse_ghci_cmd,
                        objname='GHCi command',
                        indextemplate='pair: %s; GHCi command')

    # Haddock references
    app.add_role('th-ref', haddock_role('template-haskell'))
    app.add_role('base-ref', haddock_role('base'))
    app.add_role('cabal-ref', haddock_role('Cabal'))
    app.add_role('ghc-compact-ref', haddock_role('ghc-compact'))
    app.add_role('ghc-prim-ref', haddock_role('ghc-prim'))
    app.add_role('parallel-ref', haddock_role('parallel'))
    app.add_role('array-ref', haddock_role('array'))

    app.add_object_type('rts-flag', 'rts-flag',
                        objname='runtime system command-line option',
                        parse_node=parse_flag,
                        indextemplate='pair: %s; RTS option',
                        doc_field_types=[
                            Field('since', label='Introduced in GHC version', names=['since'])
                        ])

    app.add_object_type('event-type', 'event-type',
                        objname='event log event type',
                        indextemplate='pair: %s; eventlog event type',
                        doc_field_types=[
                            Field('since', label='Introduced in GHC version', names=['since']),
                            Field('tag', label='Event type ID', names=['tag']),
                            Field('length', label='Record length', names=['length']),
                            TypedField('fields', label='Fields', names='field', typenames=('fieldtype', 'type'))
                        ])

    app.add_object_type('pragma', 'pragma',
                        objname='Haskell pragma',
                        parse_node=parse_pragma,
                        indextemplate='pair: %s; pragma',
                        doc_field_types=[
                            Field('since', label='Introduced in GHC version', names=['since']),
                            Field('where', label='Allowed contexts', names=['where'])
                        ])
Esempio n. 9
0
class CabalField(CabalObject):
    '''
    Base for fields in *.cabal files
    '''
    option_spec = {
        'noindex': directives.flag,
        'deprecated': parse_deprecated,
        'since': StrictVersion,
        'synopsis': lambda x: x
    }

    doc_field_types = [
        Field('default',
              label='Default value',
              names=['default'],
              has_arg=False)
    ]

    def handle_signature(self, sig, signode):
        '''
        As in sphinx.directives.ObjectDescription

        By default make an object description from name and adding
        either deprecated or since as annotation.
        '''
        env = self.state.document.settings.env

        sig = sig.strip()
        parts = sig.split(':', 1)
        name = parts[0]
        signode += addnodes.desc_name(name, name)
        signode += addnodes.desc_addname(': ', ': ')

        if len(parts) > 1:
            rest = parts[1].strip()
            signode += addnodes.desc_annotation(rest, rest)

        return name
Esempio n. 10
0
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type('confval',
                        'confval',
                        objname='configuration value',
                        indextemplate='pair: %s; configuration value',
                        doc_field_types=[
                            PyField('type',
                                    label=_('Type'),
                                    has_arg=False,
                                    names=('type', ),
                                    bodyrolename='class'),
                            Field(
                                'default',
                                label=_('Default'),
                                has_arg=False,
                                names=('default', ),
                            ),
                        ])
    app.add_stylesheet("css/theme_overrides.css")
    app.add_javascript("js/version_switch.js")
Esempio n. 11
0
def make_confval(app):
    # Copy-pasted from https://github.com/rtfd/sphinx_rtd_theme
    from sphinx.locale import _
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type('confval',
                        'confval',
                        objname='configuration value',
                        indextemplate='pair: %s; configuration value',
                        doc_field_types=[
                            PyField('type',
                                    label=_('Type'),
                                    has_arg=False,
                                    names=('type', ),
                                    bodyrolename='class'),
                            Field(
                                'default',
                                label=_('Default'),
                                has_arg=False,
                                names=('default', ),
                            ),
                        ])
Esempio n. 12
0
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field
    app.add_css_file('/source/_static/custom.css')
    app.add_stylesheet('/source/_static/theme_override.css')
    app.add_object_type('confval',
                        'confval',
                        objname='configuration value',
                        indextemplate='pair: %s; configuration value',
                        doc_field_types=[
                            PyField('type',
                                    label=_('Type'),
                                    has_arg=False,
                                    names=('type', ),
                                    bodyrolename='class'),
                            Field(
                                'default',
                                label=_('Default'),
                                has_arg=False,
                                names=('default', ),
                            ),
                        ])
    # Patch the MATLAB lexer to correct wrong highlighting
    from sphinx.highlighting import lexers
    from pygments.lexers import MatlabLexer
    from pygments.token import Name
    from pygments.filters import NameHighlightFilter
    matlab_lexer = MatlabLexer()
    matlab_lexer.add_filter(
        NameHighlightFilter(
            names=[
                'function', 'end', 'if', 'else', 'elseif', 'switch', 'case',
                'return', 'otherwise'
            ],
            tokentype=Name.Function,
        ))
    app.add_lexer('matlab', matlab_lexer)
Esempio n. 13
0
class DotNetProperty(DotNetObject):

    option_spec = {
        'name': directives.unchanged,
        'prefix': directives.unchanged,
        'type': directives.unchanged,
    }

    doc_field_types = [
        Field('value',
              label=l_('Value'),
              has_arg=False,
              names=('value', 'value')),
    ]

    def handle_signature(self, sig, signode):
        name = self.options['name']
        prefix = self.options['prefix']
        type_v = json.loads(self.options['type'])

        if prefix != 'readwrite':
            signode += nodes.Text(prefix, prefix)
            signode += nodes.Text(' ', u'\xa0')

        xref = addnodes.pending_xref(':ref:`' + type_v[1] + '`',
                                     refdomain='std',
                                     reftype='ref',
                                     reftarget=ws_re.sub(
                                         ' ', type_v[1].lower()),
                                     refexplicit=False)
        xref += nodes.Text(type_v[0], type_v[0])
        signode += xref
        signode += nodes.Text(' ', u'\xa0')

        signode += addnodes.desc_name(name, name)

        return name, ""
class JSONDefinition(JSONObject):
    doc_field_types = [
        Field("type", label=l_("Type"), names=("type")),
        TypedField(
            "props",
            label=l_("Properties"),
            names=("property", "prop"),
            typenames=("array", "boolean", "integer", "null", "number",
                       "object", "string"),
        )
    ]

    def handle_signature(self, sig, signode):
        import ipdb
        ipdb.set_trace()
        signode += addnodes.desc_name(sig, sig)
        fullname = self.objtype.capitalize() + " " + sig
        signode["fullname"] = fullname
        return (fullname, sig)

    def add_target_and_index(self, name_cls, sig, signode):
        signode["ids"].append("{0}-{1}".format(self.objtype, sig))
        self.env.domaindata["jsschema"]["objects"][sig] = (self.env.docname,
                                                           self.objtype, "")
Esempio n. 15
0
class BBDomain(Domain):
    name = 'bb'
    label = 'Buildbot'

    object_types = {
        'cfg': ObjType('cfg', 'cfg'),
        'sched': ObjType('sched', 'sched'),
        'chsrc': ObjType('chsrc', 'chsrc'),
        'step': ObjType('step', 'step'),
        'reporter': ObjType('reporter', 'reporter'),
        'configurator': ObjType('configurator', 'configurator'),
        'worker': ObjType('worker', 'worker'),
        'cmdline': ObjType('cmdline', 'cmdline'),
        'msg': ObjType('msg', 'msg'),
        'event': ObjType('event', 'event'),
        'rtype': ObjType('rtype', 'rtype'),
        'rpath': ObjType('rpath', 'rpath'),
    }

    directives = {
        'cfg':
        make_ref_target_directive('cfg',
                                  indextemplates=[
                                      'single: Buildmaster Config; %s',
                                      'single: %s (Buildmaster Config)',
                                  ]),
        'sched':
        make_ref_target_directive('sched',
                                  indextemplates=[
                                      'single: Schedulers; %s',
                                      'single: %s Scheduler',
                                  ]),
        'chsrc':
        make_ref_target_directive('chsrc',
                                  indextemplates=[
                                      'single: Change Sources; %s',
                                      'single: %s Change Source',
                                  ]),
        'step':
        make_ref_target_directive('step',
                                  indextemplates=[
                                      'single: Build Steps; %s',
                                      'single: %s Build Step',
                                  ]),
        'reporter':
        make_ref_target_directive('reporter',
                                  indextemplates=[
                                      'single: Reporter Targets; %s',
                                      'single: %s Reporter Target',
                                  ]),
        'configurator':
        make_ref_target_directive('configurator',
                                  indextemplates=[
                                      'single: Configurators; %s',
                                      'single: %s Configurators',
                                  ]),
        'worker':
        make_ref_target_directive('worker',
                                  indextemplates=[
                                      'single: Build Workers; %s',
                                      'single: %s Build Worker',
                                  ]),
        'cmdline':
        make_ref_target_directive('cmdline',
                                  indextemplates=[
                                      'single: Command Line Subcommands; %s',
                                      'single: %s Command Line Subcommand',
                                  ]),
        'msg':
        make_ref_target_directive('msg',
                                  indextemplates=[
                                      'single: Message Schema; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='routing key:',
                                  doc_field_types=[
                                      TypedField('key',
                                                 label='Keys',
                                                 names=('key', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                      Field('var',
                                            label='Variable',
                                            names=('var', )),
                                  ]),
        'event':
        make_ref_target_directive('event',
                                  indextemplates=[
                                      'single: event; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='event:',
                                  doc_field_types=[]),
        'rtype':
        make_ref_target_directive('rtype',
                                  indextemplates=[
                                      'single: Resource Type; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='resource type:',
                                  doc_field_types=[
                                      TypedField('attr',
                                                 label='Attributes',
                                                 names=('attr', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
        'rpath':
        make_ref_target_directive('rpath',
                                  indextemplates=[
                                      'single: Resource Path; %s',
                                  ],
                                  name_annotation='path:',
                                  has_content=True,
                                  doc_field_types=[
                                      TypedField('pathkey',
                                                 label='Path Keys',
                                                 names=('pathkey', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
        'raction':
        make_ref_target_directive('raction',
                                  indextemplates=[
                                      'single: Resource Action; %s',
                                  ],
                                  name_annotation='POST with method:',
                                  has_content=True,
                                  doc_field_types=[
                                      TypedField('body',
                                                 label='Body keys',
                                                 names=('body', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
    }

    roles = {
        'cfg': XRefRole(),
        'sched': XRefRole(),
        'chsrc': XRefRole(),
        'step': XRefRole(),
        'reporter': XRefRole(),
        'configurator': XRefRole(),
        'worker': XRefRole(),
        'cmdline': XRefRole(),
        'msg': XRefRole(),
        'event': XRefRole(),
        'rtype': XRefRole(),
        'rpath': XRefRole(),
        'index': XRefRole()
    }

    initial_data = {
        'targets': {},  # type -> target -> (docname, targetname)
    }

    indices = [
        make_index("cfg", "Buildmaster Configuration Index"),
        make_index("sched", "Scheduler Index"),
        make_index("chsrc", "Change Source Index"),
        make_index("step", "Build Step Index"),
        make_index("reporter", "Reporter Target Index"),
        make_index("configurator", "Configurator Target Index"),
        make_index("worker", "Build Worker Index"),
        make_index("cmdline", "Command Line Index"),
        make_index("msg", "MQ Routing Key Index"),
        make_index("event", "Data API Event Index"),
        make_index("rtype", "REST/Data API Resource Type Index"),
        make_index("rpath", "REST/Data API Path Index"),
        make_index("raction", "REST/Data API Actions Index"),
    ]

    def resolve_xref(self, env, fromdocname, builder, typ, target, node,
                     contnode):
        if typ == 'index':
            for idx in self.indices:
                if idx.name == target:
                    break
            else:
                raise KeyError("no index named '%s'" % target)
            return idx.resolve_ref(self, env, fromdocname, builder, typ,
                                   target, node, contnode)
        elif typ in self.directives:
            dir = self.directives[typ]
            return dir.resolve_ref(self, env, fromdocname, builder, typ,
                                   target, node, contnode)
Esempio n. 16
0
File: c.py Progetto: yhalapup/sphinx
class CObject(ObjectDescription):
    """
    Description of a C language object.
    """

    doc_field_types = [
        TypedField('parameter',
                   label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=l_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    # These C types aren't described anywhere, so don't try to create
    # a cross-reference to them
    stopwords = set(('const', 'void', 'char', 'int', 'long', 'FILE', 'struct'))

    def _parse_type(self, node, ctype):
        # add cross-ref nodes for all words
        for part in filter(None, wsplit_re.split(ctype)):
            tnode = nodes.Text(part, part)
            if part[0] in string.ascii_letters+'_' and \
                   part not in self.stopwords:
                pnode = addnodes.pending_xref('',
                                              refdomain='c',
                                              reftype='type',
                                              reftarget=part,
                                              modname=None,
                                              classname=None)
                pnode += tnode
                node += pnode
            else:
                node += tnode

    def handle_signature(self, sig, signode):
        """Transform a C signature into RST nodes."""
        # first try the function pointer signature regex, it's more specific
        m = c_funcptr_sig_re.match(sig)
        if m is None:
            m = c_sig_re.match(sig)
        if m is None:
            raise ValueError('no match')
        rettype, name, arglist, const = m.groups()

        signode += addnodes.desc_type('', '')
        self._parse_type(signode[-1], rettype)
        try:
            classname, funcname = name.split('::', 1)
            classname += '::'
            signode += addnodes.desc_addname(classname, classname)
            signode += addnodes.desc_name(funcname, funcname)
            # name (the full name) is still both parts
        except ValueError:
            signode += addnodes.desc_name(name, name)
        # clean up parentheses from canonical name
        m = c_funcptr_name_re.match(name)
        if m:
            name = m.group(1)

        typename = self.env.temp_data.get('c:type')
        if self.name == 'c:member' and typename:
            fullname = typename + '.' + name
        else:
            fullname = name

        if not arglist:
            if self.objtype == 'function':
                # for functions, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if const:
                signode += addnodes.desc_addname(const, const)
            return fullname

        paramlist = addnodes.desc_parameterlist()
        arglist = arglist.replace('`', '').replace('\\ ', '')  # remove markup
        # this messes up function pointer types, but not too badly ;)
        args = arglist.split(',')
        for arg in args:
            arg = arg.strip()
            param = addnodes.desc_parameter('', '', noemph=True)
            try:
                ctype, argname = arg.rsplit(' ', 1)
            except ValueError:
                # no argument name given, only the type
                self._parse_type(param, arg)
            else:
                self._parse_type(param, ctype)
                # separate by non-breaking space in the output
                param += nodes.emphasis(' ' + argname, u'\xa0' + argname)
            paramlist += param
        signode += paramlist
        if const:
            signode += addnodes.desc_addname(const, const)
        return fullname

    def get_index_text(self, name):
        if self.objtype == 'function':
            return _('%s (C function)') % name
        elif self.objtype == 'member':
            return _('%s (C member)') % name
        elif self.objtype == 'macro':
            return _('%s (C macro)') % name
        elif self.objtype == 'type':
            return _('%s (C type)') % name
        elif self.objtype == 'var':
            return _('%s (C variable)') % name
        else:
            return ''

    def add_target_and_index(self, name, sig, signode):
        # note target
        if name not in self.state.document.ids:
            signode['names'].append(name)
            signode['ids'].append(name)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            inv = self.env.domaindata['c']['objects']
            if name in inv:
                self.state_machine.reporter.warning(
                    'duplicate C object description of %s, ' % name +
                    'other instance in ' + self.env.doc2path(inv[name][0]),
                    line=self.lineno)
            inv[name] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(('single', indextext, name, ''))

    def before_content(self):
        self.typename_set = False
        if self.name == 'c:type':
            if self.names:
                self.env.temp_data['c:type'] = self.names[0]
                self.typename_set = True

    def after_content(self):
        if self.typename_set:
            self.env.temp_data['c:type'] = None
Esempio n. 17
0
class RoseConfigDirective(RoseDirective):
    """Directive for documenting config sections.

    Optional Attributes:
        * ``envvar`` - Associate an environment variable with this
          configuration option.
        * ``compulsory`` - Set to ``True`` for compulsory settings, omit this
          field for optional settings.

    Additional ref_context:
        * ``rose:conf-section`` - Set for parent configurations, is available
          to any child nodes.

    Example:

        Click :guilabel:`source` to view source code.

        .. code-block:: rst

           .. rose:conf:: foo

              :default: foo
              :opt argtype foo: Description of option ``foo``.
              :opt bar: Description of bar

              A setting called ``foo``.

           .. rose:conf:: bar

              A section called ``bar``.

              .. rose:conf:: baz

                 :compulsory: True
                 :env: AN_ASSOCIATED_ENVIRONMENT_VARIABLE

                 A config called ``[bar]baz``.
    """
    NAME = 'conf'
    LABEL = 'Config'
    SECTION_REF_CONTEXT = 'conf-section'
    ARGUMENT_REGEX = OPT_ARG_REGEX
    ARGUMENT_SEPARATOR = '='

    # Add custom fields.
    doc_field_types = [
        # NOTE: The field label must be sort to avoid causing a line break.
        Field('envvar',
              label='Env Var',
              has_arg=False,
              names=('env', ),
              bodyrolename='obj'),
        Field('compulsory',
              label='Compulsory',
              has_arg=True,
              names=('compulsory', )),
        Field('default', label='Default', has_arg=False, names=('default', )),
        TypedField('option',
                   label='Options',
                   names=('opt', ),
                   typerolename='obj',
                   typenames=('paramtype', 'type'),
                   can_collapse=True)
    ]

    def run(self):
        """Overridden to add the :rose:conf-section: ``ref_context`` variable
        for nested sections."""
        if self.registered_children or any('.. rose:conf::' in line
                                           for line in self.content):
            # This configuration contains other configurations i.e. it is a
            # configuration section. Apply a custom_name_template so that it is
            # written inside square brackets.
            self.custom_name_template = '[%s]'
            # Sections cannot be written with argument examples.
            self.ARGUMENT_SEPARATOR = None
            self.ARGUMENT_REGEX = None
            # Add a ref_context variable to mark this node as a config section.
            self.add_ref_context(self.SECTION_REF_CONTEXT)

        return RoseDirective.run(self)
Esempio n. 18
0
class BBDomain(Domain):
    name = 'bb'
    label = 'Buildbot'

    object_types = {
        'cfg': ObjType('cfg', 'cfg'),
        'sched': ObjType('sched', 'sched'),
        'chsrc': ObjType('chsrc', 'chsrc'),
        'step': ObjType('step', 'step'),
        'reporter': ObjType('reporter', 'reporter'),
        'configurator': ObjType('configurator', 'configurator'),
        'worker': ObjType('worker', 'worker'),
        'cmdline': ObjType('cmdline', 'cmdline'),
        'msg': ObjType('msg', 'msg'),
        'event': ObjType('event', 'event'),
        'rtype': ObjType('rtype', 'rtype'),
        'rpath': ObjType('rpath', 'rpath'),
        'raction': ObjType('raction', 'raction'),
    }

    directives = {
        'cfg':
        make_ref_target_directive('cfg',
                                  indextemplates=[
                                      'single: Buildmaster Config; %s',
                                      'single: %s (Buildmaster Config)',
                                  ]),
        'sched':
        make_ref_target_directive('sched',
                                  indextemplates=[
                                      'single: Schedulers; %s',
                                      'single: %s Scheduler',
                                  ]),
        'chsrc':
        make_ref_target_directive('chsrc',
                                  indextemplates=[
                                      'single: Change Sources; %s',
                                      'single: %s Change Source',
                                  ]),
        'step':
        make_ref_target_directive('step',
                                  indextemplates=[
                                      'single: Build Steps; %s',
                                      'single: %s Build Step',
                                  ]),
        'reporter':
        make_ref_target_directive('reporter',
                                  indextemplates=[
                                      'single: Reporter Targets; %s',
                                      'single: %s Reporter Target',
                                  ]),
        'configurator':
        make_ref_target_directive('configurator',
                                  indextemplates=[
                                      'single: Configurators; %s',
                                      'single: %s Configurators',
                                  ]),
        'worker':
        make_ref_target_directive('worker',
                                  indextemplates=[
                                      'single: Build Workers; %s',
                                      'single: %s Build Worker',
                                  ]),
        'cmdline':
        make_ref_target_directive('cmdline',
                                  indextemplates=[
                                      'single: Command Line Subcommands; %s',
                                      'single: %s Command Line Subcommand',
                                  ]),
        'msg':
        make_ref_target_directive('msg',
                                  indextemplates=[
                                      'single: Message Schema; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='routing key:',
                                  doc_field_types=[
                                      TypedField('key',
                                                 label='Keys',
                                                 names=('key', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                      Field('var',
                                            label='Variable',
                                            names=('var', )),
                                  ]),
        'event':
        make_ref_target_directive('event',
                                  indextemplates=[
                                      'single: event; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='event:',
                                  doc_field_types=[]),
        'rtype':
        make_ref_target_directive('rtype',
                                  indextemplates=[
                                      'single: Resource Type; %s',
                                  ],
                                  has_content=True,
                                  name_annotation='resource type:',
                                  doc_field_types=[
                                      TypedField('attr',
                                                 label='Attributes',
                                                 names=('attr', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
        'rpath':
        make_ref_target_directive('rpath',
                                  indextemplates=[
                                      'single: Resource Path; %s',
                                  ],
                                  name_annotation='path:',
                                  has_content=True,
                                  doc_field_types=[
                                      TypedField('pathkey',
                                                 label='Path Keys',
                                                 names=('pathkey', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
        'raction':
        make_ref_target_directive('raction',
                                  indextemplates=[
                                      'single: Resource Action; %s',
                                  ],
                                  name_annotation='POST with method:',
                                  has_content=True,
                                  doc_field_types=[
                                      TypedField('body',
                                                 label='Body keys',
                                                 names=('body', ),
                                                 typenames=('type', ),
                                                 can_collapse=True),
                                  ]),
    }

    roles = {
        'cfg': XRefRole(),
        'sched': XRefRole(),
        'chsrc': XRefRole(),
        'step': XRefRole(),
        'reporter': XRefRole(),
        'configurator': XRefRole(),
        'worker': XRefRole(),
        'cmdline': XRefRole(),
        'msg': XRefRole(),
        'event': XRefRole(),
        'rtype': XRefRole(),
        'rpath': XRefRole(),
        'index': XRefRole()
    }

    initial_data = {
        'targets': {},  # type -> target -> (docname, targetname)
    }

    indices = [
        make_index("cfg", "Buildmaster Configuration Index"),
        make_index("sched", "Scheduler Index"),
        make_index("chsrc", "Change Source Index"),
        make_index("step", "Build Step Index"),
        make_index("reporter", "Reporter Target Index"),
        make_index("configurator", "Configurator Target Index"),
        make_index("worker", "Build Worker Index"),
        make_index("cmdline", "Command Line Index"),
        make_index("msg", "MQ Routing Key Index"),
        make_index("event", "Data API Event Index"),
        make_index("rtype", "REST/Data API Resource Type Index"),
        make_index("rpath", "REST/Data API Path Index"),
        make_index("raction", "REST/Data API Actions Index"),
    ]

    def resolve_xref(self, env, fromdocname, builder, typ, target, node,
                     contnode):
        if typ == 'index':
            for idx in self.indices:
                if idx.name == target:
                    break
            else:
                raise KeyError("no index named '%s'" % target)
            return idx.resolve_ref(self, env, fromdocname, builder, typ,
                                   target, node, contnode)
        elif typ in self.directives:
            dir = self.directives[typ]
            return dir.resolve_ref(self, env, fromdocname, builder, typ,
                                   target, node, contnode)

    def merge_domaindata(self, docnames, otherdata):
        for typ in self.object_types:
            if typ not in otherdata['targets']:
                continue

            if typ not in self.data['targets']:
                self.data['targets'][typ] = otherdata['targets'][typ]
                continue

            self_data = self.data['targets'][typ]
            other_data = otherdata['targets'][typ]

            for target_name, target_data in other_data.items():
                if target_name in self_data:
                    # for some reason we end up with multiple references to the same things in
                    # multiple domains. If both instances point to the same location, ignore it,
                    # otherwise issue a warning.
                    if other_data[target_name] == self_data[target_name]:
                        continue

                    self_path = '{0}#{1}'.format(
                        self.env.doc2path(self_data[target_name][0]),
                        self_data[target_name][1])

                    other_path = '{0}#{1}'.format(
                        self.env.doc2path(other_path[target_name][0]),
                        other_path[target_name][1])

                    logger.warning(('Duplicate index {} reference {} in {}, '
                                    'other instance in {}').format(
                                        typ, target_name, self_path,
                                        other_path))
                else:
                    self_data[target_name] = target_data
Esempio n. 19
0
class MongoDBObject(ObjectDescription):
    """
    Description of a MongoDB object.
    """
    #: If set to ``True`` this object is callable and a `desc_parameterlist` is
    #: added
    has_arguments = False

    #: what is displayed right before the documentation entry
    display_prefix = None

    def handle_signature(self, sig, signode):
        sig = sig.strip()
        if '(' in sig and sig[-1:] == ')':
            prefix, arglist = sig.split('(', 1)
            prefix = prefix.strip()
            arglist = arglist[:-1].strip()
        else:
            prefix = sig
            arglist = None
        if '.' in prefix:
            nameprefix, name = prefix.rsplit('.', 1)
        else:
            nameprefix = None
            name = prefix

        objectname = self.env.temp_data.get('mongodb:object')
        if nameprefix:
            if objectname:
                # someone documenting the method of an attribute of the current
                # object? shouldn't happen but who knows...
                nameprefix = objectname + '.' + nameprefix
            fullname = nameprefix + '.' + name
        elif objectname:
            fullname = objectname + '.' + name
        else:
            # just a function or constructor
            objectname = ''
            fullname = name

        signode['object'] = objectname
        signode['fullname'] = fullname

        if self.display_prefix:
            signode += addnodes.desc_annotation(self.display_prefix,
                                                self.display_prefix)
        if nameprefix:
            signode += addnodes.desc_addname(nameprefix + '.', nameprefix + '.')
        signode += addnodes.desc_name(name, name)
        if self.has_arguments:
            if not arglist:
                signode += addnodes.desc_parameterlist()
            else:
                _pseudo_parse_arglist(signode, arglist)
        return fullname, nameprefix

    def add_target_and_index(self, name_obj, sig, signode):
        objectname = self.options.get(
            'object', self.env.temp_data.get('mongodb:object'))
        fullname = name_obj[0]
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname.replace('$', '_S_'))
            signode['first'] = not self.names
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['mongodb']['objects']
            # if fullname in objects:
            #     self.state_machine.reporter.warning(
            #         'duplicate object description of %s, ' % fullname +
            #         'other instance in ' +
            #         self.env.doc2path(objects[fullname][0]),
            #         line=self.lineno)
            objects[fullname] = self.env.docname, self.objtype
        # elif self.objtype == "binary":
        #     signode['names'].append(fullname)
        #     signode['ids'].append(fullname.replace('$', '_S_'))
        #     signode['first'] = not self.names
        #     self.state.document.note_explicit_target(signode)

        indextext = self.get_index_text(objectname, name_obj)
        if indextext:
            self.indexnode['entries'].append(('single', indextext,
                                              fullname.replace('$', '_S_'),
                                              ''))

    def get_index_text(self, objectname, name_obj):
        name, obj = name_obj
        if self.objtype == 'dbcommand':
            return _('%s (database command)') % name
        elif self.objtype == 'operator':
            return _('%s (operator)') % name
        elif self.objtype == 'projection':
            return _('%s (projection operator)') % name
        elif self.objtype == 'program':
            return _('%s (program)') % name
        elif self.objtype == 'setting':
            return _('%s (setting)') % (name)
        elif self.objtype == 'status':
            return _('%s (status)') % (name)
        elif self.objtype == 'stats':
            return _('%s (statistic)') % (name)
        elif self.objtype == 'data':
            return _('%s (shell output)') % (name)
        elif self.objtype == 'method':
            return _('%s (shell method)') % (name)
        elif self.objtype == 'collflag':
            return _('%s (collection flag)') % (name)
        elif self.objtype == 'readmode':
            return _('%s (read preference mode)') % (name)
        elif self.objtype == 'error':
            return _('%s (error code)') % (name)
        elif self.objtype == 'macro':
            return _('%s (JavaScript shell macro)') % (name)
        elif self.objtype == 'limit':
            return _('%s (MongoDB system limit)') % (name)
        return ''

    def run(self):
        return super(MongoDBObject, self).run()

    doc_field_types = [
        TypedField('arguments', label=l_('Arguments'),
                   names=('argument', 'arg', 'parameter', 'param'),
                   typerolename='method', typenames=('paramtype', 'type')),
        TypedField('options', label=l_('Options'),
                   names=('options', 'opts', 'option', 'opt'),
                   typerolename=('dbcommand', 'setting', 'status', 'stats', 'aggregator'),
                   typenames=('optstype', 'type')),
        TypedField('fields', label=l_('Fields'),
                   names=('fields', 'fields', 'field', 'field'),
                   typerolename=('dbcommand', 'setting', 'status', 'stats', 'aggregator'),
                   typenames=('fieldtype', 'type')),
        TypedField('flags', label=l_('Flags'),
                   names=('flags', 'flags', 'flag', 'flag'),
                   typerolename=('dbcommand', 'setting', 'status', 'stats', 'aggregator'),
                   typenames=('flagtype', 'type')),
        GroupedField('errors', label=l_('Throws'), rolename='err',
                     names=('throws', ),
                     can_collapse=True),
        GroupedField('exception', label=l_('Exception'), rolename='err',
                     names=('exception', ),
                     can_collapse=True),
        Field('returnvalue', label=l_('Returns'), has_arg=False,
              names=('returns', 'return')),
        Field('returntype', label=l_('Return type'), has_arg=False,
              names=('rtype',)),
    ]
class ChapelObject(ObjectDescription):
    """Base class for Chapel directives. It has methods for parsing signatures of
    any form, and generating target and index text.
    """

    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
        'annotation': directives.unchanged,
    }

    doc_field_types = [
        ChapelTypedField('parameter', label=_('Arguments'),
                         names=('param', 'parameter', 'arg', 'argument'),
                         typerolename='chplref',
                         typenames=('paramtype', 'type'),
                         can_collapse=True),
        Field('returnvalue', label=_('Returns'), has_arg=False,
              names=('returns', 'return')),
        Field('yieldvalue', label=_('Yields'), has_arg=False,
              names=('yields', 'yield')),
        Field('returntype', label=_('Return type'), has_arg=False,
              names=('rtype',)),
        Field('yieldtype', label=_('Yield type'), has_arg=False,
              names=('ytype',)),
        GroupedField('errorhandling', label=_('Throws'),
                     names=('throw', 'throws'), can_collapse=True),
    ]

    @staticmethod
    def _pseudo_parse_arglist(signode, arglist):
        """Parse list of comma separated arguments.

        Arguments can have optional types.
        """
        paramlist = addnodes.desc_parameterlist()
        stack = [paramlist]
        try:
            for argument in arglist.split(','):
                argument = argument.strip()
                ends_open = 0
                ends_close = 0
                while argument.startswith('['):
                    stack.append(addnodes.desc_optional())
                    stack[-2] += stack[-1]
                    argument = argument[1:].strip()
                while argument.startswith(']'):
                    stack.pop()
                    argument = argument[1:].strip()
                while argument.endswith(']') and not argument.endswith('[]'):
                    ends_close += 1
                    argument = argument[:-1].strip()
                while argument.endswith('['):
                    ends_open += 1
                    argument = argument[:-1].strip()
                if argument:
                    stack[-1] += addnodes.desc_parameter(argument, argument)
                while ends_open:
                    stack.append(addnodes.desc_optional())
                    stack[-2] += stack[-1]
                    ends_open -= 1
                while ends_close:
                    stack.pop()
                    ends_close -= 1
            if len(stack) != 1:
                raise IndexError
        except IndexError:
            # If there are too few or too many elements on the stack, just give
            # up and treat the whole argument list as one argument, discarding
            # the already partially populated paramlist node.
            signode += addnodes.desc_parameterlist()
            signode[-1] += addnodes.desc_parameter(arglist, arglist)
        else:
            signode += paramlist

    def _get_attr_like_prefix(self, sig):
        """Return prefix text for attribute or data directive."""
        sig_match = chpl_attr_sig_pattern.match(sig)
        if sig_match is None:
            return ChapelObject.get_signature_prefix(self, sig)

        prefixes, _, _, _ = sig_match.groups()
        if prefixes:
            return prefixes.strip() + ' '
        elif self.objtype == 'type':
            return 'type' + ' '
        else:
            return ChapelObject.get_signature_prefix(self, sig)

    def _get_proc_like_prefix(self, sig):
        """Return prefix text for function or method directive
        (and similar).
        """
        sig_match = chpl_sig_pattern.match(sig)
        if sig_match is None:
            return ChapelObject.get_signature_prefix(self, sig)

        prefixes, _, _, _, _ = sig_match.groups()
        if prefixes:
            return prefixes.strip() + ' '
        elif self.objtype.startswith('iter'):
            return 'iter' + ' '
        elif self.objtype in ('method', 'function'):
            return 'proc' + ' '
        else:
            return ChapelObject.get_signature_prefix(self, sig)

    def _is_attr_like(self):
        """Returns True when objtype is attribute or data."""
        return self.objtype in ('attribute', 'data', 'type', 'enum')

    def _is_proc_like(self):
        """Returns True when objtype is *function or *method."""
        return (self.objtype in
                ('function', 'iterfunction', 'method', 'itermethod'))

    def _get_sig_prefix(self, sig):
        """Return signature prefix text. For attribute, data, and proc/iter directives
        this might be part of the signature. E.g. `type myNewType` will return
        a prefix of 'type' and `inline proc foo()` will return 'inline proc'.
        """
        if self._is_proc_like():
            return self._get_proc_like_prefix(sig)
        elif self._is_attr_like():
            return self._get_attr_like_prefix(sig)
        else:
            return ChapelObject.get_signature_prefix(self, sig)

    def get_signature_prefix(self, sig):
        """May return a prefix to put before the object name in
        the signature.
        """
        return ''

    def needs_arglist(self):
        """May return True if an empty argument list is to be generated even if the
        document contains none.
        """
        return False

    def handle_signature(self, sig, signode):
        """Parse the signature *sig* into individual nodes and append them to the
        *signode*. If ValueError is raises, parsing is aborted and the whole
        *sig* string is put into a single desc_name node.

        The return value is the value that identifies the object. IOW, it is
        the identifier that will be used to reference this object, datum,
        attribute, proc, etc. It is a tuple of "fullname" (including module and
        class(es)) and the classes. See also :py:meth:`add_target_and_index`.
        """
        if self._is_attr_like():
            sig_match = chpl_attr_sig_pattern.match(sig)
            if sig_match is None:
                raise ValueError('Signature does not parse: {0}'.format(sig))
            func_prefix, name_prefix, name, retann = sig_match.groups()
            arglist = None
        else:
            sig_match = chpl_sig_pattern.match(sig)
            if sig_match is None:
                raise ValueError('Signature does not parse: {0}'.format(sig))

            func_prefix, name_prefix, name, arglist, retann = \
                sig_match.groups()

        modname = self.options.get(
            'module', self.env.temp_data.get('chpl:module'))
        classname = self.env.temp_data.get('chpl:class')

        if classname:
            if name_prefix and name_prefix.startswith(classname):
                fullname = name_prefix + name
                # class name is given again in the signature
                name_prefix = name_prefix[len(classname):].lstrip('.')
            elif name_prefix:
                # class name is given in the signature, but different
                # (shouldn't happen)
                fullname = classname + '.' + name_prefix + name
            else:
                # class name is not given in the signature
                fullname = classname + '.' + name
        else:
            if name_prefix:
                classname = name_prefix.rstrip('.')
                fullname = name_prefix + name
            else:
                classname = ''
                fullname = name

        signode['module'] = modname
        signode['class'] = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
        # if func_prefix:
        #     signode += addnodes.desc_addname(func_prefix, func_prefix)
        if name_prefix:
            signode += addnodes.desc_addname(name_prefix, name_prefix)

        anno = self.options.get('annotation')

        signode += addnodes.desc_name(name, name)

        if not arglist:
            # If this needs an arglist, and parens were provided in the
            # signature, add a parameterlist. Chapel supports paren-less
            # functions and methods, which can act as computed properties. If
            # arglist is the empty string, the signature included parens. If
            # arglist is None, it did not include parens.
            if self.needs_arglist() and arglist is not None:
                # for callables, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if retann:
                signode += addnodes.desc_type(retann, retann)
            if anno:
                signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
            return fullname, name_prefix

        self._pseudo_parse_arglist(signode, arglist)
        if retann:
            signode += addnodes.desc_type(retann, retann)
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        """Return the text for the index entry of the object."""
        raise NotImplementedError('must be implemented in subclasses')

    def add_target_and_index(self, name_cls, sig, signode):
        """Add cross-reference IDs and entries to the index node, if
        applicable. *name_cls* is the return value of
        :py:meth:`handle_signature`.
        """
        modname = self.options.get(
            'module', self.env.temp_data.get('chpl:module'))
        fullname = (modname and modname + '.' or '') + name_cls[0]
        # note target
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['chpl']['objects']
            if fullname in objects:
                self.state_machine.reporter.warning(
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]) +
                    ', use :noindex: for one of them',
                    line=self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(('single', indextext,
                                              fullname, '', None))

    def before_content(self):
        """Called before parsing content. Set flag to help with class scoping.
        """
        self.clsname_set = False

    def after_content(self):
        """Called after parsing content. If any classes were added to the env
        temp_data, make sure they are removed.
        """
        if self.clsname_set:
            self.env.temp_data.pop('chpl:class', None)
Esempio n. 21
0
class PyObject(ObjectDescription):
    """
    Description of a general Python object.

    :cvar allow_nesting: Class is an object that allows for nested namespaces
    :vartype allow_nesting: bool
    """
    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
        'annotation': directives.unchanged,
    }

    doc_field_types = [
        PyTypedField('parameter', label=_('Parameters'),
                     names=('param', 'parameter', 'arg', 'argument',
                            'keyword', 'kwarg', 'kwparam'),
                     typerolename='class', typenames=('paramtype', 'type'),
                     can_collapse=True),
        PyTypedField('variable', label=_('Variables'), rolename='obj',
                     names=('var', 'ivar', 'cvar'),
                     typerolename='class', typenames=('vartype',),
                     can_collapse=True),
        PyGroupedField('exceptions', label=_('Raises'), rolename='exc',
                       names=('raises', 'raise', 'exception', 'except'),
                       can_collapse=True),
        Field('returnvalue', label=_('Returns'), has_arg=False,
              names=('returns', 'return')),
        PyField('returntype', label=_('Return type'), has_arg=False,
                names=('rtype',), bodyrolename='class'),
    ]

    allow_nesting = False

    def get_signature_prefix(self, sig: str) -> str:
        """May return a prefix to put before the object name in the
        signature.
        """
        return ''

    def needs_arglist(self) -> bool:
        """May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
        """Transform a Python signature into RST nodes.

        Return (fully qualified name of the thing, classname if any).

        If inside a class, the current class name is handled intelligently:
        * it is stripped from the displayed name if present
        * it is added to the full name (return value) if not present
        """
        m = py_sig_re.match(sig)
        if m is None:
            raise ValueError
        prefix, name, arglist, retann = m.groups()

        # determine module and class name (if applicable), as well as full name
        modname = self.options.get('module', self.env.ref_context.get('py:module'))
        classname = self.env.ref_context.get('py:class')
        if classname:
            add_module = False
            if prefix and (prefix == classname or
                           prefix.startswith(classname + ".")):
                fullname = prefix + name
                # class name is given again in the signature
                prefix = prefix[len(classname):].lstrip('.')
            elif prefix:
                # class name is given in the signature, but different
                # (shouldn't happen)
                fullname = classname + '.' + prefix + name
            else:
                # class name is not given in the signature
                fullname = classname + '.' + name
        else:
            add_module = True
            if prefix:
                classname = prefix.rstrip('.')
                fullname = prefix + name
            else:
                classname = ''
                fullname = name

        signode['module'] = modname
        signode['class'] = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if prefix:
            signode += addnodes.desc_addname(prefix, prefix)
        elif add_module and self.env.config.add_module_names:
            if modname and modname != 'exceptions':
                # exceptions are a special case, since they are documented in the
                # 'exceptions' module.
                nodetext = modname + '.'
                signode += addnodes.desc_addname(nodetext, nodetext)

        signode += addnodes.desc_name(name, name)
        if arglist:
            try:
                signode += _parse_arglist(arglist)
            except SyntaxError:
                # fallback to parse arglist original parser.
                # it supports to represent optional arguments (ex. "func(foo [, bar])")
                _pseudo_parse_arglist(signode, arglist)
            except NotImplementedError as exc:
                logger.warning("could not parse arglist (%r): %s", arglist, exc)
                _pseudo_parse_arglist(signode, arglist)
        else:
            if self.needs_arglist():
                # for callables, add an empty parameter list
                signode += addnodes.desc_parameterlist()

        if retann:
            signode += addnodes.desc_returns(retann, retann)

        anno = self.options.get('annotation')
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)

        return fullname, prefix

    def get_index_text(self, modname: str, name: Tuple[str, str]) -> str:
        """Return the text for the index entry of the object."""
        raise NotImplementedError('must be implemented in subclasses')

    def add_target_and_index(self, name_cls: Tuple[str, str], sig: str,
                             signode: desc_signature) -> None:
        modname = self.options.get('module', self.env.ref_context.get('py:module'))
        fullname = (modname + '.' if modname else '') + name_cls[0]
        node_id = make_id(self.env, self.state.document, modname or '', name_cls[0])
        signode['ids'].append(node_id)

        # Assign old styled node_id(fullname) not to break old hyperlinks (if possible)
        # Note: Will removed in Sphinx-5.0  (RemovedInSphinx50Warning)
        if node_id != fullname and fullname not in self.state.document.ids:
            signode['ids'].append(fullname)

        self.state.document.note_explicit_target(signode)

        domain = cast(PythonDomain, self.env.get_domain('py'))
        domain.note_object(fullname, self.objtype, node_id, location=signode)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(('single', indextext, node_id, '', None))

    def before_content(self) -> None:
        """Handle object nesting before content

        :py:class:`PyObject` represents Python language constructs. For
        constructs that are nestable, such as a Python classes, this method will
        build up a stack of the nesting heirarchy so that it can be later
        de-nested correctly, in :py:meth:`after_content`.

        For constructs that aren't nestable, the stack is bypassed, and instead
        only the most recent object is tracked. This object prefix name will be
        removed with :py:meth:`after_content`.
        """
        prefix = None
        if self.names:
            # fullname and name_prefix come from the `handle_signature` method.
            # fullname represents the full object name that is constructed using
            # object nesting and explicit prefixes. `name_prefix` is the
            # explicit prefix given in a signature
            (fullname, name_prefix) = self.names[-1]
            if self.allow_nesting:
                prefix = fullname
            elif name_prefix:
                prefix = name_prefix.strip('.')
        if prefix:
            self.env.ref_context['py:class'] = prefix
            if self.allow_nesting:
                classes = self.env.ref_context.setdefault('py:classes', [])
                classes.append(prefix)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            modules.append(self.env.ref_context.get('py:module'))
            self.env.ref_context['py:module'] = self.options['module']

    def after_content(self) -> None:
        """Handle object de-nesting after content

        If this class is a nestable object, removing the last nested class prefix
        ends further nesting in the object.

        If this class is not a nestable object, the list of classes should not
        be altered as we didn't affect the nesting levels in
        :py:meth:`before_content`.
        """
        classes = self.env.ref_context.setdefault('py:classes', [])
        if self.allow_nesting:
            try:
                classes.pop()
            except IndexError:
                pass
        self.env.ref_context['py:class'] = (classes[-1] if len(classes) > 0
                                            else None)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            if modules:
                self.env.ref_context['py:module'] = modules.pop()
            else:
                self.env.ref_context.pop('py:module')
Esempio n. 22
0
class PyObject(ObjectDescription):
    """
    Description of a general Python object.
    """
    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
        'annotation': directives.unchanged,
    }

    doc_field_types = [
        PyTypedField('parameter',
                     label=l_('Parameters'),
                     names=('param', 'parameter', 'arg', 'argument', 'keyword',
                            'kwarg', 'kwparam'),
                     typerolename='obj',
                     typenames=('paramtype', 'type'),
                     can_collapse=True),
        PyTypedField('variable',
                     label=l_('Variables'),
                     rolename='obj',
                     names=('var', 'ivar', 'cvar'),
                     typerolename='obj',
                     typenames=('vartype', ),
                     can_collapse=True),
        PyGroupedField('exceptions',
                       label=l_('Raises'),
                       rolename='exc',
                       names=('raises', 'raise', 'exception', 'except'),
                       can_collapse=True),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        PyField('returntype',
                label=l_('Return type'),
                has_arg=False,
                names=('rtype', ),
                bodyrolename='obj'),
    ]

    def get_signature_prefix(self, sig):
        # type: (unicode) -> unicode
        """May return a prefix to put before the object name in the
        signature.
        """
        return ''

    def needs_arglist(self):
        # type: () -> bool
        """May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig, signode):  # type: ignore
        # type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
        """Transform a Python signature into RST nodes.

        Return (fully qualified name of the thing, classname if any).

        If inside a class, the current class name is handled intelligently:
        * it is stripped from the displayed name if present
        * it is added to the full name (return value) if not present
        """
        m = py_sig_re.match(sig)  # type: ignore
        if m is None:
            raise ValueError
        name_prefix, name, arglist, retann = m.groups()

        # determine module and class name (if applicable), as well as full name
        modname = self.options.get('module',
                                   self.env.ref_context.get('py:module'))
        classname = self.env.ref_context.get('py:class')
        if classname:
            add_module = False
            if name_prefix and name_prefix.startswith(classname):
                fullname = name_prefix + name
                # class name is given again in the signature
                name_prefix = name_prefix[len(classname):].lstrip('.')
            elif name_prefix:
                # class name is given in the signature, but different
                # (shouldn't happen)
                fullname = classname + '.' + name_prefix + name
            else:
                # class name is not given in the signature
                fullname = classname + '.' + name
        else:
            add_module = True
            if name_prefix:
                classname = name_prefix.rstrip('.')
                fullname = name_prefix + name
            else:
                classname = ''
                fullname = name

        signode['module'] = modname
        signode['class'] = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if name_prefix:
            signode += addnodes.desc_addname(name_prefix, name_prefix)
        # exceptions are a special case, since they are documented in the
        # 'exceptions' module.
        elif add_module and self.env.config.add_module_names:
            modname = self.options.get('module',
                                       self.env.ref_context.get('py:module'))
            if modname and modname != 'exceptions':
                nodetext = modname + '.'
                signode += addnodes.desc_addname(nodetext, nodetext)

        anno = self.options.get('annotation')

        signode += addnodes.desc_name(name, name)
        if not arglist:
            if self.needs_arglist():
                # for callables, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if retann:
                signode += addnodes.desc_returns(retann, retann)
            if anno:
                signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
            return fullname, name_prefix

        _pseudo_parse_arglist(signode, arglist)
        if retann:
            signode += addnodes.desc_returns(retann, retann)
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        # type: (unicode, unicode) -> unicode
        """Return the text for the index entry of the object."""
        raise NotImplementedError('must be implemented in subclasses')

    def add_target_and_index(self, name_cls, sig, signode):
        # type: (unicode, unicode, addnodes.desc_signature) -> None
        modname = self.options.get('module',
                                   self.env.ref_context.get('py:module'))
        fullname = (modname and modname + '.' or '') + name_cls[0]
        # note target
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['py']['objects']
            if fullname in objects:
                self.state_machine.reporter.warning(
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]) +
                    ', use :noindex: for one of them',
                    line=self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, fullname, '', None))

    def before_content(self):
        # type: () -> None
        # needed for automatic qualification of members (reset in subclasses)
        self.clsname_set = False

    def after_content(self):
        # type: () -> None
        if self.clsname_set:
            self.env.ref_context.pop('py:class', None)
Esempio n. 23
0
 def __init__(self, name, names=(), label=None, rolename=None):
     Field.__init__(self, name, names, label, False, rolename)
Esempio n. 24
0
class CPPObject(ObjectDescription):
    """Description of a C++ language object."""

    doc_field_types = [
        GroupedField('parameter', label=l_('Parameters'),
                     names=('param', 'parameter', 'arg', 'argument'),
                     can_collapse=True),
        GroupedField('exceptions', label=l_('Throws'), rolename='cpp:class',
                     names=('throws', 'throw', 'exception'),
                     can_collapse=True),
        Field('returnvalue', label=l_('Returns'), has_arg=False,
              names=('returns', 'return')),
    ]

    def attach_name(self, node, name):
        owner, name = name.split_owner()
        varname = unicode(name)
        if owner is not None:
            owner = unicode(owner) + '::'
            node += addnodes.desc_addname(owner, owner)
        node += addnodes.desc_name(varname, varname)

    def attach_type_suffixes(self, node, suffixes):
        for suffix in suffixes:
            node += nodes.Text(unicode(suffix))

    def attach_type(self, node, type):
        # XXX: link to c?
        text = unicode(type)
        pnode = addnodes.pending_xref(
            '', refdomain='cpp', reftype='type',
            reftarget=text, modname=None, classname=None)
        pnode['cpp:parent'] = self.env.temp_data.get('cpp:parent')
        pnode += nodes.Text(text)
        node += pnode

    def attach_modifiers(self, node, obj, visibility='public'):
        if obj.visibility != visibility:
            node += addnodes.desc_annotation(obj.visibility,
                                             obj.visibility)
            node += nodes.Text(' ')
        if obj.static:
            node += addnodes.desc_annotation('static', 'static')
            node += nodes.Text(' ')
        if getattr(obj, 'constexpr', False):
            node += addnodes.desc_annotation('constexpr', 'constexpr')
            node += nodes.Text(' ')

    def add_target_and_index(self, sigobj, sig, signode):
        theid = sigobj.get_id()
        name = unicode(sigobj.name)
        if theid not in self.state.document.ids:
            signode['names'].append(theid)
            signode['ids'].append(theid)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)

            self.env.domaindata['cpp']['objects'].setdefault(name,
                (self.env.docname, self.objtype, theid))

        indextext = self.get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(('single', indextext, theid, ''))

    def before_content(self):
        lastname = self.names and self.names[-1]
        if lastname and not self.env.temp_data.get('cpp:parent'):
            assert isinstance(lastname, NamedDefExpr)
            self.env.temp_data['cpp:parent'] = lastname.name
            self.parentname_set = True
        else:
            self.parentname_set = False

    def after_content(self):
        if self.parentname_set:
            self.env.temp_data['cpp:parent'] = None

    def parse_definition(self, parser):
        raise NotImplementedError()

    def describe_signature(self, signode, arg):
        raise NotImplementedError()

    def handle_signature(self, sig, signode):
        parser = DefinitionParser(sig)
        try:
            rv = self.parse_definition(parser)
            parser.assert_end()
        except DefinitionError, e:
            self.state_machine.reporter.warning(e.description, line=self.lineno)
            raise ValueError
        self.describe_signature(signode, rv)

        parent = self.env.temp_data.get('cpp:parent')
        if parent is not None:
            rv = rv.clone()
            rv.name = rv.name.prefix(parent)
        return rv
Esempio n. 25
0
class JavaMethod(JavaObject):
    doc_field_types = [
        TypedField(
            'parameter',
            label=_('Parameters'),  # replaced the old "label=l_('Parameters')"
            names=('param', 'parameter', 'arg', 'argument'),
            typerolename='type',
            typenames=('type', )),
        Field(
            'returnvalue',
            label=_('Returns'),  # replaced the old "label=l_('Returns')"
            has_arg=False,
            names=('returns', 'return')),
        GroupedField(
            'throws',
            names=('throws', ),
            label=_('Throws'),  # replaced the old "label=l_('Throws')"
            rolename='type')
    ]

    def handle_method_signature(self, sig, signode):
        try:
            member = javalang.parse.parse_member_signature(sig)
        except javalang.parser.JavaSyntaxError:
            raise self.error("syntax error in method signature")

        if not isinstance(member, javalang.tree.MethodDeclaration):
            raise self.error("expected method declaration")

        mods = formatter.output_modifiers(member.modifiers).build()
        signode += nodes.Text(mods + ' ', mods + ' ')

        if member.type_parameters:
            type_params = formatter.output_type_params(
                member.type_parameters).build()
            signode += nodes.Text(type_params, type_params)
            signode += nodes.Text(' ', ' ')

        rnode = addnodes.desc_type('', '')
        rnode += self._build_type_node(member.return_type)

        signode += rnode
        signode += nodes.Text(' ', ' ')
        signode += addnodes.desc_name(member.name, member.name)

        paramlist = addnodes.desc_parameterlist()
        for parameter in member.parameters:
            param = addnodes.desc_parameter('', '', noemph=True)
            param += self._build_type_node(parameter.type)

            if parameter.varargs:
                param += nodes.Text('...', '')

            param += nodes.emphasis(' ' + parameter.name, ' ' + parameter.name)
            paramlist += param
        signode += paramlist

        param_reprs = [
            formatter.output_type(param.type, with_generics=False).build()
            for param in member.parameters
        ]
        return member.name + '(' + ', '.join(param_reprs) + ')'

    def get_index_text(self, package, type, name):
        return _('%s (Java method)' % (name, ))
Esempio n. 26
0
class PhpObject(ObjectDescription):
    """
    Description of a general PHP object.
    """
    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
    }

    doc_field_types = [
        TypedField('parameter', label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='obj', typenames=('paramtype', 'type')),
        TypedField('variable', label=l_('Variables'), rolename='obj',
                   names=('var', 'ivar', 'cvar'),
                   typerolename='obj', typenames=('vartype',)),
        GroupedField('exceptions', label=l_('Throws'), rolename='exc',
                     names=('throws', 'throw', 'exception', 'except'),
                     can_collapse=True),
        Field('returnvalue', label=l_('Returns'), has_arg=False,
              names=('returns', 'return')),
        Field('returntype', label=l_('Return type'), has_arg=False,
              names=('rtype', 'returntype')),
    ]

    def get_signature_prefix(self, sig):
        """
        May return a prefix to put before the object name in the signature.
        """
        return ''

    def needs_arglist(self):
        """
        May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig, signode):
        """
        Transform a PHP signature into RST nodes.
        Returns (fully qualified name of the thing, classname if any).

        If inside a class, the current class name is handled intelligently:
        * it is stripped from the displayed name if present
        * it is added to the full name (return value) if not present
        """
        m = php_sig_re.match(sig)
        if m is None:
            raise ValueError

        name_prefix, name, arglist, retann = m.groups()

        if not name_prefix:
            name_prefix = ""

        # determine module and class name (if applicable), as well as full name
        modname = self.options.get(
            'namespace', self.env.temp_data.get('php:namespace'))

        classname = self.env.temp_data.get('php:class')
        separator = separators[self.objtype]

        if self.objtype == 'global' or self.objtype == 'function':
            add_module = False
            modname = None
            classname = None
            fullname = name
        else:
            add_module = True
            # name_prefix and a non-static method, means the classname was 
            # repeated. Trim off the <class>::
            if name_prefix and self.objtype != 'staticmethod':
                if name_prefix.startswith(classname):
                    name_prefix = name_prefix[len(classname):].rstrip('::')
                classname = classname.rstrip('::')
                fullname = name_prefix + classname + separator + name
            elif name_prefix:
                classname = classname.rstrip('::')
                fullname = name_prefix + name

            # Currently in a class, but not creating another class,
            elif classname and not self.objtype in ['class', 'exception', 'interface', 'trait']:
                if not self.env.temp_data['php:in_class']:
                    name_prefix = classname + separator

                fullname = classname + separator + name
            else:
                classname = ''
                fullname = name

        signode['namespace'] = modname
        signode['class'] = self.class_name = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)

        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if name_prefix:
            if modname and not self.env.temp_data['php:in_class']:
                name_prefix = modname + NS + name_prefix
            signode += addnodes.desc_addname(name_prefix, name_prefix)

        elif add_module and self.env.config.add_module_names:
            if self.objtype == 'global':
                nodetext = ''
                signode += addnodes.desc_addname(nodetext, nodetext)
            else:
                modname = self.options.get(
                    'namespace', self.env.temp_data.get('php:namespace'))

                if modname and not self.env.temp_data.get('php:in_class', False):
                    nodetext = modname + NS
                    signode += addnodes.desc_addname(nodetext, nodetext)

        signode += addnodes.desc_name(name, name)
        if not arglist:
            if self.needs_arglist():
                # for callables, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if retann:
                signode += addnodes.desc_returns(retann, retann)
            return fullname, name_prefix

        signode += addnodes.desc_parameterlist()

        stack = [signode[-1]]
        for token in php_paramlist_re.split(arglist):
            if token == '[':
                opt = addnodes.desc_optional()
                stack[-1] += opt
                stack.append(opt)
            elif token == ']':
                try:
                    stack.pop()
                except IndexError:
                    raise ValueError
            elif not token or token == ',' or token.isspace():
                pass
            else:
                token = token.strip()
                stack[-1] += addnodes.desc_parameter(token, token)
        if len(stack) != 1:
            raise ValueError
        if retann:
            signode += addnodes.desc_returns(retann, retann)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        """
        Return the text for the index entry of the object.
        """
        raise NotImplementedError('must be implemented in subclasses')

    def _is_class_member(self):
        return self.objtype.startswith('method') or self.objtype.startswith('attr')

    def add_target_and_index(self, name_cls, sig, signode):
        if self.objtype == 'global':
            modname = ''
        else:
            modname = self.options.get(
                'namespace', self.env.temp_data.get('php:namespace'))
        separator = separators[self.objtype]
        if self._is_class_member():
            if signode['class']:
                prefix = modname and modname + NS or ''
            else:
                prefix = modname and modname + NS or ''
        else:
            prefix = modname and modname + NS or ''
        fullname = prefix + name_cls[0]

        # note target
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['php']['objects']
            if fullname in objects:
                self.env.warn(
                    self.env.docname,
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]),
                    self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(('single', indextext,
                                              fullname, fullname))
Esempio n. 27
0
  ('index', slug, project, author, slug, project, 'Miscellaneous'),
]


# Extensions to theme docs
def setup(app):
    from sphinx.domains.python import PyField
    from sphinx.util.docfields import Field

    app.add_object_type(
        'confval',
        'confval',
        objname='configuration value',
        indextemplate='pair: %s; configuration value',
        doc_field_types=[
            PyField(
                'type',
                label=_('Type'),
                has_arg=False,
                names=('type',),
                bodyrolename='class'
            ),
            Field(
                'default',
                label=_('Default'),
                has_arg=False,
                names=('default',),
            ),
        ]
    )
Esempio n. 28
0
class AdaObject(ObjectDescription):
    """
    Description of an Ada language object.
    """

    doc_field_types = [
        TypedField('parameter',
                   label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=l_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    def needs_arglist(self):
        return self.objtype == 'function' or self.objtype == 'procedure'

    def _resolve_module_name(self, signode, modname, name):
        env_modname = self.options.get(
            'module', self.env.temp_data.get('ada:module', 'ada'))
        if modname:
            fullname = modname + name
            signode['module'] = modname[:-1]
        else:
            fullname = env_modname + '.' + name
            signode['module'] = env_modname

        signode['fullname'] = fullname
        name_prefix = signode['module'] + '.'
        signode += addnodes.desc_addname(name_prefix, name_prefix)
        signode += addnodes.desc_name(name, name)
        return fullname

    def _handle_function_signature(self, sig, signode):
        m = ada_func_sig_re.match(sig)
        if m is None:
            print("m did not match the function")
            raise ValueError

        modname, name, dummy, arglist, returntype, abstract = m.groups()
        fullname = self._resolve_module_name(signode, modname, name)

        if not arglist:
            if self.needs_arglist():
                # for functions and procedures, add an empty parameter list
                new_node = addnodes.desc_parameterlist()
                new_node.child_text_separator = '; '
                signode += new_node
            if returntype:
                signode += addnodes.desc_returns(returntype, returntype)
            return fullname

        signode += nodes.Text(' ')

        new_node = addnodes.desc_parameterlist()
        new_node.child_text_separator = '; '
        signode += new_node

        stack = [signode[-1]]
        counters = [0, 0]
        for token in string.split(arglist, ';'):
            pieces = string.split(token, ':')
            name = pieces[0].strip()
            stack[-1] += addnodes.desc_parameter(
                name, name + " : " + pieces[1].strip())

            if len(stack) == 1:
                counters[0] += 1
            else:
                counters[1] += 1

        if len(stack) != 1:
            raise ValueError
        if not counters[1]:
            fullname = '%s/%d' % (fullname, counters[0])
        else:
            fullname = '%s/%d..%d' % (fullname, counters[0], sum(counters))
        if returntype:
            signode += addnodes.desc_returns(returntype, returntype)
        return fullname

    def _handle_procedure_signature(self, sig, signode):
        m = ada_proc_sig_re.match(sig)
        if m is None:
            print("m did not match")
            raise ValueError

        modname, name, dummy, arglist, abstract = m.groups()
        fullname = self._resolve_module_name(signode, modname, name)

        if not arglist:
            if self.needs_arglist():
                # for functions and procedures, add an empty parameter list
                newnode = addnodes.desc_parameterlist()
                newnode.child_text_separator = '; '
                signode += newnode

        signode += nodes.Text(' ')

        newnode = addnodes.desc_parameterlist()
        newnode.child_text_separator = '; '
        signode += newnode

        stack = [signode[-1]]
        counters = [0, 0]
        for token in string.split(arglist, ';'):
            pieces = string.split(token, ':')
            name = pieces[0].strip()
            stack[-1] += addnodes.desc_parameter(
                name, name + " : " + pieces[1].strip())
            if len(stack) == 1:
                counters[0] += 1
            else:
                counters[1] += 1

        if len(stack) != 1:
            raise ValueError
        if not counters[1]:
            fullname = '%s/%d' % (fullname, counters[0])
        else:
            fullname = '%s/%d..%d' % (fullname, counters[0], sum(counters))
        return fullname

    def _handle_type_signature(self, sig, signode):
        m = ada_type_sig_re.match(sig)
        if m is None:
            print("m did not match")
            raise ValueError

        name, value = m.groups()
        fullname = self._resolve_module_name(signode, '', name)

        # signode += addnodes.desc_parameterlist()

        # stack = [signode[-1]]

        # signode += addnodes.desc_type(name, name + " is " + value)
        signode += addnodes.desc_type(name, '')

        return fullname

    def handle_signature(self, sig, signode):
        if sig.startswith('function'):
            return self._handle_function_signature(sig, signode)
        elif sig.startswith('type'):
            return self._handle_type_signature(sig, signode)
        else:  # sig.startswith('procedure'):
            return self._handle_procedure_signature(sig, signode)

    def _get_index_text(self, name):
        if self.objtype == 'function':
            return _('%s (Ada function)') % name
        elif self.objtype == 'procedure':
            return _('%s (Ada procedure)') % name
        elif self.objtype == 'type':
            return _('%s (Ada type)') % name
        else:
            return ''

    def add_target_and_index(self, name, sig, signode):
        pieces = string.split(name, '.')
        if name not in self.state.document.ids:
            signode['names'].append(name)
            signode['ids'].append(name)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            if self.objtype == 'function':
                finv = self.env.domaindata['ada']['functions']
                fname, arity = name.split('/')
                if '..' in arity:
                    first, last = map(int, arity.split('..'))
                else:
                    first = last = int(arity)
                for arity_index in range(first, last + 1):
                    if fname in finv and arity_index in finv[fname]:
                        self.env.warn(
                            self.env.docname,
                            ('duplicate Ada function description'
                             'of %s, ') % name + 'other instance in ' +
                            self.env.doc2path(finv[fname][arity_index][0]),
                            self.lineno)
                    arities = finv.setdefault(fname, {})
                    arities[arity_index] = (self.env.docname, name)
            if self.objtype == 'procedure':
                finv = self.env.domaindata['ada']['procedures']
                fname, arity = name.split('/')
                if '..' in arity:
                    first, last = map(int, arity.split('..'))
                else:
                    first = last = int(arity)
                for arity_index in range(first, last + 1):
                    if fname in finv and arity_index in finv[fname]:
                        self.env.warn(
                            self.env.docname,
                            ('duplicate Ada procedure description'
                             'of %s, ') % name + 'other instance in ' +
                            self.env.doc2path(finv[fname][arity_index][0]),
                            self.lineno)
                    arities = finv.setdefault(fname, {})
                    arities[arity_index] = (self.env.docname, name)
            else:
                oinv = self.env.domaindata['ada']['objects']
                if name in oinv:
                    self.env.warn(
                        self.env.docname,
                        'duplicate Ada object description of %s, ' % name +
                        'other instance in ' +
                        self.env.doc2path(oinv[name][0]), self.lineno)
                oinv[name] = (self.env.docname, self.objtype)

        indextext = self._get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(('single', indextext, name, name))

        plain_name = pieces[-1]
        indextext = self._get_index_text(plain_name)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, name, plain_name))
Esempio n. 29
0
 def __init__(self, name, names=(), typenames=(), label=None,
              typerolename=None):
     Field.__init__(self, name, names, label, False, None)
     self.typenames = typenames
     self.typerolename = typerolename
Esempio n. 30
0
class CephOption(ObjectDescription):
    """
    emit option loaded from given command/options/<name>.yaml.in file
    """
    has_content = True
    required_arguments = 1
    optional_arguments = 0
    final_argument_whitespace = False
    option_spec = {
        'module': directives.unchanged,
        'default': directives.unchanged
    }

    doc_field_types = [
        Field('default',
              label=_('Default'),
              has_arg=False,
              names=('default', )),
        Field('type',
              label=_('Type'),
              has_arg=False,
              names=('type', ),
              bodyrolename='class'),
    ]

    template = jinja_template()
    opts: Dict[str, Dict[str, FieldValueT]] = {}
    mgr_opts: Dict[str,  # module name
                   Dict[str,  # option name
                        Dict[str,  # field_name
                             FieldValueT]]] = {}

    def _load_yaml(self) -> Dict[str, Dict[str, FieldValueT]]:
        if CephOption.opts:
            return CephOption.opts
        opts = []
        for fn in status_iterator(self.config.ceph_confval_imports,
                                  'loading options...', 'red',
                                  len(self.config.ceph_confval_imports),
                                  self.env.app.verbosity):
            self.env.note_dependency(fn)
            try:
                with open(fn, 'r') as f:
                    yaml_in = io.StringIO()
                    for line in f:
                        if '@' not in line:
                            yaml_in.write(line)
                    yaml_in.seek(0)
                    opts += yaml.safe_load(yaml_in)['options']
            except OSError as e:
                message = f'Unable to open option file "{fn}": {e}'
                raise self.error(message)
        CephOption.opts = dict((opt['name'], opt) for opt in opts)
        return CephOption.opts

    def _normalize_path(self, dirname):
        my_dir = os.path.dirname(os.path.realpath(__file__))
        src_dir = os.path.abspath(os.path.join(my_dir, '../..'))
        return os.path.join(src_dir, dirname)

    def _is_mgr_module(self, dirname, name):
        if not os.path.isdir(os.path.join(dirname, name)):
            return False
        if not os.path.isfile(os.path.join(dirname, name, '__init__.py')):
            return False
        return name not in ['tests']

    @contextlib.contextmanager
    def mocked_modules(self):
        # src/pybind/mgr/tests
        from tests import mock
        mock_imports = [
            'rados', 'rbd', 'cephfs', 'dateutil', 'dateutil.parser'
        ]
        # make dashboard happy
        mock_imports += [
            'OpenSSL', 'jwt', 'bcrypt', 'jsonpatch', 'rook.rook_client',
            'rook.rook_client.ceph', 'rook.rook_client._helper',
            'cherrypy=3.2.3'
        ]
        # make diskprediction_local happy
        mock_imports += ['numpy', 'scipy']
        # make restful happy
        mock_imports += [
            'pecan', 'pecan.rest', 'pecan.hooks', 'werkzeug',
            'werkzeug.serving'
        ]

        for m in mock_imports:
            args = {}
            parts = m.split('=', 1)
            mocked = parts[0]
            if len(parts) > 1:
                args['__version__'] = parts[1]
            sys.modules[mocked] = mock.Mock(**args)

        try:
            yield
        finally:
            for m in mock_imports:
                mocked = m.split('=', 1)[0]
                sys.modules.pop(mocked)

    def _collect_options_from_module(self, name):
        with self.mocked_modules():
            mgr_mod = __import__(name, globals(), locals(), [], 0)
            # import 'M' from src/pybind/mgr/tests
            from tests import M

            def subclass(x):
                try:
                    return issubclass(x, M)
                except TypeError:
                    return False

            ms = [
                c for c in mgr_mod.__dict__.values()
                if subclass(c) and 'Standby' not in c.__name__
            ]
            [m] = ms
            assert isinstance(m.MODULE_OPTIONS, list)
            return m.MODULE_OPTIONS

    def _load_module(self, module) -> Dict[str, Dict[str, FieldValueT]]:
        mgr_opts = CephOption.mgr_opts.get(module)
        if mgr_opts is not None:
            return mgr_opts
        python_path = self.config.ceph_confval_mgr_python_path
        for path in python_path.split(':'):
            sys.path.insert(0, self._normalize_path(path))
        module_path = self.env.config.ceph_confval_mgr_module_path
        module_path = self._normalize_path(module_path)
        sys.path.insert(0, module_path)
        if not self._is_mgr_module(module_path, module):
            raise self.error(
                f'module "{module}" not found under {module_path}')
        fn = os.path.join(module_path, module, 'module.py')
        if os.path.exists(fn):
            self.env.note_dependency(fn)
        os.environ['UNITTEST'] = 'true'
        opts = self._collect_options_from_module(module)
        CephOption.mgr_opts[module] = dict((opt['name'], opt) for opt in opts)
        return CephOption.mgr_opts[module]

    def _current_module(self) -> str:
        return self.options.get('module',
                                self.env.ref_context.get('ceph:module'))

    def _render_option(self, name) -> str:
        cur_module = self._current_module()
        if cur_module:
            opt = self._load_module(cur_module).get(name)
        else:
            opt = self._load_yaml().get(name)
        if opt is None:
            raise self.error(f'Option "{name}" not found!')
        if cur_module and 'type' not in opt:
            # the type of module option defaults to 'str'
            opt['type'] = 'str'
        desc = opt.get('fmt_desc') or opt.get('long_desc') or opt.get('desc')
        opt_default = opt.get('default')
        default = self.options.get('default', opt_default)
        try:
            return self.template.render(opt=opt, desc=desc, default=default)
        except Exception as e:
            message = (f'Unable to render option "{name}": {e}. ',
                       f'opt={opt}, desc={desc}, default={default}')
            raise self.error(message)

    def handle_signature(self, sig: str,
                         signode: addnodes.desc_signature) -> str:
        signode.clear()
        signode += addnodes.desc_name(sig, sig)
        # normalize whitespace like XRefRole does
        name = ws_re.sub(' ', sig)
        cur_module = self._current_module()
        if cur_module:
            return '/'.join(['mgr', cur_module, name])
        else:
            return name

    def transform_content(self, contentnode: addnodes.desc_content) -> None:
        name = self.arguments[0]
        source, lineno = self.get_source_info()
        source = f'{source}:{lineno}:<confval>'
        fields = StringList(self._render_option(name).splitlines() + [''],
                            source=source,
                            parent_offset=lineno)
        with switch_source_input(self.state, fields):
            self.state.nested_parse(fields, 0, contentnode)

    def add_target_and_index(self, name: str, sig: str,
                             signode: addnodes.desc_signature) -> None:
        node_id = make_id(self.env, self.state.document, self.objtype, name)
        signode['ids'].append(node_id)
        self.state.document.note_explicit_target(signode)
        entry = f'{name}; configuration option'
        self.indexnode['entries'].append(('pair', entry, node_id, '', None))
        std = self.env.get_domain('std')
        std.note_object(self.objtype, name, node_id, location=signode)
Esempio n. 31
0
 def __init__(self, name, names=(), label=None, rolename=None,
              can_collapse=False):
     Field.__init__(self, name, names, label, True, rolename)
     self.can_collapse = can_collapse
Esempio n. 32
0
class PyObject(ObjectDescription):
    """
    Description of a general Python object.

    :cvar allow_nesting: Class is an object that allows for nested namespaces
    :vartype allow_nesting: bool
    """
    option_spec = {
        'noindex': directives.flag,
        'module': directives.unchanged,
        'annotation': directives.unchanged,
    }

    doc_field_types = [
        PyTypedField('parameter', label=_('Parameters'),
                     names=('param', 'parameter', 'arg', 'argument',
                            'keyword', 'kwarg', 'kwparam'),
                     typerolename='class', typenames=('paramtype', 'type'),
                     can_collapse=True),
        PyTypedField('variable', label=_('Variables'), rolename='obj',
                     names=('var', 'ivar', 'cvar'),
                     typerolename='class', typenames=('vartype',),
                     can_collapse=True),
        PyGroupedField('exceptions', label=_('Raises'), rolename='exc',
                       names=('raises', 'raise', 'exception', 'except'),
                       can_collapse=True),
        Field('returnvalue', label=_('Returns'), has_arg=False,
              names=('returns', 'return')),
        PyField('returntype', label=_('Return type'), has_arg=False,
                names=('rtype',), bodyrolename='class'),
    ]

    allow_nesting = False

    def get_signature_prefix(self, sig):
        # type: (unicode) -> unicode
        """May return a prefix to put before the object name in the
        signature.
        """
        return ''

    def needs_arglist(self):
        # type: () -> bool
        """May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig, signode):
        # type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
        """Transform a Python signature into RST nodes.

        Return (fully qualified name of the thing, classname if any).

        If inside a class, the current class name is handled intelligently:
        * it is stripped from the displayed name if present
        * it is added to the full name (return value) if not present
        """
        m = py_sig_re.match(sig)  # type: ignore
        if m is None:
            raise ValueError
        name_prefix, name, arglist, retann = m.groups()

        # determine module and class name (if applicable), as well as full name
        modname = self.options.get(
            'module', self.env.ref_context.get('py:module'))
        classname = self.env.ref_context.get('py:class')
        if classname:
            add_module = False
            if name_prefix and name_prefix.startswith(classname):
                fullname = name_prefix + name
                # class name is given again in the signature
                name_prefix = name_prefix[len(classname):].lstrip('.')
            elif name_prefix:
                # class name is given in the signature, but different
                # (shouldn't happen)
                fullname = classname + '.' + name_prefix + name
            else:
                # class name is not given in the signature
                fullname = classname + '.' + name
        else:
            add_module = True
            if name_prefix:
                classname = name_prefix.rstrip('.')
                fullname = name_prefix + name
            else:
                classname = ''
                fullname = name

        signode['module'] = modname
        signode['class'] = classname
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if name_prefix:
            signode += addnodes.desc_addname(name_prefix, name_prefix)
        # exceptions are a special case, since they are documented in the
        # 'exceptions' module.
        elif add_module and self.env.config.add_module_names:
            modname = self.options.get(
                'module', self.env.ref_context.get('py:module'))
            if modname and modname != 'exceptions':
                nodetext = modname + '.'
                signode += addnodes.desc_addname(nodetext, nodetext)

        anno = self.options.get('annotation')

        signode += addnodes.desc_name(name, name)
        if not arglist:
            if self.needs_arglist():
                # for callables, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if retann:
                signode += addnodes.desc_returns(retann, retann)
            if anno:
                signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
            return fullname, name_prefix

        _pseudo_parse_arglist(signode, arglist)
        if retann:
            signode += addnodes.desc_returns(retann, retann)
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        # type: (unicode, unicode) -> unicode
        """Return the text for the index entry of the object."""
        raise NotImplementedError('must be implemented in subclasses')

    def add_target_and_index(self, name_cls, sig, signode):
        # type: (unicode, unicode, addnodes.desc_signature) -> None
        modname = self.options.get(
            'module', self.env.ref_context.get('py:module'))
        fullname = (modname and modname + '.' or '') + name_cls[0]
        # note target
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['py']['objects']
            if fullname in objects:
                self.state_machine.reporter.warning(
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]) +
                    ', use :noindex: for one of them',
                    line=self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(('single', indextext,
                                              fullname, '', None))

    def before_content(self):
        # type: () -> None
        """Handle object nesting before content

        :py:class:`PyObject` represents Python language constructs. For
        constructs that are nestable, such as a Python classes, this method will
        build up a stack of the nesting heirarchy so that it can be later
        de-nested correctly, in :py:meth:`after_content`.

        For constructs that aren't nestable, the stack is bypassed, and instead
        only the most recent object is tracked. This object prefix name will be
        removed with :py:meth:`after_content`.
        """
        prefix = None
        if self.names:
            # fullname and name_prefix come from the `handle_signature` method.
            # fullname represents the full object name that is constructed using
            # object nesting and explicit prefixes. `name_prefix` is the
            # explicit prefix given in a signature
            (fullname, name_prefix) = self.names[-1]
            if self.allow_nesting:
                prefix = fullname
            elif name_prefix:
                prefix = name_prefix.strip('.')
        if prefix:
            self.env.ref_context['py:class'] = prefix
            if self.allow_nesting:
                classes = self.env.ref_context.setdefault('py:classes', [])
                classes.append(prefix)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            modules.append(self.env.ref_context.get('py:module'))
            self.env.ref_context['py:module'] = self.options['module']

    def after_content(self):
        # type: () -> None
        """Handle object de-nesting after content

        If this class is a nestable object, removing the last nested class prefix
        ends further nesting in the object.

        If this class is not a nestable object, the list of classes should not
        be altered as we didn't affect the nesting levels in
        :py:meth:`before_content`.
        """
        classes = self.env.ref_context.setdefault('py:classes', [])
        if self.allow_nesting:
            try:
                classes.pop()
            except IndexError:
                pass
        self.env.ref_context['py:class'] = (classes[-1] if len(classes) > 0
                                            else None)
        if 'module' in self.options:
            modules = self.env.ref_context.setdefault('py:modules', [])
            if modules:
                self.env.ref_context['py:module'] = modules.pop()
            else:
                self.env.ref_context.pop('py:module')
Esempio n. 33
0
class GolangObject(ObjectDescription):
    """
    Description of a Golang language object.
    """
    doc_field_types = [
        TypedField('parameter',
                   label=_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    # These Go types aren't described anywhere, so don't try to create
    # a cross-reference to them
    stopwords = set(('const', 'int', 'uint', 'uintptr', 'int8', 'int16',
                     'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64',
                     'string', 'error', '{}interface', '..{}interface'))

    def handle_signature(self, sig, signode):
        m = go_func_sig_re.match(sig)
        if m is not None:
            return self._handle_function_signature(sig, signode, m)

        m = go_sig_re.match(sig)
        if m is not None:
            return self._handle_general_signature(sig, signode, m)

    def _handle_general_signature(self, sig, signode, m):
        # determine package name, as well as full name
        # default package is 'builtin'
        env_pkgname = self.options.get(
            'package', self.env.temp_data.get('go:package', 'builtin'))

        name, = m.groups()
        if '.' in name:
            pkgname, funcname = name.split('.', 1)
            name_prefix = pkgname + '.'
            signode += addnodes.desc_addname(name_prefix, name_prefix)
            signode += addnodes.desc_name(funcname, funcname)
            fullname = name
        else:
            fullname = "%s.%s" % (env_pkgname, name)
            signode += addnodes.desc_name(name, name)
        return fullname

    def _parse_type(self, node, gotype):
        # add cross-ref nodes for all words
        for part in filter(None, wsplit_re.split(gotype)):
            tnode = nodes.Text(part, part)
            if part[0] in string.ascii_letters+'_' and \
                   part not in self.stopwords:
                pnode = addnodes.pending_xref('',
                                              refdomain='go',
                                              reftype='type',
                                              reftarget=part,
                                              modname=None,
                                              classname=None)
                pnode += tnode
                node += pnode
            else:
                node += tnode

    def _resolve_package_name(self, signode, struct, name):
        # determine package name, as well as full name
        # default package is 'builtin'
        env_pkgname = self.options.get(
            'package', self.env.temp_data.get('go:package', 'builtin'))

        fullname = ""
        if struct:
            signode += addnodes.desc_addname("(", "(")
            try:
                arg, typ = struct.split(' ', 1)
                signode += addnodes.desc_addname(arg + ' ', arg + u'\xa0')
            except ValueError:
                typ = struct
            signode += addnodes.desc_name(typ, typ)
            signode += addnodes.desc_addname(") ", ")" + u'\xa0')

            try:
                pkgname, typename = typ.split('.', 1)
                fullname = "(%s.%s) %s" % (pkgname, typename, name)
                signode['package'] = pkgname
            except ValueError:
                fullname = "(%s.%s) %s" % (env_pkgname, typ, name)
                signode['package'] = env_pkgname
        else:
            try:
                pkgname, funcname = name.split('.', 1)
                name = funcname
                name_prefix = pkgname + '.'
                signode += addnodes.desc_name(name_prefix, name_prefix)
            except ValueError:
                pkgname = env_pkgname
                funcname = name
            fullname = "%s.%s" % (pkgname, funcname)
            signode['package'] = pkgname

        signode += addnodes.desc_name(name, name)
        return fullname

    def _handle_function_signature(self, sig, signode, m):
        if m is None:
            raise ValueError
        struct, name, arglist, retann = m.groups()
        signode += addnodes.desc_addname("func ", "func" + u'\xa0')
        fullname = self._resolve_package_name(signode, struct, name)

        if not arglist:
            # for callables, add an empty parameter list
            signode += addnodes.desc_parameterlist()
        else:
            paramlist = addnodes.desc_parameterlist()
            args = arglist.split(",")
            for arg in args:
                arg = arg.strip()
                param = addnodes.desc_parameter('', '', noemph=True)
                try:
                    argname, gotype = arg.split(' ', 1)
                except ValueError:
                    # no argument name given, only the type
                    self._parse_type(param, arg)
                else:
                    param += nodes.emphasis(argname + ' ', argname + u'\xa0')
                    self._parse_type(param, gotype)
                    # separate by non-breaking space in the output
                paramlist += param
            signode += paramlist

        if retann:
            signode += addnodes.desc_returns(retann, retann)
        return fullname

    def _get_index_text(self, name):
        if self.objtype == 'function':
            return _('%s (Golang function)') % name
        elif self.objtype == 'variable':
            return _('%s (Golang variable)') % name
        elif self.objtype == 'const':
            return _('%s (Golang const)') % name
        elif self.objtype == 'type':
            return _('%s (Golang type)') % name
        else:
            return ''

    def add_target_and_index(self, name, sig, signode):
        if name not in self.state.document.ids:
            signode['names'].append(name)
            signode['ids'].append(name)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)

            if self.objtype == 'function':
                finv = self.env.domaindata['go']['functions']
                if name in finv:
                    self.env.warn(
                        self.env.docname,
                        'duplicate Golang object description of %s, ' % name +
                        'other instance in ' +
                        self.env.doc2path(finv[name][0]), self.lineno)
                finv[name] = (self.env.docname, self.objtype)
            else:
                oinv = self.env.domaindata['go']['objects']
                if name in oinv:
                    self.env.warn(
                        self.env.docname,
                        'duplicate Golang object description of %s, ' % name +
                        'other instance in ' +
                        self.env.doc2path(oinv[name][0]), self.lineno)
                oinv[name] = (self.env.docname, self.objtype)

        indextext = self._get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(('single', indextext, name, name))
Esempio n. 34
0
File: c.py Progetto: ezc/sphinx-1
class CObject(ObjectDescription):
    """
    Description of a C language object.
    """

    doc_field_types = [
        TypedField('parameter',
                   label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument'),
                   typerolename='type',
                   typenames=('type', )),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=l_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    # These C types aren't described anywhere, so don't try to create
    # a cross-reference to them
    stopwords = set((
        'const',
        'void',
        'char',
        'wchar_t',
        'int',
        'short',
        'long',
        'float',
        'double',
        'unsigned',
        'signed',
        'FILE',
        'clock_t',
        'time_t',
        'ptrdiff_t',
        'size_t',
        'ssize_t',
        'struct',
        '_Bool',
    ))

    def _parse_type(self, node, ctype):
        # type: (nodes.Node, unicode) -> None
        # add cross-ref nodes for all words
        for part in [_f for _f in wsplit_re.split(ctype)
                     if _f]:  # type: ignore
            tnode = nodes.Text(part, part)
            if part[0] in string.ascii_letters + '_' and \
               part not in self.stopwords:
                pnode = addnodes.pending_xref('',
                                              refdomain='c',
                                              reftype='type',
                                              reftarget=part,
                                              modname=None,
                                              classname=None)
                pnode += tnode
                node += pnode
            else:
                node += tnode

    def _parse_arglist(self, arglist):
        # type: (unicode) -> Iterator[unicode]
        while True:
            m = c_funcptr_arg_sig_re.match(arglist)  # type: ignore
            if m:
                yield m.group()
                arglist = c_funcptr_arg_sig_re.sub('', arglist)  # type: ignore
                if ',' in arglist:
                    _, arglist = arglist.split(',', 1)
                else:
                    break
            else:
                if ',' in arglist:
                    arg, arglist = arglist.split(',', 1)
                    yield arg
                else:
                    yield arglist
                    break

    def handle_signature(self, sig, signode):
        # type: (unicode, addnodes.desc_signature) -> unicode
        """Transform a C signature into RST nodes."""
        # first try the function pointer signature regex, it's more specific
        m = c_funcptr_sig_re.match(sig)  # type: ignore
        if m is None:
            m = c_sig_re.match(sig)  # type: ignore
        if m is None:
            raise ValueError('no match')
        rettype, name, arglist, const = m.groups()

        signode += addnodes.desc_type('', '')
        self._parse_type(signode[-1], rettype)
        try:
            classname, funcname = name.split('::', 1)
            classname += '::'
            signode += addnodes.desc_addname(classname, classname)
            signode += addnodes.desc_name(funcname, funcname)
            # name (the full name) is still both parts
        except ValueError:
            signode += addnodes.desc_name(name, name)
        # clean up parentheses from canonical name
        m = c_funcptr_name_re.match(name)
        if m:
            name = m.group(1)

        typename = self.env.ref_context.get('c:type')
        if self.name == 'c:member' and typename:
            fullname = typename + '.' + name
        else:
            fullname = name

        if not arglist:
            if self.objtype == 'function':
                # for functions, add an empty parameter list
                signode += addnodes.desc_parameterlist()
            if const:
                signode += addnodes.desc_addname(const, const)
            return fullname

        paramlist = addnodes.desc_parameterlist()
        arglist = arglist.replace('`', '').replace('\\ ', '')  # remove markup
        # this messes up function pointer types, but not too badly ;)
        for arg in self._parse_arglist(arglist):
            arg = arg.strip()
            param = addnodes.desc_parameter('', '', noemph=True)
            try:
                m = c_funcptr_arg_sig_re.match(arg)  # type: ignore
                if m:
                    self._parse_type(param, m.group(1) + '(')
                    param += nodes.emphasis(m.group(2), m.group(2))
                    self._parse_type(param, ')(' + m.group(3) + ')')
                    if m.group(4):
                        param += addnodes.desc_addname(m.group(4), m.group(4))
                else:
                    ctype, argname = arg.rsplit(' ', 1)
                    self._parse_type(param, ctype)
                    # separate by non-breaking space in the output
                    param += nodes.emphasis(' ' + argname, u'\xa0' + argname)
            except ValueError:
                # no argument name given, only the type
                self._parse_type(param, arg)
            paramlist += param
        signode += paramlist
        if const:
            signode += addnodes.desc_addname(const, const)
        return fullname

    def get_index_text(self, name):
        # type: (unicode) -> unicode
        if self.objtype == 'function':
            return _('%s (C function)') % name
        elif self.objtype == 'member':
            return _('%s (C member)') % name
        elif self.objtype == 'macro':
            return _('%s (C macro)') % name
        elif self.objtype == 'type':
            return _('%s (C type)') % name
        elif self.objtype == 'var':
            return _('%s (C variable)') % name
        else:
            return ''

    def add_target_and_index(self, name, sig, signode):
        # type: (unicode, unicode, addnodes.desc_signature) -> None
        # for C API items we add a prefix since names are usually not qualified
        # by a module name and so easily clash with e.g. section titles
        targetname = 'c.' + name
        if targetname not in self.state.document.ids:
            signode['names'].append(targetname)
            signode['ids'].append(targetname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            inv = self.env.domaindata['c']['objects']
            if name in inv:
                self.state_machine.reporter.warning(
                    'duplicate C object description of %s, ' % name +
                    'other instance in ' + self.env.doc2path(inv[name][0]),
                    line=self.lineno)
            inv[name] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(name)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, targetname, '', None))

    def before_content(self):
        # type: () -> None
        self.typename_set = False
        if self.name == 'c:type':
            if self.names:
                self.env.ref_context['c:type'] = self.names[0]
                self.typename_set = True

    def after_content(self):
        # type: () -> None
        if self.typename_set:
            self.env.ref_context.pop('c:type', None)
Esempio n. 35
0
class BsvObject(ObjectDescription):
    """
    Description of a general Bsv object.
    """
    option_spec = {
        'noindex': directives.flag,
        'package': directives.unchanged,
        'annotation': directives.unchanged,
        'parameter': directives.unchanged,
        'returntype': directives.unchanged,
    }

    doc_field_types = [
        TypedField('parameter',
                   label=l_('Parameters'),
                   names=('param', 'parameter', 'arg', 'argument', 'keyword',
                          'kwarg', 'kwparam'),
                   typerolename='obj',
                   typenames=('paramtype', 'type'),
                   can_collapse=True),
        TypedField('variable',
                   label=l_('Variables'),
                   rolename='obj',
                   names=('var', 'ivar', 'cvar'),
                   typerolename='obj',
                   typenames=('vartype', ),
                   can_collapse=True),
        GroupedField('exceptions',
                     label=l_('Raises'),
                     rolename='exc',
                     names=('raises', 'raise', 'exception', 'except'),
                     can_collapse=True),
        Field('returnvalue',
              label=l_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=l_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]

    def get_signatures(self):
        siglines = ObjectDescription.get_signatures(self)
        return siglines

    def get_signature_prefix(self, sig):
        """May return a prefix to put before the object name in the
        signature.
        """
        return ''

    def needs_arglist(self):
        """May return true if an empty argument list is to be generated even if
        the document contains none.
        """
        return False

    def handle_signature(self, sig, signode):
        """Transform a Bsv signature into RST nodes.

        Return (fully qualified name of the thing, interfacename if any).

        If inside a interface, the current interface name is handled intelligently:
        * it is stripped from the displayed name if present
        * it is added to the full name (return value) if not present
        """
        print('BsvObject.handle_signature', sig)
        name_prefix = ''
        name = sig
        arglist = ''
        retann = ''
        if self.objtype in ['interface', 'instance', 'typeclass']:
            split = sig.split('#', 1)
            name = split[0]
            if len(split) > 1:
                arglist = split[1]
                m = bsv_param_re.match(arglist)
                if m: arglist = m.group(1)
        elif self.objtype in ['subinterface', 'field']:
            split = sig.rsplit(' ', 1)
            print('rsplit', split)
            name = split[-1]
            if len(split) > 1:
                retann = split[0]
        elif self.objtype in ['method', 'function']:
            split = sig.split(' ', 1)
            retann = split[0]
            nameparams = split[1]
            split = nameparams.split('(', 1)
            name = split[0]
            if len(split) > 1:
                arglist = split[1][0:-1]
        elif self.objtype in ['module']:
            split = sig.split('#', 1)
            name = split[0]
            if len(split) > 1:
                depth = 0
                paramreturn = split[1]
                #print('module', paramreturn, len(paramreturn))
                for i in range(0, len(paramreturn)):
                    c = paramreturn[i]
                    if c == '(': depth = depth + 1
                    elif c == ')': depth = depth - 1

                    #print(i, c, depth)
                    if depth == 0:
                        endofparam = i
                        break
                arglist = paramreturn[1:endofparam]
                retann = paramreturn[endofparam + 1:-1]
                #print(arglist)
                #print(endofparam, retann)

        # determine package and interface name (if applicable), as well as full name
        modname = self.options.get('package',
                                   self.env.temp_data.get('bsv:package'))
        interfacename = self.env.temp_data.get('bsv:interface')
        if interfacename:
            add_package = False
            if name_prefix and name_prefix.startswith(interfacename):
                fullname = name_prefix + name
                # interface name is given again in the signature
                name_prefix = name_prefix[len(interfacename):].lstrip('.')
            elif name_prefix:
                # interface name is given in the signature, but different
                # (shouldn't happen)
                fullname = interfacename + '.' + name_prefix + name
            else:
                # interface name is not given in the signature
                fullname = interfacename + '.' + name
        else:
            add_package = True
            if name_prefix:
                interfacename = name_prefix.rstrip('.')
                fullname = name_prefix + name
            else:
                interfacename = ''
                fullname = name

        signode['package'] = modname
        signode['interface'] = interfacename
        signode['fullname'] = fullname

        sig_prefix = self.get_signature_prefix(sig)
        if sig_prefix:
            signode += addnodes.desc_annotation(sig_prefix, sig_prefix)

        if name_prefix:
            signode += addnodes.desc_addname(name_prefix, name_prefix)
        # exceptions are a special case, since they are documented in the
        # 'exceptions' package.
        elif add_package and self.env.config.add_package_names:
            modname = self.options.get('package',
                                       self.env.temp_data.get('bsv:package'))
            if modname and modname != 'exceptions':
                nodetext = modname + '::'
                signode += addnodes.desc_addname(nodetext, nodetext)

        anno = self.options.get('annotation')

        signode += addnodes.desc_name(name, name)
        #print('arglist', arglist)
        if not arglist:
            if self.needs_arglist():
                # for callables, add an empty parameter list
                if arglist:
                    signode += addnodes.desc_parameterlist(text=arglist)
                elif self.options.get('parameter'):
                    signode += addnodes.desc_parameterlist(
                        text=self.options.get('parameter'))
            if retann:
                signode += addnodes.desc_returns(text=retann)
            elif self.options.get('returntype'):
                signode += addnodes.desc_returns(
                    text=self.options.get('returntype'))
            if anno:
                signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
            #print('signode', signode)
            return fullname, name_prefix

        _pseudo_parse_arglist(signode, arglist)
        if retann:
            signode += addnodes.desc_returns(retann, retann)
        if anno:
            signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
        return fullname, name_prefix

    def get_index_text(self, modname, name):
        """Return the text for the index entry of the object."""
        raise NotImplementedError('must be implemented in subinterfacees')

    def add_target_and_index(self, name_cls, sig, signode):
        modname = self.options.get('package',
                                   self.env.temp_data.get('bsv:package'))
        fullname = (modname and modname + '::' or '') + name_cls[0]
        # note target
        if fullname not in self.state.document.ids:
            signode['names'].append(fullname)
            signode['ids'].append(fullname)
            signode['first'] = (not self.names)
            self.state.document.note_explicit_target(signode)
            objects = self.env.domaindata['bsv']['objects']
            if fullname in objects:
                self.state_machine.reporter.warning(
                    'duplicate object description of %s, ' % fullname +
                    'other instance in ' +
                    self.env.doc2path(objects[fullname][0]) +
                    ', use :noindex: for one of them',
                    line=self.lineno)
            objects[fullname] = (self.env.docname, self.objtype)

        indextext = self.get_index_text(modname, name_cls)
        if indextext:
            self.indexnode['entries'].append(
                ('single', indextext, fullname, ''))

    def before_content(self):
        # needed for automatic qualification of members (reset in subinterfacees)
        self.clsname_set = False

    def after_content(self):
        if self.clsname_set:
            self.env.temp_data['bsv:interface'] = None