from functools import wraps from pathlib import Path from re import compile from subprocess import run from typing import Callable, Dict, Iterable, List, Mapping, ParamSpec, Tuple, TypeVar WORKDIR = Path.cwd() PROJECT_DIR = Path(__file__).resolve().absolute().parent.relative_to(WORKDIR) OUTPUT_FILE = PROJECT_DIR / "Lecture.pdf" idRegex = compile(r"^(\d+)\..+$") def get_id(file: Path): matches = idRegex.search(file.name) if matches is None: print(f"WARNING: File '{file.name}' hasn't got an id in the filename!") return None return int(matches.group(1)) def not_output_file(file: Path): global OUTPUT_FILE return file != OUTPUT_FILE T = TypeVar("T") Params = ParamSpec("Params") def get_sequential(f: Callable[Params, Mapping[int, T]]) -> Callable[Params, List[T]]: @wraps(f) def wrapper(*args: Params.args, **kwargs: Params.kwargs): items = f(*args, **kwargs) def get_or_raise(i: int): item = items.get(i) if item is None: raise Exception(f"Expected Item with index {i}, but it was not found!") return item return list(map(get_or_raise, range(len(items)))) return wrapper def only_unique_ids(f: Callable[Params, Iterable[Tuple[int, T]]]) -> Callable[Params, Dict[int, T]]: @wraps(f) def wrapper(*args: Params.args, **kwargs: Params.kwargs): items: Dict[int, T] = dict() for uid, pdf in f(*args, **kwargs): existing = items.get(uid) if existing is not None: raise ValueError(f"Got item '{pdf}' with id {uid}, but '{existing}' already has that id!") items[uid] = pdf return items return wrapper @get_sequential @only_unique_ids def get_files(path: Path): global OUTPUT_FILE files = path.rglob("*.pdf") for file in files: if file == OUTPUT_FILE: continue number = get_id(file) if number is None: continue yield number, file def main(): pdfs = get_files(PROJECT_DIR) for pdf in pdfs: print(f"Adding file {pdf.name}") cmd = ["pdftk"] cmd.extend(map(str, pdfs)) cmd.append("cat") cmd.append("output") cmd.append(str(OUTPUT_FILE)) run(cmd) if __name__ == "__main__": main()