Merge pull request 'Merge/create epub into main' (#2) from merge/create-epub-into-main into main

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-08-06 18:26:05 -03:00
7 changed files with 184 additions and 0 deletions
+1
View File
@@ -136,6 +136,7 @@ venv/
ENV/
env.bak/
venv.bak/
.tmp-samples/
# Spyder project settings
.spyderproject
+6
View File
@@ -10,3 +10,9 @@
[submodule "src/vendor/epub2tts-kokoro"]
path = src/vendor/epub2tts-kokoro
url = https://github.com/aedocw/epub2tts-kokoro
[submodule "src/vendor/epub3-samples"]
path = src/vendor/epub3-samples
url = https://github.com/IDPF/epub3-samples
[submodule "src/vendor/sample-epub-minimal"]
path = src/vendor/sample-epub-minimal
url = https://github.com/thansen0/sample-epub-minimal
+12
View File
@@ -18,6 +18,18 @@ Recent Python (>=3.11), pip (>=22.3), some sort of virtula environment recommend
3. Test install running `epub-tts --version`
- Make sure the venv is activated or that pip installed the package in your PATH
# Sample EPUB download
After cloning with submodules, the repository now includes the EPUB 3 sample collection under `src/vendor/epub3-samples`.
Use the new console entrypoints to export the Moby Dick samples as EPUB files:
- `download-moby-dick` creates `.tmp-samples/moby-dick.epub`
- `download-moby-dick-media-overlays` creates `.tmp-samples/moby-dick-mo.epub`
- `download-epub-minimal` creates `.tmp-samples/minimal.epub`
The staging directory `.tmp-samples/` is included in `.gitignore` so generated artifacts stay out of version control.
#
# Citation
+3
View File
@@ -41,6 +41,9 @@ Issues = "https://git.silveirarosa.com/renatoxsr/epub-tts/issues"
[project.scripts]
epub-tts = "epub_tts.__main__:main"
download-moby-dick = "epub_tts.sample_download:main"
download-moby-dick-media-overlays = "epub_tts.sample_download:main_with_media_overlay"
download-epub-minimal = "epub_tts.sample_download:main_minimal_epub"
# SETUPTOOLS
[tool.setuptools.packages.find]
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2025-2026 Renato Xavier da Silveira Rosa
# See [LICENSE](./LICENSE) or [BSD-3-Clause-Clear](https://spdx.org/licenses/BSD-3-Clause-Clear.html)
"""Download EPUB sample files from a vendored samples repository and package them as EPUB archives."""
from __future__ import annotations
import argparse
import shutil
import zipfile
from pathlib import Path
from typing import Optional
from epub_tts.vendor_utils import get_repo_path
def get_project_root() -> Path:
return Path(__file__).resolve().parents[1].parent
def get_temp_sample_root() -> Path:
return get_project_root() / ".tmp-samples"
def get_sample_directory(with_media_overlay: bool) -> Path:
sample_name = "moby-dick-mo" if with_media_overlay else "moby-dick"
sample_dir = get_repo_path("epub3-samples") / "30" / sample_name
if not sample_dir.exists():
raise FileNotFoundError(
f"Sample directory not found: {sample_dir}. Ensure the epub3-samples submodule is initialized."
)
return sample_dir
def get_minimal_sample_file() -> Path:
sample_file = get_repo_path("sample-epub-minimal") / "minimal.epub"
if not sample_file.exists():
raise FileNotFoundError(
f"Sample EPUB file not found: {sample_file}. Ensure the sample-epub-minimal submodule is initialized."
)
return sample_file
def copy_sample_to_temp(sample_dir: Path) -> Path:
temp_root = get_temp_sample_root()
temp_root.mkdir(parents=True, exist_ok=True)
dest_dir = temp_root / sample_dir.name
if dest_dir.exists():
shutil.rmtree(dest_dir)
shutil.copytree(sample_dir, dest_dir)
return dest_dir
def copy_file_to_temp(sample_file: Path) -> Path:
temp_root = get_temp_sample_root()
temp_root.mkdir(parents=True, exist_ok=True)
dest_file = temp_root / sample_file.name
shutil.copy2(sample_file, dest_file)
return dest_file
def zip_sample_directory(sample_dir: Path, output_path: Path) -> Path:
output_path.parent.mkdir(parents=True, exist_ok=True)
if output_path.exists():
output_path.unlink()
mimetype_file = sample_dir / "mimetype"
with zipfile.ZipFile(output_path, mode="w", compression=zipfile.ZIP_DEFLATED) as archive:
if mimetype_file.exists():
archive.write(mimetype_file, "mimetype", compress_type=zipfile.ZIP_STORED)
for path in sorted(sample_dir.rglob("*")):
if path.is_file() and path != mimetype_file:
archive.write(path, path.relative_to(sample_dir).as_posix())
return output_path
def download_sample_moby_dick(
output: Optional[str] = None,
with_media_overlay: bool = False,
) -> Path:
sample_dir = get_sample_directory(with_media_overlay=with_media_overlay)
temp_sample_dir = copy_sample_to_temp(sample_dir)
default_output = get_temp_sample_root() / f"{sample_dir.name}.epub"
output_path = Path(output) if output else default_output
output_path = output_path.with_suffix(".epub")
return zip_sample_directory(temp_sample_dir, output_path)
def download_minimal_epub_sample(output: Optional[str] = None) -> Path:
sample_file = get_minimal_sample_file()
temp_sample_file = copy_file_to_temp(sample_file)
default_output = get_temp_sample_root() / sample_file.name
output_path = Path(output) if output else default_output
output_path = output_path.with_suffix(".epub")
if temp_sample_file != output_path:
output_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(temp_sample_file, output_path)
return output_path
def main(argv: Optional[list[str]] = None) -> int:
parser = argparse.ArgumentParser(
description="Download the Moby Dick EPUB sample and package it as an EPUB file."
)
parser.add_argument(
"-o",
"--output",
help="Output EPUB file path. Defaults to .tmp-samples/moby-dick.epub or .tmp-samples/moby-dick-mo.epub.",
)
args = parser.parse_args(argv)
output_path = download_sample_moby_dick(
output=args.output,
with_media_overlay=False,
)
print(f"Created EPUB sample archive: {output_path}")
return 0
def main_with_media_overlay(argv: Optional[list[str]] = None) -> int:
parser = argparse.ArgumentParser(
description=(
"Download the Moby Dick EPUB sample with media overlay and package it as an EPUB file."
)
)
parser.add_argument(
"-o",
"--output",
help="Output EPUB file path. Defaults to .tmp-samples/moby-dick-mo.epub.",
)
args = parser.parse_args(argv)
output_path = download_sample_moby_dick(
output=args.output,
with_media_overlay=True,
)
print(f"Created EPUB sample archive: {output_path}")
return 0
def main_minimal_epub(argv: Optional[list[str]] = None) -> int:
parser = argparse.ArgumentParser(
description=(
"Download the minimal EPUB sample and copy it to an EPUB file."
)
)
parser.add_argument(
"-o",
"--output",
help="Output EPUB file path. Defaults to .tmp-samples/minimal.epub.",
)
args = parser.parse_args(argv)
output_path = download_minimal_epub_sample(output=args.output)
print(f"Created minimal EPUB sample archive: {output_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Vendored Submodule
+1