diff --git a/comictaggerlib/filerenamer.py b/comictaggerlib/filerenamer.py index 561fc48..8fc59af 100644 --- a/comictaggerlib/filerenamer.py +++ b/comictaggerlib/filerenamer.py @@ -79,12 +79,39 @@ class MetadataFormatter(string.Formatter): return "" return cast(str, super().format_field(value, format_spec)) + def convert_field(self, value: Any, conversion: str) -> str: + if conversion == "u": + return str(value).upper() + if conversion == "l": + return str(value).casefold() + if conversion == "c": + return str(value).capitalize() + if conversion == "S": + return str(value).swapcase() + if conversion == "t": + return str(value).title() + return cast(str, super().convert_field(value, conversion)) + def handle_replacements(self, string: str, replacements: list[Replacement]) -> str: for find, replace, strict_only in replacements: if self.is_strict() or not strict_only: string = string.replace(find, replace) return string + def none_replacement(self, value: Any, replacement: str, r: str) -> Any: + if r == "-" and value is None or value == "": + return replacement + if r == "+" and value is not None: + return replacement + return value + + def split_replacement(self, field_name: str) -> tuple[str, str, str]: + if "-" in field_name: + return field_name.rpartition("-") + if "+" in field_name: + return field_name.rpartition("+") + return field_name, "", "" + def is_strict(self) -> bool: return self.platform in [Platform.UNIVERSAL, Platform.WINDOWS] @@ -124,6 +151,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, r, replacement = self.split_replacement(field_name) field_name = field_name.casefold() # this is some markup, find the object and do the formatting @@ -136,6 +164,8 @@ class MetadataFormatter(string.Formatter): obj, arg_used = self.get_field(field_name, args, kwargs) used_args.add(arg_used) + obj = self.none_replacement(obj, replacement, r) + # do any conversion on the resulting object obj = self.convert_field(obj, conversion) # type: ignore diff --git a/testing/filenames.py b/testing/filenames.py index 79fdb23..ee21829 100644 --- a/testing/filenames.py +++ b/testing/filenames.py @@ -750,6 +750,76 @@ fnames = [ ] rnames = [ + ( + "{series!c} {price} {year}", # Capitalize + False, + "universal", + "Cory doctorow's futuristic tales of the here and now 2007.cbz", + does_not_raise(), + ), + ( + "{series!t} {price} {year}", # Title Case + False, + "universal", + "Cory Doctorow'S Futuristic Tales Of The Here And Now 2007.cbz", + does_not_raise(), + ), + ( + "{series!S} {price} {year}", # Swap Case + False, + "universal", + "cORY dOCTOROW'S fUTURISTIC tALES OF THE hERE AND nOW 2007.cbz", + does_not_raise(), + ), + ( + "{title!l} {price} {year}", # Lowercase + False, + "universal", + "anda's game 2007.cbz", + does_not_raise(), + ), + ( + "{title!u} {price} {year}", # Upper Case + False, + "universal", + "ANDA'S GAME 2007.cbz", + does_not_raise(), + ), + ( + "{title} {price} {year+}", # Empty alternate value + False, + "universal", + "Anda's Game.cbz", + does_not_raise(), + ), + ( + "{title} {price} {year+year!u}", # Alternate value Upper Case + False, + "universal", + "Anda's Game YEAR.cbz", + does_not_raise(), + ), + ( + "{title} {price} {year+year}", # Alternate Value + False, + "universal", + "Anda's Game year.cbz", + does_not_raise(), + ), + ( + "{title} {price-0} {year}", # Default value + False, + "universal", + "Anda's Game 0 2007.cbz", + does_not_raise(), + ), + ( + "{title} {price+0} {year}", # Alternate Value + False, + "universal", + "Anda's Game 2007.cbz", + does_not_raise(), + ), ( "{series} #{issue} - {title} ({year}) ({price})", # price should be none False,