feature: create zip, fixes #9

This commit is contained in:
Matthias Jung
2026-02-22 23:49:45 +01:00
parent 0ffd0a3c24
commit 3596ce80d4
2 changed files with 43 additions and 0 deletions
+5
View File
@@ -23,6 +23,7 @@ def main(
output: Annotated[str | None, typer.Option("--output", "-o", help="Destination directory to build to.")] = None, output: Annotated[str | None, typer.Option("--output", "-o", help="Destination directory to build to.")] = None,
render_editions: Annotated[bool, typer.Option(help="Skip building editions.")] = True, render_editions: Annotated[bool, typer.Option(help="Skip building editions.")] = True,
render_solutions: Annotated[bool, typer.Option(help="Skip building solutions.")] = True, render_solutions: Annotated[bool, typer.Option(help="Skip building solutions.")] = True,
build_zip: Annotated[bool, typer.Option(help="Whether to build a zip file of the output.")] = False,
) -> None: ) -> None:
conf = config.Config(content_path=input, build_path=output) conf = config.Config(content_path=input, build_path=output)
bd = build.Build(conf) bd = build.Build(conf)
@@ -42,6 +43,10 @@ def main(
# Copy assets to build folder # Copy assets to build folder
bd.build_assets() bd.build_assets()
if build_zip:
# Build zip file of output
bd.build_zip()
if __name__ == "__main__": if __name__ == "__main__":
app() app()
+38
View File
@@ -1,7 +1,9 @@
import json import json
import os
import random import random
import re import re
import shutil import shutil
import zipfile
from pathlib import Path from pathlib import Path
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
@@ -515,3 +517,39 @@ class Build:
page = solution_template.render(question=question, solution=solution, number=solution_file.stem) page = solution_template.render(question=question, solution=solution, number=solution_file.stem)
page = self.__build_page(page, course_wrapper=False) page = self.__build_page(page, course_wrapper=False)
file.write(page) file.write(page)
def build_zip(self, zip_name: str | None = None) -> Path:
"""Create a zip archive of the complete build output directory.
The zip file is written into the build directory itself and is excluded
from the archive contents.
"""
build_dir = self.config.p_build
build_dir.mkdir(parents=True, exist_ok=True)
zip_path = build_dir / (zip_name if zip_name is not None else f"{build_dir.name}.zip")
zip_path = zip_path.resolve()
# If a previous archive exists, remove it first to avoid zipping stale data.
if zip_path.exists():
zip_path.unlink()
tqdm.write(f"Creating zip archive: {zip_path}")
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
# os.walk includes dotfiles; sort for stable archives.
for root, dirs, files in os.walk(build_dir):
dirs.sort()
files.sort()
root_path = Path(root)
for filename in files:
file_path = (root_path / filename).resolve()
if file_path == zip_path:
continue
arcname = file_path.relative_to(build_dir.resolve())
zf.write(file_path, arcname=arcname)
return zip_path