From 7d7fdbb07a62aef2cd96eebb209260ee1a749bd7 Mon Sep 17 00:00:00 2001 From: Apoorv Darshan Date: Wed, 18 Feb 2026 21:20:31 +0530 Subject: [PATCH] fix: handle ENOTDIR in Config.from_file() with silent=True `from_pyfile()` correctly suppresses `ENOTDIR` when `silent=True`, but `from_file()` was missing it. This caused an `OSError` when a path component is a regular file instead of a directory (e.g. `~/.myapp` is a file and loading `~/.myapp/config.toml`). --- src/flask/config.py | 2 +- tests/test_config.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/flask/config.py b/src/flask/config.py index 34ef1a57..9e37f2bd 100644 --- a/src/flask/config.py +++ b/src/flask/config.py @@ -293,7 +293,7 @@ class Config(dict): # type: ignore[type-arg] with open(filename, "r" if text else "rb") as f: obj = load(f) except OSError as e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR): + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): return False e.strerror = f"Unable to load configuration file ({e.strerror})" diff --git a/tests/test_config.py b/tests/test_config.py index e5b1906e..cacefde1 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -195,6 +195,19 @@ def test_config_missing_file(): assert not app.config.from_file("missing.json", load=json.load, silent=True) +def test_config_enotdir_silent(tmp_path): + """from_file with silent=True should not raise when a path component + is a file instead of a directory (ENOTDIR).""" + # Create a regular file where a directory is expected in the path. + not_a_dir = tmp_path / "not_a_dir" + not_a_dir.write_text("") + app = flask.Flask(__name__) + app.config.root_path = str(tmp_path) + assert not app.config.from_file( + os.path.join("not_a_dir", "config.json"), load=json.load, silent=True + ) + + def test_custom_config_class(): class Config(flask.Config): pass