Exemple #1
0
def test_core_parse():
    parser = Parser()
    a = A()
    parser.register(a.pattern_d, a.render_digit)

    source = "123456789"
    assert parser.parse(source) == source
Exemple #2
0
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"]
Exemple #3
0
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>]"
Exemple #4
0
    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
Exemple #5
0
def parser(jupyter, header, embed):
    parser = Parser()
    jupyter.parser = parser
    header.parser = parser
    embed.parser = parser

    return parser
Exemple #6
0
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]"
Exemple #7
0
 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
Exemple #8
0
 def parser(self) -> Parser:
     if self._parser is None:
         self.parser = Parser()
     return self._parser  # type: ignore
Exemple #9
0
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)
Exemple #10
0
    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)