Fix Config.from_file() silent mode not handling ENOTDIR
`Config.from_file()` with `silent=True` did not handle `errno.ENOTDIR`, causing it to raise an error when a path component is a regular file instead of a directory. This was inconsistent with `Config.from_pyfile()`, which has handled ENOTDIR since PR #2581. fixes #5912 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d3b78fd18a
commit
c8ecf241e3
3 changed files with 26 additions and 1 deletions
|
|
@ -3,6 +3,9 @@ Version 3.2.0
|
||||||
|
|
||||||
Unreleased
|
Unreleased
|
||||||
|
|
||||||
|
- ``Config.from_file()`` with ``silent=True`` now handles ``ENOTDIR``
|
||||||
|
errors, matching the behavior of ``Config.from_pyfile()``. :issue:`5912`
|
||||||
|
|
||||||
- Drop support for Python 3.9. :pr:`5730`
|
- Drop support for Python 3.9. :pr:`5730`
|
||||||
- Remove previously deprecated code: ``__version__``. :pr:`5648`
|
- Remove previously deprecated code: ``__version__``. :pr:`5648`
|
||||||
- ``RequestContext`` has merged with ``AppContext``. ``RequestContext`` is now
|
- ``RequestContext`` has merged with ``AppContext``. ``RequestContext`` is now
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ class Config(dict): # type: ignore[type-arg]
|
||||||
with open(filename, "r" if text else "rb") as f:
|
with open(filename, "r" if text else "rb") as f:
|
||||||
obj = load(f)
|
obj = load(f)
|
||||||
except OSError as e:
|
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
|
return False
|
||||||
|
|
||||||
e.strerror = f"Unable to load configuration file ({e.strerror})"
|
e.strerror = f"Unable to load configuration file ({e.strerror})"
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,28 @@ def test_config_missing_file():
|
||||||
assert not app.config.from_file("missing.json", load=json.load, silent=True)
|
assert not app.config.from_file("missing.json", load=json.load, silent=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_enotdir_from_pyfile(tmp_path):
|
||||||
|
"""from_pyfile with silent=True handles ENOTDIR when a path
|
||||||
|
component is a regular file rather than a directory."""
|
||||||
|
# Create a regular file that will block directory traversal.
|
||||||
|
blocker = tmp_path / "not_a_dir"
|
||||||
|
blocker.write_text("x")
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
# Trying to open "not_a_dir/settings.cfg" raises ENOTDIR.
|
||||||
|
assert not app.config.from_pyfile(str(blocker / "settings.cfg"), silent=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_enotdir_from_file(tmp_path):
|
||||||
|
"""from_file with silent=True handles ENOTDIR when a path
|
||||||
|
component is a regular file rather than a directory."""
|
||||||
|
blocker = tmp_path / "not_a_dir"
|
||||||
|
blocker.write_text("x")
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
assert not app.config.from_file(
|
||||||
|
str(blocker / "config.json"), load=json.load, silent=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_custom_config_class():
|
def test_custom_config_class():
|
||||||
class Config(flask.Config):
|
class Config(flask.Config):
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue