Skip to content

Comic

MetadataFormat

Bases: Enum

An enumeration of supported metadata formats for comic books.

This enum defines the different metadata formats that can be stored within comic book archives. Each format has specific characteristics and use cases.

ATTRIBUTE DESCRIPTION
METRON_INFO

MetronInfo format - A comprehensive metadata format that includes detailed bibliographic information and is designed for library and collection management systems.

COMIC_INFO

ComicInfo format - The standard metadata format used by ComicRack and other comic reading applications.

UNKNOWN

Unknown or unsupported metadata format.

Examples:

Python Console Session
>>> fmt = MetadataFormat.COMIC_INFO
>>> print(fmt)  # Output: ComicInfo
>>> comic = Comic(Path("example.cbz"))
>>> comic.has_metadata(MetadataFormat.METRON_INFO)

Functions

__str__() -> str

Return a human-readable string representation of the metadata format.

RETURNS DESCRIPTION
str

A capitalized string representation (e.g., "ComicInfo", "MetronInfo").

TYPE: str

Examples:

Python Console Session
>>> str(MetadataFormat.COMIC_INFO)
'ComicInfo'

ComicError

Bases: Exception

Base exception for all comic-related errors.

This is the parent class for all exceptions raised by the Comic class and related functionality. Use this for general exception handling.

ComicArchiveError

Bases: ComicError

Exception raised when there are issues with the comic archive file.

This exception is raised when:

  • The comic file doesn't exist
  • The archive is corrupted or unreadable
  • Archive format is not supported
  • File system permissions prevent access

ComicMetadataError

Bases: ComicError

Exception raised when there are issues with comic metadata operations.

This exception is raised when:

  • Metadata format is not supported
  • Metadata parsing fails
  • Metadata validation errors occur

Comic(path: Path | str)

A comprehensive comic book archive handler with metadata support.

The Comic class provides a high-level interface for working with comic book archives in CBZ (ZIP) CBR (RAR), CBT (TAR) and CB7 (7ZIP) formats. It supports reading and writing metadata in ComicInfo and MetronInfo formats, page manipulation, and archive validation.

Key Features
  • Support for CBZ/ZIP, CBR/RAR, CBT/TAR, and CB7/7ZIP (optional) comic archives
  • Read/write ComicInfo and MetronInfo metadata
  • Page extraction and manipulation
  • Archive validation and format detection
  • Metadata validation with schema version detection
  • Export capabilities (e.g., CBR to CBZ conversion / CBT to CBZ conversion)
Thread Safety

This class is not thread-safe. Each thread should use its own Comic instance.

Performance Considerations
  • Page lists and metadata are cached after first access
  • Large archives may consume significant memory when processing all pages
  • RAR archives are read-only due to library limitations

Examples:

Basic usage:

Python Console Session
>>> from pathlib import Path
>>> comic = Comic(Path("my_comic.cbz"))
>>>
>>> # Check if it's a valid comic
>>> if comic.is_valid_comic():
...     print(f"Comic '{comic.name}' has {comic.get_number_of_pages()} pages")
>>>
>>> # Read metadata
>>> if comic.has_metadata(MetadataFormat.COMIC_INFO):
...     metadata = comic.read_metadata(MetadataFormat.COMIC_INFO)
...     print(f"Series: {metadata.series.name}")
>>>
>>> # Get a page
>>> page_data = comic.get_page(0)  # First page
>>> if page_data:
...     with open("cover.jpg", "wb") as f:
...         f.write(page_data)
ATTRIBUTE DESCRIPTION
path

The file system path to the comic archive.

TYPE: Path

name

The filename of the comic archive.

TYPE: str

size

The size of the comic archive in bytes.

TYPE: int

Initialize a Comic object with the provided path.

PARAMETER DESCRIPTION
path

The file system path to the comic archive. Can be a string or Path object. The file must exist and be a valid ZIP or RAR archive.

TYPE: Path | str

RAISES DESCRIPTION
ComicArchiveError

If the path doesn't exist, isn't accessible, or can't be opened as a valid archive format.

Examples:

Python Console Session
>>> comic = Comic("my_comic.cbz")
>>> comic_ = Comic(Path("/path/to/comic.cbr"))
>>> print(comic.name)
>>> print(comic_.name)

Attributes

name: str property

Get the filename of the comic archive.

RETURNS DESCRIPTION
str

The filename without the directory path.

TYPE: str

path: Path property

Get the file system path of the comic archive.

RETURNS DESCRIPTION
Path

The path to the comic archive file.

TYPE: Path

size: int property

Get the size of the comic archive file in bytes.

RETURNS DESCRIPTION
int

The file size in bytes.

TYPE: int

RAISES DESCRIPTION
OSError

If the file cannot be accessed or doesn't exist.

Functions

__eq__(other: object) -> bool

Check if two Comic objects are equal based on their file paths.

PARAMETER DESCRIPTION
other

Another object to compare with.

TYPE: object

RETURNS DESCRIPTION
bool

True if both objects are Comic instances with the same path.

TYPE: bool

__hash__() -> int

Make Comic objects hashable based on their file path.

RETURNS DESCRIPTION
int

Hash value based on the file path.

TYPE: int

Note

This allows Comic objects to be used in sets and as dictionary keys.

__repr__() -> str

Return a detailed string representation of the Comic object.

RETURNS DESCRIPTION
str

A string representation showing the path and page count.

TYPE: str

Examples:

Python Console Session
>>> comic = Comic(Path("example.cbz"))
>>> repr(comic)
"Comic(path=PosixPath('/comics/example.cbz'), pages=24)"

__str__() -> str

Return the name of the comic file.

RETURNS DESCRIPTION
str

The filename of the comic archive.

TYPE: str

export_as_zip(zip_filename: Path) -> bool

Export the comic archive to CBZ (ZIP) format.

Converts RAR/CBR, CBT, or CB7 archives to ZIP/CBZ format. Returns True immediately if already ZIP. Preserves all pages, metadata, and directory structure.

PARAMETER DESCRIPTION
zip_filename

Path where the ZIP archive will be created (overwrites if exists).

TYPE: Path

RETURNS DESCRIPTION
bool

True if successful or already ZIP, False if failed.

TYPE: bool

Note

Large archives may require significant time and disk space for conversion.

get_metadata_formats() -> set[MetadataFormat]

Return the set of metadata formats present in the archive.

RETURNS DESCRIPTION
set[MetadataFormat]

A set of MetadataFormat enums representing the available metadata.

get_number_of_pages() -> int

Get the total number of pages (images) in the archive.

RETURNS DESCRIPTION
int

The number of image files in the archive.

TYPE: int

Note

This count includes only supported image formats and excludes hidden files. The result is cached for performance.

get_page(index: int) -> bytes | None

Retrieve the raw image data for a specific page.

PARAMETER DESCRIPTION
index

The 0-based index of the page to retrieve.

TYPE: int

RETURNS DESCRIPTION
bytes | None

bytes | None: The raw image data of the page, or None if the page cannot be retrieved (invalid index or read error).

Examples:

Python Console Session
>>> comic = Comic(Path("example.cbz"))
>>> page_data = comic.get_page(0)  # Get first page
>>> if page_data:
...     with open("page_1.jpg", "wb") as f:
...         f.write(page_data)
Note

The returned data is the raw image file content and can be written directly to a file or processed with image libraries like PIL.

get_page_name(index: int) -> str | None

Get the filename of a page by its index.

PARAMETER DESCRIPTION
index

The 0-based index of the page.

TYPE: int

RETURNS DESCRIPTION
str | None

str | None: The filename of the page within the archive, or None if the index is invalid or out of range.

Examples:

Python Console Session
>>> comic = Comic(Path("example.cbz"))
>>> filename = comic.get_page_name(0)
>>> print(filename)  # Output: "page_01.jpg"

get_page_name_list(sort_list: bool = True) -> list[str]

Get a list of all page filenames in the archive.

PARAMETER DESCRIPTION
sort_list

Whether to sort the list using natural sorting. Default is True.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
list[str]

list[str]: A list of page filenames, filtered to include only image files.

Note
  • Only image files are included in the list
  • Hidden files (starting with '.') are excluded
  • Natural sorting ensures proper ordering (e.g., page10.jpg comes after page2.jpg)
  • Results are cached for performance

has_metadata(fmt: MetadataFormat) -> bool

Check if the archive contains metadata in the specified format.

Performs case-insensitive search for metadata files. Results are cached.

PARAMETER DESCRIPTION
fmt

Metadata format to check (COMIC_INFO or METRON_INFO).

TYPE: MetadataFormat

RETURNS DESCRIPTION
bool

True if metadata exists, False otherwise.

TYPE: bool

is_archive_valid() -> bool

Test whether the archive file is valid and readable.

This method performs a comprehensive check to determine if the archive can be opened and read as either a ZIP or RAR file.

RETURNS DESCRIPTION
bool

True if the archive is valid and readable, False otherwise.

TYPE: bool

Note

This method is more thorough than just checking file extensions, as it actually attempts to open and validate the archive structure.

is_image(name_path: Path) -> bool staticmethod

Check if a file is a supported image format.

PARAMETER DESCRIPTION
name_path

The path to check (can be filename or full path).

TYPE: Path

RETURNS DESCRIPTION
bool

True if the file has a supported image extension and isn't a hidden file (doesn't start with '.').

TYPE: bool

Note

Supported formats: .jpg, .jpeg, .png, .gif, .webp Hidden files (starting with '.') are excluded.

is_valid_comic() -> bool

Perform comprehensive validation of the comic archive.

Checks file existence, archive validity, and comic content (at least one image).

RETURNS DESCRIPTION
bool

True if valid comic archive, False otherwise.

TYPE: bool

is_writable() -> bool

Check if the archive supports write operations.

RETURNS DESCRIPTION
bool

True if the archive can be modified, False otherwise.

TYPE: bool

Note

RAR archives are typically read-only due to library limitations. ZIP archives can be written to if the file system permissions allow it.

read_metadata(metadata_format: MetadataFormat) -> Metadata

Read metadata from the archive in the specified format.

PARAMETER DESCRIPTION
metadata_format

The format of metadata to read (COMIC_INFO or METRON_INFO).

TYPE: MetadataFormat

RETURNS DESCRIPTION
Metadata

The parsed metadata object, or an empty Metadata instance if the format is not recognized or parsing fails.

TYPE: Metadata

Examples:

Python Console Session
>>> comic = Comic(Path("example.cbz"))
>>> if comic.has_metadata(MetadataFormat.COMIC_INFO):
...     metadata = comic.read_metadata(MetadataFormat.COMIC_INFO)
...     print(f"Series: {metadata.series.name}")
...     print(f"Issue: {metadata.issue}")
Note
  • The result is cached after first read
  • Page list validation is performed to ensure consistency
  • Returns empty Metadata object if format is unsupported

read_raw_ci_metadata() -> str | None

Read raw ComicInfo metadata XML from the archive.

RETURNS DESCRIPTION
str | None

str | None: The raw ComicInfo XML as a string, or None if not found.

Note

This method returns the raw XML content without any parsing or validation. Use read_metadata() for parsed metadata objects.

read_raw_mi_metadata() -> str | None

Read raw MetronInfo metadata XML from the archive.

RETURNS DESCRIPTION
str | None

str | None: The raw MetronInfo XML as a string, or None if not found.

Note

This method returns the raw XML content without any parsing or validation. Use read_metadata() for parsed metadata objects.

remove_metadata(metadata_format_list: list[MetadataFormat]) -> bool

Remove metadata from the comic archive.

PARAMETER DESCRIPTION
metadata_format_list

A list of metadata formats to remove.

TYPE: list[MetadataFormat]

RETURNS DESCRIPTION
bool

True if any metadata was successfully removed or didn't exist, False if an error occurred.

TYPE: bool

Examples:

Python Console Session
>>> comic = Comic(Path("example.cbz"))
>>> success = comic.remove_metadata([MetadataFormat.COMIC_INFO])
>>> if success:
...     print("ComicInfo metadata removed")
Note
  • If the metadata doesn't exist, this method returns True
  • The archive must be writable
  • All metadata files matching the format are removed (case-insensitive)

remove_pages(pages_index: list[int]) -> bool

Remove pages from the comic archive by their indices (0-based).

This is a destructive operation that cannot be undone. Metadata caches are invalidated after successful removal.

PARAMETER DESCRIPTION
pages_index

List of zero-based page indices to remove.

TYPE: list[int]

RETURNS DESCRIPTION
bool

True if successful, False if failed.

TYPE: bool

RAISES DESCRIPTION
ValueError

If any page index is negative or out of range.

seems_to_be_a_comic_archive() -> bool

Determine if the file appears to be a comic book archive.

A file is considered a comic archive if it meets the following criteria:

  1. It's a supported archive based on it's extension
  2. It contains at least one image file
RETURNS DESCRIPTION
bool

True if the file appears to be a comic archive, False otherwise.

TYPE: bool

Note

This is a heuristic check and may not catch all edge cases. Use is_valid_comic() for a more comprehensive validation.

validate_metadata(metadata_format: MetadataFormat) -> SchemaVersion

Validate metadata XML and return its schema version.

PARAMETER DESCRIPTION
metadata_format

Format to validate (COMIC_INFO or METRON_INFO).

TYPE: MetadataFormat

RETURNS DESCRIPTION
SchemaVersion

Detected schema version, or SchemaVersion.Unknown if invalid/not found.

TYPE: SchemaVersion

write_metadata(metadata: Metadata, metadata_format: MetadataFormat) -> bool

Write metadata to the comic archive in the specified format.

PARAMETER DESCRIPTION
metadata

Metadata object to write.

TYPE: Metadata

metadata_format

Format to use: - COMIC_INFO: ComicRack reader standard format - METRON_INFO: A new comic book metadata format

TYPE: MetadataFormat

Returns: bool: True if successful, False if failed (read-only archive, I/O errors).

RAISES DESCRIPTION
ComicMetadataError

If metadata format is not supported.

Note

ComicInfo writes include page size calculations (slower for large archives). MetronInfo writes skip page calculations (faster).

Examples:

Python Console Session
>>> comic = Comic("example.cbz")
>>> metadata = Metadata()
>>> metadata.series = "Amazing Spider-Man"
>>> comic.write_metadata(metadata, MetadataFormat.COMIC_INFO)