def run(self):
     doc = self.state.document
     env = doc.settings.env
     if 'layout' in self.options:
         layout = self.options['layout']
     else:
         layout = env.config.demo_layout
     if not self.layout_re.match(layout):
         return [
             doc.reporter.error("invalid layout specifier: %s" % layout,
                                lineno=self.lineno)
         ]
     order = []
     for block in layout.split(','):
         block = block.strip()
         is_hidden = block[0] == '-'
         block = block.lstrip('+-')
         order.append((block, is_hidden))
     wrapper = nodes.compound(classes=['demo-wrapper'])
     data = "\n".join(self.content)
     for block, is_hidden in order:
         if block == 'demo':
             header = nodes.paragraph(classes=['demo-header'])
             header += nodes.Text("Demo")
             if is_hidden:
                 header['classes'].append('demo-hide')
             demo = nodes.raw(data,
                              data,
                              format='html',
                              classes=['demo-area'])
             html_wrapper = addnodes.only(expr='html')
             html_wrapper += header
             html_wrapper += demo
             wrapper += html_wrapper
         elif block == 'source':
             header = nodes.paragraph(classes=['demo-header'])
             header += nodes.Text("Source")
             if is_hidden:
                 header['classes'].append('demo-hide')
             source = nodes.literal_block(data,
                                          data,
                                          language='html',
                                          classes=['demo-source'])
             html_wrapper = addnodes.only(expr='html')
             html_wrapper += header
             wrapper += html_wrapper
             wrapper += source
         else:
             assert False, block
     return [wrapper]
Exemplo n.º 2
0
def doctree_read(app, doctree):
    # Add viewcode nodes for code elements referenced in the document.

    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    # handle desc (description) nodes (module contents)
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not _update_tags(env, modname, fullname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            # build up an xref and add it to the desc node
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('',
                                              reftype='viewcode',
                                              refdomain='std',
                                              refexplicit=False,
                                              reftarget=pagename,
                                              refid=fullname,
                                              refdoc=env.docname)
            onlynode[0] += nodes.inline('',
                                        _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode

    # handle index nodes (modules themselves)
    for objnode in doctree.traverse(addnodes.index):
        # extract module name by de-munging the "target" field
        index_target = objnode['entries'][0][2]
        if not index_target.startswith('module-'):
            continue
        modname = index_target.replace('module-', '', 1)
        _update_tags(env, modname)
        pagename = '_modules/' + modname.replace('.', '/')
        # build up an xref and add it in a new paragraph after the index node
        xref = addnodes.pending_xref('',
                                     reftype='viewcode',
                                     refdomain='std',
                                     refexplicit=False,
                                     reftarget=pagename,
                                     refid='',
                                     refdoc=env.docname)
        xref += nodes.inline('', _('[source]'), classes=['viewcode-link'])
        idx = objnode.parent.index(objnode) + 1
        objnode.parent.insert(idx, nodes.paragraph('', '', xref))
Exemplo n.º 3
0
    def run(self):
        from docutils import nodes
        from sphinx import addnodes
        from sphinx.util.nodes import set_source_info

        node = addnodes.only()
        node.document = self.state.document
        set_source_info(self, node)
        node['expr'] = self.arguments[0]

        # hack around title style bookkeeping
        surrounding_title_styles = self.state.memo.title_styles
        surrounding_section_level = self.state.memo.section_level
        self.state.memo.title_styles = []
        self.state.memo.section_level = 0
        try:
            result = self.state.nested_parse(self.content,
                                             0,
                                             node,
                                             match_titles=1)
            depth = len(surrounding_title_styles)
            if self.state.memo.title_styles:
                style = self.state.memo.title_styles[0]
                if style in surrounding_title_styles:
                    depth = surrounding_title_styles.index(style)
            parent = self.state.parent
            for i in range(len(surrounding_title_styles) - depth):
                if parent.parent:
                    parent = parent.parent
            parent.append(node)
        finally:
            self.state.memo.title_styles = surrounding_title_styles
            self.state.memo.section_level = surrounding_section_level
        return []
Exemplo n.º 4
0
    def run(self):
        sponsor_link = self.env.config.sponsor_link
        organization = self.env.config.organization

        admonition_node = nodes.admonition(classes=["admonition-sponsor"])
        admonition_node += nodes.title(text="Sponsor")

        # Parse admonition body contents.
        # Needs to use a container here instead of list otherwise exception.
        node_list = nodes.container()
        self.state.nested_parse(self.content, self.content_offset, node_list)
        admonition_node += node_list.children

        # Add sponsor button for HTML and fallback for PDF.
        html = f"<iframe src=\"{sponsor_link}/button\" title=\"Sponsor {organization}\" height=\"35\" width=\"116\" style=\"border: 0; display: block;\"></iframe>"
        html_node = nodes.raw(text=html, format="html")
        only_pdf = addnodes.only(expr="latex")
        only_pdf_paragraph = nodes.inline()
        self.state.nested_parse(
            nodes.inline(text=f":link:`Sponsor Us <{sponsor_link}?o=esb>`"), 0,
            only_pdf_paragraph)
        only_pdf += only_pdf_paragraph

        admonition_node += html_node
        admonition_node += only_pdf

        return [admonition_node]
Exemplo n.º 5
0
 def handle_options(self, sig, signode):
     if not self.make_section_and_title and self.options.get('title'):
         self.state_machine.reporter.warning(
             "A ':title:' option was given for Protobuf object '%s' in document '%s', but this was ignored since "
             "the Protobuf type '%s' is configured not to render any title."
             % (sig, self.env.docname, self.objtype),
             line=self.lineno)
     # Source links
     file_path = self.options.get('src_file_path', '').strip()
     if file_path:
         base_url = self.options.get('src_base_url', '').strip(
         ) or self.env.config.protobufdomain_sourcelinks_base_url
         # TODO via config/template to allow custom line range anchors (e.g. '#1' for Gerrit or '#L1-L7' for GitHub).
         linerange = self.options.get('src_linerange', '').strip()
         linerange_anchor = "#" + linerange.split("-", 1)[0]
         url = base_url + file_path + linerange_anchor
         # class and title looks as with 'viewcode' extension. Rather than extending that extension with support for
         # this domain, create our own link for now...
         pnode = nodes.reference('',
                                 '',
                                 internal=False,
                                 refuri=url,
                                 reftype='viewcode',
                                 refdomain='std',
                                 refexplicit=False)
         pnode['classes'].append('viewcode-link')
         pnode['classes'].append('headerlink')
         pnode += nodes.inline('', 'source')
         srclink_node = addnodes.only(expr='html')
         srclink_node += pnode
         signode += srclink_node
Exemplo n.º 6
0
    def run(self):
        from docutils import nodes
        from sphinx import addnodes
        from sphinx.util.nodes import set_source_info

        node = addnodes.only()
        node.document = self.state.document
        set_source_info(self, node)
        node['expr'] = self.arguments[0]

        # hack around title style bookkeeping
        surrounding_title_styles = self.state.memo.title_styles
        surrounding_section_level = self.state.memo.section_level
        self.state.memo.title_styles = []
        self.state.memo.section_level = 0
        try:
            result = self.state.nested_parse(self.content, 0, node,
                                             match_titles=1)
            depth = len(surrounding_title_styles)
            if self.state.memo.title_styles:
                style = self.state.memo.title_styles[0]
                if style in surrounding_title_styles:
                    depth = surrounding_title_styles.index(style)
            parent = self.state.parent
            for i in xrange(len(surrounding_title_styles) - depth):
                if parent.parent:
                    parent = parent.parent
            parent.append(node)
        finally:
            self.state.memo.title_styles = surrounding_title_styles
            self.state.memo.section_level = surrounding_section_level
        return []
Exemplo n.º 7
0
 def run(self):
     node = addnodes.only()
     node.document = self.state.document
     node.line = self.lineno
     node['expr'] = self.arguments[0]
     self.state.nested_parse(self.content, self.content_offset, node,
                             match_titles=1)
     return [node]
Exemplo n.º 8
0
 def run(self):
     node = addnodes.only()
     node.document = self.state.document
     node.line = self.lineno
     node['expr'] = self.arguments[0]
     self.state.nested_parse(self.content, self.content_offset, node,
                             match_titles=1)
     return [node]
 def run(self):
     doc = self.state.document
     env = doc.settings.env
     if 'layout' in self.options:
         layout = self.options['layout']
     else:
         layout = env.config.demo_layout
     if not self.layout_re.match(layout):
         return [doc.reporter.error("invalid layout specifier: %s" % layout,
                                    lineno=self.lineno)]
     order = []
     for block in layout.split(','):
         block = block.strip()
         is_hidden = block[0] == '-'
         block = block.lstrip('+-')
         order.append((block, is_hidden))
     wrapper = nodes.compound(classes=['demo-wrapper'])
     data = "\n".join(self.content)
     for block, is_hidden in order:
         if block == 'demo':
             header = nodes.paragraph(classes=['demo-header'])
             header += nodes.Text("Demo")
             if is_hidden:
                 header['classes'].append('demo-hide')
             demo = nodes.raw(data, data,
                              format='html',
                              classes=['demo-area'])
             html_wrapper = addnodes.only(expr='html')
             html_wrapper += header
             html_wrapper += demo
             wrapper += html_wrapper
         elif block == 'source':
             header = nodes.paragraph(classes=['demo-header'])
             header += nodes.Text("Source")
             if is_hidden:
                 header['classes'].append('demo-hide')
             source = nodes.literal_block(data, data,
                                          language='html',
                                          classes=['demo-source'])
             html_wrapper = addnodes.only(expr='html')
             html_wrapper += header
             wrapper += html_wrapper
             wrapper += source
         else:
             assert False, block
     return [wrapper]
Exemplo n.º 10
0
def build_result_table(product, cut):
    meta = product.get('meta')
    data = product.get('data')
    if 'domain' not in meta:
        return
    build = get_build_by_domain(meta['domain'])
    if not build.span:
        return
    table_node = nodes.table()
    measures = build.measures(data, cut)
    group_node = nodes.tgroup(cols=build.span)
    table_node += group_node
    for measure in measures:
        colspec_node = nodes.colspec(colwidth=measure)
        group_node += colspec_node
    head_node = nodes.thead()
    group_node += head_node
    head_rows = build.head(build.head_height())
    if head_rows:
        for row in head_rows:
            row_node = nodes.row()
            head_node += row_node
            for cell, rowspan, colspan, classes in row:
                entry_node = nodes.entry(classes=classes)
                if rowspan > 1:
                    entry_node['morerows'] = rowspan - 1
                if colspan > 1:
                    entry_node['morecols'] = colspan - 1
                row_node += entry_node
                para_node = nodes.paragraph()
                entry_node += para_node
                text_node = nodes.Text(cell)
                para_node += text_node
    body_node = nodes.tbody()
    group_node += body_node
    body_rows = build.body(build.body_height(data, cut), data, cut)
    if body_rows:
        for row in body_rows:
            row_node = nodes.row()
            body_node += row_node
            for cell, rowspan, colspan, classes in row:
                entry_node = nodes.entry(classes=classes)
                if rowspan > 1:
                    entry_node['morerows'] = rowspan - 1
                if colspan > 1:
                    entry_node['morecols'] = colspan - 1
                row_node += entry_node
                para_node = nodes.paragraph()
                entry_node += para_node
                text_node = nodes.Text(cell)
                if any(cls in classes for cls in
                       ['htsql-empty-val', 'htsql-null-val', 'htsql-cut']):
                    only_node = addnodes.only(expr='latex or text')
                    only_node += text_node
                    para_node += only_node
                else:
                    para_node += text_node
    return table_node
Exemplo n.º 11
0
def doctree_read(app, doctree):
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False
            return
        if not isinstance(analyzer.code, text_type):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        if entry is None or entry[0] != code:
            analyzer.find_tags()
            entry = code, analyzer.tags, {}, refname
            env._viewcode_modules[modname] = entry
        elif entry is False:
            return
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = _get_full_modname(app, modname, fullname)
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 12
0
def doctree_read(app, doctree):
    env = app.builder.env
    if not hasattr(env, "_viewcode_modules"):
        env._viewcode_modules = {}

    def has_tag(modname, fullname, docname):
        entry = env._viewcode_modules.get(modname, None)
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False
            return
        if not isinstance(analyzer.code, str):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        if entry is None or entry[0] != code:
            analyzer.find_tags()
            entry = code, analyzer.tags, {}
            env._viewcode_modules[modname] = entry
        elif entry is False:
            return
        code, tags, used = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get("domain") != "py":
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get("module")
            if not modname:
                continue
            fullname = signode.get("fullname")
            if not has_tag(modname, fullname, env.docname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = "_modules/" + modname.replace(".", "/")
            onlynode = addnodes.only(expr="html")
            onlynode += addnodes.pending_xref(
                "",
                reftype="viewcode",
                refdomain="std",
                refexplicit=False,
                reftarget=pagename,
                refid=fullname,
                refdoc=env.docname,
            )
            onlynode[0] += nodes.inline("", _("[source]"), classes=["viewcode-link"])
            signode += onlynode
Exemplo n.º 13
0
def doctree_read(app, doctree):
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    def has_tag(modname, fullname, docname):
        entry = env._viewcode_modules.get(modname, None)
        if entry is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False
                return
            analyzer.find_tags()
            if not isinstance(analyzer.code, unicode):
                code = analyzer.code.decode(analyzer.encoding)
            else:
                code = analyzer.code
            entry = code, analyzer.tags, {}
            env._viewcode_modules[modname] = entry
        elif entry is False:
            return
        code, tags, used = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('',
                                              reftype='viewcode',
                                              refdomain='std',
                                              refexplicit=False,
                                              reftarget=pagename,
                                              refid=fullname,
                                              refdoc=env.docname)
            onlynode[0] += nodes.inline('',
                                        _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 14
0
def doctree_read(app, doctree):
    # Add viewcode nodes for code elements referenced in the document.

    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    # handle desc (description) nodes (module contents)
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not _update_tags(env, modname, fullname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            # build up an xref and add it to the desc node
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode

    # handle index nodes (modules themselves)
    for objnode in doctree.traverse(addnodes.index):
        # extract module name by de-munging the "target" field
        index_target = objnode['entries'][0][2]
        if not index_target.startswith('module-'):
            continue
        modname = index_target.replace('module-', '', 1)
        _update_tags(env, modname)
        pagename = '_modules/' + modname.replace('.', '/')
        # build up an xref and add it in a new paragraph after the index node
        xref = addnodes.pending_xref(
            '', reftype='viewcode', refdomain='std', refexplicit=False,
            reftarget=pagename, refid='', refdoc=env.docname)
        xref += nodes.inline('', _('[source]'),
                                    classes=['viewcode-link'])
        idx = objnode.parent.index(objnode) + 1
        objnode.parent.insert(idx, nodes.paragraph('', '', xref))
Exemplo n.º 15
0
    def make_httpdomain_rst(self, mapped_routes):
        node = nodes.section()
        node.document = self.state.document
        result = ViewList()

        routes = {}

        for route in mapped_routes:
            if route['method'] == ANY_KEY:
                method = 'any'
            else:
                method = route['method']

            directives = http_directive(
                method,
                route['pattern'],
                route['docs'],
            )

            routes[(method, route['pattern'])] = route

            for line in directives:
                result.append(line, '<autopyramid>')

        nested_parse_with_titles(self.state, result, node)

        for objnode in node.traverse(addnodes.desc):
            if objnode.get('domain') != 'http':
                continue

            for signode in objnode:
                if not isinstance(signode, addnodes.desc_signature):
                    continue
                method = signode.get('method')
                path = signode.get('path')
                mapped_route = routes.get((method, path))
                if not method or not path or not mapped_route:
                    continue

                xref_node = self._make_view_source_xref(mapped_route)
                if not xref_node:
                    continue

                xref_node += nodes.inline('',
                                          '[source]',
                                          classes=['viewcode-link'])

                source_node = addnodes.only(expr='html')
                source_node += xref_node

                signode += source_node

        return node.children
Exemplo n.º 16
0
def youtube_embed(id):
    html = f"""
    <div class="video-container">
        <iframe width="100%" height="100%" src="https://www.youtube-nocookie.com/embed/{id}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
        </iframe>
    </div>"""

    # Add only HTML node.
    only_html = addnodes.only(expr="html")

    text = "https://www.youtube.com/watch?v={id}"

    # Add YouTube HTML to only node.
    only_html += nodes.raw(text=html, format="html")

    # Add fallback for PDFs.
    only_pdf = addnodes.only(expr="latex")
    # TODO: add optional fallback text
    only_pdf += nodes.paragraph(text=f"https://www.youtube.com/watch?v={id}")

    return [only_html, only_pdf]
Exemplo n.º 17
0
def doctree_read(app, doctree):
    # Get the configuration parameters
    if app.config.edit_on_github_project == 'REQUIRED':
        raise ValueError(
            "The edit_on_github_project configuration variable must be "
            "provided in the conf.py")

    source_root = app.config.edit_on_github_source_root
    url = get_url_base(app)

    docstring_message = app.config.edit_on_github_docstring_message

    # Handle the docstring-editing links
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            obj = import_object(modname, fullname)
            anchor = None
            if obj is not None:
                try:
                    lines, lineno = inspect.getsourcelines(obj)
                except:
                    pass
                else:
                    anchor = '#L%d' % lineno
            if anchor:
                real_modname = inspect.getmodule(obj).__name__
                path = '%s%s%s.py%s' % (url, source_root,
                                        real_modname.replace('.', '/'), anchor)
                onlynode = addnodes.only(expr='html')
                onlynode += nodes.reference(
                    reftitle=app.config.edit_on_github_help_message,
                    refuri=path)
                onlynode[0] += nodes.inline(
                    '',
                    '',
                    nodes.raw('', '&nbsp;', format='html'),
                    nodes.Text(docstring_message),
                    classes=['edit-on-github', 'viewcode-link'])
                signode += onlynode
Exemplo n.º 18
0
def doctree_read(app, doctree):
    # type: (Sphinx, nodes.Node) -> None
    env = app.builder.env

    resolve_target = getattr(env.config, 'linkcode_resolve', None)
    if not callable(env.config.linkcode_resolve):
        raise LinkcodeError(
            "Function `linkcode_resolve` is not given in conf.py")

    domain_keys = {
        'py': ['module', 'fullname'],
        'c': ['names'],
        'cpp': ['names'],
        'js': ['object', 'fullname'],
    }

    for objnode in doctree.traverse(addnodes.desc):
        domain = objnode.get('domain')
        uris = set()  # type: Set[unicode]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue

            # Convert signode to a specified format
            info = {}
            for key in domain_keys.get(domain, []):
                value = signode.get(key)
                if not value:
                    value = ''
                info[key] = value
            if not info:
                continue

            # Call user code to resolve the link
            uri = resolve_target(domain, info)
            if not uri:
                # no source
                continue

            if uri in uris or not uri:
                # only one link per name, please
                continue
            uris.add(uri)

            inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])
            onlynode = addnodes.only(expr='html')
            onlynode += nodes.reference('',
                                        '',
                                        inline,
                                        internal=False,
                                        refuri=uri)
            signode += onlynode
Exemplo n.º 19
0
 def build_toc(node, depth=1):
     # type: (nodes.Node, int) -> List[nodes.Node]
     entries = []
     for sectionnode in node:
         # find all toctree nodes in this section and add them
         # to the toc (just copying the toctree node which is then
         # resolved in self.get_and_resolve_doctree)
         if isinstance(sectionnode, addnodes.only):
             onlynode = addnodes.only(expr=sectionnode['expr'])
             blist = build_toc(sectionnode, depth)
             if blist:
                 onlynode += blist.children  # type: ignore
                 entries.append(onlynode)
             continue
         if not isinstance(sectionnode, nodes.section):
             for toctreenode in traverse_in_section(
                     sectionnode, addnodes.toctree):
                 item = toctreenode.copy()
                 entries.append(item)
                 # important: do the inventory stuff
                 TocTree(app.env).note(docname, toctreenode)
             continue
         title = sectionnode[0]
         # copy the contents of the section title, but without references
         # and unnecessary stuff
         visitor = SphinxContentsFilter(doctree)
         title.walkabout(visitor)
         nodetext = visitor.get_entry_text()
         if not numentries[0]:
             # for the very first toc entry, don't add an anchor
             # as it is the file's title anyway
             anchorname = ''
         else:
             anchorname = '#' + sectionnode['ids'][0]
         numentries[0] += 1
         # make these nodes:
         # list_item -> compact_paragraph -> reference
         reference = nodes.reference('',
                                     '',
                                     internal=True,
                                     refuri=docname,
                                     anchorname=anchorname,
                                     *nodetext)
         para = addnodes.compact_paragraph('', '', reference)
         item = nodes.list_item('', para)
         sub_item = build_toc(sectionnode, depth + 1)
         item += sub_item
         entries.append(item)
     if entries:
         return nodes.bullet_list('', *entries)
     return []
Exemplo n.º 20
0
def doctree_read(app, doctree):
    # type: (Sphinx, nodes.Node) -> None
    env = app.builder.env

    resolve_target = getattr(env.config, 'linkcode_resolve', None)
    if not callable(env.config.linkcode_resolve):
        raise LinkcodeError(
            "Function `linkcode_resolve` is not given in conf.py")

    domain_keys = {
        'py': ['module', 'fullname'],
        'c': ['names'],
        'cpp': ['names'],
        'js': ['object', 'fullname'],
    }

    for objnode in doctree.traverse(addnodes.desc):
        domain = objnode.get('domain')
        uris = set()  # type: Set[str]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue

            # Convert signode to a specified format
            info = {}
            for key in domain_keys.get(domain, []):
                value = signode.get(key)
                if not value:
                    value = ''
                info[key] = value
            if not info:
                continue

            if 'lineno' in signode.attributes:
                info['lineno'] = signode.attributes['lineno']
            # Call user code to resolve the link
            uri = resolve_target(domain, info)
            if not uri:
                # no source
                continue

            if uri in uris or not uri:
                # only one link per name, please
                continue
            uris.add(uri)

            inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])
            onlynode = addnodes.only(expr='html')
            onlynode += nodes.reference('', '', inline, internal=False, refuri=uri)
            signode += onlynode
Exemplo n.º 21
0
    def add_source_link(self, signode: addnodes.desc) -> None:
        """
        Add link to source code to *signode*
        """
        filename, lineno = self.options['source'].split(':')
        if not hasattr(self.env, '_snakefiles'):
            self.env._snakefiles = set()
        self.env._snakefiles.add(filename)

        onlynode = addnodes.only(expr='html')  # show only in html
        onlynode += nodes.reference(
            '', refuri='_snakefiles/{}.html#line-{}'.format(filename, lineno))
        onlynode[0] += nodes.inline('', '[source]', classes=['viewcode-link'])
        signode += onlynode
Exemplo n.º 22
0
def doctree_read(app, doctree):
    # Get the configuration parameters
    if app.config.edit_on_github_project == 'REQUIRED':
        raise ValueError(
            "The edit_on_github_project configuration variable must be "
            "provided in the conf.py")

    source_root = app.config.edit_on_github_source_root
    url = get_url_base(app)

    docstring_message = app.config.edit_on_github_docstring_message

    # Handle the docstring-editing links
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            obj = import_object(modname, fullname)
            anchor = None
            if obj is not None:
                try:
                    lines, lineno = inspect.getsourcelines(obj)
                except:
                    pass
                else:
                    anchor = '#L%d' % lineno
            if anchor:
                real_modname = inspect.getmodule(obj).__name__
                path = '%s%s%s.py%s' % (
                    url, source_root, real_modname.replace('.', '/'), anchor)
                onlynode = addnodes.only(expr='html')
                onlynode += nodes.reference(
                    reftitle=app.config.edit_on_github_help_message,
                    refuri=path)
                onlynode[0] += nodes.inline(
                    '', '', nodes.raw('', '&nbsp;', format='html'),
                    nodes.Text(docstring_message),
                    classes=['edit-on-github', 'viewcode-link'])
                signode += onlynode
Exemplo n.º 23
0
 def build_toc(node, depth=1):
     # type: (nodes.Element, int) -> nodes.bullet_list
     entries = []  # type: List[nodes.Element]
     for sectionnode in node:
         # find all toctree nodes in this section and add them
         # to the toc (just copying the toctree node which is then
         # resolved in self.get_and_resolve_doctree)
         if isinstance(sectionnode, nodes.section):
             title = sectionnode[0]
             # copy the contents of the section title, but without references
             # and unnecessary stuff
             visitor = SphinxContentsFilter(doctree)
             title.walkabout(visitor)
             nodetext = visitor.get_entry_text()
             if not numentries[0]:
                 # for the very first toc entry, don't add an anchor
                 # as it is the file's title anyway
                 anchorname = ''
             else:
                 anchorname = '#' + sectionnode['ids'][0]
             numentries[0] += 1
             # make these nodes:
             # list_item -> compact_paragraph -> reference
             reference = nodes.reference(
                 '', '', internal=True, refuri=docname,
                 anchorname=anchorname, *nodetext)
             para = addnodes.compact_paragraph('', '', reference)
             item = nodes.list_item('', para)  # type: nodes.Element
             sub_item = build_toc(sectionnode, depth + 1)
             if sub_item:
                 item += sub_item
             entries.append(item)
         elif isinstance(sectionnode, addnodes.only):
             onlynode = addnodes.only(expr=sectionnode['expr'])
             blist = build_toc(sectionnode, depth)
             if blist:
                 onlynode += blist.children
                 entries.append(onlynode)
         elif isinstance(sectionnode, nodes.Element):
             for toctreenode in traverse_in_section(sectionnode,
                                                    addnodes.toctree):
                 item = toctreenode.copy()
                 entries.append(item)
                 # important: do the inventory stuff
                 TocTree(app.env).note(docname, toctreenode)
     if entries:
         return nodes.bullet_list('', *entries)
     return None
Exemplo n.º 24
0
    def run(self):
        # type: () -> List[nodes.Node]
        node = addnodes.only()
        node.document = self.state.document
        self.set_source_info(node)
        node['expr'] = self.arguments[0]

        # Same as util.nested_parse_with_titles but try to handle nested
        # sections which should be raised higher up the doctree.
        memo = self.state.memo  # type: Any
        surrounding_title_styles = memo.title_styles
        surrounding_section_level = memo.section_level
        memo.title_styles = []
        memo.section_level = 0
        try:
            self.state.nested_parse(self.content,
                                    self.content_offset,
                                    node,
                                    match_titles=True)
            title_styles = memo.title_styles
            if (not surrounding_title_styles or not title_styles
                    or title_styles[0] not in surrounding_title_styles
                    or not self.state.parent):
                # No nested sections so no special handling needed.
                return [node]
            # Calculate the depths of the current and nested sections.
            current_depth = 0
            parent = self.state.parent
            while parent:
                current_depth += 1
                parent = parent.parent
            current_depth -= 2
            title_style = title_styles[0]
            nested_depth = len(surrounding_title_styles)
            if title_style in surrounding_title_styles:
                nested_depth = surrounding_title_styles.index(title_style)
            # Use these depths to determine where the nested sections should
            # be placed in the doctree.
            n_sects_to_raise = current_depth - nested_depth + 1
            parent = cast(nodes.Element, self.state.parent)
            for i in range(n_sects_to_raise):
                if parent.parent:
                    parent = parent.parent
            parent.append(node)
            return []
        finally:
            memo.title_styles = surrounding_title_styles
            memo.section_level = surrounding_section_level
Exemplo n.º 25
0
def doctree_read(app, doctree):
    env = app.builder.env

    resolve_target = getattr(env.config, 'linkcode_resolve', None)
    if not isinstance(env.config.linkcode_resolve, collections.Callable):
        raise LinkcodeError(
            "Function `linkcode_resolve` is not given in conf.py")

    domain_keys = dict(
        py=['module', 'fullname'],
        c=['names'],
        cpp=['names'],
        js=['object', 'fullname'],
    )

    for objnode in doctree.traverse(addnodes.desc):
        domain = objnode.get('domain')
        uris = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue

            # Convert signode to a specified format
            info = {}
            for key in domain_keys.get(domain, []):
                value = signode.get(key)
                if not value:
                    value = ''
                info[key] = value
            if not info:
                continue

            # Call user code to resolve the link
            uri = resolve_target(domain, info)
            if not uri:
                # no source
                continue

            if uri in uris or not uri:
                # only one link per name, please
                continue
            uris.add(uri)

            onlynode = addnodes.only(expr='html')
            onlynode += nodes.reference('', '', internal=False, refuri=uri)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 26
0
    def run(self):
        # type: () -> List[nodes.Node]
        node = addnodes.only()
        node.document = self.state.document
        set_source_info(self, node)
        node['expr'] = self.arguments[0]

        # Same as util.nested_parse_with_titles but try to handle nested
        # sections which should be raised higher up the doctree.
        memo = self.state.memo  # type: Any
        surrounding_title_styles = memo.title_styles
        surrounding_section_level = memo.section_level
        memo.title_styles = []
        memo.section_level = 0
        try:
            self.state.nested_parse(self.content, self.content_offset,
                                    node, match_titles=True)
            title_styles = memo.title_styles
            if (not surrounding_title_styles or
                    not title_styles or
                    title_styles[0] not in surrounding_title_styles or
                    not self.state.parent):
                # No nested sections so no special handling needed.
                return [node]
            # Calculate the depths of the current and nested sections.
            current_depth = 0
            parent = self.state.parent
            while parent:
                current_depth += 1
                parent = parent.parent
            current_depth -= 2
            title_style = title_styles[0]
            nested_depth = len(surrounding_title_styles)
            if title_style in surrounding_title_styles:
                nested_depth = surrounding_title_styles.index(title_style)
            # Use these depths to determine where the nested sections should
            # be placed in the doctree.
            n_sects_to_raise = current_depth - nested_depth + 1
            parent = cast(nodes.Element, self.state.parent)
            for i in range(n_sects_to_raise):
                if parent.parent:
                    parent = parent.parent
            parent.append(node)
            return []
        finally:
            memo.title_styles = surrounding_title_styles
            memo.section_level = surrounding_section_level
Exemplo n.º 27
0
    def build_toc(node, depth=1, main=False, title_visited=False):
      entries = []
      for sectionnode in node:
# EV: added or condition on 'main' and 'title_visited'
        # find all toctree nodes in this section and add them
        # to the toc (just copying the toctree node which is then
        # resolved in self.get_and_resolve_doctree)
        if isinstance(sectionnode, addnodes.only):
          onlynode = addnodes.only(expr=sectionnode['expr'])
          blist = build_toc(sectionnode, depth)
          if blist:
            onlynode += blist.children
            entries.append(onlynode)
        if not isinstance(sectionnode, nodes.section) or (main and title_visited):
          for toctreenode in traverse_in_section(sectionnode,
                                                 addnodes.toctree):
            item = toctreenode.copy()
            entries.append(item)
            # important: do the inventory stuff
            self.note_toctree(docname, toctreenode)
          continue
        title = sectionnode[0]
        # copy the contents of the section title, but without references
        # and unnecessary stuff
        visitor = SphinxContentsFilter(document)
        title.walkabout(visitor)
        nodetext = visitor.get_entry_text()
        if not numentries[0]:
          # for the very first toc entry, don't add an anchor
          # as it is the file's title anyway
          anchorname = ''
        else:
          anchorname = '#' + sectionnode['ids'][0]
        numentries[0] += 1
        reference = nodes.reference(
          '', '', internal=True, refuri=docname,
          anchorname=anchorname, *nodetext)
        para = addnodes.compact_paragraph('', '', reference)
        item = nodes.list_item('', para)
        if maxdepth == 0 or depth < maxdepth:
# EV: set 'main' and 'title_visited' args
          item += build_toc(sectionnode, depth+1, main=main, title_visited=True)
        entries.append(item)
      if entries:
        return nodes.bullet_list('', *entries)
      return []
Exemplo n.º 28
0
def _add_pending_source_cross_reference(app: Sphinx, signode: Node,
                                        fullname: str) -> None:
    """
    Adds a pending source cross reference to the signature in the doctree, `signode`.

    The viewcode and linkcode extensions walk the doctree once parsed and
    then add this node, however since sphinx_c_autodoc already has to add
    logic, the `module` option to the directives it seems more practical to
    just create the full pending cross reference here, and then viewcode is
    an extension which will populate this cross refernce.

    Args:
        app (Sphinx):
            The sphinx app currently doing the processing.
        signode (Node):
            The signature node to apply the source code cross reference to.
        fullname (str):
            The dotted fullname of the C construct.
    """
    module = signode.get("module")
    if module is None:
        return

    source_page = _get_source_page_name(module)

    # Using the `viewcode-link` to be consistent with the python versions in
    # case someone else wants to walk the tree and do other links
    inline = nodes.inline("", "[source]", classes=["viewcode-link"])

    # Limit this cross referencing only to html
    html_node = addnodes.only(expr="html")
    html_node += addnodes.pending_xref(
        "",
        inline,
        reftype=f"{C_DOMAIN_LINK_PREFIX}viewcode",
        refdomain="std",
        refexplicit=False,
        reftarget=source_page,
        refid=f"{C_DOMAIN_LINK_PREFIX}{fullname}",
        refdoc=app.builder.env.docname,
        module=module,
        fullname=fullname,
    )

    signode += html_node
Exemplo n.º 29
0
    def run(self):
        node = addnodes.only()
        node.document = self.state.document
        set_source_info(self, node)
        node['expr'] = 'iguide'

        class_value = ['iguide', self.arguments[0]]
            
        pending = nodes.pending(misc.ClassAttribute,
                                {'class': class_value, 
                                 'directive': self.name},
                                self.block_text)
        self.state_machine.document.note_pending(pending)
        node += pending

        self.state.nested_parse(self.content, self.content_offset, node,
                                match_titles=1)
        return [node]
Exemplo n.º 30
0
    def run(self) -> List[nodes.Node]:
        """
		Create the installation node.
		"""

        if self.env.docname != self.env.config.master_doc:  # pragma: no cover
            warnings.warn(
                "The 'sidebar-links' directive can only be used on the Sphinx master doc. "
                "No links will be shown.",
                UserWarning,
            )
            return []

        body = StringList([
            ".. toctree::",
            "    :hidden:",
        ])

        with body.with_indent("    ", 1):
            if "caption" in self.options:
                body.append(f":caption: {self.options['caption']}")
            else:  # pragma: no cover
                body.append(":caption: Links")

            body.blankline()

            if "github" in self.options:
                body.append(self.process_github_option())
            if "pypi" in self.options:
                body.append(
                    f"PyPI <https://pypi.org/project/{self.options['pypi']}>")

            body.extend(self.content)

        body.blankline()
        body.blankline()

        only_node = addnodes.only(expr="html")
        content_node = nodes.paragraph(rawsource=str(body))
        only_node += content_node
        self.state.nested_parse(docutils.statemachine.StringList(body),
                                self.content_offset, content_node)

        return [only_node]
Exemplo n.º 31
0
def doctree_read(app, doctree):
    env = app.builder.env

    resolve_target = getattr(env.config, "linkcode_resolve", None)
    if not callable(env.config.linkcode_resolve):
        raise LinkcodeError("Function `linkcode_resolve` is not given in conf.py")

    domain_keys = dict(py=["module", "fullname"], c=["names"], cpp=["names"], js=["object", "fullname"])

    for objnode in doctree.traverse(addnodes.desc):
        domain = objnode.get("domain")
        uris = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue

            # Convert signode to a specified format
            info = {}
            for key in domain_keys.get(domain, []):
                value = signode.get(key)
                if not value:
                    value = ""
                info[key] = value
            if not info:
                continue

            # Call user code to resolve the link
            uri = resolve_target(domain, info)
            if not uri:
                # no source
                continue

            if uri in uris or not uri:
                # only one link per name, please
                continue
            uris.add(uri)

            onlynode = addnodes.only(expr="html")
            onlynode += nodes.reference("", "", internal=False, refuri=uri)
            onlynode[0] += nodes.inline("", _("[source]"), classes=["viewcode-link"])
            signode += onlynode
Exemplo n.º 32
0
    def run(self):
        link = self.arguments[0]
        embed_type = "Card" if "/c/" in link else "Board"

        container = nodes.container()

        html = f"""
        <blockquote class="trello-{embed_type.lower()}-compact">
            <a href="{link}">Trello {embed_type}</a>
        </blockquote>"""

        html_node = nodes.raw(text=html, format="html")
        only_pdf = addnodes.only(expr="latex")
        # We need to provide a node for nested parsing. And another node for populating the parsed node.
        only_pdf_paragraph = nodes.inline()
        self.state.nested_parse(
            nodes.inline(text=f"`Trello {embed_type} <{link}>`_"), 0,
            only_pdf_paragraph)
        only_pdf += only_pdf_paragraph
        container += html_node
        container += only_pdf
        return container.children
Exemplo n.º 33
0
    def run(self) -> List[nodes.Node]:
        """
		Process the content of the directive.
		"""

        summary = getattr(self.config, "documentation_summary", '').strip()

        if not summary:
            return []  # pragma: no cover

        # if self.env.app.builder.format.lower() == "latex" or not summary:
        # 	return []

        targetid = f'documentation-summary-{self.env.new_serialno("documentation-summary"):d}'

        onlynode = addnodes.only(expr="html")

        content = f'**{summary}**'
        content_node = nodes.paragraph(rawsource=content, ids=[targetid])
        onlynode += content_node
        self.state.nested_parse(StringList([content]), self.content_offset,
                                content_node)
        summary_node_purger.add_node(self.env, content_node, content_node,
                                     self.lineno)

        if "meta" in self.options:
            meta_content = f'.. meta::\n    :description: {self.config.project} -- {summary}\n'
            meta_node = nodes.paragraph(rawsource=meta_content, ids=[targetid])
            onlynode += meta_node
            self.state.nested_parse(
                StringList(meta_content.split('\n')),
                self.content_offset,
                meta_node,
            )
            summary_node_purger.add_node(self.env, meta_node, meta_node,
                                         self.lineno)

        return [onlynode]
Exemplo n.º 34
0
    def run(self):
        self.assert_has_content()

        node = addnodes.only()
        node.document = self.state.document
        set_source_info(self, node)
        node['expr'] = 'iguide'

        text = '\n'.join(self.content)
        admonition_node = nodes.admonition(text, **self.options)
        self.add_name(admonition_node)
            
        title_text = self.arguments[0]
        textnodes, messages = self.state.inline_text(title_text,
                                                     self.lineno)
        admonition_node += nodes.title(title_text, '', *textnodes)
        admonition_node += messages
        admonition_node['classes'] += ['iguide']
        
        self.state.nested_parse(self.content, self.content_offset,
                                admonition_node)
        node += admonition_node

        return [node]
Exemplo n.º 35
0
def doctree_read(app, doctree):
    # type: (Sphinx, nodes.Node) -> None
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}  # type: ignore
    if app.builder.name == "singlehtml":
        return
    if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:
        return

    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        if entry is False:
            return

        code_tags = app.emit_firstresult('viewcode-find-source', modname)
        if code_tags is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False  # type: ignore
                return

            if not isinstance(analyzer.code, text_type):
                code = analyzer.code.decode(analyzer.encoding)
            else:
                code = analyzer.code

            analyzer.find_tags()
            tags = analyzer.tags
        else:
            code, tags = code_tags

        if entry is None or entry[0] != code:
            entry = code, tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()  # type: Set[unicode]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_follow_imported_members:
                new_modname = app.emit_firstresult(
                    'viewcode-follow-imported', modname, fullname,
                )
                if not new_modname:
                    new_modname = _get_full_modname(app, modname, fullname)
                modname = new_modname
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 36
0
def doctree_read(app, doctree):

    classes_to_attributes = {}

    def get_unique_parts(parts):
        unique_parts = [parts[0]]
        for part in parts[1:]:
            if part != unique_parts[-1]:
                unique_parts.append(part)
            else:
                break
        return unique_parts

    for desc_node in doctree.traverse(addnodes.desc):
        if desc_node.get('domain') != 'py':
            continue

        signature_node = desc_node.traverse(addnodes.desc_signature)[0]
        module_name = signature_node.get('module')
        object_name = signature_node.get('fullname')
        object_type = desc_node.get('objtype')
        module = importlib.import_module(module_name)

        # Strip 'abjad.tools.' or 'experimental.tools.' from signature.
        # Also strip duplicate class names.
        if object_type in ('function', 'class'):
            addname_node = signature_node.traverse(addnodes.desc_addname)[0]
            text = addname_node[0].astext()
            parts = [x for x in text.split('.') if x]
            parts = get_unique_parts(parts)
            if parts[0] in ('abjad', 'experimental'):
                parts = parts[2:-1]
            text = '{}.'.format('.'.join(parts))
            addname_node[0] = nodes.Text(text)

        if object_type == 'class':
            cls = getattr(module, object_name, None)
            if cls is None:
                continue
            if cls not in classes_to_attributes:
                classes_to_attributes[cls] = {}
                attributes = inspect.classify_class_attrs(cls)
                for attribute in attributes:
                    classes_to_attributes[cls][attribute.name] = attribute
            if inspect.isabstract(cls):
                labelnode = addnodes.only(expr='html')
                labelnode.append(nodes.literal(
                    '',
                    ' abstract ',
                    classes=['attribute', 'abstract'],
                    ))
                signature_node.insert(0, labelnode)

        elif object_type in ('method', 'attribute', 'staticmethod', 'classmethod'):
            object_parts = object_name.split('.')
            cls_name, attr_name = object_name.split('.')
            cls = getattr(module, cls_name, None)
            if cls is None:
                continue
            attr = getattr(cls, attr_name)
            inspected_attr = classes_to_attributes[cls][attr_name]
            label_node = addnodes.only(expr='html')
            defining_class = inspected_attr.defining_class
            if defining_class != cls:
                addname_node = signature_node.traverse(
                    addnodes.desc_addname)[0]
                xref_node = addnodes.pending_xref(
                    '',
                    refdomain='py',
                    refexplicit=True,
                    reftype='class',
                    reftarget='{}.{}'.format(
                        defining_class.__module__,
                        defining_class.__name__,
                        ))
                xref_node.append(nodes.literal(
                    '',
                    '{}'.format(defining_class.__name__),
                    ))
                html_only_class_name_node = addnodes.only(expr='html')
                html_only_class_name_node.append(nodes.Text('('))
                html_only_class_name_node.append(xref_node)
                html_only_class_name_node.append(nodes.Text(').'))
                latex_only_class_name_node = addnodes.only(expr='latex')
                latex_only_class_name_node.append(nodes.Text(
                    '({}).'.format(defining_class.__name__),
                    ))
                addname_node.clear()
                addname_node.append(html_only_class_name_node)
                addname_node.append(latex_only_class_name_node)
                label_node.append(nodes.literal(
                    '',
                    ' inherited ',
                    classes=['attribute', 'inherited'],
                    ))
            if getattr(attr, '__isabstractmethod__', False):
                label_node.append(nodes.literal(
                    '',
                    ' abstract ',
                    classes=['attribute', 'abstract'],
                    ))
            if isinstance(attr, types.FunctionType):
                # remove Sphinx's annotation, so we can use our own.
                signature_node.pop(0)
                label_node.append(nodes.literal(
                    '',
                    ' staticmethod ',
                    classes=['attribute', 'staticmethod'],
                    ))
            elif hasattr(attr, 'im_self') and attr.im_self is not None:
                signature_node.pop(0)
                label_node.append(nodes.literal(
                    '',
                    ' classmethod ',
                    classes=['attribute', 'classmethod'],
                    ))
            signature_node.insert(0, label_node)
Exemplo n.º 37
0
def doctree_read(app, doctree):
    # type: (Sphinx, nodes.Node) -> None
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}  # type: ignore
    if app.builder.name == "singlehtml":
        return
    if app.builder.name.startswith(
            "epub") and not env.config.viewcode_enable_epub:
        return

    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        try:
            analyzer = ModuleAnalyzer.for_module(modname)
        except Exception:
            env._viewcode_modules[modname] = False  # type: ignore
            return
        if not isinstance(analyzer.code, text_type):
            code = analyzer.code.decode(analyzer.encoding)
        else:
            code = analyzer.code
        if entry is False:
            return
        elif entry is None or entry[0] != code:
            analyzer.find_tags()
            entry = code, analyzer.tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()  # type: Set[unicode]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = _get_full_modname(app, modname, fullname)
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('',
                                              reftype='viewcode',
                                              refdomain='std',
                                              refexplicit=False,
                                              reftarget=pagename,
                                              refid=fullname,
                                              refdoc=env.docname)
            onlynode[0] += nodes.inline('',
                                        _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 38
0
def doctree_read(app, doctree):
    # Get the configuration parameters
    if app.config.edit_on_github_project == 'REQUIRED':
        raise ValueError(
            "The edit_on_github_project configuration variable must be "
            "provided in the conf.py")

    source_root = app.config.edit_on_github_source_root
    if source_root != '' and not source_root.endswith('/'):
        source_root += '/'
    doc_root = app.config.edit_on_github_doc_root
    if doc_root != '' and not doc_root.endswith('/'):
        doc_root += '/'
    url = 'http://github.com/%s/tree/%s/' % (
        app.config.edit_on_github_project,
        app.config.edit_on_github_branch)

    docstring_message = app.config.edit_on_github_docstring_message
    page_message = app.config.edit_on_github_page_message

    # Handle the "edit this page" link
    doc_path = os.path.relpath(doctree.get('source'), app.builder.srcdir)
    if not re.match(app.config.edit_on_github_skip_regex, doc_path):
        path = url + doc_root + doc_path
        onlynode = addnodes.only(expr='html')
        onlynode += nodes.reference(
            reftitle=app.config.edit_on_bitbucket_help_message, refuri=path)
        onlynode[0] += nodes.inline(
            '', page_message, classes=['edit-on-github'])
        para = nodes.paragraph()
        para.update_basic_atts({'classes':['edit-on-github-para']})
        para += onlynode
        if 'edit-section' in doctree[-1].attributes['classes']:
            doctree[-1] += para
        else:
            section = nodes.section()
            section.update_basic_atts({'classes':['edit-section']})
            section += para
            doctree += section

    # Handle the docstring-editing links
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            obj = import_object(modname, fullname)
            anchor = None
            if obj is not None:
                try:
                    lines, lineno = inspect.getsourcelines(obj)
                except:
                    pass
                else:
                    anchor = '#L%d' % lineno
            if anchor:
                path = '%s%s%s.py%s' % (
                    url, source_root, modname.replace('.', '/'), anchor)
                onlynode = addnodes.only(expr='html')
                onlynode += nodes.reference(
                    reftitle=app.config.edit_on_github_help_message,
                    refuri=path)
                onlynode[0] += nodes.inline(
                    '', '', nodes.raw('', '&nbsp;', format='html'),
                    nodes.Text(docstring_message),
                    classes=['edit-on-github', 'viewcode-link'])
                signode += onlynode
Exemplo n.º 39
0
def doctree_read(app, doctree):

    classes_to_attributes = {}

    def get_unique_parts(parts):
        unique_parts = [parts[0]]
        for part in parts[1:]:
            if part != unique_parts[-1]:
                unique_parts.append(part)
            else:
                break
        return unique_parts

    for desc_node in doctree.traverse(addnodes.desc):
        if desc_node.get('domain') != 'py':
            continue

        signature_node = desc_node.traverse(addnodes.desc_signature)[0]
        module_name = signature_node.get('module')
        object_name = signature_node.get('fullname')
        object_type = desc_node.get('objtype')
        module = importlib.import_module(module_name)

        if object_type == 'class':
            cls = getattr(module, object_name, None)
            if cls is None:
                continue
            if cls not in classes_to_attributes:
                classes_to_attributes[cls] = {}
                attributes = inspect.classify_class_attrs(cls)
                for attribute in attributes:
                    classes_to_attributes[cls][attribute.name] = attribute
            if inspect.isabstract(cls):
                labelnode = addnodes.only(expr='html')
                labelnode.append(nodes.emphasis(
                    'abstract ',
                    'abstract ',
                    classes=['property'],
                    ))
                signature_node.insert(0, labelnode)

        elif object_type in ('method', 'attribute', 'staticmethod', 'classmethod'):
            cls_name, attr_name = object_name.split('.')
            cls = getattr(module, cls_name, None)
            if cls is None:
                continue
            attr = getattr(cls, attr_name)
            inspected_attr = classes_to_attributes[cls][attr_name]
            label_node = addnodes.only(expr='html')
            defining_class = inspected_attr.defining_class
            if defining_class != cls:
                addname_node = signature_node.traverse(
                    addnodes.desc_addname)[0]
                if defining_class.__module__.startswith('supriya'):
                    reftarget = defining_class.__module__
                else:
                    reftarget = '{}.{}'.format(
                        defining_class.__module__,
                        defining_class.__name__,
                        )
                xref_node = addnodes.pending_xref(
                    '',
                    refdomain='py',
                    refexplicit=True,
                    reftype='class',
                    reftarget=reftarget,
                    )
                xref_node.append(nodes.literal(
                    '',
                    '{}'.format(defining_class.__name__),
                    classes=['descclassname'],
                    ))
                html_only_class_name_node = addnodes.only(expr='html')
                html_only_class_name_node.append(nodes.Text('('))
                html_only_class_name_node.append(xref_node)
                html_only_class_name_node.append(nodes.Text(').'))
                latex_only_class_name_node = addnodes.only(expr='latex')
                latex_only_class_name_node.append(nodes.Text(
                    '({}).'.format(defining_class.__name__),
                    ))
                addname_node.clear()
                addname_node.append(html_only_class_name_node)
                addname_node.append(latex_only_class_name_node)
                #label_node.append(nodes.emphasis(
                #    'inherited ',
                #    'inherited ',
                #    classes=['property'],
                #    ))
            if getattr(attr, '__isabstractmethod__', False):
                label_node.append(nodes.emphasis(
                    'abstract ',
                    'abstract ',
                    classes=['property'],
                    ))
            if hasattr(attr, 'im_self') and attr.im_self is not None:
                signature_node.pop(0)
                label_node.append(nodes.emphasis(
                    'classmethod ',
                    'classmethod ',
                    classes=['property'],
                    ))
            signature_node.insert(0, label_node)
Exemplo n.º 40
0
		def build_toc(node: nodes.Element, depth: int = 1) -> Optional[nodes.bullet_list]:
			"""
			Build the table of contents.

			:param node:
			:param depth:
			"""

			entries: List[nodes.Element] = []
			item: nodes.Element
			toctree_plus_types = set(app.env.config.toctree_plus_types)

			for sectionnode in node:
				# find all toctree nodes in this section and add them
				# to the toc (just copying the toctree node which is then
				# resolved in self.get_and_resolve_doctree)

				if isinstance(sectionnode, nodes.section):
					title = sectionnode[0]
					# copy the contents of the section title, but without references
					# and unnecessary stuff
					visitor = SphinxContentsFilter(doctree)
					title.walkabout(visitor)
					nodetext = visitor.get_entry_text()

					if not numentries[0]:
						# for the very first toc entry, don't add an anchor
						# as it is the file's title anyway
						anchorname = ''
					else:
						anchorname = f'#{sectionnode["ids"][0]}'

					numentries[0] += 1

					# make these nodes:
					# list_item -> compact_paragraph -> reference
					reference = nodes.reference(
							'',
							'',
							internal=True,
							refuri=docname,
							anchorname=anchorname,
							*nodetext,
							)

					para = addnodes.compact_paragraph('', '', reference)
					item = nodes.list_item('', para)
					sub_item = build_toc(sectionnode, depth + 1)

					if sub_item:
						item += sub_item

					entries.append(item)

				elif isinstance(sectionnode, addnodes.desc):
					# Add class, function and method directives to toctree.
					# (doesn't currently work for method directives - are they nested?)

					if sectionnode.attributes["objtype"] in toctree_plus_types:

						attributes = sectionnode.children[0].attributes
						if not attributes["ids"]:
							# Has no anchor
							continue

						title = attributes.get("fullname", sectionnode.children[0].astext())

						if sectionnode.attributes["objtype"] in {"method", "attribute"}:
							# TODO: remove special case
							title = title.split('.', 1)[-1]

						anchorname = f'#{attributes["ids"][0]}'

						reference = nodes.reference(
								'',
								'',
								internal=True,
								refuri=docname,
								anchorname=anchorname,
								*[nodes.literal(text=title)],
								)
						para = addnodes.compact_paragraph('', '', reference)
						item = nodes.list_item('', para)

						sub_item = build_toc(sectionnode.children[1], depth + 1)

						if sub_item:
							item += sub_item

						entries.append(item)

					elif TOCTREE_PLUS_DEBUG:
						print(sectionnode)
						pprint(sectionnode.attributes["objtype"])

				elif isinstance(sectionnode, addnodes.only):
					onlynode = addnodes.only(expr=sectionnode["expr"])
					blist = build_toc(sectionnode, depth)
					if blist:
						onlynode += blist.children
						entries.append(onlynode)

				elif isinstance(sectionnode, nodes.Element):

					for toctreenode in traverse_in_section(sectionnode, addnodes.toctree):
						item = toctreenode.copy()
						entries.append(item)

						# important: do the inventory stuff
						TocTree(app.env).note(docname, toctreenode)

			if entries:
				return nodes.bullet_list('', *entries)
			else:
				return None
Exemplo n.º 41
0
def doctree_read(app, doctree):
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}

    def get_full_modname(modname, attribute):
        try:
            __import__(modname)
        except Exception as error:
            if not app.quiet:
                app.info(traceback.format_exc().rstrip())
            app.warn('viewcode can\'t import %s, failed with error "%s"' %
                (modname, error))
            return None
        module = sys.modules[modname]
        try:
            # Allow an attribute to have multiple parts and incidentally allow
            # repeated .s in the attribute.
            attr = attribute.split('.')
            value = module
            for attr in attribute.split('.'):
                if attr:
                    value = safe_getattr(value, attr)
        except AttributeError:
            app.warn('Didn\'t find %s in %s' % (attribute, module.__name__))
            return None
        else:
            return safe_getattr(value, '__module__', None)


    def has_tag(modname, fullname, docname, refname):
        entry = env._viewcode_modules.get(modname, None)
        if entry is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
            except Exception:
                env._viewcode_modules[modname] = False
                return
            analyzer.find_tags()
            if not isinstance(analyzer.code, text_type):
                code = analyzer.code.decode(analyzer.encoding)
            else:
                code = analyzer.code
            entry = code, analyzer.tags, {}, refname
            env._viewcode_modules[modname] = entry
        elif entry is False:
            return
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True


    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = get_full_modname(modname, fullname)
            if not modname:
                continue
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode
Exemplo n.º 42
0
    def style_document(app, document):
        def get_unique_parts(parts):
            unique_parts = [parts[0]]
            for part in parts[1:]:
                if part != unique_parts[-1]:
                    unique_parts.append(part)
                else:
                    break
            return unique_parts

        classes_to_attributes = {}
        for desc_node in document.traverse(addnodes.desc):
            if desc_node.get('domain') != 'py':
                continue
            signature_node = desc_node.traverse(addnodes.desc_signature)[0]
            module_name = signature_node.get('module')
            object_name = signature_node.get('fullname')
            object_type = desc_node.get('objtype')
            module = importlib.import_module(module_name)
            if object_type in ('function', 'class'):
                addname_node = signature_node.traverse(
                    addnodes.desc_addname)[0]
                text = addname_node[0].astext()
                parts = [x for x in text.split('.') if x]
                parts = get_unique_parts(parts)
                if parts[0] in ('abjad', 'experimental', 'ide'):
                    parts = parts[-1:]
                if parts:
                    text = '{}.'.format('.'.join(parts))
                else:
                    text = ''
                addname_node[0] = nodes.Text(text)
            if object_type == 'class':
                cls = getattr(module, object_name, None)
                if cls is None:
                    continue
                if cls not in classes_to_attributes:
                    classes_to_attributes[cls] = {}
                    attributes = inspect.classify_class_attrs(cls)
                    for attribute in attributes:
                        classes_to_attributes[cls][attribute.name] = attribute
                if inspect.isabstract(cls):
                    labelnode = addnodes.only(expr='html')
                    labelnode.append(
                        nodes.emphasis(
                            'abstract ',
                            'abstract ',
                            classes=['property'],
                        ))
                    signature_node.insert(0, labelnode)
            elif object_type in ('method', 'attribute', 'staticmethod',
                                 'classmethod'):
                cls_name, attr_name = object_name.split('.')
                cls = getattr(module, cls_name, None)
                if cls is None:
                    continue
                attr = getattr(cls, attr_name)
                inspected_attr = classes_to_attributes[cls][attr_name]
                label_node = addnodes.only(expr='html')
                defining_class = inspected_attr.defining_class
                if defining_class != cls:
                    addname_node = signature_node.traverse(
                        addnodes.desc_addname)[0]
                    if defining_class.__module__.startswith('abjad'):
                        reftarget = defining_class.__module__
                    else:
                        reftarget = '{}.{}'.format(
                            defining_class.__module__,
                            defining_class.__name__,
                        )
                    xref_node = addnodes.pending_xref(
                        '',
                        refdomain='py',
                        refexplicit=True,
                        reftype='class',
                        reftarget=reftarget,
                    )
                    xref_node.append(
                        nodes.literal(
                            '',
                            '{}'.format(defining_class.__name__),
                            classes=['descclassname'],
                        ))
                    html_only_class_name_node = addnodes.only(expr='html')
                    html_only_class_name_node.append(nodes.Text('('))
                    html_only_class_name_node.append(xref_node)
                    html_only_class_name_node.append(nodes.Text(').'))
                    latex_only_class_name_node = addnodes.only(expr='latex')
                    latex_only_class_name_node.append(
                        nodes.Text('({}).'.format(defining_class.__name__), ))
                    addname_node.clear()
                    addname_node.append(html_only_class_name_node)
                    addname_node.append(latex_only_class_name_node)
                if getattr(attr, '__isabstractmethod__', False):
                    label_node.append(
                        nodes.emphasis(
                            'abstract ',
                            'abstract ',
                            classes=['property'],
                        ))
                if hasattr(attr, 'im_self') and attr.im_self is not None:
                    signature_node.pop(0)
                    label_node.append(
                        nodes.emphasis(
                            'classmethod ',
                            'classmethod ',
                            classes=['property'],
                        ))
                signature_node.insert(0, label_node)
Exemplo n.º 43
0
    def run(self):
        env = self.state.document.settings.env
        extcode_config = env.app.config.extcode

        if not extcode_config:
            if all(opt not in self.options for opt in self.extra_option_spec):
                return super(ExtCode, self).run()  # nothing to do special

        rendered_block = self.options.get('rendered-block',
                                          extcode_config.get('rendered-block'))

        line_annotations = {}
        annotations = self.options.get('annotations', [])
        annotationsmap = dict((k.astext(), v) for k, v in annotations)
        for i, c in enumerate(self.content):
            match = annotation_matcher(c)
            if match:
                self.content[i], label = match.groups()
                if label in annotationsmap:
                    line_annotations[i] = (label, annotationsmap[label])
                else:
                    #TODO: warning
                    line_annotations[i] = (label, None)

        # get literal from modified self.content
        literal = super(ExtCode, self).run()[0]
        # line_annotations attribute will be used for writer (not yet)
        literal['line_annotations'] = line_annotations

        wrapper = extcode(classes=['extcode'])
        set_source_info(self, wrapper)

        #check: can parse rst? and partial build?
        try:
            partial_doc = sandbox_rst_parser(u'\n'.join(self.content),
                                             env.doc2path(env.docname),
                                             env.settings)
            partial_out = sandbox_partial_builder(partial_doc, env)
        except Exception as e:
            env.warn(env.docname,
                     u'extcode: partial build failed: %s' % str(e),
                     lineno=self.lineno)
            partial_doc = None
            partial_out = None

        if literal['language'] == 'rst' and rendered_block:
            wrapper['classes'].append('extcode-layout-' + rendered_block)

            rendered = nodes.container()
            set_source_info(self, rendered)

            only_html = addnodes.only(expr='html')
            set_source_info(self, only_html)
            only_html += nodes.raw(partial_out,
                                   partial_out,
                                   format='html',
                                   classes=['extcode-rendered'])
            rendered += only_html

            if 'rendered-image' in self.options:
                only_xml = addnodes.only(expr='xml')
                set_source_info(self, only_xml)
                only_xml += nodes.image(self.options['rendered-image'],
                                        uri=self.options['rendered-image'])
                rendered += only_xml

            #FIXME: need translation support
            make_text = lambda t: nodes.inline(t, t)

            if rendered_block == 'horizontal':
                table = build_table(
                    [[make_text('literal'),
                      make_text('rendered')], [literal, rendered]], [1, 1],
                    head_rows=1,
                    attrs={'classes': ['extcode-layout']})
                table.setdefault('classes', []).append('extcode-layout')
                wrapper.append(table)

            elif rendered_block == 'vertical':
                table = build_table([[make_text('literal'), literal],
                                     [make_text('rendered'), rendered]],
                                    [2, 8],
                                    stub_columns=1,
                                    attrs={'classes': ['extcode-layout']})
                table.setdefault('classes', []).append('extcode-layout')
                wrapper.append(table)

            else:  # toggle, tab
                wrapper.append(literal)
                wrapper.append(rendered)
        else:
            wrapper.append(literal)

        if line_annotations and 'annotate-inline' in self.options:
            prefix = '... '  #TODO prefixi customization
            contents = []
            for i in range(0, len(self.content)):
                label, value = line_annotations.get(i, ('', None))
                line = nodes.line()
                if label and value:
                    #FIXME: label and explanation need translation support
                    abbr = nodes.abbreviation(
                        label, label
                    )  #TODO: label customization (i.e. render with number)
                    abbr['explanation'] = value.astext()
                    line.append(nodes.inline(prefix, prefix))
                    line.append(abbr)
                elif label:
                    line.append(nodes.inline(prefix, prefix))
                    line.append(nodes.Text(label, label))
                contents.append(line)
            overlay = nodes.line_block(classes=['extcode-overlay'])
            set_source_info(self, overlay)
            overlay.extend(contents)
            wrapper.append(overlay)

        if annotations and 'annotate-block' in self.options:
            annotations['classes'] = ['extcode-annotations']
            set_source_info(self, annotations)
            wrapper.append(annotations)

        return [wrapper]
Exemplo n.º 44
0
def doctree_read(app, doctree):
    # Get the configuration parameters
    if app.config.edit_on_github_project == 'REQUIRED':
        raise ValueError(
            "The edit_on_github_project configuration variable must be "
            "provided in the conf.py")

    source_root = app.config.edit_on_github_source_root
    if source_root != '' and not source_root.endswith('/'):
        source_root += '/'
    doc_root = app.config.edit_on_github_doc_root
    if doc_root != '' and not doc_root.endswith('/'):
        doc_root += '/'
    url = 'http://github.com/%s/tree/%s/' % (app.config.edit_on_github_project,
                                             app.config.edit_on_github_branch)

    docstring_message = app.config.edit_on_github_docstring_message
    page_message = app.config.edit_on_github_page_message

    # Handle the "edit this page" link
    doc_path = os.path.relpath(doctree.get('source'), app.builder.srcdir)
    if not re.match(app.config.edit_on_github_skip_regex, doc_path):
        path = url + doc_root + doc_path
        onlynode = addnodes.only(expr='html')
        onlynode += nodes.reference(
            reftitle=app.config.edit_on_bitbucket_help_message, refuri=path)
        onlynode[0] += nodes.inline('',
                                    page_message,
                                    classes=['edit-on-github'])
        para = nodes.paragraph()
        para.update_basic_atts({'classes': ['edit-on-github-para']})
        para += onlynode
        if 'edit-section' in doctree[-1].attributes['classes']:
            doctree[-1] += para
        else:
            section = nodes.section()
            section.update_basic_atts({'classes': ['edit-section']})
            section += para
            doctree += section

    # Handle the docstring-editing links
    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            if not modname:
                continue
            fullname = signode.get('fullname')
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            obj = import_object(modname, fullname)
            anchor = None
            if obj is not None:
                try:
                    lines, lineno = inspect.getsourcelines(obj)
                except:
                    pass
                else:
                    anchor = '#L%d' % lineno
            if anchor:
                path = '%s%s%s.py%s' % (url, source_root,
                                        modname.replace('.', '/'), anchor)
                onlynode = addnodes.only(expr='html')
                onlynode += nodes.reference(
                    reftitle=app.config.edit_on_github_help_message,
                    refuri=path)
                onlynode[0] += nodes.inline(
                    '',
                    '',
                    nodes.raw('', '&nbsp;', format='html'),
                    nodes.Text(docstring_message),
                    classes=['edit-on-github', 'viewcode-link'])
                signode += onlynode
Exemplo n.º 45
0
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = get_full_modname(modname, fullname)
            if not modname:
                continue
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref(
                '', reftype='viewcode', refdomain='std', refexplicit=False,
                reftarget=pagename, refid=fullname,
                refdoc=env.docname)
            onlynode[0] += nodes.inline('', _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode


def missing_reference(app, env, node, contnode):
    # resolve our "viewcode" reference nodes -- they need special treatment
    if node['reftype'] == 'viewcode':
        return make_refnode(app.builder, node['refdoc'], node['reftarget'],
                            node['refid'], contnode)
Exemplo n.º 46
0
def doctree_read(app: Sphinx, doctree: Node) -> None:
    env = app.builder.env
    if not hasattr(env, '_viewcode_modules'):
        env._viewcode_modules = {}  # type: ignore
    if app.builder.name == "singlehtml":
        return
    if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:
        return

    def has_tag(modname: str, fullname: str, docname: str, refname: str) -> bool:
        entry = env._viewcode_modules.get(modname, None)  # type: ignore
        if entry is False:
            return False

        code_tags = app.emit_firstresult('viewcode-find-source', modname)
        if code_tags is None:
            try:
                analyzer = ModuleAnalyzer.for_module(modname)
                analyzer.find_tags()
            except Exception:
                env._viewcode_modules[modname] = False  # type: ignore
                return False

            code = analyzer.code
            tags = analyzer.tags
        else:
            code, tags = code_tags

        if entry is None or entry[0] != code:
            entry = code, tags, {}, refname
            env._viewcode_modules[modname] = entry  # type: ignore
        _, tags, used, _ = entry
        if fullname in tags:
            used[fullname] = docname
            return True

        return False

    for objnode in doctree.traverse(addnodes.desc):
        if objnode.get('domain') != 'py':
            continue
        names = set()  # type: Set[str]
        for signode in objnode:
            if not isinstance(signode, addnodes.desc_signature):
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_follow_imported_members:
                new_modname = app.emit_firstresult(
                    'viewcode-follow-imported', modname, fullname,
                )
                if not new_modname:
                    new_modname = _get_full_modname(app, modname, fullname)
                modname = new_modname
            if not modname:
                continue
            fullname = signode.get('fullname')
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('', inline, reftype='viewcode', refdomain='std',
                                              refexplicit=False, reftarget=pagename,
                                              refid=fullname, refdoc=env.docname)
            signode += onlynode
Exemplo n.º 47
0
                continue
            modname = signode.get('module')
            fullname = signode.get('fullname')
            refname = modname
            if env.config.viewcode_import:
                modname = get_full_modname(modname, fullname)
            if not modname:
                continue
            if not has_tag(modname, fullname, env.docname, refname):
                continue
            if fullname in names:
                # only one link per name, please
                continue
            names.add(fullname)
            pagename = '_modules/' + modname.replace('.', '/')
            onlynode = addnodes.only(expr='html')
            onlynode += addnodes.pending_xref('',
                                              reftype='viewcode',
                                              refdomain='std',
                                              refexplicit=False,
                                              reftarget=pagename,
                                              refid=fullname,
                                              refdoc=env.docname)
            onlynode[0] += nodes.inline('',
                                        _('[source]'),
                                        classes=['viewcode-link'])
            signode += onlynode


def missing_reference(app, env, node, contnode):
    # resolve our "viewcode" reference nodes -- they need special treatment