def test_core_parse(): parser = Parser() a = A() parser.register(a.pattern_d, a.render_digit) source = "123456789" assert parser.parse(source) == source
def test_split(): a = Renderer_A() parser = Parser() parser.register(a.pattern_ab, a.render_ab) parser.register(a.pattern_cd, a.render_cd) assert len(parser.patterns) == 2 assert len(parser.renders) == 2 assert len(parser.cell_classes) == 2 keys = list(parser.patterns.keys()) assert keys == ["renderer_a__ab", "renderer_a__cd"] source = "a ab ba cd dc a ab a ab a ab" splitter = parser.split(source) cell = next(splitter) assert repr(cell) == "Cell(source='a ', match=None, output='')" cell = next(splitter) assert cell.match is not None assert list(cell.render(splitter, parser)) == ["ba"] cell = next(splitter) cell = next(splitter) assert cell.match is not None assert cell.parse(splitter, parser) == "dc" assert splitter.send('a ab') is None cell = next(splitter) assert repr(cell) == "Cell(source='a ', match=None, output='')" cell = next(splitter) assert cell.match is not None assert list(cell.render(splitter, parser)) == ["ba"]
def test_core_parse_with_decorate(): parser = Parser() a = B() parser.register(a.pattern_a, a.render_a) parser.register(a.pattern_b, a.render_b) source = "a12aa345" assert parser.parse(source) == "{B}<12>[{B}<345>]"
def register( self, renderers: Iterable[Renderer], name: str = "default", preprocess: Optional[Callable[[str], str]] = None, postprocess: Optional[Callable[[str], str]] = None, ) -> None: """Register renderer's processes to a parser. Parameters ---------- renderers List of Renderer name The name of Parser """ if name in self.parsers: raise ValueError(f"Duplicated parser name '{name}'") parser = Parser(name) # type: ignore for renderer in renderers: renderer.parser = parser self.parsers[name] = parser self.renderers[name] = list(renderers) if preprocess: self.preprocesses[name] = preprocess if postprocess: self.postprocesses[name] = postprocess
def parser(jupyter, header, embed): parser = Parser() jupyter.parser = parser header.parser = parser embed.parser = parser return parser
def test_core_parse_complex(): parser = Parser() a = A() parser.register(a.pattern_d, a.render_digit) parser.register(a.pattern_w, a.render_word) source = "1a b2b abb 3bbacb5" assert parser.parse(source) == "1a [2] ba[ b]3[[a]][4][5]"
def configure_parser(self, parser: Parser) -> Parser: for render_name, pattern in self.patterns.items(): render = self.renders[render_name] parser.register(pattern, render, render_name) return parser
def parser(self) -> Parser: if self._parser is None: self.parser = Parser() return self._parser # type: ignore
class Renderer(Base): patterns: Dict[str, str] = field(default_factory=dict, init=False) renders: Dict[str, Render] = field(default_factory=dict, init=False) page: Page = field(default_factory=Page, init=False) _parser: Optional[Parser] = field(default=None, init=False) class_parser = None def __post_init__(self): super().__post_init__() self.init() def __post_repr__(self): return len(self.renders) def init(self) -> None: """Called from __post_init__.""" pass def start(self) -> None: """Called at conversion start""" pass def enter(self) -> None: """Called at page enter event""" pass def exit(self) -> None: """Called at page exit event""" pass def register(self, pattern: str, render: Render, render_name: str = "") -> None: if not render_name: render_name = get_render_name(render) self.patterns[render_name] = pattern self.renders[render_name] = render @property def parser(self) -> Parser: if self._parser is None: self.parser = Parser() return self._parser # type: ignore @parser.setter def parser(self, parser: Parser) -> None: self._parser = self.configure_parser(parser) def configure_parser(self, parser: Parser) -> Parser: for render_name, pattern in self.patterns.items(): render = self.renders[render_name] parser.register(pattern, render, render_name) return parser def set_config(self, *args, **kwargs) -> None: for arg in args: for key, value in arg.items(): *prefix, key = key.split(".") config = self.config for pre in prefix: config = config.setdefault(pre, {}) config[key] = value self.config.update(kwargs) def set_template(self, names: Union[str, List[str]], directory: str = ".") -> List: module = importlib.import_module(self.__module__) default = os.path.join(os.path.dirname(module.__file__), "templates") loader = FileSystemLoader([directory, default]) env = Environment(loader=loader, autoescape=select_autoescape(["jinja2"])) names = [names] if isinstance(names, str) else names templates = [] for name in names: if ":" in name: name, path = name.split(":") else: path = name template_name = f"{path}.jinja2" if "." not in name else name template = env.get_template(template_name) self.config[f"{name}_template"] = template templates.append(template) return templates def render(self, name: str, context: Dict[str, Any], **kwargs) -> str: template = self.config[f"{name}_template"] return template.render(context, config=self.config, **kwargs) def parse(self, source: str = "") -> str: return self.parser.parse(source or self.page.source, decorate=self.decorate) def decorate(self, cell): """Decorate cell.output after parse. Overwritten by subclass.""" pass def findall(self, source: str = "") -> List: if self.class_parser is None: self.class_parser = Parser() self.configure_parser(self.class_parser) return self.class_parser.findall(source or self.page.source)
def findall(self, source: str = "") -> List: if self.class_parser is None: self.class_parser = Parser() self.configure_parser(self.class_parser) return self.class_parser.findall(source or self.page.source)