Turn comicapi.archivers.* into plugins

This commit is contained in:
Timmy Welch 2022-08-17 15:53:19 -07:00
parent 2f7e3921ef
commit 712986ee69
No known key found for this signature in database
17 changed files with 237 additions and 235 deletions

View File

@ -1,19 +1,15 @@
from __future__ import annotations
from comicapi.archivers.unknown import UnknownArchiver
__all__ = ["UnknownArchiver"]
from comicapi.archivers.archiver import Archiver
from comicapi.archivers.folder import FolderArchiver
from comicapi.archivers.rar import RarArchiver, rar_support
from comicapi.archivers.sevenzip import SevenZipArchiver, z7_support
from comicapi.archivers.rar import RarArchiver
from comicapi.archivers.sevenzip import SevenZipArchiver
from comicapi.archivers.zip import ZipArchiver
__all__ = [
"UnknownArchiver",
"FolderArchiver",
"RarArchiver",
"rar_support",
"ZipArchiver",
"SevenZipArchiver",
"z7_support",
]
class UnknownArchiver(Archiver):
def name(self) -> str:
return "Unknown"
__all__ = ["Archiver", "UnknownArchiver", "FolderArchiver", "RarArchiver", "ZipArchiver", "SevenZipArchiver"]

View File

@ -0,0 +1,62 @@
from __future__ import annotations
import pathlib
from typing import Protocol, runtime_checkable
@runtime_checkable
class Archiver(Protocol):
"""Archiver Protocol"""
path: pathlib.Path
enabled: bool = True
def __init__(self):
self.path = pathlib.Path()
def get_comment(self) -> str:
return ""
def set_comment(self, comment: str) -> bool:
return False
def supports_comment(self) -> bool:
return False
def read_file(self, archive_file: str) -> bytes:
raise NotImplementedError
def remove_file(self, archive_file: str) -> bool:
return False
def write_file(self, archive_file: str, data: bytes) -> bool:
return False
def get_filename_list(self) -> list[str]:
return []
def rebuild(self, exclude_list: list[str]) -> bool:
return False
def copy_from_archive(self, other_archive: Archiver) -> bool:
return False
def is_writable(self) -> bool:
return False
def extension(self) -> str:
return ""
def name(self) -> str:
return ""
@classmethod
def is_valid(cls, path: pathlib.Path) -> bool:
return False
@classmethod
def open(cls, path: pathlib.Path) -> Archiver:
archiver = cls()
archiver.path = path
return archiver

View File

@ -4,17 +4,17 @@ import logging
import os
import pathlib
from comicapi.archivers import UnknownArchiver
from comicapi.archivers import Archiver
logger = logging.getLogger(__name__)
class FolderArchiver(UnknownArchiver):
class FolderArchiver(Archiver):
"""Folder implementation"""
def __init__(self, path: pathlib.Path | str) -> None:
super().__init__(path)
def __init__(self) -> None:
super().__init__()
self.comment_file_name = "ComicTaggerFolderComment.txt"
def get_comment(self) -> str:
@ -70,7 +70,7 @@ class FolderArchiver(UnknownArchiver):
logger.error("Error listing files in folder archive [%s]: %s", e, self.path)
return []
def copy_from_archive(self, other_archive: UnknownArchiver) -> bool:
def copy_from_archive(self, other_archive: Archiver) -> bool:
"""Replace the current zip with one copied from another archive"""
try:
for filename in other_archive.get_filename_list():
@ -88,3 +88,10 @@ class FolderArchiver(UnknownArchiver):
return False
else:
return True
def name(self) -> str:
return "Folder"
@classmethod
def is_valid(cls, path: pathlib.Path | str) -> bool:
return os.path.isdir(path)

View File

@ -9,7 +9,7 @@ import subprocess
import tempfile
import time
from comicapi.archivers import UnknownArchiver
from comicapi.archivers import Archiver
try:
from unrar.cffi import rarfile
@ -25,11 +25,13 @@ if not rar_support:
logger.error("unrar-cffi unavailable")
class RarArchiver(UnknownArchiver):
class RarArchiver(Archiver):
"""RAR implementation"""
def __init__(self, path: pathlib.Path | str, rar_exe_path: str = "rar") -> None:
super().__init__(path)
enabled = rar_support
def __init__(self, rar_exe_path: str = "rar") -> None:
super().__init__()
self.rar_exe_path = shutil.which(rar_exe_path) or ""
# windows only, keeps the cmd.exe from popping up
@ -199,7 +201,7 @@ class RarArchiver(UnknownArchiver):
return namelist
return []
def copy_from_archive(self, other_archive: UnknownArchiver) -> bool:
def copy_from_archive(self, other_archive: Archiver) -> bool:
"""Replace the current archive with one copied from another archive"""
try:
with tempfile.TemporaryDirectory() as tmp_dir:
@ -234,6 +236,21 @@ class RarArchiver(UnknownArchiver):
else:
return True
def is_writable(self) -> bool:
return bool(self.rar_exe_path and os.path.exists(self.rar_exe_path))
def extension(self) -> str:
return ".cbr"
def name(self) -> str:
return "RAR"
@classmethod
def is_valid(cls, path: pathlib.Path | str) -> bool:
if rar_support:
return rarfile.is_rarfile(str(path))
return False
def get_rar_obj(self) -> rarfile.RarFile | None:
if rar_support:
try:

View File

@ -6,7 +6,7 @@ import pathlib
import shutil
import tempfile
from comicapi.archivers import UnknownArchiver
from comicapi.archivers import Archiver
try:
import py7zr
@ -18,12 +18,13 @@ except ImportError:
logger = logging.getLogger(__name__)
class SevenZipArchiver(UnknownArchiver):
class SevenZipArchiver(Archiver):
"""7Z implementation"""
def __init__(self, path: pathlib.Path | str) -> None:
super().__init__(path)
enabled = z7_support
def __init__(self) -> None:
super().__init__()
# @todo: Implement Comment?
def get_comment(self) -> str:
@ -100,7 +101,7 @@ class SevenZipArchiver(UnknownArchiver):
return False
return True
def copy_from_archive(self, other_archive: UnknownArchiver) -> bool:
def copy_from_archive(self, other_archive: Archiver) -> bool:
"""Replace the current zip with one copied from another archive"""
try:
with py7zr.SevenZipFile(self.path, "w") as zout:
@ -115,3 +116,16 @@ class SevenZipArchiver(UnknownArchiver):
return False
else:
return True
def is_writable(self) -> bool:
return True
def extension(self) -> str:
return ".cb7"
def name(self) -> str:
return "Seven Zip"
@classmethod
def is_valid(cls, path: pathlib.Path | str) -> bool:
return py7zr.is_7zfile(path)

View File

@ -1,35 +0,0 @@
from __future__ import annotations
import pathlib
class UnknownArchiver:
"""Unknown implementation"""
def __init__(self, path: pathlib.Path | str) -> None:
self.path = pathlib.Path(path)
def get_comment(self) -> str:
return ""
def set_comment(self, comment: str) -> bool:
return False
def read_file(self, archive_file: str) -> bytes:
raise NotImplementedError
def remove_file(self, archive_file: str) -> bool:
return False
def write_file(self, archive_file: str, data: bytes) -> bool:
return False
def get_filename_list(self) -> list[str]:
return []
def rebuild(self, exclude_list: list[str]) -> bool:
return False
def copy_from_archive(self, other_archive: UnknownArchiver) -> bool:
return False

View File

@ -9,17 +9,17 @@ import tempfile
import zipfile
from typing import cast
from comicapi.archivers import UnknownArchiver
from comicapi.archivers import Archiver
logger = logging.getLogger(__name__)
class ZipArchiver(UnknownArchiver):
class ZipArchiver(Archiver):
"""ZIP implementation"""
def __init__(self, path: pathlib.Path | str) -> None:
super().__init__(path)
def __init__(self) -> None:
super().__init__()
def get_comment(self) -> str:
with zipfile.ZipFile(self.path, "r") as zf:
@ -99,7 +99,7 @@ class ZipArchiver(UnknownArchiver):
return False
return True
def copy_from_archive(self, other_archive: UnknownArchiver) -> bool:
def copy_from_archive(self, other_archive: Archiver) -> bool:
"""Replace the current zip with one copied from another archive"""
try:
with zipfile.ZipFile(self.path, mode="w", allowZip64=True) as zout:
@ -119,6 +119,19 @@ class ZipArchiver(UnknownArchiver):
else:
return True
def is_writable(self) -> bool:
return True
def extension(self) -> str:
return ".cbz"
def name(self) -> str:
return "ZIP"
@classmethod
def is_valid(cls, path: pathlib.Path | str) -> bool:
return zipfile.is_zipfile(path)
def write_zip_comment(self, filename: pathlib.Path | str, comment: str) -> bool:
"""
This is a custom function for writing a comment to a zip file,

View File

@ -19,31 +19,23 @@ import logging
import os
import pathlib
import shutil
import zipfile
import sys
from typing import cast
import natsort
import wordninja
from comicapi import filenamelexer, filenameparser, utils
from comicapi.archivers import FolderArchiver, RarArchiver, SevenZipArchiver, UnknownArchiver, ZipArchiver
from comicapi.archivers import Archiver, UnknownArchiver, ZipArchiver
from comicapi.comet import CoMet
from comicapi.comicbookinfo import ComicBookInfo
from comicapi.comicinfoxml import ComicInfoXml
from comicapi.genericmetadata import GenericMetadata, PageType
try:
import py7zr
z7_support = True
except ImportError:
z7_support = False
try:
from unrar.cffi import rarfile
rar_support = True
except ImportError:
rar_support = False
if sys.version_info < (3, 10):
from importlib_metadata import entry_points
else:
from importlib.metadata import entry_points
try:
from PIL import Image
@ -52,12 +44,26 @@ try:
except ImportError:
pil_available = False
logger = logging.getLogger(__name__)
if not pil_available:
logger.error("PIL unavalable")
archivers: list[type[Archiver]] = []
def load_archive_plugins() -> None:
for arch in entry_points(group="comicapi_archivers"):
try:
archiver: type[Archiver] = arch.load()
if archiver.enabled:
if not arch.module.startswith("comicapi"):
archivers.insert(0, archiver)
else:
archivers.append(archiver)
except Exception:
logger.warning("Failed to load talker: %s", arch.name)
class MetaDataStyle:
CBI = 0
@ -70,9 +76,6 @@ class MetaDataStyle:
class ComicArchive:
logo_data = b""
class ArchiveType:
SevenZip, Zip, Rar, Folder, Pdf, Unknown = list(range(6))
def __init__(
self,
path: pathlib.Path | str,
@ -96,36 +99,12 @@ class ComicArchive:
self.reset_cache()
self.default_image_path = default_image_path
# Use file extension to decide which archive test we do first
ext = self.path.suffix
self.archiver: Archiver = UnknownArchiver.open(self.path)
self.archive_type = self.ArchiveType.Unknown
self.archiver = UnknownArchiver(self.path)
if ext in [".cbr", ".rar"]:
if self.rar_test():
self.archive_type = self.ArchiveType.Rar
self.archiver = RarArchiver(self.path, rar_exe_path=self.rar_exe_path)
elif self.zip_test():
self.archive_type = self.ArchiveType.Zip
self.archiver = ZipArchiver(self.path)
else:
if self.sevenzip_test():
self.archive_type = self.ArchiveType.SevenZip
self.archiver = SevenZipArchiver(self.path)
elif self.zip_test():
self.archive_type = self.ArchiveType.Zip
self.archiver = ZipArchiver(self.path)
elif self.rar_test():
self.archive_type = self.ArchiveType.Rar
self.archiver = RarArchiver(self.path, rar_exe_path=self.rar_exe_path)
elif self.folder_test():
self.archive_type = self.ArchiveType.Folder
self.archiver = FolderArchiver(self.path)
for archiver in archivers:
if archiver.is_valid(self.path):
self.archiver = archiver.open(self.path)
break
if not ComicArchive.logo_data and self.default_image_path:
with open(self.default_image_path, mode="rb") as fd:
@ -157,63 +136,33 @@ class ComicArchive:
self.path = new_path
self.archiver.path = pathlib.Path(path)
def sevenzip_test(self) -> bool:
return z7_support and py7zr.is_7zfile(self.path)
def zip_test(self) -> bool:
return zipfile.is_zipfile(self.path)
def rar_test(self) -> bool:
return rar_support and rarfile.is_rarfile(str(self.path))
def folder_test(self) -> bool:
return self.path.is_dir()
def is_sevenzip(self) -> bool:
return self.archive_type == self.ArchiveType.SevenZip
def is_zip(self) -> bool:
return self.archive_type == self.ArchiveType.Zip
def is_rar(self) -> bool:
return self.archive_type == self.ArchiveType.Rar
def is_pdf(self) -> bool:
return self.archive_type == self.ArchiveType.Pdf
def is_folder(self) -> bool:
return self.archive_type == self.ArchiveType.Folder
def is_writable(self, check_rar_status: bool = True) -> bool:
if self.archive_type == self.ArchiveType.Unknown:
def is_writable(self, check_archive_status: bool = True) -> bool:
if isinstance(self.archiver, UnknownArchiver):
return False
if check_rar_status and self.is_rar() and not self.rar_exe_path:
if check_archive_status and not self.archiver.is_writable():
return False
if not os.access(self.path, os.W_OK):
return False
if (self.archive_type != self.ArchiveType.Folder) and (not os.access(self.path.parent, os.W_OK)):
if not (os.access(self.path, os.W_OK) or os.access(self.path.parent, os.W_OK)):
return False
return True
def is_writable_for_style(self, data_style: int) -> bool:
return not (data_style == MetaDataStyle.CBI and not self.archiver.supports_comment)
if (self.is_rar() or self.is_sevenzip()) and data_style == MetaDataStyle.CBI:
return False
return self.is_writable()
def is_zip(self) -> bool:
return self.archiver.name() == "ZIP"
def seems_to_be_a_comic_archive(self) -> bool:
if (self.is_zip() or self.is_rar() or self.is_sevenzip() or self.is_folder()) and (
self.get_number_of_pages() > 0
):
if not (isinstance(self.archiver, UnknownArchiver)) and self.get_number_of_pages() > 0:
return True
return False
def extension(self) -> str:
return self.archiver.extension()
def read_metadata(self, style: int) -> GenericMetadata:
if style == MetaDataStyle.CIX:
@ -334,7 +283,6 @@ class ComicArchive:
# seems like some archive creators are on Windows, and don't know about case-sensitivity!
if sort_list:
files = cast(list[str], natsort.os_sorted(files))
# make a sub-list of image files
@ -653,10 +601,10 @@ class ComicArchive:
return metadata
def export_as_zip(self, zip_filename: pathlib.Path | str) -> bool:
if self.archive_type == self.ArchiveType.Zip:
def export_as_zip(self, zip_filename: pathlib.Path) -> bool:
if self.archiver.name() == "ZIP":
# nothing to do, we're already a zip
return True
zip_archiver = ZipArchiver(zip_filename)
zip_archiver = ZipArchiver.open(zip_filename)
return zip_archiver.copy_from_archive(self.archiver)

View File

@ -217,14 +217,7 @@ class CLI:
if self.batch_mode:
brief = f"{ca.path}: "
if ca.is_sevenzip():
brief += "7Z archive "
elif ca.is_zip():
brief += "ZIP archive "
elif ca.is_rar():
brief += "RAR archive "
elif ca.is_folder():
brief += "Folder archive "
brief += ca.archiver.name() + " archive "
brief += f"({page_count: >3} pages)"
brief += " tags:[ "
@ -460,12 +453,7 @@ class CLI:
new_ext = "" # default
if self.options.filename_rename_set_extension_based_on_archive:
if ca.is_sevenzip():
new_ext = ".cb7"
elif ca.is_zip():
new_ext = ".cbz"
elif ca.is_rar():
new_ext = ".cbr"
new_ext = ca.extension()
renamer = FileRenamer(
md,

View File

@ -18,6 +18,7 @@ from __future__ import annotations
import argparse
import logging
import os
import pathlib
import platform
import settngs
@ -325,20 +326,23 @@ def validate_commandline_options(options: settngs.Config[settngs.Values], parser
else:
options[0].runtime_file_list = options[0].runtime_files
# take a crack at finding rar exe, if not set already
if options[0].general_rar_exe_path.strip() in ("", "rar"):
rar_path = pathlib.Path(options[0].general_rar_exe_path)
if rar_path.is_absolute() and rar_path.exists():
if rar_path.is_dir():
utils.add_to_path(str(rar_path))
else:
utils.add_to_path(str(rar_path.parent))
# take a crack at finding rar exe if it's not in the path
if not utils.which("rar"):
if platform.system() == "Windows":
# look in some likely places for Windows machines
if os.path.exists(r"C:\Program Files\WinRAR\Rar.exe"):
options[0].general_rar_exe_path = r"C:\Program Files\WinRAR\Rar.exe"
utils.add_to_path(r"C:\Program Files\WinRAR")
elif os.path.exists(r"C:\Program Files (x86)\WinRAR\Rar.exe"):
options[0].general_rar_exe_path = r"C:\Program Files (x86)\WinRAR\Rar.exe"
utils.add_to_path(r"C:\Program Files (x86)\WinRAR")
else:
if os.path.exists("/opt/homebrew/bin"):
utils.add_to_path("/opt/homebrew/bin")
# see if it's in the path of unix user
rarpath = utils.which("rar")
if rarpath is not None:
options[0].general_rar_exe_path = "rar"
return options

View File

@ -193,7 +193,7 @@ class FileSelectionList(QtWidgets.QWidget):
QtCore.QCoreApplication.processEvents()
first_added = None
rar_added = False
rar_added_ro = False
self.twList.setSortingEnabled(False)
for idx, f in enumerate(filelist):
QtCore.QCoreApplication.processEvents()
@ -206,8 +206,7 @@ class FileSelectionList(QtWidgets.QWidget):
row = self.add_path_item(f)
if row is not None:
ca = self.get_archive_by_row(row)
if ca and ca.is_rar():
rar_added = True
rar_added_ro = bool(ca and ca.archiver.name() == "RAR" and not ca.archiver.is_writable())
if first_added is None:
first_added = row
@ -224,7 +223,7 @@ class FileSelectionList(QtWidgets.QWidget):
else:
QtWidgets.QMessageBox.information(self, "File/Folder Open", "No readable comic archives were found.")
if rar_added and not utils.which(self.options.general_rar_exe_path or "rar"):
if rar_added_ro:
self.rar_ro_message()
self.twList.setSortingEnabled(True)
@ -339,14 +338,7 @@ class FileSelectionList(QtWidgets.QWidget):
filename_item.setText(item_text)
filename_item.setData(QtCore.Qt.ItemDataRole.ToolTipRole, item_text)
if fi.ca.is_sevenzip():
item_text = "7Z"
elif fi.ca.is_zip():
item_text = "ZIP"
elif fi.ca.is_rar():
item_text = "RAR"
else:
item_text = ""
item_text = fi.ca.archiver.name()
type_item.setText(item_text)
type_item.setData(QtCore.Qt.ItemDataRole.ToolTipRole, item_text)

View File

@ -160,6 +160,9 @@ class App:
f"Failed to load settings, check the log located in '{self.options[0].runtime_config.user_log_dir}' for more details",
True,
)
comicapi.comicarchive.load_archive_plugins()
if self.options[0].runtime_no_gui:
if error and error[1]:
print(f"A fatal error occurred please check the log for more information: {error[0]}") # noqa: T201

View File

@ -73,13 +73,8 @@ class RenameWindow(QtWidgets.QDialog):
self.renamer.replacements = self.options[0].rename_replacements
new_ext = ca.path.suffix # default
if self.options[0].rename_set_extension_based_on_archive:
if ca.is_sevenzip():
new_ext = ".cb7"
elif ca.is_zip():
new_ext = ".cbz"
elif ca.is_rar():
new_ext = ".cbr"
if self.options[0].filename_rename_set_extension_based_on_archive:
new_ext = ca.extension()
if md is None:
md = ca.read_metadata(self.data_style)
@ -206,7 +201,7 @@ class RenameWindow(QtWidgets.QDialog):
logger.info("%s: Filename is already good!", comic[1])
continue
if not comic[0].is_writable(check_rar_status=False):
if not comic[0].is_writable(check_archive_status=False):
continue
comic[0].rename(utils.unique_file(full_path))

View File

@ -696,16 +696,7 @@ Have fun!
self.lblFilename.setText(filename)
if ca.is_sevenzip():
self.lblArchiveType.setText("7Z archive")
elif ca.is_zip():
self.lblArchiveType.setText("ZIP archive")
elif ca.is_rar():
self.lblArchiveType.setText("RAR archive")
elif ca.is_folder():
self.lblArchiveType.setText("Folder archive")
else:
self.lblArchiveType.setText("")
self.lblArchiveType.setText(ca.archiver.name() + " archive")
page_count = f" ({ca.get_number_of_pages()} pages)"
self.lblPageCount.setText(page_count)

View File

@ -59,12 +59,18 @@ setup(
exclude=["tests", "testing"],
),
package_data={"comictaggerlib": ["ui/*", "graphics/*"], "comicapi": ["data/*"]},
entry_points=dict(
console_scripts=["comictagger=comictaggerlib.main:main"],
pyinstaller40=[
entry_points={
"console_scripts": ["comictagger=comictaggerlib.main:main"],
"pyinstaller40": [
"hook-dirs = comictaggerlib.__pyinstaller:get_hook_dirs",
],
),
"comicapi.archivers": [
"zip = comicapi.archivers.zip:ZipArchiver",
"sevenzip = comicapi.archivers.sevenzip:SevenZipArchiver",
"rar = comicapi.archivers.rar:RarArchiver",
"folder = comicapi.archivers.folder:FolderArchiver",
],
},
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Console",

View File

@ -4,15 +4,17 @@ import platform
import shutil
import pytest
from importlib_metadata import entry_points
import comicapi.comicarchive
import comicapi.genericmetadata
from testing.filenames import datadir
@pytest.mark.xfail(not comicapi.comicarchive.rar_support, reason="rar support")
def test_getPageNameList():
@pytest.mark.xfail(not comicapi.archivers.rar.rar_support, reason="rar support")
def test_getPageNameList(load_archive_plugins):
c = comicapi.comicarchive.ComicArchive(datadir / "fake_cbr.cbr")
assert c.seems_to_be_a_comic_archive()
pageNameList = c.get_page_name_list()
assert pageNameList == [
@ -56,24 +58,26 @@ def test_save_cbi(tmp_comic):
md = tmp_comic.read_cbi()
@pytest.mark.xfail(not (comicapi.comicarchive.rar_support and shutil.which("rar")), reason="rar support")
@pytest.mark.xfail(not (comicapi.archivers.rar.rar_support and shutil.which("rar")), reason="rar support")
def test_save_cix_rar(tmp_path):
cbr_path = datadir / "fake_cbr.cbr"
shutil.copy(cbr_path, tmp_path)
tmp_comic = comicapi.comicarchive.ComicArchive(tmp_path / cbr_path.name)
assert tmp_comic.seems_to_be_a_comic_archive()
assert tmp_comic.write_cix(comicapi.genericmetadata.md_test)
md = tmp_comic.read_cix()
assert md.replace(pages=[]) == comicapi.genericmetadata.md_test.replace(pages=[])
@pytest.mark.xfail(not (comicapi.comicarchive.rar_support and shutil.which("rar")), reason="rar support")
@pytest.mark.xfail(not (comicapi.archivers.rar.rar_support and shutil.which("rar")), reason="rar support")
def test_save_cbi_rar(tmp_path):
cbr_path = datadir / "fake_cbr.cbr"
shutil.copy(cbr_path, tmp_path)
tmp_comic = comicapi.comicarchive.ComicArchive(tmp_path / cbr_path.name)
assert tmp_comic.seems_to_be_a_comic_archive()
assert tmp_comic.write_cbi(comicapi.genericmetadata.md_test)
md = tmp_comic.read_cbi()
@ -118,16 +122,8 @@ def test_invalid_zip(tmp_comic):
archivers = [
comicapi.comicarchive.ZipArchiver,
comicapi.comicarchive.FolderArchiver,
pytest.param(
comicapi.comicarchive.SevenZipArchiver,
marks=pytest.mark.xfail(not (comicapi.comicarchive.z7_support), reason="7z support"),
),
pytest.param(
comicapi.comicarchive.RarArchiver,
marks=pytest.mark.xfail(not (comicapi.comicarchive.rar_support and shutil.which("rar")), reason="rar support"),
),
pytest.param(x.load(), marks=pytest.mark.xfail(not (x.load().enabled), reason="archiver not enabled"))
for x in entry_points(group="comicapi_archivers")
]
@ -135,7 +131,7 @@ archivers = [
def test_copy_from_archive(archiver, tmp_path, cbz):
comic_path = tmp_path / cbz.path.with_suffix("").name
archive = archiver(comic_path)
archive = archiver.open(comic_path)
assert archive.copy_from_archive(cbz.archiver)

View File

@ -23,12 +23,17 @@ from testing.comicdata import all_seed_imprints, seed_imprints
@pytest.fixture
def cbz():
def cbz(load_archive_plugins):
yield comicapi.comicarchive.ComicArchive(filenames.cbz_path)
@pytest.fixture
def tmp_comic(tmp_path):
def load_archive_plugins():
comicapi.comicarchive.load_archive_plugins()
@pytest.fixture
def tmp_comic(tmp_path, load_archive_plugins):
shutil.copy(filenames.cbz_path, tmp_path)
yield comicapi.comicarchive.ComicArchive(tmp_path / filenames.cbz_path.name)