Esempio n. 1
0
class KOSAttribute(KOSObject):

    doc_field_types = [
        Field('access', label=l_('Access'), has_arg=False),
        Field('type'  , label=l_('Type'  ), has_arg=False),
    ]

    def handle_signature(self, sig, signode):
        m = ks_sig_re.match(sig)
        name = m.group('object')
        struct = None  #might override further down

        current_struct = self.env.temp_data.get('ks:structure')
        if m.group('prefix') is None:
            if current_struct is not None:
                struct = current_struct
                fullname = current_struct + ':' + name
            else:
                raise Exception("Attribute name lacks a prefix and isn't " +
                    "indented inside a structure section.  Problem " +
                    "occurred at " + self.env.docname + ", line " +
                     str(self.lineno) + 
                     ".")
        else:
            struct = m.group('prefix').split(':')[-1]
            fullname = struct + ':' + name

        if struct is not None:
            if struct != '':
                signode += addnodes.desc_type(struct,struct+':')
        signode += addnodes.desc_name(fullname, name)

        return fullname

    def get_index_text(self, objectname, name):
        return _('{}'.format(name))
Esempio n. 2
0
class JSCallable(JSObject):
    """Description of a JavaScript function, method or constructor."""
    has_arguments = True

    doc_field_types = [
        TypedField('arguments',
                   label=_('Arguments'),
                   names=('argument', 'arg', 'parameter', 'param'),
                   typerolename='func',
                   typenames=('paramtype', 'type')),
        GroupedField('errors',
                     label=_('Throws'),
                     rolename='err',
                     names=('throws', ),
                     can_collapse=True),
        Field('returnvalue',
              label=_('Returns'),
              has_arg=False,
              names=('returns', 'return')),
        Field('returntype',
              label=_('Return type'),
              has_arg=False,
              names=('rtype', )),
    ]
Esempio n. 3
0
class LuaFunction(LuaObject):
    typename = "function"

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

    def build_objtype(self):
        return self.options.get('objtype') or ""

    def needs_arglist(self):
        return True

    def get_index_name(self, names):
        return '%s()' % (names['fullname'])
Esempio n. 4
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('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. 5
0
class AlloyMacro(AlloyCallable):
    """Description of an Alloy macro."""
    has_arguments = False
    display_prefix = "let "

    doc_field_types = [
        TypedField('arguments',
                   label=_('Arguments'),
                   names=('argument', 'arg', 'parameter', 'param'),
                   typerolename='func',
                   typenames=('paramtype', 'type')),
        Field('expandsto',
              label=_('Expands to'),
              has_arg=False,
              names=('expand', 'expansion')),
    ]
class ClifInst(ClifObject):
    """A Cranelift IR instruction."""

    doc_field_types = [
        TypedField('argument', label=l_('Arguments'),
                   names=('in', 'arg'),
                   typerolename='type', typenames=('type',)),
        TypedField('result', label=l_('Results'),
                   names=('out', 'result'),
                   typerolename='type', typenames=('type',)),
        GroupedField(
            'typevar', names=('typevar',), label=l_('Type Variables')),
        GroupedField('flag', names=('flag',), label=l_('Flags')),
        Field('resulttype', label=l_('Result type'), has_arg=False,
              names=('rtype',)),
    ]

    def handle_signature(self, sig, signode):
        # Look for signatures like
        #
        #   v0, v1 = foo op0, op1
        #   v0 = foo
        #   foo op0

        parts = re.split(sep_equal, sig, 1)
        if len(parts) == 2:
            # Outgoing parameters.
            parse_params(parts[0], signode)
            signode += nodes.Text(' = ')
            name = parts[1]
        else:
            name = parts[0]

        # Parse 'name arg, arg'
        parts = name.split(None, 1)
        name = parts[0]
        signode += addnodes.desc_name(name, name)

        if len(parts) == 2:
            # Incoming parameters.
            signode += nodes.Text(' ')
            parse_params(parts[1], signode)

        return name

    def get_index_text(self, name):
        return name
Esempio n. 7
0
def setup(app):
    from sphinx.util.docfields import Field
    app.add_object_type(
        directivename="conf",
        rolename="conf",
        objname="configuration value",
        indextemplate="pair: %s; configuration value",
        doc_field_types=[
            Field(
                'type',
                label='Type',
                has_arg=False,
                names=('type',),
                bodyrolename='class'
            ),
        ]
    )
Esempio n. 8
0
class LuaData(LuaObject):
    typename = "data"

    option_spec = dict(
        readonly=directives.flag,
        **LuaObject.option_spec
    )

    doc_field_types = [
        Field('type', label=l_('Type'), has_arg=False,
              names=('type',)),
    ]

    def build_objtype(self):
        if 'readonly' in self.options:
            return "const %s" % (self.options.get('objtype') or "")
        else:
            return self.options.get('objtype') or ""
Esempio n. 9
0
class JSAttribute(JSObject):

    doc_field_types = [
        AnnotateField('type', label=l_('Type'), names=('type',),
                      bodyrolename='class', annotate_type=ANNOTATE_TYPE,
                      has_arg=False),
        Field('default', label=l_('Default'), names=('default',), has_arg=False),
        BoolField('required', label=l_('Required'), has_arg=False,
                  names=('require', 'required')),
        BoolField('static', label=l_('Static'), names=('static',), has_arg=False),
        AnnotateField('readonly', label=l_('Read-only'), names=('readonly', 'ro'),
                      annotate_type=ANNOTATE_READ_ONLY, has_arg=False),
        AnnotateField('extends', label=l_('Extends'),
                      names=('extend', 'extends', 'inherits', 'inherit'),
                      annotate_type=ANNOTATE_EXTENDS, bodyrolename='class',
                      has_arg=False),
        AnnotateField('inheritedFrom', label=l_('inheritedFrom'), names=('inheritedFrom', 'inheritedFrom'),
                                  annotate_type=ANNOTATE_INHERITEDFROM, has_arg=False),
    ]
Esempio n. 10
0
class DmlProperty(DmlObject):
    """Description of a function."""

    option_spec: OptionSpec = DmlObject.option_spec.copy()
    option_spec.update({
        'const': directives.flag,
        'readonly': directives.flag,
        'type': directives.unchanged,
    })
    
    doc_field_types = [
        Field('default', label=_('Default'), names=('default')),
        GroupedField('throws', label=_('Throws'), names=('throws', 'throw', 'error', 'err'), can_collapse=True)
    ]

    def split_signature(self, sig: str) -> Tuple[str, str, List[str], List[str]]:
        
        # return tuple:
        #   - type (class, property, event, function) -> str
        #   - name -> str
        #   - arglist -> List[str]
        #   - annotations -> List[str]
           
        if not "type" in self.options:
            raise Exception("DML property always needs type assigned")
        
        typ = "property " + self.options["type"]
        name = sig
        arglist = None

        annotations = []
        if 'const' in self.options:
            annotations.append("constant")
        if 'readonly' in self.options:
            annotations.append("readonly")   
            
        return (typ, name, arglist, annotations)


    def get_index_text(self, name_cls: Tuple[str, str]) -> str:
        # add index in own add_target_and_index() instead.
        return "PropertyName " + name_cls[0]
Esempio n. 11
0
class LuaClass(LuaObject):
    doc_field_types = [
        Field('extend', label=l_('Extends'), has_arg=False,
              names=('extend',)),
    ]

    typename = "object"

    def get_index_type(self):
        return "%s" % (self.__class__.typename)

    def before_content(self):
        LuaObject.before_content(self)
        if self.names:
            self.env.temp_data['lua:class'] = self.names[0]['fullname']

    def after_content(self):
        LuaObject.after_content(self)
        if self.names:
            self.env.temp_data['lua:class'] = None
Esempio n. 12
0
class PSTable(PSschemaObject):

    doc_field_types = [
        TypedField('column',
                   label=l_('Columns'),
                   rolename='obj',
                   names=('col', 'column', 'cols'),
                   typerolename='obj',
                   typenames=('paramtype', 'type')),
        Field('inpatch',
              label=l_('Included in Patch'),
              has_arg=False,
              names=('inpatch')),
        TypedField('versioninfo',
                   label=l_('Version Info'),
                   rolename='obj',
                   names=('version', 'versioninfo'),
                   typerolename='obj',
                   typenames=('paramtype', 'type')),
    ]
Esempio n. 13
0
def setup(app: Sphinx) -> None:
    """Register the ``confval`` role and directive.

    This allows to declare theme options as their own object
    for styling and cross-referencing.
    """
    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. 14
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. 15
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. 16
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. 17
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. 18
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. 19
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. 20
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. 21
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. 22
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. 23
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. 25
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. 26
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. 27
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. 28
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. 29
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. 30
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))