Artifex/control_plane/authoring/management/commands/story_sources.py

91 lines
3.6 KiB
Python
Raw Normal View History

from __future__ import annotations
from pathlib import Path
from django.core.management.base import BaseCommand, CommandError
from control_plane.authoring.models import (
DocumentAuthority,
DocumentType,
Series,
Work,
WorkType,
)
from control_plane.authoring.sources import discover_source_paths, inspect_source, register_source
class Command(BaseCommand):
help = "Register immutable, authority-labelled story source documents and passages."
def add_arguments(self, parser) -> None:
parser.add_argument("action", choices=["register"])
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--series-slug", required=True)
parser.add_argument("--series-title", required=True)
parser.add_argument("--work-slug", required=True)
parser.add_argument("--work-title", required=True)
parser.add_argument("--work-type", choices=WorkType.values, default=WorkType.BOOK)
parser.add_argument("--authority", choices=DocumentAuthority.values, required=True)
parser.add_argument(
"--document-type", choices=DocumentType.values, default=DocumentType.OTHER
)
parser.add_argument("--include-glob", action="append", default=[])
parser.add_argument("--dry-run", action="store_true")
def handle(self, *args, **options) -> None:
root: Path = options["root"]
if not root.exists():
raise CommandError(f"source root does not exist: {root}")
paths = discover_source_paths(root, options["include_glob"])
if not paths:
raise CommandError(f"no supported UTF-8 source files found under {root}")
if options["dry_run"]:
for path in paths:
result = inspect_source(path, root)
self.stdout.write(
f"DRY-RUN {result.logical_key} sha256={result.source_sha256} "
f"passages={result.passage_count} authority={options['authority']}"
)
self.stdout.write(
self.style.SUCCESS(f"Discovered {len(paths)} source files; no changes made.")
)
return
series, _ = Series.objects.get_or_create(
slug=options["series_slug"], defaults={"title": options["series_title"]}
)
work, _ = Work.objects.get_or_create(
series=series,
slug=options["work_slug"],
defaults={
"title": options["work_title"],
"work_type": options["work_type"],
},
)
counts = {"created": 0, "versioned": 0, "unchanged": 0}
for path in paths:
try:
result = register_source(
work=work,
path=path,
root=root,
authority=options["authority"],
document_type=options["document_type"],
)
except UnicodeDecodeError as exc:
raise CommandError(f"source is not valid UTF-8: {path}") from exc
except ValueError as exc:
raise CommandError(str(exc)) from exc
counts[result.status] += 1
self.stdout.write(
f"{result.status.upper()} {result.logical_key} v{result.version} "
f"passages={result.passage_count}"
)
self.stdout.write(
self.style.SUCCESS(
f"Registered {len(paths)} files: {counts['created']} created, "
f"{counts['versioned']} versioned, {counts['unchanged']} unchanged."
)
)