Source code for plbuilder.builder

from pathlib import Path
from typing import Sequence, List, Optional, Union
import importlib.util
import os
import sys

from pydantic import BaseModel
from pyexlatex.logic.output.api.formats import OutputFormats
from pyexlatex.models.document import DocumentBase

from plbuilder.paths import (
    SLIDES_SOURCE_PATH,
    slides_source_path,
    DOCUMENTS_SOURCE_PATH,
    documents_source_path,
    templates_path_func,
)
from plbuilder.templater import output_template

sys.path.append(
    os.path.abspath(os.getcwd())
)  # needed to be able to import local plbuild directory

IGNORED_FILES = [
    "__init__.py",
]


[docs]class BuildOptions(BaseModel): output_folder: Path file_name: str output_format: OutputFormats = OutputFormats.PDF handouts_folder: Optional[Path] = None
[docs]class BuildConfig(BaseModel): model: DocumentBase options: BuildOptions
[docs] class Config: arbitrary_types_allowed = True
[docs]def get_all_source_files() -> List[str]: slide_sources = [ file for file in next(os.walk(SLIDES_SOURCE_PATH))[2] if file not in IGNORED_FILES ] slide_sources = [slides_source_path(file) for file in slide_sources] doc_sources = [ file for file in next(os.walk(DOCUMENTS_SOURCE_PATH))[2] if file not in IGNORED_FILES ] doc_sources = [documents_source_path(file) for file in doc_sources] return slide_sources + doc_sources
[docs]def build_all(desired_output_format: Optional[OutputFormats] = None): files = get_all_source_files() [ build_by_file_path(file, desired_output_format=desired_output_format) for file in files ]
[docs]def build_by_file_path( file_path: str, desired_output_format: Optional[OutputFormats] = None ): _print_now(f"Building {file_path}") mod = _module_from_file(file_path) configs: List[BuildConfig] = mod.get_outputs() # type: ignore for config in configs: if desired_output_format is not None: # Override file setting if user passes setting in CLI config.options.output_format = desired_output_format _build_by_config(config) _print_now(f"Done creating {config.options.file_name}.")
def _build_by_config(config: BuildConfig): if not os.path.exists(config.options.output_folder): os.makedirs(config.options.output_folder) _output_document( config.model, str(config.options.output_folder), config.options.file_name, output_format=config.options.output_format, ) def _output_document( doc: DocumentBase, outfolder: str, out_name: str, output_format: OutputFormats = OutputFormats.PDF, ): if output_format == OutputFormats.PDF: out_method = getattr(doc, "to_pdf") elif output_format == OutputFormats.HTML: out_method = getattr(doc, "to_html") else: raise ValueError(f"unsupported output format {output_format}") out_method(outfolder, out_name) def _module_from_file(file_path: str): mod_name = os.path.basename(file_path).strip(".py") return _module_from_file_and_name(file_path, mod_name) def _module_from_file_and_name(file_path: str, module_name: str): spec = importlib.util.spec_from_file_location(module_name, file_path) if spec is None: raise ValueError(f"could not extract spec from {file_path} {module_name}") mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) # type: ignore return mod def _print_now(*args): print(*args) sys.stdout.flush() if __name__ == "__main__": build_all()