From a87e6dfe803993d40a523f34213c6ee9c3ded4a7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 16 May 2026 00:38:14 +0000 Subject: [PATCH] fix(dfm): handle non-directory entries in ~/.config scan scan_dotfiles called _find_config_file before verifying the path was a directory, so a regular file at ~/.config/ (e.g. mimeapps.list) caused os.listdir to raise NotADirectoryError and crash window init. Reorder the check so _find_config_file only runs on directories, and harden _find_config_file itself against NotADirectoryError / FileNotFoundError as defense in depth. --- scripts/stoa-dfm/dfm/core/scanner.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/stoa-dfm/dfm/core/scanner.py b/scripts/stoa-dfm/dfm/core/scanner.py index e53d5ce..d8dffdb 100644 --- a/scripts/stoa-dfm/dfm/core/scanner.py +++ b/scripts/stoa-dfm/dfm/core/scanner.py @@ -155,9 +155,9 @@ def scan_dotfiles(home_dir: str | None = None) -> list[DotfileEntry]: if os.path.isdir(config_dir): for dirname, display_name in KNOWN_CONFIG_DIRS.items(): dirpath = os.path.join(config_dir, dirname) - if os.path.exists(dirpath): + if os.path.isdir(dirpath): config_file = _find_config_file(dirpath) - if os.path.isdir(dirpath) and config_file: + if config_file: entries.append(DotfileEntry( name=dirname, display_name=display_name, @@ -166,14 +166,14 @@ def scan_dotfiles(home_dir: str | None = None) -> list[DotfileEntry]: config_file=config_file, icon_name=_get_icon_for_config(dirname), )) - elif os.path.isfile(dirpath): - entries.append(DotfileEntry( - name=dirname, - display_name=display_name, - path=dirpath, - is_directory=False, - icon_name=_get_icon_for_config(dirname), - )) + elif os.path.isfile(dirpath): + entries.append(DotfileEntry( + name=dirname, + display_name=display_name, + path=dirpath, + is_directory=False, + icon_name=_get_icon_for_config(dirname), + )) # Sort by display name entries.sort(key=lambda e: e.display_name.lower()) @@ -199,7 +199,7 @@ def _find_config_file(dirpath: str) -> str: ext = os.path.splitext(f)[1].lower() if ext in (".conf", ".ini", ".toml", ".yaml", ".yml", ".json", ".cfg"): return fpath - except PermissionError: + except (PermissionError, NotADirectoryError, FileNotFoundError): pass # Fallback: any readable file @@ -213,7 +213,7 @@ def _find_config_file(dirpath: str) -> str: return fpath except (UnicodeDecodeError, PermissionError): continue - except PermissionError: + except (PermissionError, NotADirectoryError, FileNotFoundError): pass return ""