Add basic logging

This commit is contained in:
Timmy Welch 2022-04-04 18:59:26 -07:00
parent 2db80399a6
commit c50cef568e
41 changed files with 289 additions and 98 deletions

View File

@ -14,11 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import xml.etree.ElementTree as ET
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata
logger = logging.getLogger(__name__)
class CoMet:

View File

@ -47,6 +47,9 @@ from comicapi.filenameparser import FileNameParser
from comicapi.genericmetadata import GenericMetadata, PageType
logger = logging.getLogger(__name__)
if not pil_available:
logger.exception("PIL unavalable")
sys.path.insert(0, os.path.abspath("."))
@ -77,10 +80,10 @@ class SevenZipArchiver:
with py7zr.SevenZipFile(self.path, "r") as zf:
data = zf.read(archive_file)[archive_file].read()
except py7zr.Bad7zFile as e:
logger.waning("bad 7zip file [%s]: %s :: %s", e, self.path, archive_file)
logger.error("bad 7zip file [%s]: %s :: %s", e, self.path, archive_file)
raise IOError
except Exception as e:
logger.waning("bad 7zip file [%s]: %s :: %s", e, self.path, archive_file)
logger.error("bad 7zip file [%s]: %s :: %s", e, self.path, archive_file)
raise IOError
return data
@ -116,7 +119,7 @@ class SevenZipArchiver:
return namelist
except Exception as e:
logger.warning("Unable to get 7zip file list [%s]: %s", e, self.path)
logger.error("Unable to get 7zip file list [%s]: %s", e, self.path)
return []
def rebuild_zip_file(self, exclude_list):
@ -134,8 +137,8 @@ class SevenZipArchiver:
with py7zr.SevenZipFile(tmp_name, "w") as zout:
for fname, bio in zin.read(targets).items():
zout.writef(bio, fname)
except Exception as e:
logger.warning("Exception[%s]: %s", e, self.path)
except Exception:
logger.exception("Error rebuilding 7zip file: %s", self.path)
return []
# replace with the new file
@ -151,7 +154,7 @@ class SevenZipArchiver:
if data is not None:
zout.writestr(data, fname)
except Exception as e:
logger.warning("Error while copying to %s: %s", self.path, e)
logger.exception("Error while copying to %s: %s", self.path, e)
return False
else:
return True
@ -180,10 +183,10 @@ class ZipArchiver:
try:
data = zf.read(archive_file)
except zipfile.BadZipfile as e:
logger.warning("bad zipfile [%s]: %s :: %s", e, self.path, archive_file)
logger.error("bad zipfile [%s]: %s :: %s", e, self.path, archive_file)
raise IOError from e
except Exception as e:
logger.warning("bad zipfile [%s]: %s :: %s", e, self.path, archive_file)
logger.error("bad zipfile [%s]: %s :: %s", e, self.path, archive_file)
raise IOError from e
return data
@ -209,7 +212,7 @@ class ZipArchiver:
zf.writestr(archive_file, data)
return True
except Exception as e:
logger.warning("writing zip file failed [%s]: %s", e, self.path)
logger.error("writing zip file failed [%s]: %s", e, self.path)
return False
def get_filename_list(self):
@ -218,7 +221,7 @@ class ZipArchiver:
namelist = zf.namelist()
return namelist
except Exception as e:
logger.warning("Unable to get zipfile list [%s]: %s", e, self.path)
logger.error("Unable to get zipfile list [%s]: %s", e, self.path)
return []
def rebuild_zip_file(self, exclude_list):
@ -229,15 +232,19 @@ class ZipArchiver:
tmp_fd, tmp_name = tempfile.mkstemp(dir=os.path.dirname(self.path))
os.close(tmp_fd)
with zipfile.ZipFile(self.path, "r") as zin:
with zipfile.ZipFile(tmp_name, "w", allowZip64=True) as zout:
for item in zin.infolist():
buffer = zin.read(item.filename)
if item.filename not in exclude_list:
zout.writestr(item, buffer)
try:
with zipfile.ZipFile(self.path, "r") as zin:
with zipfile.ZipFile(tmp_name, "w", allowZip64=True) as zout:
for item in zin.infolist():
buffer = zin.read(item.filename)
if item.filename not in exclude_list:
zout.writestr(item, buffer)
# preserve the old comment
zout.comment = zin.comment
# preserve the old comment
zout.comment = zin.comment
except Exception:
logger.exception("Error rebuilding 7zip file: %s", self.path)
return []
# replace with the new file
os.remove(self.path)
@ -299,6 +306,7 @@ class ZipArchiver:
else:
raise Exception("Failed to write comment to zip file!")
except Exception:
logger.exception()
return False
else:
return True
@ -317,8 +325,8 @@ class ZipArchiver:
if comment is not None:
if not self.write_zip_comment(self.path, comment):
return False
except Exception as e:
logger.warning("Error while copying to %s: %s", self.path, e)
except Exception:
logger.exception("Error while copying to %s", self.path)
return False
else:
return True
@ -371,8 +379,8 @@ class RarArchiver:
if platform.system() == "Darwin":
time.sleep(1)
os.remove(tmp_name)
except Exception as e:
logger.warning(e)
except Exception:
logger.exception("Failed to set a comment")
return False
else:
return True
@ -401,10 +409,10 @@ class RarArchiver:
)
continue
except (OSError, IOError) as e:
logger.warning("read_file(): [%s] %s:%s attempt #%d", e, self.path, archive_file, tries)
logger.error("read_file(): [%s] %s:%s attempt #%d", e, self.path, archive_file, tries)
time.sleep(1)
except Exception as e:
logger.warning(
logger.error(
"Unexpected exception in read_file(): [%s] for %s:%s attempt #%d", e, self.path, archive_file, tries
)
break
@ -489,7 +497,7 @@ class RarArchiver:
namelist.append(item.filename)
except (OSError, IOError) as e:
logger.warning(f"get_filename_list(): [{e}] {self.path} attempt #{tries}".format(str(e), self.path, tries))
logger.error(f"get_filename_list(): [{e}] {self.path} attempt #{tries}".format(str(e), self.path, tries))
time.sleep(1)
else:
@ -505,7 +513,7 @@ class RarArchiver:
rarc = rarfile.RarFile(self.path)
except (OSError, IOError) as e:
logger.warning("getRARObj(): [%s] %s attempt #%s", e, self.path, tries)
logger.error("getRARObj(): [%s] %s attempt #%s", e, self.path, tries)
time.sleep(1)
else:
@ -537,7 +545,7 @@ class FolderArchiver:
data = f.read()
f.close()
except IOError:
pass
logger.exception("Failed to read: %s", fname)
return data
@ -549,6 +557,7 @@ class FolderArchiver:
f.write(data)
f.close()
except:
logger.exception("Failed to read: %s", fname)
return False
else:
return True
@ -559,6 +568,7 @@ class FolderArchiver:
try:
os.remove(fname)
except:
logger.exception("Failed to read: %s", fname)
return False
else:
return True
@ -787,7 +797,7 @@ class ComicArchive:
try:
image_data = self.archiver.read_file(filename)
except IOError:
logger.warning("Error reading in page. Substituting logo page.")
logger.exception("Error reading in page. Substituting logo page.")
image_data = ComicArchive.logo_data
return image_data
@ -815,7 +825,7 @@ class ComicArchive:
if count < 5:
return None
# count the length of every filename, and count occurences
# count the length of every filename, and count occurrences
length_buckets = {}
for name in name_list:
fname = os.path.split(name)[1]
@ -828,7 +838,7 @@ class ComicArchive:
# sort by most common
sorted_buckets = sorted(iter(length_buckets.items()), key=lambda k_v: (k_v[1], k_v[0]), reverse=True)
# statistical mode occurence is first
# statistical mode occurrence is first
mode_length = sorted_buckets[0][0]
# we are only going to consider the final image file:
@ -955,7 +965,7 @@ class ComicArchive:
try:
raw_cix = self.archiver.read_file(self.ci_xml_filename)
except IOError as e:
logger.warning("Error reading in raw CIX!: %s", e)
logger.error("Error reading in raw CIX!: %s", e)
raw_cix = ""
return raw_cix
@ -1022,15 +1032,13 @@ class ComicArchive:
def read_raw_comet(self):
if not self.has_comet():
err_msg = self.path + " doesn't have CoMet data!"
logger.info(err_msg)
logger.info("%s doesn't have CoMet data!", self.path)
return None
try:
raw_comet = self.archiver.read_file(self.comet_filename)
except IOError as e:
err_msg = f"Error reading in raw CoMet!: {e}"
logger.warning(err_msg)
except:
logger.exception("Error reading in raw CoMet!")
raw_comet = ""
return raw_comet
@ -1110,7 +1118,8 @@ class ComicArchive:
p["ImageSize"] = str(len(data))
p["ImageHeight"] = str(h)
p["ImageWidth"] = str(w)
except IOError:
except Exception as e:
logger.warning("decoding image failed: %s", e)
p["ImageSize"] = str(len(data))
else:

View File

@ -15,12 +15,15 @@
# limitations under the License.
import json
import logging
from collections import defaultdict
from datetime import datetime
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata
logger = logging.getLogger(__name__)
class ComicBookInfo:
def metadata_from_string(self, string):

View File

@ -14,12 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import xml.etree.ElementTree as ET
from comicapi import utils
from comicapi.genericmetadata import GenericMetadata
from comicapi.issuestring import IssueString
logger = logging.getLogger(__name__)
class ComicInfoXml:

View File

@ -20,10 +20,13 @@ This should probably be re-written, but, well, it mostly works!
# Some portions of this code were modified from pyComicMetaThis project
# http://code.google.com/p/pycomicmetathis/
import logging
import os
import re
from urllib.parse import unquote
logger = logging.getLogger(__name__)
class FileNameParser:
def __init__(self):

View File

@ -20,10 +20,13 @@ possible, however lossy it might be
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import List, TypedDict
from comicapi import utils
logger = logging.getLogger(__name__)
class PageType:

View File

@ -20,6 +20,11 @@ comics industry throws at us.
# limitations under the License.
import logging
logger = logging.getLogger(__name__)
class IssueString:
def __init__(self, text):

View File

@ -16,6 +16,7 @@
import codecs
import locale
import logging
import os
import platform
import re
@ -25,6 +26,8 @@ from collections import defaultdict
import pycountry
logger = logging.getLogger(__name__)
class UtilsVars:
already_fixed_encoding = False

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
from typing import List, Optional
@ -25,6 +26,8 @@ from comictaggerlib.resulttypes import MultipleMatch
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class AutoTagMatchWindow(QtWidgets.QDialog):
volume_id = 0

View File

@ -15,12 +15,16 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class AutoTagProgressWindow(QtWidgets.QDialog):
def __init__(self, parent):

View File

@ -15,10 +15,14 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class AutoTagStartWindow(QtWidgets.QDialog):
def __init__(self, parent, settings, msg):

View File

@ -13,8 +13,13 @@
# 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.
import logging
from comicapi.genericmetadata import GenericMetadata
logger = logging.getLogger(__name__)
class CBLTransformer:
def __init__(self, metadata: GenericMetadata, settings):

View File

@ -17,6 +17,7 @@
# limitations under the License.
import json
import logging
import os
import sys
from pprint import pprint
@ -32,6 +33,7 @@ from comictaggerlib.resulttypes import MultipleMatch, OnlineMatchResults
from comictaggerlib.settings import ComicTaggerSettings
filename_encoding = sys.getfilesystemencoding()
logger = logging.getLogger(__name__)
def actual_issue_data_fetch(match, settings, opts):
@ -41,7 +43,7 @@ def actual_issue_data_fetch(match, settings, opts):
comic_vine.wait_for_rate_limit = opts.wait_and_retry_on_rate_limit
cv_md = comic_vine.fetch_issue_data(match["volume_id"], match["issue_number"], settings)
except ComicVineTalkerException:
print("Network error while getting issue details. Save aborted", file=sys.stderr)
logger.exception("Network error while getting issue details. Save aborted")
return None
if settings.apply_cbl_transform_on_cv_import:
@ -54,15 +56,18 @@ def actual_metadata_save(ca: ComicArchive, opts, md):
if not opts.dryrun:
# write out the new data
if not ca.write_metadata(md, opts.data_style):
print("The tag save seemed to fail!", file=sys.stderr)
logger.error("The tag save seemed to fail!")
return False
print("Save complete.", file=sys.stderr)
print("Save complete.")
logger.info("Save complete.")
else:
if opts.terse:
print("dry-run option was set, so nothing was written", file=sys.stderr)
logger.info("dry-run option was set, so nothing was written")
print("dry-run option was set, so nothing was written")
else:
print("dry-run option was set, so nothing was written, but here is the final set of tags:", file=sys.stderr)
logger.info("dry-run option was set, so nothing was written, but here is the final set of tags:")
print("dry-run option was set, so nothing was written, but here is the final set of tags:")
print(f"{md}")
return True
@ -147,7 +152,7 @@ def post_process_matches(match_results: OnlineMatchResults, opts, settings):
def cli_mode(opts, settings):
if len(opts.file_list) < 1:
print("You must specify at least one filename. Use the -h option for more info", file=sys.stderr)
logger.error("You must specify at least one filename. Use the -h option for more info")
return
match_results = OnlineMatchResults()
@ -183,15 +188,15 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
ca = ComicArchive(filename, settings.rar_exe_path, ComicTaggerSettings.get_graphic("nocover.png"))
if not os.path.lexists(filename):
print("Cannot find " + filename, file=sys.stderr)
logger.error("Cannot find " + filename)
return
if not ca.seems_to_be_a_comic_archive():
print(f"Sorry, but {filename} is not a comic archive!", file=sys.stderr)
logger.error("Sorry, but %s is not a comic archive!", filename)
return
if not ca.is_writable() and (opts.delete_tags or opts.copy_tags or opts.save_tags or opts.rename_file):
print("This archive is not writable for that tag type", file=sys.stderr)
logger.error("This archive is not writable for that tag type")
return
has = [False, False, False]
@ -328,12 +333,12 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
comic_vine.wait_for_rate_limit = opts.wait_and_retry_on_rate_limit
cv_md = comic_vine.fetch_issue_data_by_issue_id(opts.issue_id, settings)
except ComicVineTalkerException:
print("Network error while getting issue details. Save aborted", file=sys.stderr)
logger.exception("Network error while getting issue details. Save aborted")
match_results.fetch_data_failures.append(ca.path)
return
if cv_md is None:
print(f"No match for ID {opts.issue_id} was found.", file=sys.stderr)
logger.error("No match for ID %s was found.", opts.issue_id)
match_results.no_matches.append(ca.path)
return
@ -343,7 +348,7 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
ii = IssueIdentifier(ca, settings)
if md is None or md.is_empty:
print("No metadata given to search online with!", file=sys.stderr)
logger.error("No metadata given to search online with!")
match_results.no_matches.append(ca.path)
return
@ -382,19 +387,19 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
if choices:
if low_confidence:
print("Online search: Multiple low confidence matches. Save aborted", file=sys.stderr)
logger.error("Online search: Multiple low confidence matches. Save aborted")
match_results.low_confidence_matches.append(MultipleMatch(ca, matches))
return
print("Online search: Multiple good matches. Save aborted", file=sys.stderr)
logger.error("Online search: Multiple good matches. Save aborted")
match_results.multiple_matches.append(MultipleMatch(ca, matches))
return
if low_confidence and opts.abortOnLowConfidence:
print("Online search: Low confidence match. Save aborted", file=sys.stderr)
logger.error("Online search: Low confidence match. Save aborted")
match_results.low_confidence_matches.append(MultipleMatch(ca, matches))
return
if not found_match:
print("Online search: No match found. Save aborted", file=sys.stderr)
logger.error("Online search: No match found. Save aborted")
match_results.no_matches.append(ca.path)
return
@ -428,7 +433,7 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
md = create_local_metadata(opts, ca, use_tags)
if md.series is None:
print(msg_hdr + "Can't rename without series name", file=sys.stderr)
logger.error(msg_hdr + "Can't rename without series name")
return
new_ext = None # default
@ -448,7 +453,7 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
new_name = renamer.determine_name(ca.path, ext=new_ext)
if new_name == os.path.basename(ca.path):
print(msg_hdr + "Filename is already good!", file=sys.stderr)
logger.error(msg_hdr + "Filename is already good!")
return
folder = os.path.dirname(os.path.abspath(ca.path))
@ -469,7 +474,7 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
msg_hdr = f"{ca.path}: "
if not ca.is_rar():
print(msg_hdr + "Archive is not a RAR.", file=sys.stderr)
logger.error(msg_hdr + "Archive is not a RAR.")
return
rar_file = os.path.abspath(os.path.abspath(filename))
@ -490,7 +495,7 @@ def process_file_cli(filename, opts, settings, match_results: OnlineMatchResults
try:
os.unlink(rar_file)
except:
print(msg_hdr + "Error deleting original RAR after export", file=sys.stderr)
logger.exception(msg_hdr + "Error deleting original RAR after export")
delete_success = False
else:
delete_success = True

View File

@ -15,6 +15,7 @@
# limitations under the License.
import datetime
import logging
import os
import sqlite3 as lite
@ -22,6 +23,8 @@ from comicapi import utils
from comictaggerlib import ctversion
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class ComicVineCacher:
def __init__(self):

View File

@ -15,6 +15,7 @@
# limitations under the License.
import json
import logging
import re
import sys
import time
@ -30,6 +31,8 @@ from comicapi.issuestring import IssueString
from comictaggerlib import ctversion
from comictaggerlib.comicvinecacher import ComicVineCacher
logger = logging.getLogger(__name__)
try:
from PyQt5 import QtCore, QtNetwork
@ -37,6 +40,8 @@ try:
except ImportError:
qt_available = False
logger = logging.getLogger(__name__)
class SelectDetails(TypedDict):
image_url: str
@ -115,7 +120,7 @@ class ComicVineTalker:
def write_log(self, text):
if self.log_func is None:
print(text, file=sys.stderr)
logger.info(text, file=sys.stderr)
else:
self.log_func(text)
@ -599,7 +604,7 @@ class ComicVineTalker:
except:
# we caught an error rebuilding the table.
# just bail and remove the formatting
print("table parse error")
logger.exception("table parse error")
newstring.replace("{}", "")
return newstring
@ -743,12 +748,11 @@ class ComicVineTalker:
try:
cv_response = json.loads(bytes(data))
except Exception:
print("Comic Vine query failed to get JSON data", file=sys.stderr)
print(str(data), file=sys.stderr)
logger.exception("Comic Vine query failed to get JSON data\n%s", str(data))
return
if cv_response["status_code"] != 1:
print("Comic Vine query failed with error: [{0}]. ".format(cv_response["error"]), file=sys.stderr)
logger.error("Comic Vine query failed with error: [%s]. ", cv_response["error"])
return
image_url = cv_response["results"]["image"]["super_url"]

View File

@ -19,6 +19,8 @@ TODO: This should be re-factored using subclasses!
# limitations under the License.
import logging
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from comicapi.comicarchive import ComicArchive
@ -29,6 +31,8 @@ from comictaggerlib.pageloader import PageLoader
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import get_qimage_from_data, reduce_widget_font_size
logger = logging.getLogger(__name__)
def clickable(widget):
"""Allow a label to be clickable"""

View File

@ -15,10 +15,14 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class CreditEditorWindow(QtWidgets.QDialog):
ModeEdit = 0

View File

@ -15,10 +15,14 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class ExportConflictOpts:
dontCreate = 1

View File

@ -15,12 +15,15 @@
# limitations under the License.
import datetime
import logging
import os
import re
from comicapi.genericmetadata import GenericMetadata
from comicapi.issuestring import IssueString
logger = logging.getLogger(__name__)
class FileRenamer:
def __init__(self, metadata):

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
from typing import List
@ -24,6 +25,8 @@ from comicapi.comicarchive import ComicArchive
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import center_window_on_parent, reduce_widget_font_size
logger = logging.getLogger(__name__)
class FileTableWidgetItem(QtWidgets.QTableWidgetItem):
def __lt__(self, other):

View File

@ -30,9 +30,13 @@ except ImportError:
qt_available = False
import logging
from comictaggerlib import ctversion
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class ImageFetcherException(Exception):
pass
@ -81,10 +85,9 @@ class ImageFetcher:
if blocking or not qt_available:
if image_data is None:
try:
print(url)
image_data = requests.get(url, headers={"user-agent": "comictagger/" + ctversion.version}).content
except Exception as e:
print(e)
logger.exception("Fetching url failed: %s")
raise ImageFetcherException("Network Error!") from e
# save the image to the cache
@ -106,7 +109,7 @@ class ImageFetcher:
def finish_request(self, reply):
# read in the image data
print("request finished")
logger.debug("request finished")
image_data = reply.readAll()
# save the image to the cache

View File

@ -15,6 +15,7 @@
# limitations under the License.
import io
import logging
from functools import reduce
try:
@ -23,6 +24,7 @@ try:
pil_available = True
except ImportError:
pil_available = False
logger = logging.getLogger(__name__)
class ImageHasher:
@ -38,16 +40,16 @@ class ImageHasher:
self.image = Image.open(path)
else:
self.image = Image.open(io.BytesIO(data))
except Exception as e:
print(f"Image data seems corrupted! [{e}]")
except Exception:
logger.exception("Image data seems corrupted!")
# just generate a bogus image
self.image = Image.new("L", (1, 1))
def average_hash(self):
try:
image = self.image.resize((self.width, self.height), Image.ANTIALIAS).convert("L")
except Exception as e:
print("average_hash error:", e)
except Exception:
logger.exception("average_hash error")
return int(0)
pixels = list(image.getdata())

View File

@ -15,10 +15,14 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class ImagePopup(QtWidgets.QDialog):
def __init__(self, parent, image_pixmap):

View File

@ -15,6 +15,7 @@
# limitations under the License.
import io
import logging
import sys
from typing import List, TypedDict
@ -27,6 +28,8 @@ from comictaggerlib.imagefetcher import ImageFetcher, ImageFetcherException
from comictaggerlib.imagehasher import ImageHasher
from comictaggerlib.resulttypes import IssueResult
logger = logging.getLogger(__name__)
try:
from PIL import Image
@ -141,8 +144,8 @@ class IssueIdentifier:
try:
cropped_im = im.crop((int(w / 2), 0, w, h))
except Exception as e:
print("cropCover() error:", e)
except:
logger.exception("cropCover() error")
return None
output = io.BytesIO()

View File

@ -15,6 +15,8 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from comicapi.issuestring import IssueString
@ -23,6 +25,8 @@ from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class IssueNumberTableWidgetItem(QtWidgets.QTableWidgetItem):
def __lt__(self, other):

View File

@ -15,10 +15,14 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class LogWindow(QtWidgets.QDialog):
def __init__(self, parent):

View File

@ -14,28 +14,58 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import logging.handlers
import os
import pathlib
import platform
import signal
import sys
import traceback
import pkg_resources
from comictaggerlib import cli
from comictaggerlib.comicvinetalker import ComicVineTalker
from comictaggerlib.ctversion import version
from comictaggerlib.options import Options
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger("comictagger")
logging.getLogger("comicapi").setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
try:
qt_available = True
from PyQt5 import QtGui, QtWidgets
from comictaggerlib.taggerwindow import TaggerWindow
except ImportError as e:
print(e)
logging.debug(e)
qt_available = False
def rotate(handler: logging.handlers.RotatingFileHandler, filename: pathlib.Path):
if filename.is_file() and filename.stat().st_size > 0:
handler.doRollover()
def ctmain():
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.WARNING)
file_handler = logging.handlers.RotatingFileHandler(
ComicTaggerSettings.get_settings_folder() / "logs" / "ComicTagger.log", encoding="utf-8", backupCount=10
)
rotate(file_handler, ComicTaggerSettings.get_settings_folder() / "logs" / "ComicTagger.log")
logging.basicConfig(
handlers=[
stream_handler,
file_handler,
],
level=logging.WARNING,
format="%(asctime)s | %(name)s | %(levelname)s | %(message)s",
datefmt="%Y-%m-%dT%H:%M:%S",
)
opts = Options()
opts.parse_cmd_line_args()
@ -55,12 +85,27 @@ def ctmain():
signal.signal(signal.SIGINT, signal.SIG_DFL)
logger.info(
"ComicTagger Version: %s running on: %s PyInstaller: %s",
version,
platform.system(),
"Yes" if getattr(sys, "frozen", None) else "No",
)
logger.debug("Installed Packages")
for pkg in sorted(pkg_resources.working_set, key=lambda x: x.project_name):
logger.debug("%s\t%s", pkg.project_name, pkg.version)
if not qt_available and not opts.no_gui:
opts.no_gui = True
print("PyQt5 is not available. ComicTagger is limited to command-line mode.", file=sys.stderr)
print("PyQt5 is not available. ComicTagger is limited to command-line mode.")
logger.info("PyQt5 is not available. ComicTagger is limited to command-line mode.")
if opts.no_gui:
cli.cli_mode(opts, SETTINGS)
try:
cli.cli_mode(opts, SETTINGS)
except:
logger.exception()
else:
os.environ["QtWidgets.QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
args = []
@ -103,7 +148,7 @@ def ctmain():
sys.exit(app.exec())
except Exception:
print(traceback.format_exc())
logger.exception()
QtWidgets.QMessageBox.critical(
QtWidgets.QMainWindow(), "Error", "Unhandled exception in app:\n" + traceback.format_exc()
)

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
from PyQt5 import QtCore, QtWidgets, uic
@ -22,6 +23,8 @@ from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class MatchSelectionWindow(QtWidgets.QDialog):
volume_id = 0

View File

@ -25,8 +25,12 @@ said_yes, checked = OptionalMessageDialog.question(self, "QtWidgets.Question",
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets
logger = logging.getLogger(__name__)
StyleMessage = 0
StyleQuestion = 1

View File

@ -15,17 +15,18 @@
# limitations under the License.
import getopt
import logging
import os
import platform
import sys
import traceback
from datetime import datetime
from comicapi import utils
from comicapi.comicarchive import MetaDataStyle
from comicapi.genericmetadata import GenericMetadata
from comictaggerlib import ctversion
logger = logging.getLogger(__name__)
class Options:
help_text = """Usage: {0} [option] ... [file [files ...]]
@ -192,7 +193,7 @@ For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki
# Map the dict to the metadata object
for key, value in md_dict.items():
if not hasattr(md, key):
print(f"Warning: '{key}' is not a valid tag name")
logger.warning("'%s' is not a valid tag name", key)
else:
md.is_empty = False
setattr(md, key, value)
@ -210,7 +211,7 @@ For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki
break
sys.argv = script_args
if not os.path.exists(scriptfile):
print(f"Can't find {scriptfile}")
logger.error("Can't find %s", scriptfile)
else:
# I *think* this makes sense:
# assume the base name of the file is the module name
@ -225,10 +226,9 @@ For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki
if "main" in dir(script):
script.main()
else:
print(f"Can't find entry point 'main()' in module '{module_name}'")
except Exception as e:
print("Script raised an unhandled exception: ", e)
print(traceback.format_exc())
logger.error("Can't find entry point 'main()' in module '%s'", module_name)
except Exception:
logger.exception("Script: %s raised an unhandled exception: ", module_name)
sys.exit(0)
@ -360,7 +360,7 @@ For more help visit the wiki at: https://github.com/comictagger/comictagger/wiki
if o == "--only-set-cv-key":
self.only_set_key = True
if o == "--version":
print(f"ComicTagger {ctversion.version}: Copyright (c) 2012-{datetime.today():%Y} ComicTagger Team")
print(f"ComicTagger {ctversion.version}: Copyright (c) 2012-2022 ComicTagger Team")
print("Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)")
sys.exit(0)
if o in ("-t", "--type"):

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import platform
from PyQt5 import QtCore, QtGui, QtWidgets, uic
@ -22,6 +23,8 @@ from comicapi.comicarchive import ComicArchive
from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
class PageBrowserWindow(QtWidgets.QDialog):
def __init__(self, parent, metadata):

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Optional
from PyQt5 import QtCore, QtGui, QtWidgets, uic
@ -23,6 +24,8 @@ from comicapi.genericmetadata import PageType
from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
def item_move_events(widget):
class Filter(QtCore.QObject):

View File

@ -14,10 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from PyQt5 import QtCore
from comicapi.comicarchive import ComicArchive
logger = logging.getLogger(__name__)
class PageLoader(QtCore.QThread):
"""

View File

@ -15,11 +15,15 @@
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class IDProgressWindow(QtWidgets.QDialog):
def __init__(self, parent):

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
from typing import List
@ -27,6 +28,8 @@ from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.settingswindow import SettingsWindow
from comictaggerlib.ui.qtutils import center_window_on_parent
logger = logging.getLogger(__name__)
class RenameWindow(QtWidgets.QDialog):
def __init__(self, parent, comic_archive_list: List[comicapi.comicarchive.ComicArchive], data_style, settings):
@ -149,6 +152,7 @@ class RenameWindow(QtWidgets.QDialog):
if item["new_name"] == os.path.basename(item["archive"].path):
print(item["new_name"], "Filename is already good!")
logger.info(item["new_name"], "Filename is already good!")
continue
if not item["archive"].is_writable(check_rar_status=False):

View File

@ -15,13 +15,17 @@
# limitations under the License.
import configparser
import logging
import os
import pathlib
import platform
import sys
import uuid
from comicapi import utils
logger = logging.getLogger(__name__)
class ComicTaggerSettings:
@staticmethod
@ -30,18 +34,18 @@ class ComicTaggerSettings:
folder = os.path.join(os.environ["APPDATA"], "ComicTagger")
else:
folder = os.path.join(os.path.expanduser("~"), ".ComicTagger")
return folder
return pathlib.Path(folder)
@staticmethod
def base_dir():
if getattr(sys, "frozen", None):
return sys._MEIPASS
return os.path.dirname(os.path.abspath(__file__))
return pathlib.Path(__file__).parent
@staticmethod
def get_graphic(filename):
graphic_folder = os.path.join(ComicTaggerSettings.base_dir(), "graphics")
graphic_folder = pathlib.Path(os.path.join(ComicTaggerSettings.base_dir(), "graphics"))
return os.path.join(graphic_folder, filename)
@staticmethod

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
import platform
@ -25,6 +26,8 @@ from comictaggerlib.comicvinetalker import ComicVineTalker
from comictaggerlib.imagefetcher import ImageFetcher
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
windowsRarHelp = """
<html><head/><body><p>To write to CBR/RAR archives,
you will need to have the tools from

View File

@ -15,6 +15,7 @@
# limitations under the License.
import json
import logging
import operator
import os
import pickle
@ -58,6 +59,8 @@ from comictaggerlib.ui.qtutils import center_window_on_parent, reduce_widget_fon
from comictaggerlib.versionchecker import VersionChecker
from comictaggerlib.volumeselectionwindow import VolumeSelectionWindow
logger = logging.getLogger(__name__)
def execute(f: callable):
f()
@ -79,6 +82,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
alive = socket.waitForConnected(3000)
if alive:
print(f"Another application with key [{settings.install_id}] is already running")
logger.info(f"Another application with key [{settings.install_id}] is already running")
# send file list to other instance
if file_list:
socket.write(pickle.dumps(file_list))
@ -96,8 +100,10 @@ class TaggerWindow(QtWidgets.QMainWindow):
self.socketServer.removeServer(settings.install_id)
ok = self.socketServer.listen(settings.install_id)
if not ok:
print(
f"Cannot start local socket with key [{settings.install_id}]. Reason: {self.socketServer.errorString()}"
logger.error(
"Cannot start local socket with key [%s]. Reason: %s",
settings.install_id,
self.socketServer.errorString(),
)
sys.exit()
@ -404,6 +410,7 @@ Have fun!
QtWidgets.QMessageBox.information(
self, self.tr("Export as Zip Archive"), self.tr("No RAR archives selected!")
)
logger.warning("Export as Zip Archive. No RAR archives selected")
return
if not self.dirty_flag_verification(
@ -496,6 +503,7 @@ Please choose options below, and select OK.
for f in failed_list:
summary += f"\t{f}\n"
logger.info(summary)
dlg = LogWindow(self)
dlg.set_text(summary)
dlg.setWindowTitle("Archive Export to Zip Summary")
@ -1050,7 +1058,6 @@ Please choose options below, and select OK.
"Change Tag Read Style", "If you change read tag style now, data in the form will be lost. Are you sure?"
):
self.load_data_style = self.cbLoadDataStyle.itemData(s)
print("load style:", self.load_data_style)
self.settings.last_selected_load_data_style = self.load_data_style
self.update_menus()
if self.comic_archive is not None:
@ -1062,7 +1069,6 @@ Please choose options below, and select OK.
def set_save_data_style(self, s):
self.save_data_style = self.cbSaveDataStyle.itemData(s)
self.settings.last_selected_save_data_style = self.save_data_style
self.update_style_tweaks()
self.update_menus()
@ -1603,7 +1609,7 @@ Please choose options below, and select OK.
comic_vine.wait_for_rate_limit = self.settings.wait_and_retry_on_rate_limit
cv_md = comic_vine.fetch_issue_data(match["volume_id"], match["issue_number"], self.settings)
except ComicVineTalkerException:
print("Network error while getting issue details. Save aborted")
logger.exception("Network error while getting issue details. Save aborted")
if cv_md is not None:
if self.settings.apply_cbl_transform_on_cv_import:
@ -1641,7 +1647,7 @@ Please choose options below, and select OK.
md.series = dlg.search_string
if md is None or md.is_empty:
print("No metadata given to search online with!")
logger.error("No metadata given to search online with!")
return False, match_results
if dlg.dont_use_year:
@ -1831,6 +1837,7 @@ Please choose options below, and select OK to Auto-Tag.
else:
QtWidgets.QMessageBox.information(self, self.tr("Auto-Tag Summary"), self.tr(summary))
logger.info(summary)
def dirty_flag_verification(self, title, desc):
if self.dirty_flag:

View File

@ -1,9 +1,12 @@
"""Some utilities for the GUI"""
import io
import logging
from comictaggerlib.settings import ComicTaggerSettings
logger = logging.getLogger(__name__)
try:
from PyQt5 import QtGui

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import platform
import sys
@ -21,6 +22,8 @@ import requests
from comictaggerlib import ctversion
logger = logging.getLogger(__name__)
class VersionChecker:
def get_request_url(self, uuid, use_stats):

View File

@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtCore import pyqtSignal
@ -29,6 +30,8 @@ from comictaggerlib.progresswindow import IDProgressWindow
from comictaggerlib.settings import ComicTaggerSettings
from comictaggerlib.ui.qtutils import reduce_widget_font_size
logger = logging.getLogger(__name__)
class SearchThread(QtCore.QThread):
searchComplete = pyqtSignal()
@ -296,7 +299,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
self.progdialog.exec()
def search_canceled(self):
print("query cancelled")
logger.info("query cancelled")
self.search_thread.searchComplete.disconnect(self.search_complete)
self.search_thread.progressUpdate.disconnect(self.search_progress_update)
self.progdialog.canceled.disconnect(self.search_canceled)
@ -336,7 +339,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
)
)
except:
print("bad data error filtering filter publishers")
logger.exception("bad data error filtering filter publishers")
# pre sort the data - so that we can put exact matches first afterwards
# compare as str incase extra chars ie. '1976?'
@ -350,14 +353,14 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
reverse=True,
)
except:
print("bad data error sorting results by start_year,count_of_issues")
logger.exception("bad data error sorting results by start_year,count_of_issues")
else:
try:
self.cv_search_results = sorted(
self.cv_search_results, key=lambda i: str(i["count_of_issues"]), reverse=True
)
except:
print("bad data error sorting results by count_of_issues")
logger.exception("bad data error sorting results by count_of_issues")
# move sanitized matches to the front
if self.settings.exact_series_matches_first:
@ -371,7 +374,7 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
)
self.cv_search_results = exact_matches + non_matches
except:
print("bad data error filtering exact/near matches")
logger.exception("bad data error filtering exact/near matches")
self.update_buttons()