90 lines
3.6 KiB
Python
90 lines
3.6 KiB
Python
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."
|
|
)
|
|
)
|