2012-11-02 13:54:17 -07:00
|
|
|
#!/usr/bin/python
|
2015-02-21 18:30:32 -08:00
|
|
|
"""ComicTagger CLI functions"""
|
2022-06-02 18:32:16 -07:00
|
|
|
#
|
2023-02-16 17:23:13 -08:00
|
|
|
# Copyright 2013 ComicTagger Authors
|
2022-06-02 18:32:16 -07:00
|
|
|
#
|
2015-02-21 18:30:32 -08:00
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
2022-06-02 18:32:16 -07:00
|
|
|
#
|
2015-02-21 18:30:32 -08:00
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
2022-06-02 18:32:16 -07:00
|
|
|
#
|
2015-02-21 18:30:32 -08:00
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
2022-06-02 18:32:16 -07:00
|
|
|
from __future__ import annotations
|
2012-11-02 13:54:17 -07:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
import dataclasses
|
2023-12-17 18:10:18 -08:00
|
|
|
import functools
|
2023-12-17 15:51:43 -08:00
|
|
|
import json
|
2022-04-04 18:59:26 -07:00
|
|
|
import logging
|
2012-11-06 12:29:18 -08:00
|
|
|
import os
|
2023-12-17 15:51:43 -08:00
|
|
|
import pathlib
|
2024-06-20 16:47:10 -07:00
|
|
|
import re
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
import sys
|
2023-12-17 15:51:43 -08:00
|
|
|
from collections.abc import Collection
|
|
|
|
from typing import Any, TextIO
|
2012-11-12 16:12:43 -08:00
|
|
|
|
2024-05-10 15:51:13 -07:00
|
|
|
from comicapi import merge, utils
|
2024-06-20 16:47:10 -07:00
|
|
|
from comicapi.comicarchive import ComicArchive, tags
|
2024-05-10 15:51:13 -07:00
|
|
|
from comicapi.genericmetadata import GenericMetadata
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
from comictaggerlib.cbltransformer import CBLTransformer
|
2023-06-09 16:20:00 -07:00
|
|
|
from comictaggerlib.ctsettings import ct_ns
|
2022-07-09 22:27:45 -07:00
|
|
|
from comictaggerlib.filerenamer import FileRenamer, get_rename_dir
|
2022-10-25 21:48:01 -07:00
|
|
|
from comictaggerlib.graphics import graphics_path
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
from comictaggerlib.issueidentifier import IssueIdentifier
|
2024-04-26 21:12:06 -07:00
|
|
|
from comictaggerlib.md import prepare_metadata
|
2023-12-17 16:16:21 -08:00
|
|
|
from comictaggerlib.resulttypes import Action, IssueResult, MatchStatus, OnlineMatchResults, Result, Status
|
2023-02-09 19:33:10 -08:00
|
|
|
from comictalker.comictalker import ComicTalker, TalkerError
|
2015-02-15 02:44:00 -08:00
|
|
|
|
2022-04-04 18:59:26 -07:00
|
|
|
logger = logging.getLogger(__name__)
|
2012-12-05 20:46:01 -08:00
|
|
|
|
2015-02-15 02:44:00 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
class OutputEncoder(json.JSONEncoder):
|
|
|
|
def default(self, obj: Any) -> Any:
|
|
|
|
if isinstance(obj, pathlib.Path):
|
|
|
|
return str(obj)
|
|
|
|
if not isinstance(obj, str) and isinstance(obj, Collection):
|
|
|
|
return list(obj)
|
|
|
|
|
|
|
|
# Let the base class default method raise the TypeError
|
|
|
|
return json.JSONEncoder.default(self, obj)
|
|
|
|
|
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
class CLI:
|
2023-06-09 16:20:00 -07:00
|
|
|
def __init__(self, config: ct_ns, talkers: dict[str, ComicTalker]) -> None:
|
2023-01-31 20:21:39 -08:00
|
|
|
self.config = config
|
2023-02-09 19:33:10 -08:00
|
|
|
self.talkers = talkers
|
2022-11-26 16:47:18 -08:00
|
|
|
self.batch_mode = False
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output_file = sys.stdout
|
|
|
|
if config.Runtime_Options__json:
|
|
|
|
self.output_file = sys.stderr
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-02-09 19:33:10 -08:00
|
|
|
def current_talker(self) -> ComicTalker:
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Sources__source in self.talkers:
|
|
|
|
return self.talkers[self.config.Sources__source]
|
|
|
|
logger.error("Could not find the '%s' talker", self.config.Sources__source)
|
2023-02-09 19:33:10 -08:00
|
|
|
raise SystemExit(2)
|
|
|
|
|
2023-12-17 18:10:18 -08:00
|
|
|
def output(
|
|
|
|
self,
|
|
|
|
*args: Any,
|
|
|
|
file: TextIO | None = None,
|
|
|
|
force_output: bool = False,
|
|
|
|
already_logged: bool = False,
|
|
|
|
**kwargs: Any,
|
|
|
|
) -> None:
|
2023-12-17 15:51:43 -08:00
|
|
|
if file is None:
|
|
|
|
file = self.output_file
|
|
|
|
if not args:
|
|
|
|
log_args: tuple[Any, ...] = ("",)
|
|
|
|
elif isinstance(args[0], str):
|
|
|
|
log_args = (args[0].strip("\n"), *args[1:])
|
|
|
|
else:
|
|
|
|
log_args = args
|
2023-12-17 18:10:18 -08:00
|
|
|
if not already_logged:
|
|
|
|
logger.info(*log_args, **kwargs)
|
2023-12-17 15:51:43 -08:00
|
|
|
if self.config.Runtime_Options__verbose > 0:
|
|
|
|
return
|
2023-12-17 17:56:12 -08:00
|
|
|
if not self.config.Runtime_Options__quiet or force_output:
|
2023-12-17 15:51:43 -08:00
|
|
|
print(*args, **kwargs, file=file)
|
|
|
|
|
2023-12-17 18:17:19 -08:00
|
|
|
def run(self) -> int:
|
2023-12-17 15:51:43 -08:00
|
|
|
if len(self.config.Runtime_Options__files) < 1:
|
|
|
|
logger.error("You must specify at least one filename. Use the -h option for more info")
|
2023-12-17 18:17:19 -08:00
|
|
|
return 1
|
|
|
|
return_code = 0
|
2023-12-17 15:51:43 -08:00
|
|
|
|
|
|
|
results: list[Result] = []
|
|
|
|
match_results = OnlineMatchResults()
|
|
|
|
self.batch_mode = len(self.config.Runtime_Options__files) > 1
|
|
|
|
|
|
|
|
for f in self.config.Runtime_Options__files:
|
2024-04-26 21:12:06 -07:00
|
|
|
res, match_results = self.process_file_cli(self.config.Commands__command, f, match_results)
|
|
|
|
results.append(res)
|
2023-12-17 18:17:19 -08:00
|
|
|
if results[-1].status != Status.success:
|
|
|
|
return_code = 3
|
2023-12-17 15:51:43 -08:00
|
|
|
if self.config.Runtime_Options__json:
|
|
|
|
print(json.dumps(dataclasses.asdict(results[-1]), cls=OutputEncoder, indent=2))
|
|
|
|
sys.stdout.flush()
|
|
|
|
sys.stderr.flush()
|
|
|
|
|
|
|
|
self.post_process_matches(match_results)
|
|
|
|
|
2024-02-06 16:02:12 -08:00
|
|
|
if self.config.Auto_Tag__online:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(
|
|
|
|
f"\nFiles tagged with metadata provided by {self.current_talker().name} {self.current_talker().website}",
|
|
|
|
)
|
2023-12-17 18:17:19 -08:00
|
|
|
return return_code
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
def fetch_metadata(self, issue_id: str) -> GenericMetadata:
|
2022-11-26 16:47:18 -08:00
|
|
|
# now get the particular issue data
|
|
|
|
try:
|
2023-02-09 19:33:10 -08:00
|
|
|
ct_md = self.current_talker().fetch_comic_data(issue_id)
|
2022-11-26 16:47:18 -08:00
|
|
|
except TalkerError as e:
|
|
|
|
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
|
|
|
return GenericMetadata()
|
|
|
|
|
2024-02-06 16:02:12 -08:00
|
|
|
if self.config.Metadata_Options__apply_transform_on_import:
|
2023-01-31 20:21:39 -08:00
|
|
|
ct_md = CBLTransformer(ct_md, self.config).apply()
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
return ct_md
|
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
def write_tags(self, ca: ComicArchive, md: GenericMetadata) -> bool:
|
2023-11-19 23:14:40 -08:00
|
|
|
if not self.config.Runtime_Options__dryrun:
|
2024-06-20 16:47:10 -07:00
|
|
|
for tag_id in self.config.Runtime_Options__tags_write:
|
2022-11-26 16:47:18 -08:00
|
|
|
# write out the new data
|
2024-06-20 16:47:10 -07:00
|
|
|
if not ca.write_tags(md, tag_id):
|
|
|
|
logger.error("The tag save seemed to fail for: %s!", tags[tag_id].name())
|
2022-11-26 16:47:18 -08:00
|
|
|
return False
|
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output("Save complete.")
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Runtime_Options__quiet:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output("dry-run option was set, so nothing was written")
|
2022-05-17 18:28:37 -07:00
|
|
|
else:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output("dry-run option was set, so nothing was written, but here is the final set of tags:")
|
|
|
|
self.output(f"{md}")
|
2022-11-26 16:47:18 -08:00
|
|
|
return True
|
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
def display_match_set_for_choice(self, label: str, match_set: Result) -> None:
|
2023-12-17 17:56:12 -08:00
|
|
|
self.output(f"{match_set.original_path} -- {label}:", force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
# sort match list by year
|
2023-12-17 15:51:43 -08:00
|
|
|
match_set.online_results.sort(key=lambda k: k.year or 0)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
for counter, m in enumerate(match_set.online_results, 1):
|
|
|
|
self.output(
|
2022-11-26 16:47:18 -08:00
|
|
|
" {}. {} #{} [{}] ({}/{}) - {}".format(
|
|
|
|
counter,
|
2023-12-17 15:51:43 -08:00
|
|
|
m.series,
|
|
|
|
m.issue_number,
|
|
|
|
m.publisher,
|
|
|
|
m.month,
|
|
|
|
m.year,
|
|
|
|
m.issue_title,
|
2023-12-17 17:56:12 -08:00
|
|
|
),
|
|
|
|
force_output=True,
|
2022-11-26 16:47:18 -08:00
|
|
|
)
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Runtime_Options__interactive:
|
2022-11-26 16:47:18 -08:00
|
|
|
while True:
|
|
|
|
i = input("Choose a match #, or 's' to skip: ")
|
2023-12-17 15:51:43 -08:00
|
|
|
if (i.isdigit() and int(i) in range(1, len(match_set.online_results) + 1)) or i == "s":
|
2022-11-26 16:47:18 -08:00
|
|
|
break
|
|
|
|
if i != "s":
|
|
|
|
# save the data!
|
|
|
|
# we know at this point, that the file is all good to go
|
2023-12-17 15:51:43 -08:00
|
|
|
ca = ComicArchive(match_set.original_path)
|
2024-06-20 16:47:10 -07:00
|
|
|
md, match_set.tags_read = self.create_local_metadata(ca, self.config.Runtime_Options__tags_read)
|
|
|
|
ct_md = self.fetch_metadata(match_set.online_results[int(i) - 1].issue_id)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2024-04-26 21:12:06 -07:00
|
|
|
match_set.md = prepare_metadata(md, ct_md, self.config)
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2024-06-21 19:53:30 -07:00
|
|
|
self.write_tags(ca, match_set.md)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
def post_process_matches(self, match_results: OnlineMatchResults) -> None:
|
2023-12-17 15:51:43 -08:00
|
|
|
def print_header(header: str) -> None:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output("", force_output=True)
|
|
|
|
self.output(header, force_output=True)
|
|
|
|
self.output("------------------", force_output=True)
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
# now go through the match results
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Runtime_Options__summary:
|
2022-11-26 16:47:18 -08:00
|
|
|
if len(match_results.good_matches) > 0:
|
2023-12-17 15:51:43 -08:00
|
|
|
print_header("Successful matches:")
|
2022-11-26 16:47:18 -08:00
|
|
|
for f in match_results.good_matches:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output(f, force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
if len(match_results.no_matches) > 0:
|
2023-12-17 15:51:43 -08:00
|
|
|
print_header("No matches:")
|
2022-11-26 16:47:18 -08:00
|
|
|
for f in match_results.no_matches:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output(f, force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
if len(match_results.write_failures) > 0:
|
2023-12-17 15:51:43 -08:00
|
|
|
print_header("File Write Failures:")
|
2022-11-26 16:47:18 -08:00
|
|
|
for f in match_results.write_failures:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output(f, force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
if len(match_results.fetch_data_failures) > 0:
|
2023-12-17 15:51:43 -08:00
|
|
|
print_header("Network Data Fetch Failures:")
|
2022-11-26 16:47:18 -08:00
|
|
|
for f in match_results.fetch_data_failures:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output(f, force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-11-19 23:14:40 -08:00
|
|
|
if not self.config.Runtime_Options__summary and not self.config.Runtime_Options__interactive:
|
2022-11-26 16:47:18 -08:00
|
|
|
# just quit if we're not interactive or showing the summary
|
|
|
|
return
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
if len(match_results.multiple_matches) > 0:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output("\nArchives with multiple high-confidence matches:\n------------------", force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
for match_set in match_results.multiple_matches:
|
|
|
|
self.display_match_set_for_choice("Multiple high-confidence matches", match_set)
|
2022-06-02 18:28:54 -07:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
if len(match_results.low_confidence_matches) > 0:
|
2023-12-17 18:03:25 -08:00
|
|
|
self.output("\nArchives with low-confidence matches:\n------------------", force_output=True)
|
2022-11-26 16:47:18 -08:00
|
|
|
for match_set in match_results.low_confidence_matches:
|
2023-12-17 15:51:43 -08:00
|
|
|
if len(match_set.online_results) == 1:
|
2022-11-26 16:47:18 -08:00
|
|
|
label = "Single low-confidence match"
|
|
|
|
else:
|
|
|
|
label = "Multiple low-confidence matches"
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
self.display_match_set_for_choice(label, match_set)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
def create_local_metadata(
|
|
|
|
self, ca: ComicArchive, tags_to_read: list[str], /, tags_only: bool = False
|
|
|
|
) -> tuple[GenericMetadata, list[str]]:
|
2022-11-26 16:47:18 -08:00
|
|
|
md = GenericMetadata()
|
2023-12-18 02:37:34 -08:00
|
|
|
md.apply_default_page_list(ca.get_page_name_list())
|
2024-06-08 19:12:38 -07:00
|
|
|
filename_md = GenericMetadata()
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
# now, overlay the parsed filename info
|
2024-06-20 16:47:10 -07:00
|
|
|
if self.config.Auto_Tag__parse_filename and not tags_only:
|
2024-06-08 19:12:38 -07:00
|
|
|
filename_md = ca.metadata_from_filename(
|
2024-03-03 21:47:31 -08:00
|
|
|
self.config.Filename_Parsing__filename_parser,
|
2023-11-19 23:14:40 -08:00
|
|
|
self.config.Filename_Parsing__remove_c2c,
|
|
|
|
self.config.Filename_Parsing__remove_fcbd,
|
|
|
|
self.config.Filename_Parsing__remove_publisher,
|
2023-12-25 21:57:31 -08:00
|
|
|
self.config.Filename_Parsing__split_words,
|
|
|
|
self.config.Filename_Parsing__allow_issue_start_with_letter,
|
|
|
|
self.config.Filename_Parsing__protofolius_issue_number_scheme,
|
2022-11-26 16:47:18 -08:00
|
|
|
)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-08 19:12:38 -07:00
|
|
|
file_md = GenericMetadata()
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_used = []
|
|
|
|
for tag_id in tags_to_read:
|
|
|
|
if ca.has_tags(tag_id):
|
2022-11-26 16:47:18 -08:00
|
|
|
try:
|
2024-06-20 16:47:10 -07:00
|
|
|
t_md = ca.read_tags(tag_id)
|
|
|
|
if not t_md.is_empty:
|
2024-06-21 19:53:30 -07:00
|
|
|
file_md.overlay(
|
2024-06-20 16:47:10 -07:00
|
|
|
t_md,
|
|
|
|
self.config.Metadata_Options__tag_merge,
|
|
|
|
self.config.Metadata_Options__tag_merge_lists,
|
|
|
|
)
|
|
|
|
tags_used.append(tag_id)
|
2022-11-26 16:47:18 -08:00
|
|
|
except Exception as e:
|
|
|
|
logger.error("Failed to load metadata for %s: %s", ca.path, e)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-08 19:12:38 -07:00
|
|
|
filename_merge = merge.Mode.ADD_MISSING
|
2024-06-21 19:53:30 -07:00
|
|
|
if self.config.Auto_Tag__prefer_filename:
|
2024-06-08 19:12:38 -07:00
|
|
|
filename_merge = merge.Mode.OVERLAY
|
|
|
|
|
|
|
|
md.overlay(file_md, mode=merge.Mode.OVERLAY, merge_lists=False)
|
2024-06-20 16:47:10 -07:00
|
|
|
if not tags_only:
|
2024-06-21 19:53:30 -07:00
|
|
|
md.overlay(filename_md, mode=filename_merge, merge_lists=False)
|
2024-06-20 16:47:10 -07:00
|
|
|
# finally, use explicit stuff (always 'overlay' mode)
|
|
|
|
md.overlay(self.config.Auto_Tag__metadata, mode=merge.Mode.OVERLAY, merge_lists=True)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
return (md, tags_used)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
def print(self, ca: ComicArchive) -> Result:
|
2024-06-20 16:47:10 -07:00
|
|
|
if not self.config.Runtime_Options__tags_read:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
page_count = ca.get_number_of_pages()
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
brief = ""
|
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
if self.batch_mode:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
brief = f"{ca.path}: "
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-08-17 15:53:19 -07:00
|
|
|
brief += ca.archiver.name() + " archive "
|
2015-02-12 14:57:46 -08:00
|
|
|
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
brief += f"({page_count: >3} pages)"
|
2015-02-12 14:57:46 -08:00
|
|
|
brief += " tags:[ "
|
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
tag_names = [tags[tag_id].name() for tag_id in tags if ca.has_tags(tag_id)]
|
|
|
|
brief += " ".join(tag_names)
|
2023-12-17 21:47:43 -08:00
|
|
|
brief += " ]"
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(brief)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Runtime_Options__quiet:
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.print, Status.success, ca.path)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output()
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
md = None
|
2024-06-20 16:47:10 -07:00
|
|
|
for tag_id, tag in tags.items():
|
|
|
|
if not self.config.Runtime_Options__tags_read or tag_id in self.config.Runtime_Options__tags_read:
|
|
|
|
if ca.has_tags(tag_id):
|
|
|
|
self.output(f"--------- {tag.name()} tags ---------")
|
2023-12-17 21:47:43 -08:00
|
|
|
try:
|
|
|
|
if self.config.Runtime_Options__raw:
|
2024-06-20 16:47:10 -07:00
|
|
|
self.output(ca.read_raw_tags(tag_id))
|
2023-12-17 21:47:43 -08:00
|
|
|
else:
|
2024-06-20 16:47:10 -07:00
|
|
|
md = ca.read_tags(tag_id)
|
2023-12-17 21:47:43 -08:00
|
|
|
self.output(md)
|
|
|
|
except Exception as e:
|
2024-06-20 16:47:10 -07:00
|
|
|
logger.error("Failed to read tags from %s: %s", ca.path, e)
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.print, Status.success, ca.path, md=md)
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
def delete_tags(self, ca: ComicArchive, tag_id: str) -> Status:
|
|
|
|
tag_name = tags[tag_id].name()
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
if ca.has_tags(tag_id):
|
2023-12-17 15:51:43 -08:00
|
|
|
if not self.config.Runtime_Options__dryrun:
|
2024-06-20 16:47:10 -07:00
|
|
|
if ca.remove_tags(tag_id):
|
|
|
|
self.output(f"{ca.path}: Removed {tag_name} tags.")
|
2023-12-17 15:51:43 -08:00
|
|
|
return Status.success
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(f"{ca.path}: Tag removal seemed to fail!")
|
|
|
|
return Status.write_failure
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
2024-06-20 16:47:10 -07:00
|
|
|
self.output(f"{ca.path}: dry-run. {tag_name} tags not removed")
|
2023-12-17 15:51:43 -08:00
|
|
|
return Status.success
|
2024-06-20 16:47:10 -07:00
|
|
|
self.output(f"{ca.path}: This archive doesn't have {tag_name} tags to remove.")
|
2023-12-17 15:51:43 -08:00
|
|
|
return Status.success
|
2022-06-10 16:20:58 -07:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
def delete(self, ca: ComicArchive) -> Result:
|
2023-12-17 16:16:21 -08:00
|
|
|
res = Result(Action.delete, Status.success, ca.path)
|
2024-06-20 16:47:10 -07:00
|
|
|
for tag_id in self.config.Runtime_Options__tags_write:
|
|
|
|
status = self.delete_tags(ca, tag_id)
|
2023-12-17 15:51:43 -08:00
|
|
|
if status == Status.success:
|
2024-06-20 16:47:10 -07:00
|
|
|
res.tags_deleted.append(tag_id)
|
2023-12-17 15:51:43 -08:00
|
|
|
else:
|
|
|
|
res.status = status
|
|
|
|
return res
|
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
def _copy_tags(self, ca: ComicArchive, md: GenericMetadata, source_names: str, dst_tag_id: str) -> Status:
|
|
|
|
dst_tag_name = tags[dst_tag_id].name()
|
|
|
|
if not self.config.Runtime_Options__skip_existing_tags and ca.has_tags(dst_tag_id):
|
|
|
|
self.output(f"{ca.path}: Already has {dst_tag_name} tags. Not overwriting.")
|
2023-12-17 15:51:43 -08:00
|
|
|
return Status.existing_tags
|
2024-06-20 16:47:10 -07:00
|
|
|
|
|
|
|
if len(self.config.Commands__copy) == 1 and dst_tag_id in self.config.Commands__copy:
|
|
|
|
self.output(f"{ca.path}: Destination and source are same: {dst_tag_name}. Nothing to do.")
|
2023-12-17 15:51:43 -08:00
|
|
|
return Status.existing_tags
|
|
|
|
|
2023-12-17 21:47:43 -08:00
|
|
|
if not self.config.Runtime_Options__dryrun:
|
2024-06-20 16:47:10 -07:00
|
|
|
if self.config.Metadata_Options__apply_transform_on_bulk_operation and dst_tag_id == "cbi":
|
2023-12-17 21:47:43 -08:00
|
|
|
md = CBLTransformer(md, self.config).apply()
|
2023-12-17 15:51:43 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
if ca.write_tags(md, dst_tag_id):
|
|
|
|
self.output(f"{ca.path}: Copied {source_names} tags to {dst_tag_name}.")
|
2023-12-17 21:47:43 -08:00
|
|
|
else:
|
|
|
|
self.output(f"{ca.path}: Tag copy seemed to fail!")
|
|
|
|
return Status.write_failure
|
|
|
|
else:
|
2024-06-20 16:47:10 -07:00
|
|
|
self.output(f"{ca.path}: dry-run. {source_names} tags not copied")
|
|
|
|
return Status.success
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
def copy(self, ca: ComicArchive) -> Result:
|
2023-12-17 16:16:21 -08:00
|
|
|
res = Result(Action.copy, Status.success, ca.path)
|
2024-06-20 16:47:10 -07:00
|
|
|
src_tag_names = []
|
|
|
|
for src_tag_id in self.config.Commands__copy:
|
|
|
|
src_tag_names.append(tags[src_tag_id].name())
|
|
|
|
if ca.has_tags(src_tag_id):
|
|
|
|
res.tags_read.append(src_tag_id)
|
|
|
|
|
|
|
|
if not res.tags_read:
|
|
|
|
self.output(f"{ca.path}: This archive doesn't have any {', '.join(src_tag_names)} tags to copy.")
|
2023-12-17 21:47:43 -08:00
|
|
|
res.status = Status.read_failure
|
|
|
|
return res
|
2023-12-17 15:51:43 -08:00
|
|
|
try:
|
2024-06-20 16:47:10 -07:00
|
|
|
res.md, res.tags_read = self.create_local_metadata(ca, res.tags_read, tags_only=True)
|
2023-12-17 15:51:43 -08:00
|
|
|
except Exception as e:
|
2024-06-20 16:47:10 -07:00
|
|
|
logger.error("Failed to read tags from %s: %s", ca.path, e)
|
2023-12-17 15:51:43 -08:00
|
|
|
return res
|
2024-06-20 16:47:10 -07:00
|
|
|
|
|
|
|
for dst_tag_id in self.config.Runtime_Options__tags_write:
|
|
|
|
if dst_tag_id in self.config.Commands__copy:
|
2024-04-27 14:02:34 -07:00
|
|
|
continue
|
2024-06-20 16:47:10 -07:00
|
|
|
|
|
|
|
status = self._copy_tags(ca, res.md, ", ".join(src_tag_names), dst_tag_id)
|
2023-12-17 15:51:43 -08:00
|
|
|
if status == Status.success:
|
2024-06-20 16:47:10 -07:00
|
|
|
res.tags_written.append(dst_tag_id)
|
2023-12-17 15:51:43 -08:00
|
|
|
else:
|
|
|
|
res.status = status
|
|
|
|
return res
|
|
|
|
|
2024-04-26 21:12:06 -07:00
|
|
|
def save(self, ca: ComicArchive, match_results: OnlineMatchResults) -> tuple[Result, OnlineMatchResults]:
|
2024-06-20 16:47:10 -07:00
|
|
|
if not self.config.Runtime_Options__skip_existing_tags:
|
|
|
|
for tag_id in self.config.Runtime_Options__tags_write:
|
|
|
|
if ca.has_tags(tag_id):
|
|
|
|
self.output(f"{ca.path}: Already has {tags[tag_id].name()} tags. Not overwriting.")
|
2024-04-26 21:12:06 -07:00
|
|
|
return (
|
|
|
|
Result(
|
|
|
|
Action.save,
|
|
|
|
original_path=ca.path,
|
|
|
|
status=Status.existing_tags,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
2024-04-26 21:12:06 -07:00
|
|
|
),
|
|
|
|
match_results,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
if self.batch_mode:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(f"Processing {utils.path_to_short_str(ca.path)}...")
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
md, tags_read = self.create_local_metadata(ca, self.config.Runtime_Options__tags_read)
|
2015-02-12 14:57:46 -08:00
|
|
|
if md.issue is None or md.issue == "":
|
2023-12-17 21:47:43 -08:00
|
|
|
if self.config.Auto_Tag__assume_issue_one:
|
2015-02-12 14:57:46 -08:00
|
|
|
md.issue = "1"
|
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
matches: list[IssueResult] = []
|
2015-02-12 14:57:46 -08:00
|
|
|
# now, search online
|
2024-04-26 21:12:06 -07:00
|
|
|
|
|
|
|
ct_md = GenericMetadata()
|
2024-02-06 16:02:12 -08:00
|
|
|
if self.config.Auto_Tag__online:
|
|
|
|
if self.config.Auto_Tag__issue_id is not None:
|
2022-10-04 17:58:46 -07:00
|
|
|
# we were given the actual issue ID to search with
|
2015-02-12 14:57:46 -08:00
|
|
|
try:
|
2024-02-06 16:02:12 -08:00
|
|
|
ct_md = self.current_talker().fetch_comic_data(self.config.Auto_Tag__issue_id)
|
2022-06-28 07:21:35 -07:00
|
|
|
except TalkerError as e:
|
|
|
|
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
status=Status.fetch_data_failure,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.fetch_data_failures.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-04-26 21:12:06 -07:00
|
|
|
if ct_md is None or ct_md.is_empty:
|
2024-02-06 16:02:12 -08:00
|
|
|
logger.error("No match for ID %s was found.", self.config.Auto_Tag__issue_id)
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.no_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.no_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
else:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
if md is None or md.is_empty:
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error("No metadata given to search online with!")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.no_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.no_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-02-09 19:33:10 -08:00
|
|
|
ii = IssueIdentifier(ca, self.config, self.current_talker())
|
2022-06-28 07:21:35 -07:00
|
|
|
|
2023-12-17 18:10:18 -08:00
|
|
|
ii.set_output_function(functools.partial(self.output, already_logged=True))
|
2024-05-21 19:57:28 -07:00
|
|
|
if not self.config.Auto_Tag__use_year_when_identifying:
|
|
|
|
md.year = None
|
2024-06-20 16:47:10 -07:00
|
|
|
if self.config.Auto_Tag__ignore_leading_numbers_in_filename and md.series is not None:
|
|
|
|
md.series = re.sub(r"^([\d.]+)(.*)", r"\2", md.series)
|
2024-02-23 20:47:04 -08:00
|
|
|
result, matches = ii.identify(ca, md)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
found_match = False
|
|
|
|
choices = False
|
|
|
|
low_confidence = False
|
|
|
|
|
2024-02-23 20:47:04 -08:00
|
|
|
if result == IssueIdentifier.result_no_matches:
|
2015-02-12 14:57:46 -08:00
|
|
|
pass
|
2024-02-23 20:47:04 -08:00
|
|
|
elif result == IssueIdentifier.result_found_match_but_bad_cover_score:
|
2015-02-12 14:57:46 -08:00
|
|
|
low_confidence = True
|
|
|
|
found_match = True
|
2024-02-23 20:47:04 -08:00
|
|
|
elif result == IssueIdentifier.result_found_match_but_not_first_page:
|
2015-02-12 14:57:46 -08:00
|
|
|
found_match = True
|
2024-02-23 20:47:04 -08:00
|
|
|
elif result == IssueIdentifier.result_multiple_matches_with_bad_image_scores:
|
2015-02-12 14:57:46 -08:00
|
|
|
low_confidence = True
|
|
|
|
choices = True
|
2024-02-23 20:47:04 -08:00
|
|
|
elif result == IssueIdentifier.result_one_good_match:
|
2015-02-12 14:57:46 -08:00
|
|
|
found_match = True
|
2024-02-23 20:47:04 -08:00
|
|
|
elif result == IssueIdentifier.result_multiple_good_matches:
|
2015-02-12 14:57:46 -08:00
|
|
|
choices = True
|
|
|
|
|
|
|
|
if choices:
|
|
|
|
if low_confidence:
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error("Online search: Multiple low confidence matches. Save aborted")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.low_confidence_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.low_confidence_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error("Online search: Multiple good matches. Save aborted")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.multiple_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.multiple_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2023-11-19 23:14:40 -08:00
|
|
|
if low_confidence and self.config.Runtime_Options__abort_on_low_confidence:
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error("Online search: Low confidence match. Save aborted")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.low_confidence_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.low_confidence_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
if not found_match:
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error("Online search: No match found. Save aborted")
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.match_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.no_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.no_matches.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
# we got here, so we have a single match
|
|
|
|
|
|
|
|
# now get the particular issue data
|
2024-06-20 16:47:10 -07:00
|
|
|
ct_md = self.fetch_metadata(matches[0].issue_id)
|
2022-06-28 07:21:35 -07:00
|
|
|
if ct_md.is_empty:
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.fetch_data_failure,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.good_match,
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
|
|
|
match_results.fetch_data_failures.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2021-08-07 21:50:45 -07:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
res = Result(
|
2023-12-17 16:16:21 -08:00
|
|
|
Action.save,
|
|
|
|
status=Status.success,
|
2023-12-17 15:51:43 -08:00
|
|
|
original_path=ca.path,
|
|
|
|
online_results=matches,
|
2023-12-17 16:16:21 -08:00
|
|
|
match_status=MatchStatus.good_match,
|
2024-04-26 21:12:06 -07:00
|
|
|
md=prepare_metadata(md, ct_md, self.config),
|
2024-06-20 16:47:10 -07:00
|
|
|
tags_written=self.config.Runtime_Options__tags_write,
|
|
|
|
tags_read=tags_read,
|
2023-12-17 15:51:43 -08:00
|
|
|
)
|
2024-04-27 16:43:51 -07:00
|
|
|
assert res.md
|
2015-02-12 14:57:46 -08:00
|
|
|
# ok, done building our metadata. time to save
|
2024-06-20 16:47:10 -07:00
|
|
|
if self.write_tags(ca, res.md):
|
2023-12-17 15:51:43 -08:00
|
|
|
match_results.good_matches.append(res)
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
2023-12-17 15:51:43 -08:00
|
|
|
res.status = Status.write_failure
|
|
|
|
match_results.write_failures.append(res)
|
2024-04-26 21:12:06 -07:00
|
|
|
return res, match_results
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
def rename(self, ca: ComicArchive) -> Result:
|
2022-08-19 20:20:37 -07:00
|
|
|
original_path = ca.path
|
2015-02-12 14:57:46 -08:00
|
|
|
msg_hdr = ""
|
2022-11-26 16:47:18 -08:00
|
|
|
if self.batch_mode:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
msg_hdr = f"{ca.path}: "
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-06-20 16:47:10 -07:00
|
|
|
md, tags_read = self.create_local_metadata(ca, self.config.Runtime_Options__tags_read)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
if md.series is None:
|
2022-04-04 18:59:26 -07:00
|
|
|
logger.error(msg_hdr + "Can't rename without series name")
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.rename, Status.read_failure, original_path)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-05-17 13:57:04 -07:00
|
|
|
new_ext = "" # default
|
2024-01-22 17:00:59 -08:00
|
|
|
if self.config.File_Rename__auto_extension:
|
2022-08-17 15:53:19 -07:00
|
|
|
new_ext = ca.extension()
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-11-23 22:16:46 -08:00
|
|
|
renamer = FileRenamer(
|
2024-04-27 19:25:33 -07:00
|
|
|
None,
|
2024-02-06 16:02:12 -08:00
|
|
|
platform="universal" if self.config.File_Rename__strict_filenames else "auto",
|
2023-11-19 23:14:40 -08:00
|
|
|
replacements=self.config.File_Rename__replacements,
|
2022-11-23 22:16:46 -08:00
|
|
|
)
|
2024-04-27 19:25:33 -07:00
|
|
|
renamer.set_metadata(md, ca.path.name)
|
2023-11-19 23:14:40 -08:00
|
|
|
renamer.set_template(self.config.File_Rename__template)
|
|
|
|
renamer.set_issue_zero_padding(self.config.File_Rename__issue_number_padding)
|
|
|
|
renamer.set_smart_cleanup(self.config.File_Rename__use_smart_string_cleanup)
|
2024-04-27 19:25:33 -07:00
|
|
|
renamer.move = self.config.File_Rename__move
|
|
|
|
renamer.move_only = self.config.File_Rename__only_move
|
2022-04-18 18:44:20 -07:00
|
|
|
|
|
|
|
try:
|
2022-04-18 18:59:17 -07:00
|
|
|
new_name = renamer.determine_name(ext=new_ext)
|
2022-07-27 23:24:34 -07:00
|
|
|
except ValueError:
|
2022-04-20 13:13:03 -07:00
|
|
|
logger.exception(
|
2023-12-17 15:51:43 -08:00
|
|
|
msg_hdr
|
|
|
|
+ "Invalid format string!\n"
|
|
|
|
+ "Your rename template is invalid!\n\n"
|
|
|
|
+ "%s\n\n"
|
|
|
|
+ "Please consult the template help in the settings "
|
|
|
|
+ "and the documentation on the format at "
|
|
|
|
+ "https://docs.python.org/3/library/string.html#format-string-syntax",
|
2023-11-19 23:14:40 -08:00
|
|
|
self.config.File_Rename__template,
|
2022-04-18 18:44:20 -07:00
|
|
|
)
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.rename, Status.rename_failure, original_path, md=md)
|
2022-07-27 23:24:34 -07:00
|
|
|
except Exception:
|
2023-11-19 23:14:40 -08:00
|
|
|
logger.exception("Formatter failure: %s metadata: %s", self.config.File_Rename__template, renamer.metadata)
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.rename, Status.rename_failure, original_path, md=md)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2024-04-27 19:25:33 -07:00
|
|
|
folder = get_rename_dir(ca, self.config.File_Rename__dir if self.config.File_Rename__move else None)
|
2022-04-18 18:44:20 -07:00
|
|
|
|
2022-07-09 22:27:45 -07:00
|
|
|
full_path = folder / new_name
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-07-09 22:27:45 -07:00
|
|
|
if full_path == ca.path:
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(msg_hdr + "Filename is already good!")
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.rename, Status.success, original_path, full_path, md=md)
|
2022-04-18 18:44:20 -07:00
|
|
|
|
2015-02-12 14:57:46 -08:00
|
|
|
suffix = ""
|
2023-11-19 23:14:40 -08:00
|
|
|
if not self.config.Runtime_Options__dryrun:
|
2015-02-12 14:57:46 -08:00
|
|
|
# rename the file
|
2022-09-17 01:28:26 -07:00
|
|
|
try:
|
|
|
|
ca.rename(utils.unique_file(full_path))
|
|
|
|
except OSError:
|
|
|
|
logger.exception("Failed to rename comic archive: %s", ca.path)
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.rename, Status.write_failure, original_path, full_path, md=md)
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
|
|
|
suffix = " (dry-run, no change)"
|
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(f"renamed '{original_path.name}' -> '{new_name}' {suffix}")
|
2024-06-20 16:47:10 -07:00
|
|
|
return Result(Action.rename, Status.success, original_path, tags_read=tags_read, md=md)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
def export(self, ca: ComicArchive) -> Result:
|
2015-02-12 14:57:46 -08:00
|
|
|
msg_hdr = ""
|
2022-11-26 16:47:18 -08:00
|
|
|
if self.batch_mode:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
msg_hdr = f"{ca.path}: "
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-07-09 22:27:45 -07:00
|
|
|
if ca.is_zip():
|
|
|
|
logger.error(msg_hdr + "Archive is already a zip file.")
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.export, Status.success, ca.path)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-11-26 16:47:18 -08:00
|
|
|
filename_path = ca.path
|
2022-07-09 22:27:45 -07:00
|
|
|
new_file = filename_path.with_suffix(".cbz")
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-11-19 23:14:40 -08:00
|
|
|
if self.config.Runtime_Options__abort_on_conflict and new_file.exists():
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(msg_hdr + f"{new_file.name} already exists in the that folder.")
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.export, Status.write_failure, ca.path)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2022-07-09 22:27:45 -07:00
|
|
|
new_file = utils.unique_file(new_file)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
delete_success = False
|
|
|
|
export_success = False
|
2023-11-19 23:14:40 -08:00
|
|
|
if not self.config.Runtime_Options__dryrun:
|
2024-06-22 20:21:01 -07:00
|
|
|
if ca.export_as_zip(new_file):
|
|
|
|
export_success = True
|
2024-01-22 17:00:59 -08:00
|
|
|
if self.config.Runtime_Options__delete_original:
|
2015-02-12 14:57:46 -08:00
|
|
|
try:
|
2022-07-09 22:27:45 -07:00
|
|
|
filename_path.unlink(missing_ok=True)
|
|
|
|
delete_success = True
|
2022-06-02 18:32:16 -07:00
|
|
|
except OSError:
|
2022-07-09 22:27:45 -07:00
|
|
|
logger.exception(msg_hdr + "Error deleting original archive after export")
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
|
|
|
# last export failed, so remove the zip, if it exists
|
2022-07-09 22:27:45 -07:00
|
|
|
new_file.unlink(missing_ok=True)
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
msg = msg_hdr + f"Dry-run: Would try to create {os.path.split(new_file)[1]}"
|
2024-01-22 17:00:59 -08:00
|
|
|
if self.config.Runtime_Options__delete_original:
|
2022-06-07 20:22:33 -07:00
|
|
|
msg += " and delete original."
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(msg)
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.export, Status.success, ca.path, new_file)
|
2015-02-12 14:57:46 -08:00
|
|
|
|
|
|
|
msg = msg_hdr
|
|
|
|
if export_success:
|
Code cleanup
Remove no longer used google scripts
Remove convenience files from comicataggerlib and import comicapi directly
Add type-hints to facilitate auto-complete tools
Make PyQt5 code more compatible with PyQt6
Implement automatic tooling
isort and black for code formatting
Line length has been set to 120
flake8 for code standards with exceptions:
E203 - Whitespace before ':' - format compatiblity with black
E501 - Line too long - flake8 line limit cannot be set
E722 - Do not use bare except - fixing bare except statements is a
lot of overhead and there are already
many in the codebase
These changes, along with some manual fixes creates much more readable code.
See examples below:
diff --git a/comicapi/comet.py b/comicapi/comet.py
index d1741c5..52dc195 100644
--- a/comicapi/comet.py
+++ b/comicapi/comet.py
@@ -166,7 +166,2 @@ class CoMet:
- if credit['role'].lower() in set(self.editor_synonyms):
- ET.SubElement(
- root,
- 'editor').text = "{0}".format(
- credit['person'])
@@ -174,2 +169,4 @@ class CoMet:
self.indent(root)
+ if credit["role"].lower() in set(self.editor_synonyms):
+ ET.SubElement(root, "editor").text = str(credit["person"])
diff --git a/comictaggerlib/autotagmatchwindow.py b/comictaggerlib/autotagmatchwindow.py
index 4338176..9219f01 100644
--- a/comictaggerlib/autotagmatchwindow.py
+++ b/comictaggerlib/autotagmatchwindow.py
@@ -63,4 +63,3 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
self.skipButton, QtWidgets.QDialogButtonBox.ActionRole)
- self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setText(
- "Accept and Write Tags")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setText("Accept and Write Tags")
diff --git a/comictaggerlib/cli.py b/comictaggerlib/cli.py
index 688907d..dbd0c2e 100644
--- a/comictaggerlib/cli.py
+++ b/comictaggerlib/cli.py
@@ -293,7 +293,3 @@ def process_file_cli(filename, opts, settings, match_results):
if opts.raw:
- print((
- "{0}".format(
- str(
- ca.readRawCIX(),
- errors='ignore'))))
+ print(ca.read_raw_cix())
else:
2022-04-01 16:50:46 -07:00
|
|
|
msg += f"Archive exported successfully to: {os.path.split(new_file)[1]}"
|
2024-01-22 17:00:59 -08:00
|
|
|
if self.config.Runtime_Options__delete_original and delete_success:
|
2018-09-19 13:05:39 -07:00
|
|
|
msg += " (Original deleted) "
|
2015-02-12 14:57:46 -08:00
|
|
|
else:
|
2018-09-19 13:05:39 -07:00
|
|
|
msg += "Archive failed to export!"
|
2015-02-12 14:57:46 -08:00
|
|
|
|
2023-12-17 15:51:43 -08:00
|
|
|
self.output(msg)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
return Result(Action.export, Status.success, ca.path, new_file)
|
|
|
|
|
2024-04-26 21:12:06 -07:00
|
|
|
def process_file_cli(
|
|
|
|
self, command: Action, filename: str, match_results: OnlineMatchResults
|
|
|
|
) -> tuple[Result, OnlineMatchResults]:
|
2022-11-26 16:47:18 -08:00
|
|
|
if not os.path.lexists(filename):
|
|
|
|
logger.error("Cannot find %s", filename)
|
2024-04-26 21:12:06 -07:00
|
|
|
return Result(command, Status.read_failure, pathlib.Path(filename)), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-01-31 00:01:50 -08:00
|
|
|
ca = ComicArchive(filename, str(graphics_path / "nocover.png"))
|
2022-11-26 16:47:18 -08:00
|
|
|
|
|
|
|
if not ca.seems_to_be_a_comic_archive():
|
|
|
|
logger.error("Sorry, but %s is not a comic archive!", filename)
|
2024-04-26 21:12:06 -07:00
|
|
|
return Result(Action.rename, Status.read_failure, ca.path), match_results
|
2023-12-17 16:16:21 -08:00
|
|
|
|
|
|
|
if not ca.is_writable() and (command in (Action.delete, Action.copy, Action.save, Action.rename)):
|
2022-11-26 16:47:18 -08:00
|
|
|
logger.error("This archive is not writable")
|
2024-04-26 21:12:06 -07:00
|
|
|
return Result(command, Status.write_permission_failure, ca.path), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
if command == Action.print:
|
2024-04-26 21:12:06 -07:00
|
|
|
return self.print(ca), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
elif command == Action.delete:
|
2024-04-26 21:12:06 -07:00
|
|
|
return self.delete(ca), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
elif command == Action.copy is not None:
|
2024-04-26 21:12:06 -07:00
|
|
|
return self.copy(ca), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
elif command == Action.save:
|
2023-12-17 15:51:43 -08:00
|
|
|
return self.save(ca, match_results)
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
elif command == Action.rename:
|
2024-04-26 21:12:06 -07:00
|
|
|
return self.rename(ca), match_results
|
2022-11-26 16:47:18 -08:00
|
|
|
|
2023-12-17 16:16:21 -08:00
|
|
|
elif command == Action.export:
|
2024-04-26 21:12:06 -07:00
|
|
|
return self.export(ca), match_results
|
|
|
|
return Result(None, Status.read_failure, ca.path), match_results # type: ignore[arg-type]
|