This commit is contained in:
Rowan 2025-10-07 17:31:32 -04:00
parent f9b01181e2
commit 1b03a74478
4 changed files with 33 additions and 18 deletions

View file

@ -3,6 +3,7 @@
from argparse import ArgumentParser from argparse import ArgumentParser
from puppygirl import Puppygirl from puppygirl import Puppygirl
from puppygirl.elements.domme import PuppygirlDomme from puppygirl.elements.domme import PuppygirlDomme
from puppygirl.elements import Node
from puppygirl.renderer import ClientSideRenderer, ServerSideRenderer from puppygirl.renderer import ClientSideRenderer, ServerSideRenderer
parser = ArgumentParser("puppygirl", add_help=True) parser = ArgumentParser("puppygirl", add_help=True)
@ -24,7 +25,7 @@ def main():
renderer = ServerSideRenderer() renderer = ServerSideRenderer()
pg = Puppygirl(renderer=renderer, elements=[PuppygirlDomme]) pg = Puppygirl(renderer=renderer, elements=[PuppygirlDomme])
html = pg.fetch(args.input) html = pg.parse(Node.from_path(args.input))
if args.pretty: if args.pretty:
html = html.prettify() html = html.prettify()

View file

@ -3,11 +3,11 @@ from dataclasses import dataclass
from enum import StrEnum from enum import StrEnum
from typing import TYPE_CHECKING, Optional, Self from typing import TYPE_CHECKING, Optional, Self
from bs4 import Tag from bs4 import BeautifulSoup, Tag
from ..clonable import Clonable from ..clonable import Clonable
if TYPE_CHECKING: if TYPE_CHECKING:
from ..puppytype import ElementLike from ..puppytype import Parsable
TemplateName = "template" TemplateName = "template"
@ -32,7 +32,11 @@ class Node(Clonable):
serializable=serializable serializable=serializable
) )
def from_element(element: "ElementLike") -> Self: def from_path(path: str) -> Self:
with open(path, "r") as f:
return Node(BeautifulSoup(f.read(), 'html.parser'))
def from_element(element: "Parsable") -> Self:
if isinstance(element, Node): if isinstance(element, Node):
return element return element
return Node(element) return Node(element)
@ -88,7 +92,11 @@ class Template(Clonable):
def serializable(self, value: bool): def serializable(self, value: bool):
self._value["serializable"] = value self._value["serializable"] = value
def from_element(element: "ElementLike") -> Self: def from_path(path: str) -> Self:
with open(path, "r") as f:
return Template(BeautifulSoup(f.read(), 'html.parser'))
def from_element(element: "Parsable") -> Self:
if isinstance(element, Template): if isinstance(element, Template):
return element return element
return Template(element) return Template(element)

View file

@ -1,16 +1,16 @@
from typing import Callable, Iterable, Self from typing import Callable, Iterable, Self
from bs4 import BeautifulSoup, Tag from bs4 import BeautifulSoup, Tag
from .elements import IdAttr, Template from .elements import IdAttr, Template, Node
from .renderer import Renderable, Renderer from .renderer import Renderable, Renderer
from .puppytype import ElementLike, ElementLikeList, Parsable, Templates from .puppytype import Parsable, ParsableIterable, Parsable, Templates
class Puppygirl[R: Renderer]: class Puppygirl[R: Renderer]:
renderer: R renderer: R
elements: list[Renderable] elements: list[Renderable]
templates: Templates templates: Templates
def __init__(self, renderer: R, elements: list[Callable[[Self], Renderable]] = [], templates: ElementLikeList = []): def __init__(self, renderer: R, elements: list[Callable[[Self], Renderable]] = [], templates: ParsableIterable = []):
self.renderer = renderer self.renderer = renderer
self.templates = Puppygirl._create_template_dict(templates) self.templates = Puppygirl._create_template_dict(templates)
self.elements = [self._instantiate(el) for el in elements] self.elements = [self._instantiate(el) for el in elements]
@ -20,20 +20,25 @@ class Puppygirl[R: Renderer]:
return value(self) return value(self)
return value return value
def _create_template_dict(templates: Iterable[ElementLike]) -> Templates: def _create_template_dict(templates: Iterable[Parsable]) -> Templates:
templates = [Template.from_element(t) for t in templates] templates = [Template.from_element(t) for t in templates]
return {t[IdAttr]: t for t in templates} return {t[IdAttr]: t for t in templates}
def add_template(self, template: ElementLike): def add_template(self, template: Parsable):
template = Template.from_element(template) template = Template.from_element(template)
self._templates[template[IdAttr]] = template self._templates[template[IdAttr]] = template
def fetch(self, path: str) -> BeautifulSoup: def _is_parsed(value: Parsable) -> bool:
with open(path, "r") as f: return isinstance(value, BeautifulSoup) or \
return self.parse(f) isinstance(value, Tag) or \
isinstance(value, Node) or \
isinstance(value, Template)
def parse(self, value: Parsable) -> BeautifulSoup: def parse(self, value: Parsable) -> BeautifulSoup:
if isinstance(value, BeautifulSoup) or isinstance(value, Tag): if value is None:
return BeautifulSoup()
if Puppygirl._is_parsed(value):
return self.parse_tree(value) return self.parse_tree(value)
return self.parse_tree(BeautifulSoup(value, features='html.parser')) return self.parse_tree(BeautifulSoup(value, features='html.parser'))

View file

@ -1,12 +1,13 @@
from typing import BinaryIO, Iterable, TextIO, TypeAlias, TYPE_CHECKING from typing import IO, Iterable, TypeAlias, TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from string import Template from string import Template
from bs4 import BeautifulSoup, Tag from bs4 import BeautifulSoup, Tag
from .elements import Node from .elements import Node
Parsable: TypeAlias = "BeautifulSoup | Tag | str | bytes | TextIO | BinaryIO" Markup: TypeAlias = str | bytes | IO[str] | IO[bytes]
ElementLike: TypeAlias = "BeautifulSoup | Tag | str | Node | Template" ParsedMarkup: TypeAlias = "BeautifulSoup | Tag | Node | Template"
ElementLikeList: TypeAlias = "Iterable[ElementLike]" Parsable: TypeAlias = Markup | ParsedMarkup
ParsableIterable: TypeAlias = "Iterable[Parsable]"
RenderableElement: TypeAlias = "Node | Iterable[Node]" RenderableElement: TypeAlias = "Node | Iterable[Node]"
Templates: TypeAlias = "dict[str, Template]" Templates: TypeAlias = "dict[str, Template]"