Exemple #1
0
    def _make_section_main(self, obj=None, items=None, tag='main'):
        ''' make a section node - main '''
        filename = self.options['name']
        title = nodes.title(text=filename)

        section = nodes.section('', title, ids=[tag], names=[tag])

        # add docstring
        if self.add_docstring:
            docs = [nodes.paragraph(text=i) for i in obj.__doc__.split('\n')]
            section += nodes.line_block('', *docs)

        # add the main toc
        lines = make_list(items, links=True)
        result = statemachine.ViewList()
        for line in lines:
            result.append(line, tag)
        self.state.nested_parse(result, 0, section)

        # add any version information
        if self.add_version:
            lines = _format_version(obj)
            result = statemachine.ViewList()
            for line in lines:
                result.append(line, tag)
            self.state.nested_parse(result, 0, section)
        return section
Exemple #2
0
    def add_description_node(self, anchor, description):
        description_node = nodes.line_block()
        description_node["classes"] = ["endpoint-card__description"]

        self.state.nested_parse(description, 0, description_node)

        anchor += [description_node]
Exemple #3
0
def process_needlist(app, doctree, fromdocname):
    """
    Replace all needlist nodes with a list of the collected needs.
    Augment each need with a backlink to the original location.
    """
    env = app.builder.env

    for node in doctree.traverse(Needlist):
        if not app.config.needs_include_needs:
            # Ok, this is really dirty.
            # If we replace a node, docutils checks, if it will not lose any attributes.
            # But this is here the case, because we are using the attribute "ids" of a node.
            # However, I do not understand, why losing an attribute is such a big deal, so we delete everything
            # before docutils claims about it.
            for att in ('ids', 'names', 'classes', 'dupnames'):
                node[att] = []
            node.replace_self([])
            continue

        id = node.attributes["ids"][0]
        current_needfilter = env.need_all_needlists[id]
        all_needs = env.needs_all_needs
        content = []
        all_needs = list(all_needs.values())
        found_needs = procces_filters(all_needs, current_needfilter)

        line_block = nodes.line_block()
        for need_info in found_needs:
            para = nodes.line()
            description = "%s: %s" % (need_info["id"], need_info["title"])

            if current_needfilter["show_status"] and need_info["status"] is not None:
                description += " (%s)" % need_info["status"]

            if current_needfilter["show_tags"] and need_info["tags"] is not None:
                description += " [%s]" % "; ".join(need_info["tags"])

            title = nodes.Text(description, description)

            # Create a reference
            if not need_info["hide"]:
                ref = nodes.reference('', '')
                ref['refdocname'] = need_info['docname']
                ref['refuri'] = app.builder.get_relative_uri(
                    fromdocname, need_info['docname'])
                ref['refuri'] += '#' + need_info['target_node']['refid']
                ref.append(title)
                para += ref
            else:
                para += title
            line_block.append(para)
        content.append(line_block)

        if len(content) == 0:
            content.append(no_needs_found_paragraph())

        if current_needfilter["show_filters"]:
            content.append(used_filter_paragraph(current_needfilter))

        node.replace_self(content)
Exemple #4
0
def reference_group(name,
                    rawtext,
                    text,
                    lineno,
                    inliner,
                    options={},
                    content=[]):
    path = inliner.document.current_source
    path = str(pathlib.Path(path).relative_to(DOCS_SRC))
    _refs = REFERENCES.get(path, {}).get(text, [])
    if not _refs:
        return ([], [])
    container = nodes.enumerated_list()
    for ref in _refs:
        output = [
            *ref.get("link", Null()).as_nodes(),
            *ref.get("section", Null()).as_nodes(),
            *ref.get("user", Null()).as_nodes(),
            *ref.get("license", Null()).as_nodes(),
        ]
        if Null() == (quote := ref.get("quote", Null())):
            message = nodes.paragraph()
            for node in output:
                message.append(node)
        else:
            message = nodes.line_block("", nodes.line("", "", *output),
                                       nodes.line(
                                           "",
                                           "",
                                           *quote.as_nodes(),
                                       ))
        container.append(nodes.list_item('', message))
Exemple #5
0
def line_block(self, match, context, next_state):
    """First line of a line block."""
    block = nodes.line_block()
    self.parent += block
    lineno = self.state_machine.abs_line_number()
    line, messages, blank_finish = self.line_block_line(match, lineno)
    block += line
    self.parent += messages
    if not blank_finish:
        offset = self.state_machine.line_offset + 1   # next line
        new_line_offset, blank_finish = self.nested_list_parse(
                self.state_machine.input_lines[offset:],
                input_offset=self.state_machine.abs_line_offset() + 1,
                node=block, initial_state='LineBlock',
                blank_finish=0)
        self.goto_line(new_line_offset)
    if not blank_finish:
        self.parent += self.reporter.warning(
            'Line block ends without a blank line.',
            line=lineno+1)
    if len(block):
        if block[0].indent is None:
            block[0].indent = 0
        self.nest_line_block_lines(block)

    raw = '\n'.join(['| %s' % child.rawsource for child in block.children])
    block.rawsource = raw
    return [], next_state, []
Exemple #6
0
 def run(self):
     env = self.state.document.settings.env
     block_quote = nodes.line_block()
     block_quote['classes'].append('folders')
     node = nodes.bullet_list()
     block_quote.append(node)
     stack = [node]
     indents = [-1]
     for line in self.content:
         match = re.search('[-+] ', line)
         if match is None:
             break
         indent = match.start()
         node = nodes.list_item()
         text = line[match.end():]
         print(line[match.end():])
         if indent <= indents[-1]:
             stack.pop()
             indents.pop()
         stack[-1].append(node)
         if line[match.start()] == '+':
             node.append(nodes.inline(text='� ' + text))
             node['classes'].append('folder')
             children = nodes.bullet_list()
             node.append(children)
             stack.append(children)
             indents.append(indent)
         else:
             node.append(nodes.inline(text='🖹 ' + text))
             node['classes'].append('file')
     return [block_quote]
 def run(self):
     try:
         fields = self.future_fields.get(timeout=30)
     except Queue.Empty:
         return [self.state_machine.reporter.error(
             "Timed out while fetching fields related to action [%s]" % self.arguments[0]
         )]
     if fields is None:
         return [self.state_machine.reporter.warning(
             "Could not find any field related to the action [%s]" % self.arguments[0]
         )]
     whitelist = set(self.options.get('only', '').split())
     return [nodes.field_list('', *(
         nodes.field('',
             nodes.field_name(text=v['string'] or k),
             nodes.field_body('',
                 # keep help formatting around (e.g. newlines for lists)
                 nodes.line_block('', *(
                     nodes.line(text=line)
                     for line in v['help'].split('\n')
                 ))
             )
         )
         for k, v in fields.iteritems()
         # if there's a whitelist, only display whitelisted fields
         if not whitelist or k in whitelist
         # only display if there's a help text
         if v.get('help')
     ))]
Exemple #8
0
    def add_description_node(self, container, description, collapse,
                             collapse_children):
        description_node = nodes.line_block()
        description_node["classes"] = ["parameter__description"]

        if collapse:
            description_node["classes"] += ["collapsed"]

        self.state.nested_parse(description, 0, description_node)

        # Traverse the parsed description to see if we have sub-parameters.
        sub_parameters = description_node.traverse(nodes.container,
                                                   include_self=False)

        if len(sub_parameters):
            sub_parameter_container = nodes.container()
            sub_parameter_container["classes"] = ["parameter__children"]

            if not collapse_children:
                sub_parameter_container["classes"] += ["active"]

            # Move all sub-parameters into the new container.
            for sub_parameter in sub_parameters:
                # Skip sub-sub-parameters.
                if sub_parameter.parent is not description_node:
                    continue

                description_node.remove(sub_parameter)
                sub_parameter_container.append(sub_parameter)

            # Add the 'Show child parameters' button.
            if collapse_children:
                button_label = "Show child parameters"
                button_classes = "parameter__children-button"
            else:
                button_label = "Hide child parameters"
                button_classes = "parameter__children-button active"

            sub_parameter_button = nodes.raw(
                button_label,
                '<p class="' + button_classes + '">' +
                '<a href="javascript:void(0)" data-handler="child-parameters"'
                +
                ' data-hide-label="Hide child parameters" data-show-label="Show child parameters">'
                + button_label + '</a>' + '</p>',
                format="html")

            description_node.append(sub_parameter_button)

            # Add the new container to the description.
            description_node.append(sub_parameter_container)

        container += [description_node]
Exemple #9
0
 def run(self):
     self.assert_has_content()
     block = nodes.line_block(classes=self.options.get("class", []))
     node_list = [block]
     for line_text in self.content:
         text_nodes, messages = self.state.inline_text(line_text.strip(), self.lineno + self.content_offset)
         line = nodes.line(line_text, "", *text_nodes)
         if line_text.strip():
             line.indent = len(line_text) - len(line_text.lstrip())
         block += line
         node_list.extend(messages)
         self.content_offset += 1
     self.state.nest_line_block_lines(block)
     return node_list
Exemple #10
0
    def new_workflow_entry_section(self, workflow, ids) -> nodes.section:

        self.logger.verbose("Generating entry for {}".format(workflow.name))

        targetname = nodes.fully_normalize_name(workflow.name)
        workflow_item = nodes.section(ids=[ids], names=[targetname])
        workflow_item.append(nodes.title(text=workflow.name, ids=[ids]))
        if "nodescription" not in self.options and workflow.description:
            description_block = nodes.line_block()
            for line in workflow.description.split("\n"):
                new_line = nodes.line(text=line)
                description_block += new_line
            workflow_item.append(description_block)

        return workflow_item
Exemple #11
0
    def nest_line_block_level (self, block, indent_level, indent_levels):
        """ Recursive part of nest_line_block_segment. """

        last_indent = indent_levels[indent_level]
        line_block = nodes.line_block ()
        while len (block):
            indent = block[0].indent
            if indent < last_indent:
                break # end recursion
            if indent > last_indent:
                line_block.append (
                    self.nest_line_block_level (block, indent_level + 1, indent_levels))
                continue
            line_block.append (block.pop (0))
        return line_block
Exemple #12
0
 def run(self):
     self.assert_has_content()
     block = nodes.line_block(classes=self.options.get('class', []))
     node_list = [block]
     for line_text in self.content:
         text_nodes, messages = self.state.inline_text(
             line_text.strip(), self.lineno + self.content_offset)
         line = nodes.line(line_text, '', *text_nodes)
         if line_text.strip():
             line.indent = len(line_text) - len(line_text.lstrip())
         block += line
         node_list.extend(messages)
         self.content_offset += 1
     self.state.nest_line_block_lines(block)
     return node_list
Exemple #13
0
def visit_H2Node(self, node):
    self.h2Text = node.astext()
    self.h2Text = sphinxEncode(self.h2Text)

    strong = nodes.strong("")
    strong.children = node.children

    line = nodes.line("")
    line.append(strong)

    line_block = nodes.line_block("")
    line_block.append(line)

    node.children = []
    node.append(line_block)
Exemple #14
0
    def nest_line_block_level(self, block, indent_level, indent_levels):
        """ Recursive part of nest_line_block_segment. """

        last_indent = indent_levels[indent_level]
        line_block = nodes.line_block()
        while len(block):
            indent = block[0].indent
            if indent < last_indent:
                break  # end recursion
            if indent > last_indent:
                line_block.append(
                    self.nest_line_block_level(block, indent_level + 1,
                                               indent_levels))
                continue
            line_block.append(block.pop(0))
        return line_block
Exemple #15
0
def make_row(data):
    row = nodes.row()
    for text in data:
        entry = nodes.entry()
        row += entry
        para = nodes.paragraph()
        entry += para
        if isinstance(text, list):
            lb = nodes.line_block()
            para += lb
            for t in text:
                line = nodes.line()
                lb += line
                line += nodes.Text(t)
        else:
            para += nodes.Text(text)
    return row
Exemple #16
0
 def _append_detailed_message(self, item, detailed_message):
     detailed_message = detailed_message.strip()
     style = self.options.get('detailed-message-style', None)
     if style == 'rst':
         node = nodes.Element()
         self.state.nested_parse(
             StringList(detailed_message.splitlines()), 0, node)
         item.extend(node.children)
     elif style == 'line':
         lines = detailed_message.splitlines()
         line_block = nodes.line_block()
         line_block.extend((nodes.line(text=line) for line in lines))
         item.append(line_block)
     elif style == 'pre' or self.options.get('detailed-message-pre', False):
         item.append(nodes.literal_block(text=detailed_message))
     else:
         item.append(nodes.paragraph(text=detailed_message))
Exemple #17
0
def make_item(id, tags):
    name = extracters.get_post_title(id)
    link = f'https://codereview.meta.stackexchange.com/q/{id}/42401'
    post = Post(link, name, name)
    if not tags:
        inner = nodes.paragraph()
        inner.append(post)
    else:
        inner = nodes.line_block(
            '',
            nodes.line('', '', post),
            nodes.line(
                '',
                '', 
                *(MTag(t) for t in tags),
            )
        )
    return nodes.list_item('', inner)
Exemple #18
0
 def run(self):
     config = self.state.document.settings.env.config
     model_name = self.arguments[0]
     optfields = self.options.get('fields')
     if not optfields:
         fields = _client.model(model_name).keys()
     else:
         fields = optfields.split(' ')
     l = [
         x for x in fields if x not in
         ['create_uid', 'create_date', 'write_uid', 'write_date']
     ]
     res1 = _client.execute(model_name,
                            'fields_get',
                            l,
                            context={'lang': config.odoo_lang})
     res = OrderedDict()
     print('**************************', model_name)
     for a in l:
         res[a] = res1[a]
     classes = [config.odoodoc_fieldlistclass]
     if 'class' in self.options:
         classes.extend(self.options['class'])
     return [
         nodes.field_list(
             '',
             *(
                 nodes.field(
                     '',
                     nodes.field_name(text=v['string'] or k),
                     nodes.field_body(
                         '',
                         # keep help formatting around (e.g. newlines for lists)
                         nodes.line_block(
                             '',
                             *(nodes.line(text=line)
                               for line in v['help'].split('\n')))))
                 for k, v in res.iteritems()
                 # only display if there's a help text
                 if v.get('help')),
             classes=classes,
             format='html')
     ]
Exemple #19
0
def line_block(name, arguments, options, content, lineno,
               content_offset, block_text, state, state_machine):
    if not content:
        warning = state_machine.reporter.warning(
            'Content block expected for the "%s" directive; none found.'
            % name, nodes.literal_block(block_text, block_text), line=lineno)
        return [warning]
    block = nodes.line_block(classes=options.get('class', []))
    node_list = [block]
    for line_text in content:
        text_nodes, messages = state.inline_text(line_text.strip(),
                                                 lineno + content_offset)
        line = nodes.line(line_text, '', *text_nodes)
        if line_text.strip():
            line.indent = len(line_text) - len(line_text.lstrip())
        block += line
        node_list.extend(messages)
        content_offset += 1
    state.nest_line_block_lines(block)
    return node_list
Exemple #20
0
def line_block(name, arguments, options, content, lineno,
               content_offset, block_text, state, state_machine):
    if not content:
        warning = state_machine.reporter.warning(
            'Content block expected for the "%s" directive; none found.'
            % name, nodes.literal_block(block_text, block_text), line=lineno)
        return [warning]
    block = nodes.line_block(classes=options.get('class', []))
    node_list = [block]
    for line_text in content:
        text_nodes, messages = state.inline_text(line_text.strip(),
                                                 lineno + content_offset)
        line = nodes.line(line_text, '', *text_nodes)
        if line_text.strip():
            line.indent = len(line_text) - len(line_text.lstrip())
        block += line
        node_list.extend(messages)
        content_offset += 1
    state.nest_line_block_lines(block)
    return node_list
Exemple #21
0
 def __init__(self, options, from_verse = None, to_verse = None):
     self.options = options
     self.node_stack = [(nodes.block_quote(), 0)] # node, depth
     self.is_first = True
     self.show_label = False
     self.current_verse = 0 # TODO: Need to handle some psalms that have a 'verse 0'
     self.from_verse = from_verse
     if self.from_verse is not None and to_verse is None:
         self.to_verse = from_verse
     else:
         self.to_verse = to_verse
     if 'title' in options:
         title = nodes.Text(options['title'])
         line = nodes.line()
         line_block = nodes.line_block()
         line.append(title)
         if 'bold' in options:
             bold = nodes.strong()
             bold.append(line)
             line = bold
         line_block.append(line)
         self.node_stack[0][0].append(line_block)
Exemple #22
0
 def run(self):
     if self.env.app.builder.name != "man":
         self.arguments = ["fish-synopsis"]
         return CodeBlock.run(self)
     lexer = FishSynopsisLexer()
     result = nodes.line_block()
     for (start, tok,
          text) in lexer.get_tokens_unprocessed("\n".join(self.content)):
         if (  # Literal text.
             (tok in (Name.Function, Name.Constant) and not text.isupper())
                 or text.startswith(
                     "-")  # Literal option, even if it's uppercase.
                 or tok in (Operator, Punctuation) or text ==
                 " ]"  # Tiny hack: the closing bracket of the test(1) alias is a literal.
         ):
             node = nodes.strong(text=text)
         elif (tok in (Name.Constant, Name.Function)
               and text.isupper()):  # Placeholder parameter.
             node = nodes.emphasis(text=text)
         else:  # Grammar metacharacter or whitespace.
             node = nodes.inline(text=text)
         result.append(node)
     return [result]
Exemple #23
0
 def _update_stack(self, item, depth):
     if not self._verse_wanted():
         return
     if self.is_first:
         self.is_first = False
         self._update_stack(nodes.line_block(), depth - 2)
         self._update_stack(nodes.line(), depth - 1)
     tos,tos_depth = self.node_stack[-1]
     #print("tos:",type(tos),tos, depth, tos_depth)
     #print('stk1:',self.node_stack)
     while depth <= tos_depth:
         del self.node_stack[-1]
         old_nodes = [tos]
         #print("old:",type(tos),tos, depth, tos_depth)
         tos,tos_depth = self.node_stack[-1]
         #print("pre:",type(tos),tos, depth, tos_depth)
         while not hasattr(tos, 'append'):
             del self.node_stack[-1]
             old_nodes.insert(0, tos)
             tos, tos_depth = self.node_stack[-1]
             #print("pre!:",type(tos),tos, depth, tos_depth)
         tos.extend(old_nodes)
     self.node_stack.append((item, depth))
Exemple #24
0
    def get_section(self, section):
        try:
            lines = self.layout["layout"][section]
        except KeyError:
            # Return nothing, if not specific configuration is given for layout section
            return []

        # Needed for PDF/Latex output, where empty line_blocks raise exceptions during build
        if len(lines) == 0:
            return []

        lines_container = nodes.line_block(classes=[f"needs_{section}"])

        for line in lines:
            # line_block_node = nodes.line_block()
            line_node = nodes.line()

            line_parsed = self._parse(line)
            line_ready = self._func_replace(line_parsed)
            line_node += line_ready
            lines_container.append(line_node)

        return lines_container
    def run(self):

        p = nodes.line_block(text=self.content)
        self.state.nested_parse(self.content, self.content_offset, p)

        content = self.create_rows(p.children[0].children)
        table = nodes.table(border=0, frame='void')

        tgroup = nodes.tgroup(cols=len(content))
        table += tgroup
        for i in range(2):
            tgroup += nodes.colspec(colwidth=1)

        # thead = nodes.thead()
        # tgroup += thead
        # thead += self.create_table_row(header)

        tbody = nodes.tbody()
        tgroup += tbody
        for data_row in content:
            tbody += self.create_table_row(data_row)

        return [table]
    def run(self):

        p = nodes.line_block(text=self.content)
        self.state.nested_parse(self.content, self.content_offset, p)

        content = self.create_rows(p.children[0].children)
        table = nodes.table(border=0, frame='void')

        tgroup = nodes.tgroup(cols=len(content))
        table += tgroup
        for i in range(2):
            tgroup += nodes.colspec(colwidth=1)

        # thead = nodes.thead()
        # tgroup += thead
        # thead += self.create_table_row(header)

        tbody = nodes.tbody()
        tgroup += tbody
        for data_row in content:
            tbody += self.create_table_row(data_row)

        return [table]
Exemple #27
0
    def run(self):
        workflow = all_workflows.get(self.arguments[0])
        if not workflow:

            valid_workflows = [w for w in all_workflows.keys()]
            self.warning(f"Unable to add {self.arguments[0]}, "
                         f"Only known ones are {','.join(valid_workflows)}")
            return []
        indexnode = addnodes.index(entries=[])

        targetid = nodes.make_id("workflow-{}".format(workflow.name))

        targetname = nodes.fully_normalize_name(workflow.name)

        section = nodes.section(names=[targetname], ids=[targetid])

        if "notitle" not in self.options:
            new_title = nodes.title(workflow.name,
                                    text=workflow.name,
                                    ids=[targetid])
            section.append(new_title)

        if "description" in self.options and workflow.description:
            description_block = nodes.line_block()
            for line in workflow.description.split("\n"):
                new_line = nodes.line(text=line)
                description_block += new_line
            section += description_block
        par = nodes.paragraph()
        self.state.nested_parse(self.content, self.content_offset, par)
        section += par
        self.add_name(section)
        indexnode['entries'].append(
            ('single', workflow.name, targetid, '', workflow.name[0]))

        section.append(indexnode)
        return [section]
def construct_meta(need_data, env):
    """
    Constructs the node-structure for the status container
    :param need_data: need_info container
    :return: node
    """

    hide_options = env.config.needs_hide_options
    if not isinstance(hide_options, list):
        raise SphinxError(
            'Config parameter needs_hide_options must be of type list')

    node_meta = nodes.line_block(classes=['needs_meta'])
    # need parameters
    param_status = "status: "
    param_tags = "tags: "

    if need_data["status"] is not None and 'status' not in hide_options:
        status_line = nodes.line(classes=['status'])
        # node_status = nodes.line(param_status, param_status, classes=['status'])
        node_status = nodes.inline(param_status,
                                   param_status,
                                   classes=['status'])
        status_line.append(node_status)
        status_line.append(
            nodes.inline(need_data["status"],
                         need_data["status"],
                         classes=["needs-status",
                                  str(need_data['status'])]))
        node_meta.append(status_line)

    if need_data["tags"] and 'tags' not in hide_options:
        tag_line = nodes.line(classes=['tags'])
        # node_tags = nodes.line(param_tags, param_tags, classes=['tags'])
        node_tags = nodes.inline(param_tags, param_tags, classes=['tags'])
        tag_line.append(node_tags)
        for tag in need_data['tags']:
            # node_tags.append(nodes.inline(tag, tag, classes=["needs-tag", str(tag)]))
            # node_tags.append(nodes.inline(' ', ' '))
            tag_line.append(
                nodes.emphasis(tag, tag, classes=["needs-tag",
                                                  str(tag)]))
            tag_line.append(nodes.inline(" ", " "))
        node_meta.append(tag_line)

    # Links incoming
    if need_data['links_back'] and 'links_back' not in hide_options:
        node_incoming_line = nodes.line(classes=['links', 'incoming'])
        prefix = "links incoming: "
        node_incoming_prefix = nodes.inline(prefix, prefix)
        node_incoming_line.append(node_incoming_prefix)
        node_incoming_links = Need_incoming(reftarget=need_data['id'])
        node_incoming_links.append(
            nodes.inline(need_data['id'], need_data['id']))
        node_incoming_line.append(node_incoming_links)
        node_meta.append(node_incoming_line)

    # # Links outgoing
    if need_data['links'] and 'links' not in hide_options:
        node_outgoing_line = nodes.line(classes=['links', 'outgoing'])
        prefix = "links outgoing: "
        node_outgoing_prefix = nodes.inline(prefix, prefix)
        node_outgoing_line.append(node_outgoing_prefix)
        node_outgoing_links = Need_outgoing(reftarget=need_data['id'])
        node_outgoing_links.append(
            nodes.inline(need_data['id'], need_data['id']))
        node_outgoing_line.append(node_outgoing_links)
        node_meta.append(node_outgoing_line)

    extra_options = getattr(env.config, 'needs_extra_options', {})
    node_extra_options = []
    for key, value in extra_options.items():
        if key in hide_options:
            continue
        param_data = need_data[key]
        if param_data is None or not param_data:
            continue
        param_option = '{}: '.format(key)
        option_line = nodes.line(classes=['extra_option'])
        option_line.append(
            nodes.inline(param_option, param_option, classes=['extra_option']))
        option_line.append(
            nodes.inline(param_data,
                         param_data,
                         classes=["needs-extra-option",
                                  str(key)]))
        node_extra_options.append(option_line)

    node_meta += node_extra_options

    global_options = getattr(env.config, 'needs_global_options', {})
    node_global_options = []
    for key, value in global_options.items():
        # If a global option got locally overwritten, it must already part of extra_options.
        # In this skipp output, as this is done during extra_option handling
        if key in extra_options or key in hide_options:
            continue

        param_data = need_data[key]
        if param_data is None or not param_data:
            continue
        param_option = '{}: '.format(key)
        global_option_line = nodes.line(classes=['global_option'])
        global_option_line.append(
            nodes.inline(param_option, param_option,
                         classes=['global_option']))
        global_option_line.append(
            nodes.inline(param_data,
                         param_data,
                         classes=["needs-global-option",
                                  str(key)]))
        node_global_options.append(global_option_line)

    node_meta += node_global_options

    return node_meta
Exemple #29
0
def process_needlist(app, doctree, fromdocname):
    """
    Replace all needlist nodes with a list of the collected needs.
    Augment each need with a backlink to the original location.
    """
    env = app.builder.env

    for node in doctree.traverse(Needlist):
        if not app.config.needs_include_needs:
            # Ok, this is really dirty.
            # If we replace a node, docutils checks, if it will not lose any attributes.
            # But this is here the case, because we are using the attribute "ids" of a node.
            # However, I do not understand, why losing an attribute is such a big deal, so we delete everything
            # before docutils claims about it.
            for att in ("ids", "names", "classes", "dupnames"):
                node[att] = []
            node.replace_self([])
            continue

        id = node.attributes["ids"][0]
        current_needfilter = env.need_all_needlists[id]
        all_needs = env.needs_all_needs
        content = []
        all_needs = list(all_needs.values())
        found_needs = process_filters(app, all_needs, current_needfilter)

        line_block = nodes.line_block()

        # Add lineno to node
        line_block.line = current_needfilter["lineno"]
        for need_info in found_needs:
            para = nodes.line()
            description = "{}: {}".format(need_info["id"], need_info["title"])

            if current_needfilter["show_status"] and need_info["status"]:
                description += " (%s)" % need_info["status"]

            if current_needfilter["show_tags"] and need_info["tags"]:
                description += " [%s]" % "; ".join(need_info["tags"])

            title = nodes.Text(description, description)

            # Create a reference
            if need_info["hide"]:
                para += title
            elif need_info["is_external"]:
                ref = nodes.reference("", "")

                ref["refuri"] = check_and_calc_base_url_rel_path(
                    need_info["external_url"], fromdocname)

                ref["classes"].append(need_info["external_css"])
                ref.append(title)
                para += ref
            else:
                ref = nodes.reference("", "")
                ref["refdocname"] = need_info["docname"]
                ref["refuri"] = app.builder.get_relative_uri(
                    fromdocname, need_info["docname"])
                ref["refuri"] += "#" + need_info["target_node"]["refid"]
                ref.append(title)
                para += ref
            line_block.append(para)
        content.append(line_block)

        if len(content) == 0:
            content.append(no_needs_found_paragraph())

        if current_needfilter["show_filters"]:
            content.append(used_filter_paragraph(current_needfilter))

        node.replace_self(content)
def _process_gradebook_nodes(app, doctree, docname):
    env = app.builder.env

    # Get the first element of the path to the current document. This defines the URL for the book.
    book_url = docname.split('/')[0] + '/'

    # Look for all gradebook nodes.
    for node in doctree.traverse(_GradebookNode):
        # Traverse the global TOC, only including files in the current book. The data structure created to walk the TOC: ``[ [docnames of level 0] [docnames of level 1] ... ]``. The data structure used to store the output: ``[ [level docname] ... ]``. The core algorithm:
        #
        # 1. Initialize data structures.
        toc = [[app.config.master_doc]]
        gradebooks = _get_interactive_questions(env).gradebooks
        # The gradebook should be empty -- verify this.
        if docname in gradebooks:
            raise SphinxError('{}: Multiple gradebook directives in one document is not allowed.'.format(env.doc2path(docname)))
        gradebook = gradebooks[docname] = []
        printed_level = 0
        # 2. While ``toc`` is not empty:
        while toc[0]:
            # 1. Set ``current_docname`` = (the first docname from the end of ``toc``).
            current_docname = toc[-1][0]
            # 2. If ``current_docname`` has questions, then append ``[level docname]`` taken from the ``toc[i][0]`` for ``i = printed_level ... end of toc``.
            if _has_questions(env, current_docname):
                for printed_level in range(printed_level, len(toc)):
                    docname_to_print = toc[printed_level][0]
                    gradebook.append([ printed_level, docname_to_print ])
                printed_level += 1
            # 3. If ``current_docname`` has children, append those in the current book to ``toc``.
            children = env.toctree_includes.get(current_docname, None)
            if children:
                children = [x for x in children if x.startswith(book_url)]
            if children:
                toc += [children]
                # Note that this document's content depends on the title in current_docname. Invoking ``env.note_dependency(current_docname)`` doesn't work -- there is no current document. The resulting error is::
                #
                #   File "e:\downloads\anaconda3\lib\site-packages\sphinx\environment.py", line 821, in docname
                #     return self.temp_data['docname']
                #
                # The code behind `env.note_dependency <http://www.sphinx-doc.org/en/stable/extdev/envapi.html#sphinx.environment.BuildEnvironment.note_dependency>`_ is ``self.dependencies.setdefault(self.docname, set()).add(filename)``, where ``self.docname`` returns the current docname. So, replace this with ``docname`` (passed to this function):
                env.dependencies.setdefault(docname, set()).add(env.doc2path(current_docname))
            else:
                # Otherwise, remove ``current_docname`` from ``toc``. Find the next sibling, removing any parents found in the search for the next sibling.
                del toc[-1][0]
                while toc[0] and not toc[-1]:
                    del toc[-1]
                    del toc[-1][0]
                printed_level = min(printed_level, len(toc))

        # Next, transform this list into HTML. It's too late to insert reST -- the parser is done. Instead, we need to insert nodes, which is more painful than straight HTML.
        html = ['<table border=0 style="align: center; width=500px;">']
        line_block_node = nodes.line_block()
        for level, current_docname in gradebook:
            # Compute the appropriate hyperlink relative path. I'd prefer to insert a ``pending_xref`` node to have it do this, but the doctree is already resolved, so these can't be used.
            rp = os.path.relpath(os.path.dirname('/' + current_docname), start=os.path.dirname('/' + docname)) + '/'
            ext = _get_html_suffix(app)
            link = rp + os.path.basename(current_docname) + ext
            if _has_questions(env, current_docname):
                grade = '{{{{ grade("{}") }}}}'.format(current_docname + ext)
            else:
                grade = ''
            html += [
                '<tr>'
                '<td><div style="margin-left: {}em;">'.format(level) +
                # Mimic how Sphinx inserts ``:doc:`` links using ``class`` and a ``span``.
                '<a class="reference internal" href="{}"><span class="doc">{}</span></a></div></td>'.format(link, env.titles[current_docname].astext()) +
                '<td>{}</td>'.format(grade) +
                '</tr>'
            ]
        html += ['</table>']

        raw_node = nodes.raw('gradebook', utils.unescape(''.join(html), 1), format='html')
        node.replace_self(raw_node)
def process_needfilters(app, doctree, fromdocname):
    # Replace all needlist nodes with a list of the collected needs.
    # Augment each need with a backlink to the original location.
    env = app.builder.env

    # NEEDFILTER
    for node in doctree.traverse(Needfilter):
        if not app.config.needs_include_needs:
            # Ok, this is really dirty.
            # If we replace a node, docutils checks, if it will not lose any attributes.
            # But this is here the case, because we are using the attribute "ids" of a node.
            # However, I do not understand, why losing an attribute is such a big deal, so we delete everything
            # before docutils claims about it.
            for att in ('ids', 'names', 'classes', 'dupnames'):
                node[att] = []
            node.replace_self([])
            continue

        id = node.attributes["ids"][0]
        current_needfilter = env.need_all_needfilters[id]
        all_needs = env.needs_all_needs

        if current_needfilter["layout"] == "list":
            content = []

        elif current_needfilter["layout"] == "diagram":
            content = []
            try:
                if "sphinxcontrib.plantuml" not in app.config.extensions:
                    raise ImportError
                from sphinxcontrib.plantuml import plantuml
            except ImportError:
                content = nodes.error()
                para = nodes.paragraph()
                text = nodes.Text("PlantUML is not available!",
                                  "PlantUML is not available!")
                para += text
                content.append(para)
                node.replace_self(content)
                continue

            plantuml_block_text = ".. plantuml::\n" \
                                  "\n" \
                                  "   @startuml" \
                                  "   @enduml"
            puml_node = plantuml(plantuml_block_text, **dict())
            puml_node["uml"] = "@startuml\n"
            puml_connections = ""

        elif current_needfilter["layout"] == "table":
            content = nodes.table()
            tgroup = nodes.tgroup()
            id_colspec = nodes.colspec(colwidth=5)
            title_colspec = nodes.colspec(colwidth=15)
            type_colspec = nodes.colspec(colwidth=5)
            status_colspec = nodes.colspec(colwidth=5)
            links_colspec = nodes.colspec(colwidth=5)
            tags_colspec = nodes.colspec(colwidth=5)
            tgroup += [
                id_colspec, title_colspec, type_colspec, status_colspec,
                links_colspec, tags_colspec
            ]
            tgroup += nodes.thead(
                '',
                nodes.row('', nodes.entry('', nodes.paragraph('', 'ID')),
                          nodes.entry('', nodes.paragraph('', 'Title')),
                          nodes.entry('', nodes.paragraph('', 'Type')),
                          nodes.entry('', nodes.paragraph('', 'Status')),
                          nodes.entry('', nodes.paragraph('', 'Links')),
                          nodes.entry('', nodes.paragraph('', 'Tags'))))
            tbody = nodes.tbody()
            tgroup += tbody
            content += tgroup

        all_needs = list(all_needs.values())

        if current_needfilter["sort_by"] is not None:
            if current_needfilter["sort_by"] == "id":
                all_needs = sorted(all_needs, key=lambda node: node["id"])
            elif current_needfilter["sort_by"] == "status":
                all_needs = sorted(all_needs, key=status_sorter)

        found_needs = procces_filters(all_needs, current_needfilter)

        line_block = nodes.line_block()
        for need_info in found_needs:
            if current_needfilter["layout"] == "list":
                para = nodes.line()
                description = "%s: %s" % (need_info["id"], need_info["title"])

                if current_needfilter["show_status"] and need_info[
                        "status"] is not None:
                    description += " (%s)" % need_info["status"]

                if current_needfilter["show_tags"] and need_info[
                        "tags"] is not None:
                    description += " [%s]" % "; ".join(need_info["tags"])

                title = nodes.Text(description, description)

                # Create a reference
                if not need_info["hide"]:
                    ref = nodes.reference('', '')
                    ref['refdocname'] = need_info['docname']
                    ref['refuri'] = app.builder.get_relative_uri(
                        fromdocname, need_info['docname'])
                    ref['refuri'] += '#' + need_info['target_node']['refid']
                    ref.append(title)
                    para += ref
                else:
                    para += title

                line_block.append(para)
            elif current_needfilter["layout"] == "table":
                row = nodes.row()
                row += row_col_maker(app,
                                     fromdocname,
                                     env.needs_all_needs,
                                     need_info,
                                     "id",
                                     make_ref=True)
                row += row_col_maker(app, fromdocname, env.needs_all_needs,
                                     need_info, "title")
                row += row_col_maker(app, fromdocname, env.needs_all_needs,
                                     need_info, "type_name")
                row += row_col_maker(app, fromdocname, env.needs_all_needs,
                                     need_info, "status")
                row += row_col_maker(app,
                                     fromdocname,
                                     env.needs_all_needs,
                                     need_info,
                                     "links",
                                     ref_lookup=True)
                row += row_col_maker(app, fromdocname, env.needs_all_needs,
                                     need_info, "tags")
                tbody += row
            elif current_needfilter["layout"] == "diagram":
                # Link calculation
                # All links we can get from docutils functions will be relative.
                # But the generated link in the svg will be relative to the svg-file location
                # (e.g. server.com/docs/_images/sqwxo499cnq329439dfjne.svg)
                # and not to current documentation. Therefore we need to add ../ to get out of the _image folder.
                try:
                    link = "../" + app.builder.get_target_uri(need_info['docname']) \
                           + "?highlight={0}".format(urlParse(need_info['title'])) \
                           + "#" \
                           + need_info['target_node']['refid'] \
                        # Gets mostly called during latex generation

                except NoUri:
                    link = ""

                diagram_template = Template(env.config.needs_diagram_template)
                node_text = diagram_template.render(**need_info)

                puml_node[
                    "uml"] += '{style} "{node_text}" as {id} [[{link}]] {color}\n'.format(
                        id=need_info["id"],
                        node_text=node_text,
                        link=link,
                        color=need_info["type_color"],
                        style=need_info["type_style"])
                for link in need_info["links"]:
                    puml_connections += '{id} --> {link}\n'.format(
                        id=need_info["id"], link=link)

        if current_needfilter["layout"] == "list":
            content.append(line_block)

        if current_needfilter["layout"] == "diagram":
            puml_node["uml"] += puml_connections

            # Create a legend

            if current_needfilter["show_legend"]:
                puml_node["uml"] += "legend\n"
                puml_node["uml"] += "|= Color |= Type |\n"
                for need in app.config.needs_types:
                    puml_node[
                        "uml"] += "|<back:{color}> {color} </back>| {name} |\n".format(
                            color=need["color"], name=need["title"])
                puml_node["uml"] += "endlegend\n"
            puml_node["uml"] += "@enduml"
            puml_node["incdir"] = os.path.dirname(
                current_needfilter["docname"])
            puml_node["filename"] = os.path.split(
                current_needfilter["docname"])[1]  # Needed for plantuml >= 0.9
            content.append(puml_node)

        if len(content) == 0:
            nothing_found = "No needs passed the filters"
            para = nodes.line()
            nothing_found_node = nodes.Text(nothing_found, nothing_found)
            para += nothing_found_node
            content.append(para)
        if current_needfilter["show_filters"]:
            para = nodes.paragraph()
            filter_text = "Used filter:"
            filter_text += " status(%s)" % " OR ".join(
                current_needfilter["status"]) if len(
                    current_needfilter["status"]) > 0 else ""
            if len(current_needfilter["status"]) > 0 and len(
                    current_needfilter["tags"]) > 0:
                filter_text += " AND "
            filter_text += " tags(%s)" % " OR ".join(
                current_needfilter["tags"]) if len(
                    current_needfilter["tags"]) > 0 else ""
            if (len(current_needfilter["status"]) > 0
                    or len(current_needfilter["tags"]) > 0) and len(
                        current_needfilter["types"]) > 0:
                filter_text += " AND "
            filter_text += " types(%s)" % " OR ".join(
                current_needfilter["types"]) if len(
                    current_needfilter["types"]) > 0 else ""

            filter_node = nodes.emphasis(filter_text, filter_text)
            para += filter_node
            content.append(para)

        node.replace_self(content)
Exemple #32
0
 def div_p(self, elem, depth):
     #print (' '*depth, depth,'<p>')
     self._update_stack(nodes.line_block(), depth - 1)
     node = nodes.line()
     self._update_stack(node, depth)
    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]
Exemple #34
0
        targetnode = nodes.target('', '', ids=[targetid])
		targetnode['classes'] = ['epigraph']

        node = quote_node()
		node += nodes.block_quote(
			'',
			nodes.paragraph('', '\n'.join(self.content), classes=['text']))
		#state.nested_parse(self.content, self.content_offset, node)

        for element in node:
            if isinstance(element, nodes.block_quote):
                element['classes'] += ['epigraph']

		signode = [nodes.attribution('--', '--')]
		# Embed all components within attributions
		siglb = nodes.line_block('')
		# Pre-format some
		if 'date' in options:
			options['date'] = '[%(date)s]' % options
		if 'source' in options:
			options['source'] = 'Source: %(source)s' % options
		for el in ['author', 'date', 'affiliation', 'source']:
			if el in options:
				siglb += [nodes.inline('', '  '+options[el], classes=[el])]
		signode[0].extend(siglb)
		node[0].extend(signode)
		node.line = self.lineno
		# tune up options
		_prep_tags(self.options)
		node.options = options
        return [targetnode] + [node]