From 3ae2bd2f598c3f8dddcdc08d559ccd285b6d3193 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Sun, 27 Feb 2022 12:10:42 +0100 Subject: [PATCH] PICARD-2425: Handle possible exceptions with os.path.realpath E.g. on Windows this can cause exceptions if drives are mounted without mount manager. --- picard/file.py | 9 +++------ picard/ui/coverartbox.py | 7 +++++-- picard/util/__init__.py | 2 ++ picard/util/filenaming.py | 11 +++++++++-- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/picard/file.py b/picard/file.py index 578c174ac..2c3d6e6dc 100644 --- a/picard/file.py +++ b/picard/file.py @@ -78,6 +78,7 @@ from picard.util import ( find_best_match, format_time, is_absolute_path, + normpath, thread, tracknum_and_title_from_filename, ) @@ -506,14 +507,10 @@ class File(QtCore.QObject, Item): if settings["move_files"]: new_dirname = settings["move_files_to"] if not is_absolute_path(new_dirname): - new_dirname = os.path.normpath(os.path.join(os.path.dirname(filename), new_dirname)) + new_dirname = os.path.join(os.path.dirname(filename), new_dirname) else: new_dirname = os.path.dirname(filename) - try: - new_dirname = os.path.realpath(new_dirname) - except FileNotFoundError: - # os.path.realpath can fail if cwd does not exist and path is relative - pass + new_dirname = normpath(new_dirname) new_filename = os.path.basename(filename) if settings["rename_files"] or settings["move_files"]: diff --git a/picard/ui/coverartbox.py b/picard/ui/coverartbox.py index 930aed29b..08d0dd7bc 100644 --- a/picard/ui/coverartbox.py +++ b/picard/ui/coverartbox.py @@ -55,7 +55,10 @@ from picard.coverart.image import ( ) from picard.file import File from picard.track import Track -from picard.util import imageinfo +from picard.util import ( + imageinfo, + normpath, +) from picard.util.lrucache import LRUCache from picard.ui.item import FileListItem @@ -411,7 +414,7 @@ class CoverArtBox(QtWidgets.QGroupBox): parse_response_type=None, queryargs=queryargs, priority=True, important=True) elif url.scheme() == 'file': - path = os.path.normpath(os.path.realpath(url.toLocalFile().rstrip("\0"))) + path = normpath(url.toLocalFile().rstrip("\0")) if path and os.path.exists(path): with open(path, 'rb') as f: data = f.read() diff --git a/picard/util/__init__.py b/picard/util/__init__.py index f583ef3ed..90f92fb3a 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -170,6 +170,8 @@ def normpath(path): path = os.path.realpath(path) except OSError as why: # realpath can fail if path does not exist or is not accessible + # or on Windows if drives are mounted without mount manager + # (see https://tickets.metabrainz.org/browse/PICARD-2425). log.warning('Failed getting realpath for "%s": %s', path, why) return os.path.normpath(path) diff --git a/picard/util/filenaming.py b/picard/util/filenaming.py index 1320494ce..ba9978f12 100644 --- a/picard/util/filenaming.py +++ b/picard/util/filenaming.py @@ -400,8 +400,15 @@ def samefile_different_casing(path1, path2): path2 = os.path.normpath(path2) if path1 == path2 or not os.path.exists(path1) or not os.path.exists(path2): return False - dir1 = os.path.realpath(os.path.normcase(os.path.dirname(path1))) - dir2 = os.path.realpath(os.path.normcase(os.path.dirname(path2))) + dir1 = os.path.normcase(os.path.dirname(path1)) + dir2 = os.path.normcase(os.path.dirname(path2)) + try: + dir1 = os.path.realpath(dir1) + dir2 = os.path.realpath(dir2) + except OSError: + # os.path.realpath can fail if cwd does not exist and path is relative + # or on Windows if drives are mounted without mount manager. + pass if dir1 != dir2 or not samefile(path1, path2): return False file1 = os.path.basename(path1)