Implement support for protofolius's permission scheme

This commit is contained in:
Timmy Welch 2023-09-06 04:50:05 -04:00
parent 0a2340b6dc
commit f6be7919d7
12 changed files with 352 additions and 86 deletions

View File

@ -22,7 +22,7 @@ import shutil
import sys
from typing import cast
from comicapi import filenamelexer, filenameparser, utils
from comicapi import utils
from comicapi.archivers import Archiver, UnknownArchiver, ZipArchiver
from comicapi.comet import CoMet
from comicapi.comicbookinfo import ComicBookInfo
@ -541,53 +541,39 @@ class ComicArchive:
remove_fcbd: bool = False,
remove_publisher: bool = False,
split_words: bool = False,
allow_issue_start_with_letter: bool = False,
protofolius_issue_number_scheme: bool = False,
) -> GenericMetadata:
metadata = GenericMetadata()
filename = self.path.name
if split_words:
import wordninja
filename_info = utils.parse_filename(
self.path.name,
complicated_parser=complicated_parser,
remove_c2c=remove_c2c,
remove_fcbd=remove_fcbd,
remove_publisher=remove_publisher,
split_words=split_words,
allow_issue_start_with_letter=allow_issue_start_with_letter,
protofolius_issue_number_scheme=protofolius_issue_number_scheme,
)
metadata.alternate_number = utils.xlate(filename_info.get("alternate", None))
metadata.issue = utils.xlate(filename_info.get("issue", None))
metadata.issue_count = utils.xlate_int(filename_info.get("issue_count", None))
metadata.publisher = utils.xlate(filename_info.get("publisher", None))
metadata.series = utils.xlate(filename_info.get("series", None))
metadata.title = utils.xlate(filename_info.get("title", None))
metadata.volume = utils.xlate_int(filename_info.get("volume", None))
metadata.volume_count = utils.xlate_int(filename_info.get("volume_count", None))
metadata.year = utils.xlate_int(filename_info.get("year", None))
filename = " ".join(wordninja.split(self.path.stem)) + self.path.suffix
if complicated_parser:
lex = filenamelexer.Lex(filename)
p = filenameparser.Parse(
lex.items, remove_c2c=remove_c2c, remove_fcbd=remove_fcbd, remove_publisher=remove_publisher
)
metadata.alternate_number = utils.xlate(p.filename_info["alternate"])
metadata.issue = utils.xlate(p.filename_info["issue"])
metadata.issue_count = utils.xlate_int(p.filename_info["issue_count"])
metadata.publisher = utils.xlate(p.filename_info["publisher"])
metadata.series = utils.xlate(p.filename_info["series"])
metadata.title = utils.xlate(p.filename_info["title"])
metadata.volume = utils.xlate_int(p.filename_info["volume"])
metadata.volume_count = utils.xlate_int(p.filename_info["volume_count"])
metadata.year = utils.xlate_int(p.filename_info["year"])
metadata.scan_info = utils.xlate(p.filename_info["remainder"])
metadata.format = "FCBD" if p.filename_info["fcbd"] else None
if p.filename_info["annual"]:
metadata.format = "Annual"
else:
fnp = filenameparser.FileNameParser()
fnp.parse_filename(filename)
if fnp.issue:
metadata.issue = fnp.issue
if fnp.series:
metadata.series = fnp.series
if fnp.volume:
metadata.volume = utils.xlate_int(fnp.volume)
if fnp.year:
metadata.year = utils.xlate_int(fnp.year)
if fnp.issue_count:
metadata.issue_count = utils.xlate_int(fnp.issue_count)
if fnp.remainder:
metadata.scan_info = fnp.remainder
metadata.scan_info = utils.xlate(filename_info.get("remainder", None))
metadata.format = "FCBD" if filename_info.get("fcbd", None) else None
if filename_info.get("annual", None):
metadata.format = "Annual"
if filename_info.get("format", None):
metadata.format = filename_info["format"]
metadata.is_empty = False
return metadata
def export_as_zip(self, zip_filename: pathlib.Path) -> bool:

View File

@ -87,7 +87,7 @@ class Item:
class Lexer:
def __init__(self, string: str) -> None:
def __init__(self, string: str, allow_issue_start_with_letter: bool = False) -> None:
self.input: str = string # The string being scanned
# The next lexing function to enter
self.state: Callable[[Lexer], Callable | None] | None = None # type: ignore[type-arg]
@ -98,6 +98,7 @@ class Lexer:
self.brace_depth: int = 0 # Nesting depth of { }
self.sbrace_depth: int = 0 # Nesting depth of [ ]
self.items: list[Item] = []
self.allow_issue_start_with_letter = allow_issue_start_with_letter
# Next returns the next rune in the input.
def get(self) -> str:
@ -196,7 +197,7 @@ def lex_filename(lex: Lexer) -> Callable[[Lexer], Callable | None] | None: # ty
return lex_space
elif r == ".":
r = lex.peek()
if r < "0" or "9" < r:
if not r.isdigit():
lex.emit(ItemType.Dot)
return lex_filename
@ -204,15 +205,17 @@ def lex_filename(lex: Lexer) -> Callable[[Lexer], Callable | None] | None: # ty
return lex_number
elif r == "'":
r = lex.peek()
if r in "0123456789":
if r.isdigit():
return lex_number
lex.emit(ItemType.Text) # TODO: Change to Text
elif "0" <= r <= "9":
lex.backup()
return lex_number
elif r == "#":
if "0" <= lex.peek() <= "9":
return lex_number
if lex.allow_issue_start_with_letter and is_alpha_numeric(lex.peek()):
return lex_issue_number
elif lex.peek().isdigit() or lex.peek() in "-+.":
return lex_issue_number
lex.emit(ItemType.Symbol)
elif is_operator(r):
if r == "-" and lex.peek() == "-":
@ -329,6 +332,28 @@ def lex_number(lex: Lexer) -> Callable[[Lexer], Callable | None] | None: # type
return lex_filename
def lex_issue_number(lex: Lexer) -> Callable[[Lexer], Callable | None] | None: # type: ignore[type-arg]
# Only called when lex.input[lex.start] == "#"
original_start = lex.pos
found_number = False
while True:
r = lex.get()
if is_alpha_numeric(r):
if r.isnumeric():
found_number = True
else:
lex.backup()
break
if not found_number:
lex.pos = original_start
lex.emit(ItemType.Symbol)
else:
lex.emit(ItemType.IssueNumber)
return lex_filename
def is_space(character: str) -> bool:
return character in "_ \t"
@ -346,7 +371,7 @@ def is_symbol(character: str) -> bool:
return unicodedata.category(character)[0] in "PS"
def Lex(filename: str) -> Lexer:
lex = Lexer(string=os.path.basename(filename))
def Lex(filename: str, allow_issue_start_with_letter: bool = False) -> Lexer:
lex = Lexer(os.path.basename(filename), allow_issue_start_with_letter)
lex.run()
return lex

View File

@ -324,6 +324,21 @@ class FilenameInfo(TypedDict, total=False):
volume: str
volume_count: str
year: str
format: str
protofolius_issue_number_scheme = {
"B": "biography/best of",
"C": "compact edition",
"E": "entrtainment/puzzle edition",
"F": "familiy book edition",
"J": "jubileum (anniversary) edition",
"P": "pocket edition",
"N": "newly brought out/restyled edition",
"O": "old editions (or oblong format)",
"S": "special edition",
"X": "X-rated edition",
}
eof = filenamelexer.Item(filenamelexer.ItemType.EOF, -1, "")
@ -341,6 +356,7 @@ class Parser:
remove_c2c: bool = False,
remove_fcbd: bool = False,
remove_publisher: bool = False,
protofolius_issue_number_scheme: bool = False,
) -> None:
self.state: Callable[[Parser], Callable | None] | None = None # type: ignore[type-arg]
self.pos = -1
@ -366,6 +382,7 @@ class Parser:
self.remove_c2c = remove_c2c
self.remove_fcbd = remove_fcbd
self.remove_publisher = remove_publisher
self.protofolius_issue_number_scheme = protofolius_issue_number_scheme
self.remove_from_remainder = []
if remove_c2c:
@ -923,6 +940,16 @@ def resolve_issue(p: Parser) -> None:
if "volume" in p.filename_info:
p.filename_info["issue"] = p.filename_info["volume"]
if (
"issue" in p.filename_info
and p.protofolius_issue_number_scheme
and len(p.filename_info["issue"]) > 1
and p.filename_info["issue"][0].isalpha()
and p.filename_info["issue"][0].upper() in protofolius_issue_number_scheme
and p.filename_info["issue"][1].isnumeric()
):
p.filename_info["format"] = protofolius_issue_number_scheme[p.filename_info["issue"][0].upper()]
def parse_finish(p: Parser) -> Callable[[Parser], Callable | None] | None: # type: ignore[type-arg]
resolve_year(p)
@ -941,7 +968,7 @@ def parse_finish(p: Parser) -> Callable[[Parser], Callable | None] | None: # ty
p.filename_info["series"] = join_title(p.series_parts)
p.used_items.extend(p.series_parts)
else:
p.filename_info["series"] = p.filename_info["issue"]
p.filename_info["series"] = p.filename_info.get("issue", "")
if "free comic book" in p.filename_info["series"].casefold():
p.filename_info["fcbd"] = True
@ -1137,6 +1164,7 @@ def Parse(
remove_c2c: bool = False,
remove_fcbd: bool = False,
remove_publisher: bool = False,
protofolius_issue_number_scheme: bool = False,
) -> Parser:
p = Parser(
lexer_result=lexer_result,
@ -1144,6 +1172,7 @@ def Parse(
remove_c2c=remove_c2c,
remove_fcbd=remove_fcbd,
remove_publisher=remove_publisher,
protofolius_issue_number_scheme=protofolius_issue_number_scheme,
)
p.run()
return p

View File

@ -32,6 +32,7 @@ class IssueString:
self.num = None
self.suffix = ""
self.prefix = ""
if text is None:
return
@ -41,18 +42,25 @@ class IssueString:
if len(text) == 0:
return
for idx, r in enumerate(text):
if not r.isalpha():
break
self.prefix = text[:idx]
self.num, self.suffix = self.get_number(text[idx:])
def get_number(self, text: str) -> tuple[float | None, str]:
num, suffix = None, ""
start = 0
# skip the minus sign if it's first
if text[0] == "-":
if text[0] in ("-", "+"):
start = 1
else:
start = 0
# if it's still not numeric at start skip it
if text[start].isdigit() or text[start] == ".":
# walk through the string, look for split point (the first non-numeric)
decimal_count = 0
for idx in range(start, len(text)):
if text[idx] not in "0123456789.":
if not (text[idx].isdigit() or text[idx] in "."):
break
# special case: also split on second "."
if text[idx] == ".":
@ -71,42 +79,48 @@ class IssueString:
if idx == 1 and start == 1:
idx = 0
part1 = text[0:idx]
part2 = text[idx : len(text)]
if part1 != "":
self.num = float(part1)
self.suffix = part2
if text[0:idx]:
num = float(text[0:idx])
suffix = text[idx : len(text)]
else:
self.suffix = text
suffix = text
return num, suffix
def as_string(self, pad: int = 0) -> str:
# return the float, left side zero-padded, with suffix attached
"""return the number, left side zero-padded, with suffix attached"""
# if there is no number return the text
if self.num is None:
return self.suffix
return self.prefix + self.suffix
# negative is added back in last
negative = self.num < 0
num_f = abs(self.num)
# used for padding
num_int = int(num_f)
num_s = str(num_int)
if float(num_int) != num_f:
num_s = str(num_f)
num_s += self.suffix
if num_f.is_integer():
num_s = str(num_int)
else:
num_s = str(num_f)
# create padding
padding = ""
# we only pad the whole number part, we don't care about the decimal
length = len(str(num_int))
if length < pad:
padding = "0" * (pad - length)
# add the padding to the front
num_s = padding + num_s
# finally add the negative back in
if negative:
num_s = "-" + num_s
return num_s
# return the prefix + formatted number + suffix
return self.prefix + num_s + self.suffix
def as_float(self) -> float | None:
# return the float, with no suffix

View File

@ -26,6 +26,7 @@ from shutil import which # noqa: F401
from typing import Any
import comicapi.data
from comicapi import filenamelexer, filenameparser
try:
import icu
@ -60,6 +61,51 @@ def os_sorted(lst: Iterable) -> Iterable:
return sorted(lst, key=key)
def parse_filename(
filename: str,
complicated_parser: bool = False,
remove_c2c: bool = False,
remove_fcbd: bool = False,
remove_publisher: bool = False,
split_words: bool = False,
allow_issue_start_with_letter: bool = False,
protofolius_issue_number_scheme: bool = False,
) -> filenameparser.FilenameInfo:
if split_words:
import wordninja
filename, ext = os.path.splitext(filename)
filename = " ".join(wordninja.split(filename)) + ext
if complicated_parser:
lex = filenamelexer.Lex(filename, allow_issue_start_with_letter)
p = filenameparser.Parse(
lex.items,
remove_c2c=remove_c2c,
remove_fcbd=remove_fcbd,
remove_publisher=remove_publisher,
protofolius_issue_number_scheme=protofolius_issue_number_scheme,
)
return p.filename_info
else:
fnp = filenameparser.FileNameParser()
fnp.parse_filename(filename)
fni = filenameparser.FilenameInfo()
if fnp.issue:
fni["issue"] = fnp.issue
if fnp.series:
fni["series"] = fnp.series
if fnp.volume:
fni["volume"] = fnp.volume
if fnp.year:
fni["year"] = fnp.year
if fnp.issue_count:
fni["issue_count"] = fnp.issue_count
if fnp.remainder:
fni["remainder"] = fnp.remainder
return fni
def combine_notes(existing_notes: str | None, new_notes: str | None, split: str) -> str:
split_notes, split_str, untouched_notes = (existing_notes or "").rpartition(split)
if split_notes or split_str:

View File

@ -119,6 +119,18 @@ def filename(parser: settngs.Manager) -> None:
action=argparse.BooleanOptionalAction,
help="Attempts to remove publisher names from filenames, currently limited to Marvel and DC. Requires --complicated-parser",
)
parser.add_setting(
"--protofolius-issue-number-scheme",
default=False,
action=argparse.BooleanOptionalAction,
help="Use an issue number scheme devised by protofolius for encoding format informatino as a letter in front of an issue number. Implies --allow-issue-start-with-letter. Requires --complicated-parser",
)
parser.add_setting(
"--allow-issue-start-with-letter",
default=False,
action=argparse.BooleanOptionalAction,
help="Allows an issue number to start with a single letter (e.g. '#X01'). Requires --complicated-parser",
)
def talker(parser: settngs.Manager) -> None:
@ -220,7 +232,7 @@ def autotag(parser: settngs.Manager) -> None:
parser.add_setting("remove_archive_after_successful_match", default=False, cmdline=False)
def validate_file_settings(config: settngs.Config[ct_ns]) -> settngs.Config[ct_ns]:
def parse_filter(config: settngs.Config[ct_ns]) -> settngs.Config[ct_ns]:
new_filter = []
remove = []
for x in config[0].Issue_Identifier_publisher_filter:
@ -235,6 +247,13 @@ def validate_file_settings(config: settngs.Config[ct_ns]) -> settngs.Config[ct_n
if x in new_filter:
new_filter.remove(x)
config[0].Issue_Identifier_publisher_filter = new_filter
return config
def validate_file_settings(config: settngs.Config[ct_ns]) -> settngs.Config[ct_ns]:
config = parse_filter(config)
if config[0].Filename_Parsing_protofolius_issue_number_scheme:
config[0].Filename_Parsing_allow_issue_start_with_letter = True
config[0].File_Rename_replacements = Replacements(
[Replacement(x[0], x[1], x[2]) for x in config[0].File_Rename_replacements[0]],

View File

@ -31,7 +31,6 @@ class settngs_namespace(settngs.TypedNS):
Runtime_Options_summary: bool
Runtime_Options_raw: bool
Runtime_Options_recursive: bool
Runtime_Options_script: str
Runtime_Options_split_words: bool
Runtime_Options_dryrun: bool
Runtime_Options_darkmode: bool
@ -70,6 +69,8 @@ class settngs_namespace(settngs.TypedNS):
Filename_Parsing_remove_c2c: bool
Filename_Parsing_remove_fcbd: bool
Filename_Parsing_remove_publisher: bool
Filename_Parsing_protofolius_issue_number_scheme: bool
Filename_Parsing_allow_issue_start_with_letter: bool
Sources_source: str
Sources_remove_html_tables: bool

View File

@ -195,6 +195,8 @@ class SettingsWindow(QtWidgets.QDialog):
self.settings_to_form()
self.rename_test()
self.dir_test()
self.leFilenameParserTest.setText(self.lblRenameTest.text())
self.filename_parser_test()
# Set General as start tab
self.tabWidget.setCurrentIndex(0)
@ -222,6 +224,15 @@ class SettingsWindow(QtWidgets.QDialog):
self.twLiteralReplacements.cellChanged.connect(self.rename_test)
self.twValueReplacements.cellChanged.connect(self.rename_test)
self.leFilenameParserTest.textEdited.connect(self.filename_parser_test)
self.cbxRemoveC2C.clicked.connect(self.filename_parser_test)
self.cbxRemoveFCBD.clicked.connect(self.filename_parser_test)
self.cbxRemovePublisher.clicked.connect(self.filename_parser_test)
self.cbxProtofoliusIssueNumberScheme.clicked.connect(self.filename_parser_test)
self.cbxProtofoliusIssueNumberScheme.clicked.connect(self.protofolius_clicked)
self.cbxAllowIssueStartWithLetter.clicked.connect(self.filename_parser_test)
self.cbxSplitWords.clicked.connect(self.filename_parser_test)
def disconnect_signals(self) -> None:
self.btnAddLiteralReplacement.clicked.disconnect()
self.btnAddValueReplacement.clicked.disconnect()
@ -241,6 +252,55 @@ class SettingsWindow(QtWidgets.QDialog):
self.leRenameTemplate.textEdited.disconnect()
self.twLiteralReplacements.cellChanged.disconnect()
self.twValueReplacements.cellChanged.disconnect()
self.leFilenameParserTest.textEdited.disconnect()
self.cbxRemoveC2C.clicked.disconnect()
self.cbxRemoveFCBD.clicked.disconnect()
self.cbxRemovePublisher.clicked.disconnect()
self.cbxProtofoliusIssueNumberScheme.clicked.disconnect()
self.cbxAllowIssueStartWithLetter.clicked.disconnect()
self.cbxSplitWords.clicked.disconnect()
def protofolius_clicked(self, *args: Any, **kwargs: Any) -> None:
if self.cbxProtofoliusIssueNumberScheme.isChecked():
self.cbxAllowIssueStartWithLetter.setEnabled(False)
self.cbxAllowIssueStartWithLetter.setChecked(True)
else:
self.cbxAllowIssueStartWithLetter.setEnabled(True)
self.filename_parser_test()
def filename_parser_test(self, *args: Any, **kwargs: Any) -> None:
self._filename_parser_test(self.leFilenameParserTest.text())
def _filename_parser_test(self, filename: str) -> None:
filename_info = utils.parse_filename(
filename=filename,
complicated_parser=self.cbxComplicatedParser.isChecked(),
remove_c2c=self.cbxRemoveC2C.isChecked(),
remove_fcbd=self.cbxRemoveFCBD.isChecked(),
remove_publisher=self.cbxRemovePublisher.isChecked(),
split_words=self.cbxSplitWords.isChecked(),
allow_issue_start_with_letter=self.cbxAllowIssueStartWithLetter.isChecked(),
protofolius_issue_number_scheme=self.cbxProtofoliusIssueNumberScheme.isChecked(),
)
report = ""
for item in (
"series",
"issue",
"issue_count",
"title",
"volume",
"volume_count",
"year",
"alternate",
"publisher",
"archive",
"remainder",
"annual",
"c2c",
"fcbd",
):
report += f"{item.title().replace('_', ' ')}: {dict(filename_info)[item]}\n"
self.lblFilenameParserTest.setText(report)
def addLiteralReplacement(self) -> None:
self.insertRow(self.twLiteralReplacements, self.twLiteralReplacements.rowCount(), Replacement("", "", False))
@ -319,6 +379,9 @@ class SettingsWindow(QtWidgets.QDialog):
self.cbxRemoveC2C.setChecked(self.config[0].Filename_Parsing_remove_c2c)
self.cbxRemoveFCBD.setChecked(self.config[0].Filename_Parsing_remove_fcbd)
self.cbxRemovePublisher.setChecked(self.config[0].Filename_Parsing_remove_publisher)
self.cbxProtofoliusIssueNumberScheme.setChecked(self.config[0].Filename_Parsing_protofolius_issue_number_scheme)
self.cbxAllowIssueStartWithLetter.setChecked(self.config[0].Filename_Parsing_allow_issue_start_with_letter)
self.switch_parser()
self.cbxClearFormBeforePopulating.setChecked(self.config[0].Issue_Identifier_clear_form_before_populating)
@ -434,6 +497,10 @@ class SettingsWindow(QtWidgets.QDialog):
self.config[0].Filename_Parsing_remove_c2c = self.cbxRemoveC2C.isChecked()
self.config[0].Filename_Parsing_remove_fcbd = self.cbxRemoveFCBD.isChecked()
self.config[0].Filename_Parsing_remove_publisher = self.cbxRemovePublisher.isChecked()
self.config[0].Filename_Parsing_allow_issue_start_with_letter = self.cbxAllowIssueStartWithLetter.isChecked()
self.config.values.Filename_Parsing_protofolius_issue_number_scheme = (
self.cbxProtofoliusIssueNumberScheme.isChecked()
)
self.config[0].Issue_Identifier_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
self.config[0].Issue_Identifier_always_use_publisher_filter = self.cbxUseFilter.isChecked()

View File

@ -318,6 +318,46 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxProtofoliusIssueNumberScheme">
<property name="text">
<string>Use protofolius's issue number scheme</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxAllowIssueStartWithLetter">
<property name="text">
<string>Allow issue numbers to start with a letter</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QCheckBox" name="cbxSplitWords">
<property name="text">
<string>!Preview only! Attempts to split words before parsing the filename. e.g. 'judgedredd' to 'judge dredd'</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leFilenameParserTest"/>
</item>
<item>
<widget class="QLabel" name="lblFilenameParserTest">
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -23,6 +23,23 @@ datadir = pathlib.Path(__file__).parent / "data"
cbz_path = datadir / "Cory Doctorow's Futuristic Tales of the Here and Now #001 - Anda's Game (2007).cbz"
names = [
(
"batman #B01 title (DC).cbz",
"protofolius_issue_number_scheme",
{
"issue": "B1",
"series": "batman",
"title": "title",
"publisher": "DC",
"volume": "",
"year": "",
"remainder": "",
"issue_count": "",
"alternate": "",
"format": "biography/best of",
},
(False, True),
),
(
"batman #3 title (DC).cbz",
"honorific and publisher in series",
@ -724,15 +741,33 @@ names = [
),
]
fnames = []
oldfnames = []
newfnames = []
for p in names:
pp = list(p)
pp[3] = p[3][0]
fnames.append(tuple(pp))
if "#" in p[0]:
pp[0] = p[0].replace("#", "")
pp[3] = p[3][1]
fnames.append(tuple(pp))
filename, reason, info, xfail = p
nxfail = xfail[0]
newfnames.append(pytest.param(filename, reason, info, nxfail))
oldfnames.append(
pytest.param(filename, reason, info, nxfail, marks=pytest.mark.xfail(condition=nxfail, reason="old parser"))
)
if "#" in filename:
filename = filename.replace("#", "")
nxfail = xfail[1]
if reason == "protofolius_issue_number_scheme":
newfnames.append(
pytest.param(
filename,
reason,
info,
nxfail,
marks=pytest.mark.xfail(condition=nxfail, reason="protofolius_issue_number_scheme"),
)
)
else:
newfnames.append(pytest.param(filename, reason, info, nxfail))
oldfnames.append(
pytest.param(filename, reason, info, nxfail, marks=pytest.mark.xfail(condition=nxfail, reason="old parser"))
)
rnames = [
(

View File

@ -2,18 +2,21 @@ from __future__ import annotations
import pytest
import comicapi.filenamelexer
import comicapi.filenameparser
from testing.filenames import fnames
from testing.filenames import newfnames, oldfnames
@pytest.mark.parametrize("filename, reason, expected, xfail", fnames)
@pytest.mark.parametrize("filename, reason, expected, xfail", newfnames)
def test_file_name_parser_new(filename, reason, expected, xfail):
lex = comicapi.filenamelexer.Lex(filename, "protofolius_issue_number_scheme" == reason)
p = comicapi.filenameparser.Parse(
comicapi.filenamelexer.Lex(filename).items,
lex.items,
first_is_alt=True,
remove_c2c=True,
remove_fcbd=True,
remove_publisher=True,
protofolius_issue_number_scheme="protofolius_issue_number_scheme" == reason,
)
fp = p.filename_info
@ -30,13 +33,13 @@ def test_file_name_parser_new(filename, reason, expected, xfail):
assert fp == expected
@pytest.mark.parametrize("filename, reason, expected, xfail", fnames)
@pytest.mark.parametrize("filename, reason, expected, xfail", oldfnames)
def test_file_name_parser(filename, reason, expected, xfail):
p = comicapi.filenameparser.FileNameParser()
p.parse_filename(filename)
fp = p.__dict__
# These are currently not tracked in this parser
for s in ["title", "alternate", "publisher", "fcbd", "c2c", "annual", "volume_count", "remainder"]:
for s in ["title", "alternate", "publisher", "fcbd", "c2c", "annual", "volume_count", "remainder", "format"]:
if s in expected:
del expected[s]
@ -44,6 +47,4 @@ def test_file_name_parser(filename, reason, expected, xfail):
if "remainder" in fp:
del fp["remainder"]
if xfail and fp != expected:
pytest.xfail("old parser")
assert fp == expected

View File

@ -12,6 +12,9 @@ issues = [
("1", 1.0, "001"),
("22.BEY", 22.0, "022.BEY"),
("22A", 22.0, "022A"),
("A22A", 22.0, "A022A"),
("A22", 22.0, "A022"),
("A22½", 22.5, "A022½"),
("22-A", 22.0, "022-A"),
("", None, ""),
]