Fix issues with renaming
Stop a crash when renaming Properly handle replacements on linux/macos
This commit is contained in:
parent
d213db3129
commit
acaf5ed510
@ -525,7 +525,10 @@ def process_file_cli(
|
||||
suffix = ""
|
||||
if not opts.dryrun:
|
||||
# rename the file
|
||||
ca.rename(utils.unique_file(full_path))
|
||||
try:
|
||||
ca.rename(utils.unique_file(full_path))
|
||||
except OSError:
|
||||
logger.exception("Failed to rename comic archive: %s", ca.path)
|
||||
else:
|
||||
suffix = " (dry-run, no change)"
|
||||
|
||||
|
@ -31,13 +31,28 @@ from comicapi.issuestring import IssueString
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Replacement(NamedTuple):
|
||||
find: str
|
||||
replce: str
|
||||
strict_only: bool
|
||||
|
||||
|
||||
class Replacements(NamedTuple):
|
||||
literal_text: list[tuple[str, str]]
|
||||
format_value: list[tuple[str, str]]
|
||||
literal_text: list[Replacement]
|
||||
format_value: list[Replacement]
|
||||
|
||||
|
||||
REPLACEMENTS = Replacements(
|
||||
literal_text=[(": ", " - "), (":", "-")], format_value=[(": ", " - "), (":", "-"), ("/", "-"), ("\\", "-")]
|
||||
literal_text=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
],
|
||||
format_value=[
|
||||
Replacement(": ", " - ", True),
|
||||
Replacement(":", "-", True),
|
||||
Replacement("/", "-", False),
|
||||
Replacement("\\", "-", True),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -64,11 +79,15 @@ class MetadataFormatter(string.Formatter):
|
||||
return ""
|
||||
return cast(str, super().format_field(value, format_spec))
|
||||
|
||||
def handle_replacements(self, string: str, replacements: list[tuple[str, str]]) -> str:
|
||||
for f, r in replacements:
|
||||
string = string.replace(f, r)
|
||||
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 is_strict(self) -> bool:
|
||||
return self.platform in [Platform.UNIVERSAL, Platform.WINDOWS]
|
||||
|
||||
def _vformat(
|
||||
self,
|
||||
format_string: str,
|
||||
@ -89,8 +108,7 @@ class MetadataFormatter(string.Formatter):
|
||||
if lstrip:
|
||||
literal_text = literal_text.lstrip("-_)}]#")
|
||||
if self.smart_cleanup:
|
||||
if self.platform in [Platform.UNIVERSAL, Platform.WINDOWS]:
|
||||
literal_text = self.handle_replacements(literal_text, self.replacements.literal_text)
|
||||
literal_text = self.handle_replacements(literal_text, self.replacements.literal_text)
|
||||
lspace = literal_text[0].isspace() if literal_text else False
|
||||
rspace = literal_text[-1].isspace() if literal_text else False
|
||||
literal_text = " ".join(literal_text.split())
|
||||
@ -136,9 +154,8 @@ class MetadataFormatter(string.Formatter):
|
||||
result[-1], _, _ = result[-1].rstrip().rpartition(" ")
|
||||
result[-1] = result[-1].rstrip("-_({[#")
|
||||
if self.smart_cleanup:
|
||||
if self.platform in [Platform.UNIVERSAL, Platform.WINDOWS]:
|
||||
# colons and slashes get special treatment
|
||||
fmt_obj = self.handle_replacements(fmt_obj, self.replacements.format_value)
|
||||
# colons and slashes get special treatment
|
||||
fmt_obj = self.handle_replacements(fmt_obj, self.replacements.format_value)
|
||||
fmt_obj = " ".join(fmt_obj.split())
|
||||
fmt_obj = str(sanitize_filename(fmt_obj, platform=self.platform))
|
||||
result.append(fmt_obj)
|
||||
|
@ -175,29 +175,37 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
center_window_on_parent(prog_dialog)
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
|
||||
for idx, comic in enumerate(zip(self.comic_archive_list, self.rename_list)):
|
||||
try:
|
||||
for idx, comic in enumerate(zip(self.comic_archive_list, self.rename_list)):
|
||||
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
if prog_dialog.wasCanceled():
|
||||
break
|
||||
idx += 1
|
||||
prog_dialog.setValue(idx)
|
||||
prog_dialog.setLabelText(comic[1])
|
||||
center_window_on_parent(prog_dialog)
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
if prog_dialog.wasCanceled():
|
||||
break
|
||||
idx += 1
|
||||
prog_dialog.setValue(idx)
|
||||
prog_dialog.setLabelText(comic[1])
|
||||
center_window_on_parent(prog_dialog)
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
|
||||
folder = get_rename_dir(comic[0], self.settings.rename_dir if self.settings.rename_move_dir else None)
|
||||
folder = get_rename_dir(comic[0], self.settings.rename_dir if self.settings.rename_move_dir else None)
|
||||
|
||||
full_path = folder / comic[1]
|
||||
full_path = folder / comic[1]
|
||||
|
||||
if full_path == comic[0].path:
|
||||
logger.info("%s: Filename is already good!", comic[1])
|
||||
continue
|
||||
if full_path == comic[0].path:
|
||||
logger.info("%s: Filename is already good!", comic[1])
|
||||
continue
|
||||
|
||||
if not comic[0].is_writable(check_rar_status=False):
|
||||
continue
|
||||
if not comic[0].is_writable(check_rar_status=False):
|
||||
continue
|
||||
|
||||
comic[0].rename(utils.unique_file(full_path))
|
||||
comic[0].rename(utils.unique_file(full_path))
|
||||
except Exception as e:
|
||||
logger.exception("Failed to rename comic archive: %s", comic[0].path)
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
"There was an issue when renaming!",
|
||||
f"Renaming failed!<br/><br/>{type(e).__name__}: {e}<br/><br/>",
|
||||
)
|
||||
|
||||
prog_dialog.hide()
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
|
@ -792,6 +792,13 @@ rnames = [
|
||||
"Anda's Game https---comicvine.gamespot.com-cory-doctorows-futuristic-tales-of-the-here-and-no-4000-140529-.cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{title} {web_link}", # Ensure slashes are replaced in metadata on linux/macos
|
||||
False,
|
||||
"Linux",
|
||||
"Anda's Game https:--comicvine.gamespot.com-cory-doctorows-futuristic-tales-of-the-here-and-no-4000-140529-.cbz",
|
||||
does_not_raise(),
|
||||
),
|
||||
(
|
||||
"{series}:{title} #{issue} ({year})", # on windows the ':' is replaced
|
||||
False,
|
||||
|
@ -98,3 +98,15 @@ def test_rename(tmp_comic, tmp_path):
|
||||
assert not old_path.exists()
|
||||
assert tmp_comic.path.exists()
|
||||
assert tmp_comic.path != old_path
|
||||
|
||||
|
||||
def test_rename_ro_dest(tmp_comic, tmp_path):
|
||||
old_path = tmp_comic.path
|
||||
dest = tmp_path / "tmp"
|
||||
dest.mkdir(mode=0o000)
|
||||
with pytest.raises(OSError):
|
||||
tmp_comic.rename(dest / "test.cbz")
|
||||
dest.chmod(mode=0o777)
|
||||
assert old_path.exists()
|
||||
assert tmp_comic.path.exists()
|
||||
assert tmp_comic.path == old_path
|
||||
|
Loading…
Reference in New Issue
Block a user