"""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)