puppygirl-py/puppygirl/pg.py

47 lines
1.6 KiB
Python

from typing import Callable, Iterable, Self
from bs4 import BeautifulSoup, Tag
from .elements import IdAttr, Template, Node
from .renderer import Renderable, Renderer
from .puppytype import Parsable, ParsableIterable, Parsable, Templates
class Puppygirl[R: Renderer]:
renderer: R
elements: list[Renderable]
templates: Templates
def __init__(self, renderer: R, elements: list[Callable[[Self], Renderable]] = [], templates: ParsableIterable = []):
self.renderer = renderer
self.templates = Puppygirl._create_template_dict(templates)
self.elements = [self._instantiate(el) for el in elements]
def _instantiate(self, value: Callable[[Self], Renderable] | Renderable) -> Renderable:
if(isinstance(value, Callable)):
return value(self)
return value
def _create_template_dict(templates: Iterable[Parsable]) -> Templates:
templates = [Template.from_element(t) for t in templates]
return {t.id: t for t in templates}
def add_template(self, template: Parsable):
template = Template.from_element(template)
self._templates[template[IdAttr]] = template
def _is_parsed(value: Parsable) -> bool:
return isinstance(value, BeautifulSoup) or \
isinstance(value, Tag) or \
isinstance(value, Node) or \
isinstance(value, Template)
def parse(self, value: Parsable) -> BeautifulSoup:
if value is None:
return BeautifulSoup(features='html.parser')
if Puppygirl._is_parsed(value):
return self.parse_tree(value)
return self.parse_tree(BeautifulSoup(value, features='html.parser'))
def parse_tree(self, tree: BeautifulSoup) -> BeautifulSoup:
return self.renderer.render(self, tree)