puppygirl-py/puppygirl/pg.py
2025-10-06 16:11:34 -04:00

42 lines
1.5 KiB
Python

from typing import Callable, Iterable, Self
from bs4 import BeautifulSoup, Tag
from elements import IdAttr, Template
from puppygirl.renderer import Renderable, Renderer
from puppygirl.puppytype import ElementLike, ElementLikeList, Parsable, Templates
class Puppygirl[R: Renderer]:
renderer: R
elements: list[Renderable]
templates: Templates
def __init__(self, renderer: R, elements: list[Callable[[Self], Renderable]] = [], templates: ElementLikeList = []):
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[ElementLike]) -> Templates:
templates = [Template(t) for t in templates]
return {t[IdAttr]: t for t in templates}
def add_template(self, template: ElementLike):
template = Template(template)
self._templates[template[IdAttr]] = template
def fetch(self, path: str) -> BeautifulSoup:
with open(path, "r") as f:
return self.parse(f)
def parse(self, value: Parsable) -> BeautifulSoup:
if isinstance(value, BeautifulSoup) or isinstance(value, Tag):
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)