Source code for lookatme.output.base

"""
Base module for lookatme output formats
"""


import os
import shutil
from typing import Any, Dict, Optional, Type


import lookatme.config as config
from lookatme.pres import Presentation
import lookatme.templating as templating


THIS_DIR = os.path.realpath(os.path.dirname(__file__))
TEMPLATE_DIR = os.path.join(THIS_DIR, "templates")
DEFINED_TYPES: Dict[str, Type["BaseOutputFormat"]] = {}


[docs]class OutputOptionError(ValueError): pass
[docs]class MissingExtraDependencyError(Exception): pass
[docs]class BaseOutputFormatMeta(type): def __new__(cls, subclass_name, bases, attrs): res = super().__new__(cls, subclass_name, bases, attrs) res_name = getattr(res, "NAME", None) if res_name is not None: DEFINED_TYPES[res_name] = res # type: ignore return res
[docs]class BaseOutputFormat(metaclass=BaseOutputFormatMeta): NAME = None DEFAULT_OPTIONS = {} REQUIRED_BINARIES = [] def __init__(self): self._curr_options = None self.log = config.get_log().getChild(f"Output[{self.NAME}]")
[docs] def format_pres(self, pres: Presentation, output_path: str, options: Dict): """Perform the action of outputting the presentation to this specific output format. """ for required_bin in self.REQUIRED_BINARIES: if not shutil.which(required_bin): raise RuntimeError( ( f"Could not convert to {self.NAME} format, " f"required binary {required_bin!r} not found" ) ) self.log.info(f"Converting presentation to {self.NAME} format") self._curr_options = options self.do_format_pres(pres, output_path) self.log.info(f" Results in {output_path}")
[docs] def render_template(self, template_name: str, context: Dict[str, Any]) -> str: template_path = os.path.join(TEMPLATE_DIR, template_name) return templating.render(template_path, context)
[docs] def do_format_pres(self, pres: Presentation, output_path: str): """Perform the action of outputting the presentation to this specific output format. """ raise NotImplementedError("do_format_pres is not implemented")
[docs] def opt(self, option_name: str, category: Optional[str] = None): """Fetch the oiption named ``option_name``. If the category isn't specified, the current formatter's options are used. This function also ensures the defaults are used if the key doesn't already exist in the provided options dict. """ opts = self._curr_options or {} category = category or self.NAME full_option = f"{category}.{option_name}" try: if full_option not in opts: if category in (None, self.NAME): return self.DEFAULT_OPTIONS[option_name] return opts[full_option] except KeyError: raise OutputOptionError( f"Option {option_name} ({full_option!r}) does not exist" )