import logging
from typing import Dict
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo
import yaml
from .scheduler import Scheduler
from .renderer import JinjaRenderer
from todays_paper_web.storage import Storage
from todays_paper_web.widgets import DataSource, View, ImageType
_LOGGER = logging.getLogger(__name__)
[docs]
class Generator:
def __init__(self, name: str, storage: Storage):
self._config: Dict = yaml.safe_load(storage.getConfig(name)) or {}
self._debugging = False
self._name = name
self._scheduler = None
self._sources = {}
self._storage: Storage = storage
self._timezone = ZoneInfo(
self._config.get("settings", {}).get("timezone", "UTC")
)
self._timestamp = datetime.now(self._timezone)
for name, config in self._config.get("sources", {}).items():
self._sources[name] = DataSource.get(
config.get("source"), config.get("params", {})
)
@property
def timezone(self) -> ZoneInfo:
return self._timezone
@property
def debugging(self) -> bool:
return self._debugging
@debugging.setter
def debugging(self, debugging) -> None:
self._debugging = debugging
[docs]
def getCurrentScreen(self) -> tuple[datetime, str, datetime]:
if not self._scheduler:
self._scheduler = Scheduler(
self._config.get("scheduler", {}), self._timezone
)
return self._scheduler.getCurrentScreen()
[docs]
def getNextScreen(self, skip: int = 0) -> tuple[datetime, str]:
if not self._scheduler:
self._scheduler = Scheduler(
self._config.get("scheduler", {}), self._timezone
)
return self._scheduler.getNextScreen(skip)
[docs]
def renderScreen(self, screenName: str) -> ImageType:
screens = self._config.get("screens", {})
width = screens.get("width", 0)
height = screens.get("height", 0)
if not width or not height:
_LOGGER.error("Screen size is not defined")
return None
config = screens.get(screenName)
if not config:
_LOGGER.error("Could not find screen %s", screenName)
return None
renderer = JinjaRenderer(config, self._sources, self._storage, self._name)
renderer.debugging = self.debugging
tree = renderer.render(width, height, self._timestamp)
if not tree:
_LOGGER.error("Could not render screen %s", screenName)
return None
view = View.get(
"screen",
None,
tree.attrib | {"width": width, "height": height},
self._storage,
self._name,
)
view.element = tree
img = view.render()
rotate = screens.get("rotate", 0)
if rotate:
img = img.rotate(rotate, expand=True)
return img
[docs]
def setTimestamp(self, timestamp: datetime) -> None:
self._timestamp = timestamp
for _, source in self._sources.items():
source.timestamp = timestamp