From bd6877031f21ce57669d992a879730f09afe092f Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 18 Apr 2021 12:41:53 +0200 Subject: [PATCH 1/2] Remove use of six module --- breathe/renderer/filter.py | 3 +-- breathe/renderer/mask.py | 5 +---- breathe/renderer/sphinxrenderer.py | 11 +++++------ requirements/production.txt | 1 - 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/breathe/renderer/filter.py b/breathe/renderer/filter.py index d0a6b6154..836e94acb 100644 --- a/breathe/renderer/filter.py +++ b/breathe/renderer/filter.py @@ -204,7 +204,6 @@ from sphinx.application import Sphinx import os -import six from typing import Any, Callable, Dict, List @@ -325,7 +324,7 @@ def __call__(self, node_stack) -> str: except AttributeError as e: # Horrible hack to silence errors on filtering unicode objects # until we fix the parsing - if type(data_object) == six.text_type: + if type(data_object) == str: return "unicode" else: raise e diff --git a/breathe/renderer/mask.py b/breathe/renderer/mask.py index 46921fdf8..076a192a3 100644 --- a/breathe/renderer/mask.py +++ b/breathe/renderer/mask.py @@ -18,9 +18,6 @@ """ -import six - - class NoParameterNamesMask: def __init__(self, data_object) -> None: self.data_object = data_object @@ -46,7 +43,7 @@ def mask(self, data_object): except AttributeError as e: # Horrible hack to silence errors on filtering unicode objects # until we fix the parsing - if isinstance(data_object, six.text_type): + if isinstance(data_object, str): node_type = "unicode" else: raise e diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index 898dcebb5..795c69a77 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -26,7 +26,6 @@ cs = None import re -import six import textwrap from typing import Callable, cast, Dict, List, Optional, Tuple, Type, Union # noqa @@ -366,7 +365,7 @@ def to_string(node): if node is not None: for p in node.content_: value = p.value - if not isinstance(value, six.text_type): + if not isinstance(value, str): value = value.valueOf_ result.append(value) return ' '.join(result) @@ -555,7 +554,7 @@ def get_filename(node) -> Optional[str]: node = node_stack[0] # An enumvalue node doesn't have location, so use its parent node for detecting # the domain instead. - if isinstance(node, six.string_types) or node.node_type == "enumvalue": + if isinstance(node, str) or node.node_type == "enumvalue": node = node_stack[1] filename = get_filename(node) if not filename and node.node_type == "compound": @@ -917,7 +916,7 @@ def visit_unicode(self, node) -> List[Node]: return [nodes.paragraph('', '', nodes.Text(line)) for line in node.split(delimiter) if line.strip()] return [nodes.Text(node)] - if node == six.u(" "): + if node == " ": return [nodes.Text(node)] return [] @@ -2020,7 +2019,7 @@ def visit_param(self, node) -> List[Node]: if node.type_: type_nodes = self.render(node.type_) # Render keywords as annotations for consistency with the cpp domain. - if len(type_nodes) > 0 and isinstance(type_nodes[0], six.text_type): + if len(type_nodes) > 0 and isinstance(type_nodes[0], str): first_node = type_nodes[0] for keyword in ['typename', 'class']: if first_node.startswith(keyword + ' '): @@ -2184,7 +2183,7 @@ def render(self, node, context: Optional[RenderContext] = None) -> List[Node]: self.context = cast(RenderContext, self.context) if not self.filter_.allow(self.context.node_stack): pass - elif isinstance(node, six.string_types): + elif isinstance(node, str): result = self.visit_unicode(node) else: method = SphinxRenderer.methods.get(node.node_type, SphinxRenderer.visit_unknown) diff --git a/requirements/production.txt b/requirements/production.txt index b0f139a80..3fa134038 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -3,4 +3,3 @@ Jinja2>=2.7.3 MarkupSafe>=0.23 Pygments>=1.6 Sphinx>=3.0,<3.6 -six>=1.9.0 From 1cf8fef8d2a4a0edd846346bdb39c4c961c9716b Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 18 Apr 2021 14:06:32 +0200 Subject: [PATCH 2/2] Fix paragraph rendering in paragraphs Fixes michaeljones/breathe#666 --- breathe/renderer/sphinxrenderer.py | 74 ++++++++++++++++++------------ examples/tinyxml/tinyxml.h | 2 +- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/breathe/renderer/sphinxrenderer.py b/breathe/renderer/sphinxrenderer.py index 795c69a77..8005dd413 100644 --- a/breathe/renderer/sphinxrenderer.py +++ b/breathe/renderer/sphinxrenderer.py @@ -1,4 +1,4 @@ -from breathe.parser import DoxygenCompoundParser +from breathe.parser import DoxygenCompoundParser, compoundsuper from breathe.project import ProjectInfo from breathe.renderer import RenderContext from breathe.renderer.filter import Filter @@ -897,29 +897,6 @@ def render_declaration(self, node, declaration=None, description=None, **kwargs) contentnode.extend(description) return nodes - def visit_unicode(self, node) -> List[Node]: - # Skip any nodes that are pure whitespace - # Probably need a better way to do this as currently we're only doing - # it skip whitespace between higher-level nodes, but this will also - # skip any pure whitespace entries in actual content nodes - # - # We counter that second issue slightly by allowing through single white spaces - # - if node.strip(): - delimiter = None - if "" in node: - delimiter = "" - elif "\n" in node: - delimiter = "\n" - if delimiter: - # Render lines as paragraphs because RST doesn't have line breaks. - return [nodes.paragraph('', '', nodes.Text(line)) - for line in node.split(delimiter) if line.strip()] - return [nodes.Text(node)] - if node == " ": - return [nodes.Text(node)] - return [] - def visit_doxygen(self, node) -> List[Node]: nodelist = [] @@ -1371,7 +1348,18 @@ def visit_docpara(self, node) -> List[Node]: if self.context and self.context.directive_args[0] == "doxygenpage": nodelist.extend(self.render_iterable(node.ordered_children)) else: - nodelist.extend(self.render_iterable(node.content)) + contentNodeCands = self.render_iterable(node.content) + # if there are consecutive nodes.Text we should collapse them + # and rerender them to ensure the right paragraphifaction + contentNodes = [] # type: List[Node] + for n in contentNodeCands: + if len(contentNodes) != 0 and isinstance(contentNodes[-1], nodes.Text): + if isinstance(n, nodes.Text): + prev = contentNodes.pop() + contentNodes.extend(self.render_string(prev.astext() + n.astext())) + continue # we have handled this node + contentNodes.append(n) + nodelist.extend(contentNodes) nodelist.extend(self.render_iterable(node.images)) paramList = self.render_iterable(node.parameterlist) @@ -1778,7 +1766,7 @@ def merge_row_types(root, elem, elems): return [table] - def visit_mixedcontainer(self, node) -> List[Node]: + def visit_mixedcontainer(self, node: compoundsuper.MixedContainer) -> List[Node]: return self.render_optional(node.getValue()) def visit_description(self, node) -> List[Node]: @@ -2174,7 +2162,33 @@ def dispatch_memberdef(self, node) -> List[Node]: "docentry": visit_docentry, } - def render(self, node, context: Optional[RenderContext] = None) -> List[Node]: + def render_string(self, node: str) -> List[Union[nodes.Text, nodes.paragraph]]: + # Skip any nodes that are pure whitespace + # Probably need a better way to do this as currently we're only doing + # it skip whitespace between higher-level nodes, but this will also + # skip any pure whitespace entries in actual content nodes + # + # We counter that second issue slightly by allowing through single white spaces + # + stripped = node.strip() + if stripped: + delimiter = None + if "" in stripped: + delimiter = "" + elif "\n" in stripped: + delimiter = "\n" + if delimiter: + # Render lines as paragraphs because RST doesn't have line breaks. + return [nodes.paragraph('', '', nodes.Text(line.strip())) + for line in node.split(delimiter) if line.strip()] + # importantly, don't strip whitespace as visit_docpara uses it to collapse + # consecutive nodes.Text and rerender them with this function. + return [nodes.Text(node)] + if node == " ": + return [nodes.Text(node)] + return [] + + def render(self, node: Node, context: Optional[RenderContext] = None) -> List[Node]: if context is None: self.context = cast(RenderContext, self.context) context = self.context.create_child_context(node) @@ -2184,17 +2198,17 @@ def render(self, node, context: Optional[RenderContext] = None) -> List[Node]: if not self.filter_.allow(self.context.node_stack): pass elif isinstance(node, str): - result = self.visit_unicode(node) + result = self.render_string(node) else: method = SphinxRenderer.methods.get(node.node_type, SphinxRenderer.visit_unknown) result = method(self, node) return result - def render_optional(self, node) -> List[Node]: + def render_optional(self, node: Node) -> List[Node]: """Render a node that can be None.""" return self.render(node) if node else [] - def render_iterable(self, iterable) -> List[Node]: + def render_iterable(self, iterable: List[Node]) -> List[Node]: output = [] for entry in iterable: output.extend(self.render(entry)) diff --git a/examples/tinyxml/tinyxml.h b/examples/tinyxml/tinyxml.h index f449dc736..273407620 100644 --- a/examples/tinyxml/tinyxml.h +++ b/examples/tinyxml/tinyxml.h @@ -1730,7 +1730,7 @@ class TiXmlPrinter : public TiXmlVisitor void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } /// Query the indention string. const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). + /** Set the line breaking string. By default set to newline (\c \n). Some operating systems prefer other characters, or can be set to the null/empty string for no indentation. */