Skip to content

Commit

Permalink
馃敡 MAINTAIN: Implement MockInliner.parse (#504)
Browse files Browse the repository at this point in the history
The only place this is normally called,
is by `RSTState.inline_text`, or in directives: `self.state.inline_text`.
But it could be potentially called by custom roles.
  • Loading branch information
chrisjsewell committed Jan 14, 2022
1 parent 707d9d5 commit ad6e39d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Expand Up @@ -161,6 +161,7 @@ def run_apidoc(app):
("py:class", "docutils.nodes.document"),
("py:class", "docutils.nodes.docinfo"),
("py:class", "docutils.nodes.Element"),
("py:class", "docutils.nodes.Node"),
("py:class", "docutils.nodes.field_list"),
("py:class", "docutils.nodes.problematic"),
("py:class", "docutils.nodes.pending"),
Expand Down
2 changes: 1 addition & 1 deletion myst_parser/docutils_renderer.py
Expand Up @@ -1046,7 +1046,7 @@ def render_myst_role(self, token: SyntaxTreeNode) -> None:
role_func, messages = roles.role(
name, self.language_module_rst, lineno, self.reporter
)
inliner = MockInliner(self, lineno)
inliner = MockInliner(self)
if role_func:
nodes, messages2 = role_func(name, rawsource, text, lineno, inliner)
# return nodes, messages + messages2
Expand Down
47 changes: 32 additions & 15 deletions myst_parser/mocking.py
Expand Up @@ -5,7 +5,7 @@
import re
import sys
from pathlib import Path
from typing import TYPE_CHECKING, List, Optional, Tuple, Type
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Type

from docutils import nodes
from docutils.parsers.rst import Directive, DirectiveError
Expand All @@ -31,28 +31,50 @@ class MockInliner:
This is parsed to role functions.
"""

def __init__(self, renderer: "DocutilsRenderer", lineno: int):
def __init__(self, renderer: "DocutilsRenderer"):
"""Initialize the mock inliner."""
self._renderer = renderer
# here we mock that the `parse` method has already been called
# which is where these attributes are set (via the RST state Memo)
self.document = renderer.document
self.reporter = renderer.document.reporter
self.language = renderer.language_module_rst
self.parent = renderer.current_node

if not hasattr(self.reporter, "get_source_and_line"):
# TODO this is called by some roles,
# but I can't see how that would work in RST?
# In docutils this is set by `RSTState.runtime_init`
self.reporter.get_source_and_line = lambda l: (self.document["source"], l)
self.parent = renderer.current_node
self.language = renderer.language_module_rst

self.rfc_url = "rfc%d.html"

def problematic(
self, text: str, rawsource: str, message: nodes.system_message
) -> nodes.problematic:
"""Record a system message from parsing."""
msgid = self.document.set_id(message, self.parent)
problematic = nodes.problematic(rawsource, rawsource, refid=msgid)
problematic = nodes.problematic(rawsource, text, refid=msgid)
prbid = self.document.set_id(problematic)
message.add_backref(prbid)
return problematic

# TODO add parse method
def parse(
self, text: str, lineno: int, memo: Any, parent: nodes.Node
) -> Tuple[List[nodes.Node], List[nodes.system_message]]:
"""Parse the text and return a list of nodes."""
# note the only place this is normally called,
# is by `RSTState.inline_text`, or in directives: `self.state.inline_text`,
# and there the state parses its own parent
# self.reporter = memo.reporter
# self.document = memo.document
# self.language = memo.language
with self._renderer.current_node_context(parent):
# the parent is never actually appended to though,
# so we make a temporary parent to parse into
container = nodes.Element()
with self._renderer.current_node_context(container):
self._renderer.nested_render_text(text, lineno, inline=True)

return container.children, []

def __getattr__(self, name: str):
"""This method is only be called if the attribute requested has not
Expand Down Expand Up @@ -87,7 +109,7 @@ def __init__(
self.document = renderer.document
self.reporter = renderer.document.reporter
self.state_machine = state_machine
self.inliner = MockInliner(renderer, lineno)
self.inliner = MockInliner(renderer)

class Struct:
document = self.document
Expand Down Expand Up @@ -172,12 +194,7 @@ def inline_text(
:returns: (list of nodes, list of messages)
"""
container = nodes.Element()
with self._renderer.current_node_context(container):
self._renderer.nested_render_text(text, lineno, inline=True)

# TODO return messages?
return container.children, []
return self.inliner.parse(text, lineno, self.memo, self._renderer.current_node)

# U+2014 is an em-dash:
attribution_pattern = re.compile("^((?:---?(?!-)|\u2014) *)(.+)")
Expand Down

0 comments on commit ad6e39d

Please sign in to comment.