diff --git a/README.md b/README.md index c3a8a3c..4182b42 100644 --- a/README.md +++ b/README.md @@ -74,13 +74,13 @@ Unlike other tagging tools, Perdoo employs a manual approach when metadata files - .cbr - .cbt - .cbz -- .cb7 _(Requires installing `cb7` dependencies: `pipx install perdoo[cb7]`)_ +- .cb7 ### Output Extensions - .cbt - .cbz _(Default)_ -- .cb7 _(Requires installing `cb7` dependencies: `pipx install perdoo[cb7]`)_ +- .cb7 ### Metadata Files diff --git a/perdoo/archives/__init__.py b/perdoo/archives/__init__.py index f697b1a..46e8cc2 100644 --- a/perdoo/archives/__init__.py +++ b/perdoo/archives/__init__.py @@ -12,6 +12,7 @@ from tarfile import is_tarfile from zipfile import is_zipfile +from py7zr import is_7zfile from rarfile import is_rarfile from perdoo.archives._base import BaseArchive @@ -20,13 +21,6 @@ from perdoo.archives.cbt import CBTArchive from perdoo.archives.cbz import CBZArchive -try: - from py7zr import is_7zfile - - py7zr_loaded = True -except ImportError: - py7zr_loaded = False - def get_archive(path: Path) -> BaseArchive: if is_zipfile(path): @@ -35,15 +29,17 @@ def get_archive(path: Path) -> BaseArchive: return CBRArchive(path=path) if is_tarfile(path): return CBTArchive(path=path) - if py7zr_loaded and is_7zfile: + if is_7zfile(path): return CB7Archive(path=path) raise NotImplementedError(f"{path.name} is an unsupported archive") def get_archive_class(extension: str) -> type[BaseArchive]: - archive_types = {"cbz": CBZArchive, "cbr": CBRArchive, "cbt": CBTArchive} - if extension == "cb7" and py7zr_loaded: - return CB7Archive - if extension in archive_types: - return archive_types[extension] + if archive_class := { + "cbz": CBZArchive, + "cbr": CBRArchive, + "cbt": CBTArchive, + "cb7": CB7Archive, + }.get(extension): + return archive_class raise NotImplementedError(f"{extension} is an unsupported archive") diff --git a/perdoo/archives/cb7.py b/perdoo/archives/cb7.py index b1a7dc8..ec1570b 100644 --- a/perdoo/archives/cb7.py +++ b/perdoo/archives/cb7.py @@ -6,70 +6,54 @@ from tempfile import TemporaryDirectory from typing import Optional +from py7zr import Bad7zFile, SevenZipFile + from perdoo.archives._base import BaseArchive from perdoo.utils import list_files -try: - import py7zr - - py7zr_loaded = True -except ImportError: - py7zr_loaded = False - LOGGER = logging.getLogger(__name__) class CB7Archive(BaseArchive): - def __init__(self, path: Path): - if not py7zr_loaded: - raise ImportError("Install Perdoo with the cb7 dependency group to use CB7 files.") - super().__init__(path=path) - def list_filenames(self) -> list[str]: try: - with py7zr.SevenZipFile(self.path, "r") as archive: + with SevenZipFile(self.path, "r") as archive: return archive.getnames() - except py7zr.Bad7zFile: + except Bad7zFile: LOGGER.exception("Unable to read %s", self.path.name) return [] def read_file(self, filename: str) -> bytes: try: - with py7zr.SevenZipFile(self.path, "r") as archive, archive.open(filename) as file: + with SevenZipFile(self.path, "r") as archive, archive.open(filename) as file: return file.read() - except (py7zr.Bad7zFile, KeyError): + except (Bad7zFile, KeyError): LOGGER.exception("Unable to read %s", self.path.name) return b"" def extract_files(self, destination: Path) -> bool: try: - with py7zr.SevenZipFile(self.path, "r") as archive: + with SevenZipFile(self.path, "r") as archive: archive.extractall(path=destination) return True - except py7zr.Bad7zFile: + except Bad7zFile: LOGGER.exception("") return False @classmethod def archive_files(cls, src: Path, output_name: str, files: list[Path]) -> Path | None: - if not py7zr_loaded: - raise ImportError("Install Perdoo with the cb7 dependency group to use CB7 files.") - output_file = src.parent / f"{output_name}.cb7" try: - with py7zr.SevenZipFile(output_file, "w") as archive: + with SevenZipFile(output_file, "w") as archive: for file in files: archive.write(file, arcname=file.name) return output_file - except py7zr.Bad7zFile: + except Bad7zFile: LOGGER.exception("") return None @staticmethod def convert(old_archive: BaseArchive) -> Optional["CB7Archive"]: - if not py7zr_loaded: - raise ImportError("Install Perdoo with the cb7 dependency group to use CB7 files.") - with TemporaryDirectory(prefix=f"{old_archive.path.stem}_") as temp_str: temp_folder = Path(temp_str) if not old_archive.extract_files(destination=temp_folder): diff --git a/perdoo/settings.py b/perdoo/settings.py index a34fea3..d2270ab 100644 --- a/perdoo/settings.py +++ b/perdoo/settings.py @@ -12,12 +12,11 @@ ] from enum import Enum -from importlib.util import find_spec from pathlib import Path from typing import Any, ClassVar, Literal import tomli_w as tomlwriter -from pydantic import BaseModel, field_validator +from pydantic import BaseModel from rich.panel import Panel from perdoo import get_config_root, get_data_root @@ -59,12 +58,6 @@ class Output(SettingsModel): format: Literal["cb7", "cbt", "cbz"] = "cbz" metadata: Metadata = Metadata() - @field_validator("format", mode="before") - def validate_format(cls, value: str) -> str: - if value == "cb7" and find_spec("py7zr") is None: - raise ImportError("Install Perdoo with the cb7 dependency group to use CB7 files.") - return value - class Comicvine(SettingsModel): api_key: str | None = None @@ -80,21 +73,11 @@ class Metron(SettingsModel): username: str | None = None -class Service(Enum): +class Service(str, Enum): COMICVINE = "Comicvine" MARVEL = "Marvel" METRON = "Metron" - @staticmethod - def load(value: str) -> "Service": - for entry in Service: - if entry.value.replace(" ", "").casefold() == value.replace(" ", "").casefold(): - return entry - raise ValueError(f"'{value}' isn't a valid Service") - - def __str__(self) -> str: - return self.value - class Services(SettingsModel): comicvine: Comicvine = Comicvine() diff --git a/pyproject.toml b/pyproject.toml index cebf1d6..46945cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ dependencies = [ "mokkari >= 3.5.0", "natsort >= 8.4.0", "pillow >= 11.0.0", + "py7zr >= 0.22.0", "pydantic >= 2.10.4", "pydantic-xml >= 2.14.1", "rarfile >= 4.2", @@ -57,11 +58,6 @@ name = "perdoo" readme = "README.md" requires-python = ">= 3.10" -[project.optional-dependencies] -cb7 = [ - "py7zr >= 0.22.0" -] - [project.scripts] Perdoo = "perdoo.__main__:app"