Generate settings for an archivers executable
This commit is contained in:
parent
c80627575a
commit
46899255c8
@ -12,6 +12,13 @@ class Archiver(Protocol):
|
||||
"""The path to the archive"""
|
||||
path: pathlib.Path
|
||||
|
||||
"""
|
||||
The name of the executable used for this archiver. This should be the base name of the executable.
|
||||
For example if 'rar.exe' is needed this should be "rar".
|
||||
If an executable is not used this should be the empty string.
|
||||
"""
|
||||
exe: str = ""
|
||||
|
||||
"""
|
||||
Whether or not this archiver is enabled.
|
||||
If external imports are required and are not available this should be false. See rar.py and sevenzip.py.
|
||||
@ -114,7 +121,9 @@ class Archiver(Protocol):
|
||||
def open(cls, path: pathlib.Path) -> Archiver:
|
||||
"""
|
||||
Opens the given archive.
|
||||
Should always return a an Archver. Should never cause an exception, is_valid will always be called before open.
|
||||
Should always return a an Archver.
|
||||
Should never cause an exception no file operations should take place in this method,
|
||||
is_valid will always be called before open.
|
||||
"""
|
||||
archiver = cls()
|
||||
archiver.path = path
|
||||
|
@ -29,10 +29,10 @@ class RarArchiver(Archiver):
|
||||
"""RAR implementation"""
|
||||
|
||||
enabled = rar_support
|
||||
exe = "rar"
|
||||
|
||||
def __init__(self, rar_exe_path: str = "rar") -> None:
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.rar_exe_path = shutil.which(rar_exe_path) or ""
|
||||
|
||||
# windows only, keeps the cmd.exe from popping up
|
||||
if platform.system() == "Windows":
|
||||
@ -46,7 +46,7 @@ class RarArchiver(Archiver):
|
||||
return rarc.comment.decode("utf-8") if rarc else ""
|
||||
|
||||
def set_comment(self, comment: str) -> bool:
|
||||
if rar_support and self.rar_exe_path:
|
||||
if rar_support and self.exe:
|
||||
try:
|
||||
# write comment to temp file
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
@ -57,7 +57,7 @@ class RarArchiver(Archiver):
|
||||
|
||||
# use external program to write comment to Rar archive
|
||||
proc_args = [
|
||||
self.rar_exe_path,
|
||||
self.exe,
|
||||
"c",
|
||||
f"-w{working_dir}",
|
||||
"-c-",
|
||||
@ -130,10 +130,10 @@ class RarArchiver(Archiver):
|
||||
raise OSError
|
||||
|
||||
def remove_file(self, archive_file: str) -> bool:
|
||||
if self.rar_exe_path:
|
||||
if self.exe:
|
||||
# use external program to remove file from Rar archive
|
||||
result = subprocess.run(
|
||||
[self.rar_exe_path, "d", "-c-", self.path, archive_file],
|
||||
[self.exe, "d", "-c-", self.path, archive_file],
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stdin=subprocess.DEVNULL,
|
||||
@ -155,14 +155,14 @@ class RarArchiver(Archiver):
|
||||
return False
|
||||
|
||||
def write_file(self, archive_file: str, data: bytes) -> bool:
|
||||
if self.rar_exe_path:
|
||||
if self.exe:
|
||||
archive_path = pathlib.PurePosixPath(archive_file)
|
||||
archive_name = archive_path.name
|
||||
archive_parent = str(archive_path.parent).lstrip("./")
|
||||
|
||||
# use external program to write file to Rar archive
|
||||
result = subprocess.run(
|
||||
[self.rar_exe_path, "a", f"-si{archive_name}", f"-ap{archive_parent}", "-c-", "-ep", self.path],
|
||||
[self.exe, "a", f"-si{archive_name}", f"-ap{archive_parent}", "-c-", "-ep", self.path],
|
||||
input=data,
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=subprocess.DEVNULL,
|
||||
@ -217,7 +217,7 @@ class RarArchiver(Archiver):
|
||||
with open(rar_cwd / filename, mode="w+b") as tmp_file:
|
||||
tmp_file.write(data)
|
||||
result = subprocess.run(
|
||||
[self.rar_exe_path, "a", "-r", "-c-", str(rar_path.absolute()), "."],
|
||||
[self.exe, "a", "-r", "-c-", str(rar_path.absolute()), "."],
|
||||
cwd=rar_cwd.absolute(),
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=subprocess.DEVNULL,
|
||||
@ -237,7 +237,7 @@ class RarArchiver(Archiver):
|
||||
return True
|
||||
|
||||
def is_writable(self) -> bool:
|
||||
return bool(self.rar_exe_path and os.path.exists(self.rar_exe_path))
|
||||
return bool(self.exe and (os.path.exists(self.exe) or shutil.which(self.exe)))
|
||||
|
||||
def extension(self) -> str:
|
||||
return ".cbr"
|
||||
|
@ -2,13 +2,16 @@ from __future__ import annotations
|
||||
|
||||
from comictaggerlib.ctoptions.cmdline import initial_cmd_line_parser, register_commandline, validate_commandline_options
|
||||
from comictaggerlib.ctoptions.file import register_settings, validate_settings
|
||||
from comictaggerlib.ctoptions.plugin import register_plugin_settings, validate_plugin_settings
|
||||
from comictaggerlib.ctoptions.types import ComicTaggerPaths
|
||||
|
||||
__all__ = [
|
||||
"initial_cmd_line_parser",
|
||||
"register_commandline",
|
||||
"register_settings",
|
||||
"register_plugin_settings",
|
||||
"validate_commandline_options",
|
||||
"validate_settings",
|
||||
"validate_plugin_settings",
|
||||
"ComicTaggerPaths",
|
||||
]
|
||||
|
@ -248,7 +248,7 @@ def autotag(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_settings(options: settngs.Config[settngs.Values], parser: settngs.Manager) -> dict[str, dict[str, Any]]:
|
||||
def validate_settings(options: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]:
|
||||
options[0].identifier_publisher_filter = [x.strip() for x in options[0].identifier_publisher_filter if x.strip()]
|
||||
options[0].rename_replacements = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in options[0].rename_replacements[0]],
|
||||
|
43
comictaggerlib/ctoptions/plugin.py
Normal file
43
comictaggerlib/ctoptions/plugin.py
Normal file
@ -0,0 +1,43 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import settngs
|
||||
|
||||
import comicapi.comicarchive
|
||||
|
||||
logger = logging.getLogger("comictagger")
|
||||
|
||||
|
||||
def archiver(manager: settngs.Manager) -> None:
|
||||
exe_registered: set[str] = set()
|
||||
for archiver in comicapi.comicarchive.archivers:
|
||||
if archiver.exe and archiver.exe not in exe_registered:
|
||||
manager.add_setting(
|
||||
f"--{archiver.exe.replace(' ', '-').replace('_', '-').strip().strip('-')}",
|
||||
default=archiver.exe,
|
||||
help="Path to the %(default)s executable\n\n",
|
||||
)
|
||||
exe_registered.add(archiver.exe)
|
||||
|
||||
|
||||
def validate_plugin_settings(options: settngs.Config) -> settngs.Config:
|
||||
cfg = settngs.normalize_config(options, file=True, cmdline=True, defaults=False)
|
||||
for archiver in comicapi.comicarchive.archivers:
|
||||
exe_name = archiver.exe.replace(" ", "-").replace("_", "-").strip().strip("-").replace("-", "_")
|
||||
if (
|
||||
exe_name in cfg[0]["archiver"]
|
||||
and cfg[0]["archiver"][exe_name]
|
||||
and cfg[0]["archiver"][exe_name] != archiver.exe
|
||||
):
|
||||
if os.path.basename(cfg[0]["archiver"][exe_name]) == archiver.exe:
|
||||
comicapi.utils.add_to_path(os.path.dirname(cfg[0]["archiver"][exe_name]))
|
||||
else:
|
||||
archiver.exe = cfg[0]["archiver"][exe_name]
|
||||
|
||||
return options
|
||||
|
||||
|
||||
def register_plugin_settings(manager: settngs.Manager):
|
||||
manager.add_group("archiver", archiver, False)
|
@ -68,12 +68,16 @@ class App:
|
||||
|
||||
def run(self) -> None:
|
||||
opts = self.initialize()
|
||||
self.load_plugins()
|
||||
self.register_options()
|
||||
self.parse_options(opts.config)
|
||||
self.initialize_dirs()
|
||||
|
||||
self.main()
|
||||
|
||||
def load_plugins(self) -> None:
|
||||
comicapi.comicarchive.load_archive_plugins()
|
||||
|
||||
def initialize(self) -> argparse.Namespace:
|
||||
opts, _ = self.initial_arg_parser.parse_known_args()
|
||||
assert opts is not None
|
||||
@ -87,6 +91,7 @@ class App:
|
||||
)
|
||||
ctoptions.register_commandline(self.manager)
|
||||
ctoptions.register_settings(self.manager)
|
||||
ctoptions.register_plugin_settings(self.manager)
|
||||
|
||||
def parse_options(self, config_paths: ctoptions.ComicTaggerPaths) -> None:
|
||||
self.options, self.config_load_success = self.manager.parse_config(
|
||||
@ -95,7 +100,8 @@ class App:
|
||||
self.options = self.manager.get_namespace(self.options)
|
||||
|
||||
self.options = ctoptions.validate_commandline_options(self.options, self.manager)
|
||||
self.options = ctoptions.validate_settings(self.options, self.manager)
|
||||
self.options = ctoptions.validate_settings(self.options)
|
||||
self.options = ctoptions.validate_plugin_settings(self.options)
|
||||
self.options = self.options
|
||||
|
||||
def initialize_dirs(self) -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user