Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.11
rev: v0.14.13
hooks:
- id: ruff-format
- id: ruff-check
Expand Down
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ File will be created on first run.
```toml
[output]
folder = "~/.local/share/perdoo"
format = "cbz"

[output.comic_info]
create = true
Expand Down Expand Up @@ -184,10 +183,6 @@ password = "<Metron Password>"
The folder where the output files will be stored.
Defaults to `~/.local/share/perdoo`.

- `output.format`
The output file format for the comic archives.
Defaults to `cbz`.

- `output.comic_info.create`
Whether to create a ComicInfo.xml file in the output archive.
Defaults to `true`.
Expand Down
31 changes: 14 additions & 17 deletions perdoo/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@

from perdoo import __version__, get_cache_root, setup_logging
from perdoo.cli import archive_app, settings_app
from perdoo.comic import SUPPORTED_IMAGE_EXTENSIONS, Comic, ComicArchiveError, ComicMetadataError
from perdoo.comic import Comic
from perdoo.comic.errors import ComicArchiveError, ComicMetadataError
from perdoo.comic.metadata import ComicInfo, MetronInfo
from perdoo.comic.metadata.comic_info import Page
from perdoo.comic.metadata.metron_info import Id, InformationSource
from perdoo.console import CONSOLE
from perdoo.metadata import ComicInfo, MetronInfo
from perdoo.metadata.comic_info import Page
from perdoo.metadata.metron_info import Id, InformationSource
from perdoo.services import BaseService, Comicvine, Metron
from perdoo.settings import Service, Services, Settings
from perdoo.utils import (
Expand Down Expand Up @@ -74,7 +75,7 @@ def _load_comics(target: Path) -> list[Comic]:
files = list_files(target) if target.is_dir() else [target]
for file in files:
try:
comics.append(Comic(file=file))
comics.append(Comic(filepath=file))
except (ComicArchiveError, ComicMetadataError) as err: # noqa: PERF203
LOGGER.error("Failed to load '%s' as a Comic: %s", file, err)
return comics
Expand Down Expand Up @@ -132,13 +133,12 @@ def get_search_details(
def load_page_info(entry: Comic, comic_info: ComicInfo) -> list[Page]:
from PIL import Image # noqa: PLC0415

from perdoo.metadata.comic_info import PageType # noqa: PLC0415
from perdoo.comic import IMAGE_EXTENSIONS # noqa: PLC0415
from perdoo.comic.metadata.comic_info import PageType # noqa: PLC0415

pages = set()
image_files = [
x
for x in entry.archive.get_filename_list()
if Path(x).suffix.lower() in SUPPORTED_IMAGE_EXTENSIONS
x for x in entry.archive.list_filenames() if Path(x).suffix.lower() in IMAGE_EXTENSIONS
]
for idx, file in enumerate(image_files):
page = next((x for x in comic_info.pages if x.image == idx), None)
Expand Down Expand Up @@ -169,7 +169,6 @@ def sync_metadata(
) -> tuple[MetronInfo | None, ComicInfo | None]:
for service_name in settings.services.order:
if service := services.get(service_name):
LOGGER.info("Searching %s for matching issue", type(service).__name__)
metron_info, comic_info = service.fetch(search=search)
if metron_info or comic_info:
return metron_info, comic_info
Expand Down Expand Up @@ -252,21 +251,19 @@ def run(
comics = _load_comics(target=target)
for index, entry in enumerate(comics):
CONSOLE.rule(
f"[{index + 1}/{len(comics)}] Importing {entry.path.name}",
f"[{index + 1}/{len(comics)}] Importing {entry.filepath.name}",
align="left",
style="subtitle",
)
if not skip_convert:
with CONSOLE.status(
f"Converting to '{settings.output.format}'", spinner="simpleDotsScrolling"
):
entry.convert(extension=settings.output.format)
with CONSOLE.status("Converting to '.cbz'", spinner="simpleDotsScrolling"):
entry.convert_to(extension="cbz")

metadata: tuple[MetronInfo | None, ComicInfo | None] = (entry.metron_info, entry.comic_info)

if sync != SyncOption.SKIP:
search = get_search_details(metadata=metadata, filename=entry.path.stem)
search.filename = entry.path.stem
search = get_search_details(metadata=metadata, filename=entry.filepath.stem)
search.filename = entry.filepath.stem
last_modified = date(1900, 1, 1)
if sync == SyncOption.OUTDATED:
metron_info, _ = metadata
Expand Down
4 changes: 2 additions & 2 deletions perdoo/cli/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def view(
bool, Option("--hide-metron-info", help="Don't show the MetronInfo details.")
] = False,
) -> None:
comic = Comic(file=target)
CONSOLE.print(f"Archive format: '{comic.path.suffix}'")
comic = Comic(filepath=target)
CONSOLE.print(f"Archive format: '{comic.filepath.suffix}'")
if not hide_metron_info:
if not comic.metron_info:
CONSOLE.print("No MetronInfo found")
Expand Down
198 changes: 0 additions & 198 deletions perdoo/comic.py

This file was deleted.

3 changes: 3 additions & 0 deletions perdoo/comic/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__all__ = ["IMAGE_EXTENSIONS", "Comic"]

from perdoo.comic.comic import IMAGE_EXTENSIONS, Comic
7 changes: 7 additions & 0 deletions perdoo/comic/archive/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__all__ = ["Archive", "CB7Archive", "CBRArchive", "CBTArchive", "CBZArchive"]

from perdoo.comic.archive._base import Archive
from perdoo.comic.archive.rar import CBRArchive
from perdoo.comic.archive.sevenzip import CB7Archive
from perdoo.comic.archive.tar import CBTArchive
from perdoo.comic.archive.zip import CBZArchive
67 changes: 67 additions & 0 deletions perdoo/comic/archive/_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
__all__ = ["Archive"]

from abc import ABC, abstractmethod
from pathlib import Path
from typing import ClassVar

from perdoo.comic.errors import ComicArchiveError

try:
from typing import Self # Python >= 3.11
except ImportError:
from typing_extensions import Self # Python < 3.11


class Archive(ABC):
_registry: ClassVar[list[type["Archive"]]] = []
EXTENSION: ClassVar[str] = ""

def __init__(self, filepath: Path) -> None:
self._filepath = filepath

def __init_subclass__(cls, **kwargs) -> None: # noqa: ANN003
super().__init_subclass__(**kwargs)
Archive._registry.append(cls)

@property
def filepath(self) -> Path:
return self._filepath

@classmethod
def load(cls, filepath: Path) -> Self:
for _cls in cls._registry:
if _cls.is_archive(filepath):
return _cls(filepath=filepath)
raise ComicArchiveError(f"Unsupported archive format: {filepath.suffix.lower()}")

@classmethod
@abstractmethod
def is_archive(cls, path: Path) -> bool: ...

@abstractmethod
def list_filenames(self) -> list[str]: ...

def exists(self, filename: str) -> bool:
return filename in self.list_filenames()

@abstractmethod
def read_file(self, filename: str) -> bytes: ...

def write_file(self, filename: str, data: str | bytes) -> None: # noqa: ARG002
raise ComicArchiveError(f"Unable to write {filename} to {self.filepath.name}.")

def remove_file(self, filename: str) -> None:
raise ComicArchiveError(f"Unable to delete {filename} in {self.filepath.name}.")

@abstractmethod
def extract_files(self, destination: Path) -> None: ...

@classmethod
def archive_files(cls, src: Path, output_name: str, files: list[Path]) -> Self: # noqa: ARG003
raise ComicArchiveError(f"Unable to archive files to {output_name}.")

@classmethod
def convert_from(cls, old_archive: "Archive") -> Self:
raise ComicArchiveError(
f"Unable to convert {old_archive.filepath.name} to a {cls.EXTENSION}"
)
Loading
Loading