-
WriteResult — Per-file outcome of a write.
-
BulkWriteItem — One unit of work for
bulk_write.
comicbox.write¶
source module comicbox.write
Public write API: single-file write_metadata and batch bulk_write.
Wraps the existing Comicbox(...).dump() plumbing with a documented, Codex-facing surface:
merge_mode:"additive"/"update"/"replace"— picks the merge strategy applied to the patch dict against the comic’s existing metadata.None(the default) defers to the config’swrite.merge_mode, itselfadditiveunless a config file or--merge-modesays otherwise. See :class:comicbox.config.settings.MergeMode.formats: which on-archive formats to write back (ComicInfo.xml, comicbox.yaml, …). Names match theMetadataFormatsenum value.delete_keys: glom key paths removed from the final metadata before writing. Merging can only add or replace — an empty patch value is pruned by the schema, so this is the only way a write can clear an existing field.dry_run: return the would-be-written payload instead of touching the archive.
bulk_write orchestrates the same call over many files via a process- global ThreadPoolExecutor (writes are I/O bound — full archive repack per CBZ). A module-level semaphore caps concurrent writes so a big batch can’t starve other disk traffic.
Classes
Functions
-
write_metadata — Write metadata to one comic archive.
-
bulk_write — Write metadata to many files in parallel.
source class WriteResult()
Per-file outcome of a write.
source class BulkWriteItem()
One unit of work for bulk_write.
source write_metadata(path: Path, patch: Mapping[str, Any], *, merge_mode: Mode | None = None, formats: Iterable[FormatName] | None = None, delete_keys: Iterable[str] | None = None, dry_run: bool = False, base_config: ComicboxSettings | None = None) → WriteResult
Write metadata to one comic archive.
patch is a comicbox-shaped dict — either the contents under the "comicbox" root tag, or the root-wrapped form Comicbox.to_dict returns ({"comicbox": {...}}); the wrapper is detected and unwrapped so the natural round-trip works.
merge_mode selects how the patch overlays the comic’s existing tags: "additive" (dicts recurse, lists concatenate), "replace" (dicts recurse, lists overwrite) or "update" (top level keys replaced wholesale, siblings of a patched key dropped). None defers to the config’s write.merge_mode; an explicit value always wins. See :class:comicbox.config.settings.MergeMode.
delete_keys are glom key paths (relative to the root tag, e.g. "summary" or "series.name") removed from the final merged metadata before serialization — the only way a write can clear an existing field, since empty patch values are pruned on schema load and merging never removes. They are layered onto the config’s general.delete_keys; unknown keys are ignored. The patch may be empty when delete_keys is non-empty (a pure-clear write).
With dry_run=True no archive is touched; the result’s dry_run_payload carries the serialized would-be-written content per requested format (keyed by format name).
Raises
source bulk_write(items: Iterable[BulkWriteItem], *, workers: int | None = None, on_event: EventHandler | None = None, stop_on_error: bool = False, cancel: threading.Event | None = None, base_config: ComicboxSettings | None = None, preflight: bool = True) → Generator[WriteResult, None, None]
Write metadata to many files in parallel.
Returns an iterator that MUST be drained: writes are submitted in a bounded window as results are consumed, so discarding the iterator without iterating performs no writes. Input handling, the BatchStarted event, and pool creation happen eagerly at call time. Abandoning the iterator midway never blocks: queued writes are cancelled and in-flight ones finish in their worker threads.
Yields :class:WriteResult per file in completion order, not submission order. Caller may pass a cancel :class:threading.Event; once set, no new writes start: in-flight writes run to completion and every queued file is reported with cancelled=True. With stop_on_error=True the first failed write trips the same cancellation (an internal event is created if the caller didn’t pass one). on_event receives the shared :class:comicbox.events stream (BatchStarted / FileParsed / FileError / BatchFinished); cancelled files emit no per-file event.
preflight (default on) sniffs every destination before any archive is written, on the first next() rather than at call time. It refuses a batch’s collisions up front – a destination already on disk, and two archives converging on one name – so a batch fails fast instead of repacking an archive and refusing it at the end, and the loser of an in-batch collision is decided by submission order rather than by thread race. It also fails an unreadable or unsupported file here, with the sniff’s own error. preflight=False restores the pre-5.2.0 behavior. The write path’s own destination claim stays either way, as the backstop for concurrent callers: two bulk_write calls in one process see each other only through it.