142 lines
4.5 KiB
Python
142 lines
4.5 KiB
Python
"""Implement statemachine and state that are needed to Generate Derivatives."""
|
|
|
|
from docutils.statemachine import StateMachineWS
|
|
from docutils.parsers.rst import languages
|
|
from docutils.parsers.rst.states import Struct, RSTState, Inliner
|
|
from docutils.parsers.rst.roles import role
|
|
from docutils.parsers.rst.directives import directive
|
|
|
|
|
|
class DummyStateMachine(StateMachineWS):
|
|
|
|
"""A dummy state machine that mimicks the property of statemachine.
|
|
|
|
This state machine cannot be used for parsing, it is only used to generate
|
|
directive and roles. Usage:
|
|
- Call `reset` to reset the state
|
|
- Then call `run_directive` or `run_role` to generate the node.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.memo = Struct(title_styles=[],
|
|
inliner=None)
|
|
self.state = RSTState(self)
|
|
self.input_offset = 0
|
|
|
|
def reset(self, document, parent, level):
|
|
"""Reset the state of state machine.
|
|
|
|
After reset, self and self.state can be used to
|
|
passed to docutils.parsers.rst.Directive.run
|
|
|
|
Parameters
|
|
----------
|
|
document: docutils document
|
|
Current document of the node.
|
|
parent: parent node
|
|
Parent node that will be used to interpret role and directives.
|
|
level: int
|
|
Current section level.
|
|
"""
|
|
self.language = languages.get_language(
|
|
document.settings.language_code)
|
|
# setup memo
|
|
self.memo.document = document
|
|
self.memo.reporter = document.reporter
|
|
self.memo.language = self.language
|
|
self.memo.section_level = level
|
|
# setup inliner
|
|
if self.memo.inliner is None:
|
|
self.memo.inliner = Inliner()
|
|
self.memo.inliner.init_customizations(document.settings)
|
|
inliner = self.memo.inliner
|
|
inliner.reporter = document.reporter
|
|
inliner.document = document
|
|
inliner.language = self.language
|
|
inliner.parent = parent
|
|
# setup self
|
|
self.document = document
|
|
self.reporter = self.memo.reporter
|
|
self.node = parent
|
|
self.state.runtime_init()
|
|
self.input_lines = document['source']
|
|
|
|
def run_directive(self, name,
|
|
arguments=None,
|
|
options=None,
|
|
content=None):
|
|
"""Generate directive node given arguments.
|
|
|
|
Parameters
|
|
----------
|
|
name : str
|
|
name of directive.
|
|
arguments : list
|
|
list of positional arguments.
|
|
options : dict
|
|
key value arguments.
|
|
content : content
|
|
content of the directive
|
|
|
|
Returns
|
|
-------
|
|
node : docutil Node
|
|
Node generated by the arguments.
|
|
"""
|
|
if options is None:
|
|
options = {}
|
|
if content is None:
|
|
content = []
|
|
if arguments is None:
|
|
arguments = []
|
|
direc, _ = directive(name, self.language, self.document)
|
|
direc = direc(name=name,
|
|
arguments=arguments,
|
|
options=options,
|
|
content=content,
|
|
lineno=self.node.line,
|
|
content_offset=0,
|
|
block_text='Dummy BlockText',
|
|
state=self.state,
|
|
state_machine=self)
|
|
return direc.run()
|
|
|
|
def run_role(self, name,
|
|
options=None,
|
|
content=None):
|
|
"""Generate a role node.
|
|
|
|
options : dict
|
|
key value arguments.
|
|
content : content
|
|
content of the directive
|
|
|
|
Returns
|
|
-------
|
|
node : docutil Node
|
|
Node generated by the arguments.
|
|
"""
|
|
if options is None:
|
|
options = {}
|
|
if content is None:
|
|
content = []
|
|
role_fn, _ = role(name,
|
|
self.language,
|
|
self.node.line,
|
|
self.reporter)
|
|
vec, _ = role_fn(name,
|
|
rawtext=str(content),
|
|
text=str(content),
|
|
lineno=self.node.line,
|
|
inliner=self.memo.inliner,
|
|
options=options,
|
|
content=content)
|
|
assert len(vec) == 1, 'only support one list in role'
|
|
return vec[0]
|
|
|
|
def get_source_and_line(self, lineno=None):
|
|
if lineno:
|
|
return (self.document['source'], lineno)
|
|
else:
|
|
return (self.document['source'], self.node.line)
|