Use casefold in place of lower
Make lint job fail if errors are detected
Use join instead of utils.list_to_string
Simplify get_recursive_filelist with the glob library
Fix handling of un-parseable numbers in xlate
This commit is contained in:
Timmy Welch 2022-07-01 16:22:01 -07:00
parent 3d84af3746
commit 68efcc74fb
21 changed files with 94 additions and 100 deletions

View File

@ -45,7 +45,7 @@ jobs:
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: nightly
- run: flake8 | reviewdog -f=flake8 -reporter=github-pr-review -tee -level=error
- run: flake8 | reviewdog -f=flake8 -reporter=github-pr-review -tee -level=error -fail-on-error
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -98,25 +98,25 @@ class CoMet:
# loop thru credits, and build a list for each role that CoMet supports
for credit in metadata.credits:
if credit["role"].lower() in set(self.writer_synonyms):
if credit["role"].casefold() in set(self.writer_synonyms):
ET.SubElement(root, "writer").text = str(credit["person"])
if credit["role"].lower() in set(self.penciller_synonyms):
if credit["role"].casefold() in set(self.penciller_synonyms):
ET.SubElement(root, "penciller").text = str(credit["person"])
if credit["role"].lower() in set(self.inker_synonyms):
if credit["role"].casefold() in set(self.inker_synonyms):
ET.SubElement(root, "inker").text = str(credit["person"])
if credit["role"].lower() in set(self.colorist_synonyms):
if credit["role"].casefold() in set(self.colorist_synonyms):
ET.SubElement(root, "colorist").text = str(credit["person"])
if credit["role"].lower() in set(self.letterer_synonyms):
if credit["role"].casefold() in set(self.letterer_synonyms):
ET.SubElement(root, "letterer").text = str(credit["person"])
if credit["role"].lower() in set(self.cover_synonyms):
if credit["role"].casefold() in set(self.cover_synonyms):
ET.SubElement(root, "coverDesigner").text = str(credit["person"])
if credit["role"].lower() in set(self.editor_synonyms):
if credit["role"].casefold() in set(self.editor_synonyms):
ET.SubElement(root, "editor").text = str(credit["person"])
ET.indent(root)
@ -177,7 +177,7 @@ class CoMet:
for n in root:
if n.tag == "character":
char_list.append((n.text or "").strip())
md.characters = utils.list_to_string(char_list)
md.characters = ", ".join(char_list)
# Now extract the credit info
for n in root:

View File

@ -935,7 +935,7 @@ class ComicArchive:
self.page_list = []
for name in files:
if (
os.path.splitext(name)[1].lower() in [".jpg", ".jpeg", ".png", ".gif", ".webp"]
os.path.splitext(name)[1].casefold() in [".jpg", ".jpeg", ".png", ".gif", ".webp"]
and os.path.basename(name)[0] != "."
):
self.page_list.append(name)
@ -1146,7 +1146,7 @@ class ComicArchive:
# look at all xml files in root, and search for CoMet data, get first
for n in self.archiver.get_filename_list():
if os.path.dirname(n) == "" and os.path.splitext(n)[1].lower() == ".xml":
if os.path.dirname(n) == "" and os.path.splitext(n)[1].casefold() == ".xml":
# read in XML file, and validate it
try:
data = ""

View File

@ -116,41 +116,41 @@ class ComicInfoXml:
# supports
for credit in metadata.credits:
if credit["role"].lower() in set(self.writer_synonyms):
if credit["role"].casefold() in set(self.writer_synonyms):
credit_writer_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.penciller_synonyms):
if credit["role"].casefold() in set(self.penciller_synonyms):
credit_penciller_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.inker_synonyms):
if credit["role"].casefold() in set(self.inker_synonyms):
credit_inker_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.colorist_synonyms):
if credit["role"].casefold() in set(self.colorist_synonyms):
credit_colorist_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.letterer_synonyms):
if credit["role"].casefold() in set(self.letterer_synonyms):
credit_letterer_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.cover_synonyms):
if credit["role"].casefold() in set(self.cover_synonyms):
credit_cover_list.append(credit["person"].replace(",", ""))
if credit["role"].lower() in set(self.editor_synonyms):
if credit["role"].casefold() in set(self.editor_synonyms):
credit_editor_list.append(credit["person"].replace(",", ""))
# second, convert each list to string, and add to XML struct
assign("Writer", utils.list_to_string(credit_writer_list))
assign("Writer", ", ".join(credit_writer_list))
assign("Penciller", utils.list_to_string(credit_penciller_list))
assign("Penciller", ", ".join(credit_penciller_list))
assign("Inker", utils.list_to_string(credit_inker_list))
assign("Inker", ", ".join(credit_inker_list))
assign("Colorist", utils.list_to_string(credit_colorist_list))
assign("Colorist", ", ".join(credit_colorist_list))
assign("Letterer", utils.list_to_string(credit_letterer_list))
assign("Letterer", ", ".join(credit_letterer_list))
assign("CoverArtist", utils.list_to_string(credit_cover_list))
assign("CoverArtist", ", ".join(credit_cover_list))
assign("Editor", utils.list_to_string(credit_editor_list))
assign("Editor", ", ".join(credit_editor_list))
assign("Publisher", md.publisher)
assign("Imprint", md.imprint)
@ -231,7 +231,7 @@ class ComicInfoXml:
md.critical_rating = utils.xlate(get("CommunityRating"), is_float=True)
tmp = utils.xlate(get("BlackAndWhite"))
if tmp is not None and tmp.lower() in ["yes", "true", "1"]:
if tmp is not None and tmp.casefold() in ["yes", "true", "1"]:
md.black_and_white = True
# Now extract the credit info
for n in root:

View File

@ -280,9 +280,9 @@ def lex_text(lex: Lexer) -> Callable:
if is_alpha_numeric(r):
if r.isnumeric(): # E.g. v1
word = lex.input[lex.start : lex.pos]
if word.lower() in key and key[word.lower()] == ItemType.InfoSpecifier:
if word.casefold() in key and key[word.casefold()] == ItemType.InfoSpecifier:
lex.backup()
lex.emit(key[word.lower()])
lex.emit(key[word.casefold()])
return lex_filename
else:
if r == "'" and lex.peek() == "s":
@ -290,12 +290,12 @@ def lex_text(lex: Lexer) -> Callable:
else:
lex.backup()
word = lex.input[lex.start : lex.pos + 1]
if word.lower() == "vol" and lex.peek() == ".":
if word.casefold() == "vol" and lex.peek() == ".":
lex.get()
word = lex.input[lex.start : lex.pos + 1]
if word.lower() in key:
lex.emit(key[word.lower()])
if word.casefold() in key:
lex.emit(key[word.casefold()])
elif cal(word):
lex.emit(ItemType.Calendar)
else:

View File

@ -529,7 +529,7 @@ def parse(p: Parser) -> Callable[[Parser], Callable | None] | None:
# Matches the extension if it is known to be an archive format e.g. cbt,cbz,zip,rar
elif item.typ == filenamelexer.ItemType.ArchiveType:
p.filename_info["archive"] = item.val.lower()
p.filename_info["archive"] = item.val.casefold()
if p.peek_back().typ == filenamelexer.ItemType.Dot:
p.used_items.append(p.peek_back())
p.used_items.append(item)
@ -554,7 +554,10 @@ def parse(p: Parser) -> Callable[[Parser], Callable | None] | None:
if p.peek().typ == filenamelexer.ItemType.Space:
p.get()
if p.series_parts and "free comic book" in (" ".join([x.val for x in p.series_parts]) + " " + item.val).lower():
if (
p.series_parts
and "free comic book" in (" ".join([x.val for x in p.series_parts]) + " " + item.val).casefold()
):
p.filename_info["fcbd"] = True
series_append = True
# If the next item is a number it's probably the volume
@ -563,7 +566,7 @@ def parse(p: Parser) -> Callable[[Parser], Callable | None] | None:
):
number = p.get()
# Mark volume info. Text will be added to the title/series later
if item.val.lower() in ["book", "tpb"]:
if item.val.casefold() in ["book", "tpb"]:
p.title_parts.extend([item, number])
p.filename_info["volume"] = t2do.convert(number.val)
p.filename_info["issue"] = t2do.convert(number.val)
@ -572,7 +575,7 @@ def parse(p: Parser) -> Callable[[Parser], Callable | None] | None:
series_append = False
# Annuals usually mean the year
elif item.val.lower() in ["annual"]:
elif item.val.casefold() in ["annual"]:
p.filename_info["annual"] = True
num = t2d.convert(number.val)
if num.isnumeric() and len(num) == 4:
@ -580,7 +583,7 @@ def parse(p: Parser) -> Callable[[Parser], Callable | None] | None:
else:
p.backup()
elif item.val.lower() in ["annual"]:
elif item.val.casefold() in ["annual"]:
p.filename_info["annual"] = True
# If we don't have a reason to exclude it from the series go back to parsing the series immediately
@ -717,7 +720,7 @@ def parse_series(p: Parser) -> Callable[[Parser], Callable | None] | None:
# We stop parsing the series when certain things come up if nothing was done with them continue where we left off
if (
p.series_parts
and p.series_parts[-1].val.lower() == "book"
and p.series_parts[-1].val.casefold() == "book"
or p.peek_back().typ == filenamelexer.ItemType.Number
or item.typ == filenamelexer.ItemType.Calendar
):
@ -746,7 +749,7 @@ def parse_series(p: Parser) -> Callable[[Parser], Callable | None] | None:
# Handle Volume
elif item.typ == filenamelexer.ItemType.InfoSpecifier:
# Exception for 'of'
if item.val.lower() == "of":
if item.val.casefold() == "of":
series[current_part].append(item)
else:
# This specifically lets 'X-Men-V1-067' parse correctly as Series: X-Men Volume: 1 Issue: 67
@ -789,7 +792,7 @@ def parse_series(p: Parser) -> Callable[[Parser], Callable | None] | None:
p.backup() # The number
break
# This is 6 in '1 of 6'
if series[current_part] and series[current_part][-1].val.lower() == "of":
if series[current_part] and series[current_part][-1].val.casefold() == "of":
series[current_part].append(item)
# We have 1 number break here, it's possible it's the issue
@ -1021,13 +1024,13 @@ def parse_info_specifier(p: Parser) -> Callable[[Parser], Callable | None] | Non
):
number = p.get()
if item.val.lower() in ["volume", "vol", "vol.", "v"]:
if item.val.casefold() in ["volume", "vol", "vol.", "v"]:
p.filename_info["volume"] = t2do.convert(number.val)
p.used_items.append(item)
p.used_items.append(number)
# 'of' is only special if it is inside a parenthesis.
elif item.val.lower() == "of":
elif item.val.casefold() == "of":
i = get_number(p, index)
if i is not None:
if p.in_something > 0:

View File

@ -209,7 +209,7 @@ class GenericMetadata:
# Remove credit role if person is blank
if c["person"] == "":
for r in reversed(self.credits):
if r["role"].lower() == c["role"].lower():
if r["role"].casefold() == c["role"].casefold():
self.credits.remove(r)
# otherwise, add it!
else:
@ -249,7 +249,7 @@ class GenericMetadata:
# look to see if it's not already there...
found = False
for c in self.credits:
if c["person"].lower() == person.lower() and c["role"].lower() == role.lower():
if c["person"].casefold() == person.casefold() and c["role"].casefold() == role.casefold():
# no need to add it. just adjust the "primary" flag as needed
c["primary"] = primary
found = True
@ -261,8 +261,8 @@ class GenericMetadata:
def get_primary_credit(self, role: str) -> str:
primary = ""
for credit in self.credits:
if (primary == "" and credit["role"].lower() == role.lower()) or (
credit["role"].lower() == role.lower() and credit["primary"]
if (primary == "" and credit["role"].casefold() == role.casefold()) or (
credit["role"].casefold() == role.casefold() and credit["primary"]
):
primary = credit["person"]
return primary
@ -319,7 +319,7 @@ class GenericMetadata:
add_attr_string("comments")
add_attr_string("notes")
add_string("tags", utils.list_to_string(self.tags))
add_string("tags", ", ".join(self.tags))
for c in self.credits:
primary = ""
@ -351,12 +351,12 @@ class GenericMetadata:
self.publisher = publisher
if self.imprint.lower() in publisher.lower():
if self.imprint.casefold() in publisher.casefold():
self.imprint = None
if self.imprint is None or self.imprint == "":
self.imprint = imprint
elif self.imprint.lower() in imprint.lower():
elif self.imprint.casefold() in imprint.casefold():
self.imprint = imprint

View File

@ -14,6 +14,7 @@
# limitations under the License.
from __future__ import annotations
import glob
import json
import logging
import os
@ -36,36 +37,17 @@ class UtilsVars:
def get_recursive_filelist(pathlist: list[str]) -> list[str]:
"""Get a recursive list of of all files under all path items in the list"""
filelist = []
filelist: list[str] = []
for p in pathlist:
# if path is a folder, walk it recursively, and all files underneath
if not isinstance(p, str):
# it's probably a QString
p = str(p)
if os.path.isdir(p):
for root, _, files in os.walk(p):
for f in files:
if not isinstance(f, str):
# it's probably a QString
f = str(f)
filelist.append(os.path.join(root, f))
filelist.extend(x for x in glob.glob(f"{p}{os.sep}/**", recursive=True) if not os.path.isdir(x))
else:
filelist.append(p)
return filelist
def list_to_string(lst: list[str | Any]) -> str:
string = ""
if lst is not None:
for item in lst:
if len(string) > 0:
string += ", "
string += item
return string
def add_to_path(dirname: str) -> None:
if dirname is not None and dirname != "":
@ -89,15 +71,18 @@ def xlate(data: Any, is_int: bool = False, is_float: bool = False) -> Any:
i = str(data).translate(defaultdict(lambda: None, zip((ord(c) for c in "1234567890."), "1234567890.")))
if i == "":
return None
if is_float:
return float(i)
return int(float(i))
try:
if is_float:
return float(i)
return int(float(i))
except ValueError:
return None
return str(data)
def remove_articles(text: str) -> str:
text = text.lower()
text = text.casefold()
articles = [
"&",
"a",

View File

@ -31,7 +31,7 @@ class CBLTransformer:
def apply(self) -> GenericMetadata:
# helper funcs
def append_to_tags_if_unique(item: str) -> None:
if item.lower() not in (tag.lower() for tag in self.metadata.tags):
if item.casefold() not in (tag.casefold() for tag in self.metadata.tags):
self.metadata.tags.append(item)
def add_string_list_to_tags(str_list: str | None) -> None:
@ -47,7 +47,7 @@ class CBLTransformer:
lone_credit: CreditMetadata | None = None
count = 0
for c in self.metadata.credits:
if c["role"].lower() in role_list:
if c["role"].casefold() in role_list:
count += 1
lone_credit = c
if count > 1:

View File

@ -21,7 +21,6 @@ import os
import sqlite3 as lite
from typing import Any
from comicapi import utils
from comictaggerlib import ctversion
from comictaggerlib.resulttypes import CVIssuesResults, CVVolumeResults, SelectDetails
from comictaggerlib.settings import ComicTaggerSettings
@ -130,7 +129,7 @@ class ComicVineCacher:
cur = con.cursor()
# remove all previous entries with this search term
cur.execute("DELETE FROM VolumeSearchCache WHERE search_term = ?", [search_term.lower()])
cur.execute("DELETE FROM VolumeSearchCache WHERE search_term = ?", [search_term.casefold()])
# now add in new results
for record in cv_search_results:
@ -150,7 +149,7 @@ class ComicVineCacher:
+ "(search_term, id, name, start_year, publisher, count_of_issues, image_url, description) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
(
search_term.lower(),
search_term.casefold(),
record["id"],
record["name"],
record["start_year"],
@ -174,7 +173,7 @@ class ComicVineCacher:
cur.execute("DELETE FROM VolumeSearchCache WHERE timestamp < ?", [str(a_day_ago)])
# fetch
cur.execute("SELECT * FROM VolumeSearchCache WHERE search_term=?", [search_term.lower()])
cur.execute("SELECT * FROM VolumeSearchCache WHERE search_term=?", [search_term.casefold()])
rows = cur.fetchall()
# now process the results
for record in rows:
@ -205,7 +204,7 @@ class ComicVineCacher:
# remove all previous entries with this search term
cur.execute("DELETE FROM AltCovers WHERE issue_id = ?", [issue_id])
url_list_str = utils.list_to_string(url_list)
url_list_str = ", ".join(url_list)
# now add in new record
cur.execute("INSERT INTO AltCovers (issue_id, url_list) VALUES(?, ?)", (issue_id, url_list_str))

View File

@ -428,7 +428,10 @@ class ComicVineTalker:
for record in issues_list_results:
if IssueString(issue_number).as_string() is None:
issue_number = "1"
if IssueString(record["issue_number"]).as_string().lower() == IssueString(issue_number).as_string().lower():
if (
IssueString(record["issue_number"]).as_string().casefold()
== IssueString(issue_number).as_string().casefold()
):
f_record = record
break
@ -497,26 +500,26 @@ class ComicVineTalker:
character_list = []
for character in character_credits:
character_list.append(character["name"])
metadata.characters = utils.list_to_string(character_list)
metadata.characters = ", ".join(character_list)
team_credits = issue_results["team_credits"]
team_list = []
for team in team_credits:
team_list.append(team["name"])
metadata.teams = utils.list_to_string(team_list)
metadata.teams = ", ".join(team_list)
location_credits = issue_results["location_credits"]
location_list = []
for location in location_credits:
location_list.append(location["name"])
metadata.locations = utils.list_to_string(location_list)
metadata.locations = ", ".join(location_list)
story_arc_credits = issue_results["story_arc_credits"]
arc_list = []
for arc in story_arc_credits:
arc_list.append(arc["name"])
if len(arc_list) > 0:
metadata.story_arc = utils.list_to_string(arc_list)
metadata.story_arc = ", ".join(arc_list)
return metadata

View File

@ -77,7 +77,7 @@ class CreditEditorWindow(QtWidgets.QDialog):
def current_role_can_be_primary(self) -> bool:
role = self.cbRole.currentText()
if str(role).lower() == "writer" or str(role).lower() == "artist":
if role.casefold() in ("artist", "writer"):
return True
return False

View File

@ -77,7 +77,7 @@ class MetadataFormatter(string.Formatter):
lstrip = False
# if there's a field, output it
if field_name is not None and field_name != "":
field_name = field_name.lower()
field_name = field_name.casefold()
# this is some markup, find the object and do the formatting
# handle arg indexing when empty field_names are given.
@ -170,7 +170,7 @@ class FileRenamer:
for Component in pathlib.PureWindowsPath(template).parts:
if (
self.platform.lower() in ["universal", "windows"] or sys.platform.lower() in ["windows"]
self.platform.casefold() in ["universal", "windows"] or sys.platform.casefold() in ["windows"]
) and self.smart_cleanup:
# colons get special treatment
Component = Component.replace(": ", " - ")

View File

@ -98,7 +98,7 @@ class IssueIdentifier:
self.length_delta_thresh = settings.id_length_delta_thresh
# used to eliminate unlikely publishers
self.publisher_filter = [s.strip().lower() for s in settings.id_publisher_filter.split(",")]
self.publisher_filter = [s.strip().casefold() for s in settings.id_publisher_filter.split(",")]
self.additional_metadata = GenericMetadata()
self.output_function: Callable[[str], None] = IssueIdentifier.default_write_output
@ -445,7 +445,7 @@ class IssueIdentifier:
# remove any series from publishers on the filter
if item["publisher"] is not None:
publisher = item["publisher"]["name"]
if publisher is not None and publisher.lower() in self.publisher_filter:
if publisher is not None and publisher.casefold() in self.publisher_filter:
publisher_approved = False
if length_approved and publisher_approved and date_approved:

View File

@ -146,8 +146,8 @@ class IssueSelectionWindow(QtWidgets.QDialog):
self.twList.setItem(row, 2, QTW_item)
if (
IssueString(record["issue_number"]).as_string().lower()
== IssueString(self.issue_number).as_string().lower()
IssueString(record["issue_number"]).as_string().casefold()
== IssueString(self.issue_number).as_string().casefold()
):
self.initial_id = record["id"]

View File

@ -281,7 +281,7 @@ def parse_metadata_from_string(mdstr: str) -> GenericMetadata:
key, value = i.split("=")
value = value.replace(replacement_token, "=").strip()
key = key.strip()
if key.lower() == "credit":
if key.casefold() == "credit":
cred_attribs = value.split(":")
role = cred_attribs[0]
person = cred_attribs[1] if len(cred_attribs) > 1 else ""

View File

@ -151,7 +151,7 @@ class SettingsWindow(QtWidgets.QDialog):
self.name = "Preferences"
self.setWindowTitle("ComicTagger " + self.name)
self.lblDefaultSettings.setText("Revert to default " + self.name.lower())
self.lblDefaultSettings.setText("Revert to default " + self.name.casefold())
self.btnResetSettings.setText("Default " + self.name)
nldt_tip = """<html>The <b>Default Name Length Match Tolerance</b> is for eliminating automatic

View File

@ -848,7 +848,7 @@ Have fun!
else:
self.cbBW.setChecked(False)
self.teTags.setText(utils.list_to_string(md.tags))
self.teTags.setText(", ".join(md.tags))
self.twCredits.setRowCount(0)
@ -1157,7 +1157,7 @@ Have fun!
# loop over credit table, mark selected rows
r = 0
for r in range(self.twCredits.rowCount()):
if str(self.twCredits.item(r, 1).text()).lower() not in cix_credits:
if str(self.twCredits.item(r, 1).text()).casefold() not in cix_credits:
self.twCredits.item(r, 1).setBackground(inactive_brush)
else:
self.twCredits.item(r, 1).setBackground(active_brush)
@ -1269,7 +1269,10 @@ Have fun!
role = str(self.twCredits.item(row, 1).text())
r = 0
for r in range(self.twCredits.rowCount()):
if self.twCredits.item(r, 0).text() != "" and str(self.twCredits.item(r, 1).text()).lower() == role.lower():
if (
self.twCredits.item(r, 0).text() != ""
and str(self.twCredits.item(r, 1).text()).casefold() == role.casefold()
):
self.twCredits.item(r, 0).setText("")
# Now set our new primary

View File

@ -351,11 +351,11 @@ class VolumeSelectionWindow(QtWidgets.QDialog):
# filter the publishers if enabled set
if self.use_filter:
try:
publisher_filter = {s.strip().lower() for s in self.settings.id_publisher_filter.split(",")}
publisher_filter = {s.strip().casefold() for s in self.settings.id_publisher_filter.split(",")}
# use '' as publisher name if None
self.cv_search_results = list(
filter(
lambda d: ("" if d["publisher"] is None else str(d["publisher"]["name"]).lower())
lambda d: ("" if d["publisher"] is None else str(d["publisher"]["name"]).casefold())
not in publisher_filter,
self.cv_search_results,
)

View File

@ -71,7 +71,7 @@ def main():
# now sort the list by issue, and then series
metadata_list.sort(key=lambda x: IssueString(x[1].issue).asString(3), reverse=False)
metadata_list.sort(key=lambda x: unicode(x[1].series).lower() + str(x[1].year), reverse=False)
metadata_list.sort(key=lambda x: unicode(x[1].series).casefold() + str(x[1].year), reverse=False)
# now print
for filename, md in metadata_list:

View File

@ -34,6 +34,7 @@ values = [
({"data": None, "is_int": True, "is_float": False}, None),
({"data": " ", "is_int": True, "is_float": False}, None),
({"data": "", "is_int": True, "is_float": False}, None),
({"data": "9..", "is_int": True, "is_float": False}, None),
({"data": "9", "is_int": False, "is_float": False}, "9"),
({"data": 9, "is_int": False, "is_float": False}, "9"),
({"data": 9, "is_int": True, "is_float": False}, 9),