Source code for flexlate.render.multi

import os
import shutil
from pathlib import Path
from typing import Final, List, Sequence

from flexlate.exc import InvalidTemplateClassException, RendererNotFoundException
from flexlate.render.renderable import Renderable
from flexlate.render.specific.base import SpecificTemplateRenderer
from flexlate.render.specific.cookiecutter import CookiecutterRenderer
from flexlate.render.specific.copier import CopierRenderer
from flexlate.temp_path import create_temp_path
from flexlate.template.base import Template
from flexlate.template.types import TemplateType
from flexlate.template_data import TemplateData

renderers: Final[List[SpecificTemplateRenderer]] = [
    CookiecutterRenderer(),
    CopierRenderer(),
]


[docs]class MultiRenderer: # TODO: register method to add user-defined template types
[docs] def render( self, renderables: Sequence[Renderable], project_root: Path = Path("."), no_input: bool = False, ) -> List[TemplateData]: out_data: List[TemplateData] = [] with create_temp_path() as temp_root: temp_folders: List[Path] = [] for i, renderable in enumerate(renderables): template = renderable.template renderer = _get_specific_renderer(template) temp_folder = temp_root / f"{i + 1}-{template.name}" / project_root.name temp_folders.append(temp_folder) if renderable.out_root.is_absolute(): relative_root = Path( os.path.relpath(renderable.out_root, project_root.absolute()) ) else: relative_root = renderable.out_root new_root = temp_folder / relative_root temp_renderable = renderable.copy(update=dict(out_root=new_root)) renderable_no_input = no_input or temp_renderable.skip_prompts template_data = renderer.render( temp_renderable, no_input=renderable_no_input ) out_data.append(template_data) _merge_file_trees(temp_folders, project_root) return out_data
[docs] def render_string( self, string: str, renderable: Renderable, ) -> str: template = renderable.template renderer = _get_specific_renderer(template) return renderer.render_string(string, renderable)
def _get_specific_renderer(template: Template) -> SpecificTemplateRenderer: if template._type == TemplateType.BASE: raise InvalidTemplateClassException( f"No renderer for template type base, did you remember to override _type when defining the template type? {template}" ) for renderer in renderers: if renderer._template_type == template._type: return renderer raise RendererNotFoundException(f"No registered renderer for template {template}") def _merge_file_trees(dirs: Sequence[Path], out_dir: Path): for directory in dirs: _copy_files_to_directory(directory, out_dir) def _copy_files_to_directory(dir: Path, out_dir: Path): for root, folders, files in os.walk(dir): in_folder = Path(root) relative_path = in_folder.relative_to(dir) out_folder = out_dir / relative_path if not out_folder.exists(): out_folder.mkdir() for file in files: in_path = in_folder / file out_path = out_folder / file if out_path.exists(): content = in_path.read_text() with open(out_path, mode="a") as f: f.write(content) else: shutil.copy(in_path, out_path)