From 6422bf669e29db4dccebb17becf1f22f1a1634bf Mon Sep 17 00:00:00 2001 From: r266-tech Date: Mon, 23 Mar 2026 02:17:36 +0800 Subject: [PATCH] Fix Config.from_file silent error handling to include ENOTDIR Config.from_file() was missing errno.ENOTDIR in its silent error handling, while Config.from_pyfile() correctly includes it. When a component of the config file path is a regular file rather than a directory (e.g., trying to load 'file/config.json' where 'file' is a regular file), from_file(silent=True) would raise an OSError instead of silently returning False. This adds ENOTDIR to match from_pyfile's behavior and adds a test to verify the fix. Fixes #5912 --- 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..2b5342b4 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_from_file_not_a_directory(tmp_path): + """from_file with silent=True returns False when a path component is not a + directory, matching the behavior of from_pyfile.""" + file_in_tmp = tmp_path / "not_a_dir" + file_in_tmp.write_text("{}") + app = flask.Flask(__name__) + app.config.root_path = str(tmp_path) + # not_a_dir/config.json: not_a_dir is a file, not a directory + assert not app.config.from_file( + "not_a_dir/config.json", load=json.load, silent=True + ) + + def test_custom_config_class(): class Config(flask.Config): pass