mirror of https://github.com/pallets/flask.git
deprecate config attributes
This commit is contained in:
parent
98ca00d545
commit
bfdd37110c
|
@ -27,6 +27,11 @@ Unreleased
|
||||||
deprecated, removing the distinction between development and debug
|
deprecated, removing the distinction between development and debug
|
||||||
mode. Debug mode should be controlled directly using the ``--debug``
|
mode. Debug mode should be controlled directly using the ``--debug``
|
||||||
option or ``app.run(debug=True)``. :issue:`4714`
|
option or ``app.run(debug=True)``. :issue:`4714`
|
||||||
|
- Some attributes that proxied config keys on ``app`` are deprecated:
|
||||||
|
``session_cookie_name``, ``send_file_max_age_default``,
|
||||||
|
``use_x_sendfile``, ``propagate_exceptions``, and
|
||||||
|
``templates_auto_reload``. Use the relevant config keys instead.
|
||||||
|
:issue:`4716`
|
||||||
- Add new customization points to the ``Flask`` app object for many
|
- Add new customization points to the ``Flask`` app object for many
|
||||||
previously global behaviors.
|
previously global behaviors.
|
||||||
|
|
||||||
|
|
|
@ -125,10 +125,9 @@ implementation that Flask is using.
|
||||||
|
|
||||||
.. admonition:: Notice
|
.. admonition:: Notice
|
||||||
|
|
||||||
The ``PERMANENT_SESSION_LIFETIME`` config key can also be an integer
|
The :data:`PERMANENT_SESSION_LIFETIME` config can be an integer or ``timedelta``.
|
||||||
starting with Flask 0.8. Either catch this down yourself or use
|
The :attr:`~flask.Flask.permanent_session_lifetime` attribute is always a
|
||||||
the :attr:`~flask.Flask.permanent_session_lifetime` attribute on the
|
``timedelta``.
|
||||||
app which converts the result to an integer automatically.
|
|
||||||
|
|
||||||
|
|
||||||
Test Client
|
Test Client
|
||||||
|
|
171
src/flask/app.py
171
src/flask/app.py
|
@ -99,7 +99,7 @@ else:
|
||||||
return inspect.iscoroutinefunction(func)
|
return inspect.iscoroutinefunction(func)
|
||||||
|
|
||||||
|
|
||||||
def _make_timedelta(value: t.Optional[timedelta]) -> t.Optional[timedelta]:
|
def _make_timedelta(value: t.Union[timedelta, int, None]) -> t.Optional[timedelta]:
|
||||||
if value is None or isinstance(value, timedelta):
|
if value is None or isinstance(value, timedelta):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -273,11 +273,35 @@ class Flask(Scaffold):
|
||||||
#: :data:`SECRET_KEY` configuration key. Defaults to ``None``.
|
#: :data:`SECRET_KEY` configuration key. Defaults to ``None``.
|
||||||
secret_key = ConfigAttribute("SECRET_KEY")
|
secret_key = ConfigAttribute("SECRET_KEY")
|
||||||
|
|
||||||
#: The secure cookie uses this for the name of the session cookie.
|
@property
|
||||||
#:
|
def session_cookie_name(self) -> str:
|
||||||
#: This attribute can also be configured from the config with the
|
"""The name of the cookie set by the session interface.
|
||||||
#: ``SESSION_COOKIE_NAME`` configuration key. Defaults to ``'session'``
|
|
||||||
session_cookie_name = ConfigAttribute("SESSION_COOKIE_NAME")
|
.. deprecated:: 2.2
|
||||||
|
Will be removed in Flask 2.3. Use ``app.config["SESSION_COOKIE_NAME"]``
|
||||||
|
instead.
|
||||||
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'session_cookie_name' is deprecated and will be removed in Flask 2.3. Use"
|
||||||
|
" 'SESSION_COOKIE_NAME' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return self.config["SESSION_COOKIE_NAME"]
|
||||||
|
|
||||||
|
@session_cookie_name.setter
|
||||||
|
def session_cookie_name(self, value: str) -> None:
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'session_cookie_name' is deprecated and will be removed in Flask 2.3. Use"
|
||||||
|
" 'SESSION_COOKIE_NAME' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
self.config["SESSION_COOKIE_NAME"] = value
|
||||||
|
|
||||||
#: A :class:`~datetime.timedelta` which is used to set the expiration
|
#: A :class:`~datetime.timedelta` which is used to set the expiration
|
||||||
#: date of a permanent session. The default is 31 days which makes a
|
#: date of a permanent session. The default is 31 days which makes a
|
||||||
|
@ -290,29 +314,70 @@ class Flask(Scaffold):
|
||||||
"PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta
|
"PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta
|
||||||
)
|
)
|
||||||
|
|
||||||
#: A :class:`~datetime.timedelta` or number of seconds which is used
|
@property
|
||||||
#: as the default ``max_age`` for :func:`send_file`. The default is
|
def send_file_max_age_default(self) -> t.Optional[timedelta]:
|
||||||
#: ``None``, which tells the browser to use conditional requests
|
"""The default value for ``max_age`` for :func:`~flask.send_file`. The default
|
||||||
#: instead of a timed cache.
|
is ``None``, which tells the browser to use conditional requests instead of a
|
||||||
#:
|
timed cache.
|
||||||
#: Configured with the :data:`SEND_FILE_MAX_AGE_DEFAULT`
|
|
||||||
#: configuration key.
|
|
||||||
#:
|
|
||||||
#: .. versionchanged:: 2.0
|
|
||||||
#: Defaults to ``None`` instead of 12 hours.
|
|
||||||
send_file_max_age_default = ConfigAttribute(
|
|
||||||
"SEND_FILE_MAX_AGE_DEFAULT", get_converter=_make_timedelta
|
|
||||||
)
|
|
||||||
|
|
||||||
#: Enable this if you want to use the X-Sendfile feature. Keep in
|
.. deprecated:: 2.2
|
||||||
#: mind that the server has to support this. This only affects files
|
Will be removed in Flask 2.3. Use
|
||||||
#: sent with the :func:`send_file` method.
|
``app.config["SEND_FILE_MAX_AGE_DEFAULT"]`` instead.
|
||||||
#:
|
|
||||||
#: .. versionadded:: 0.2
|
.. versionchanged:: 2.0
|
||||||
#:
|
Defaults to ``None`` instead of 12 hours.
|
||||||
#: This attribute can also be configured from the config with the
|
"""
|
||||||
#: ``USE_X_SENDFILE`` configuration key. Defaults to ``False``.
|
import warnings
|
||||||
use_x_sendfile = ConfigAttribute("USE_X_SENDFILE")
|
|
||||||
|
warnings.warn(
|
||||||
|
"'send_file_max_age_default' is deprecated and will be removed in Flask"
|
||||||
|
" 2.3. Use 'SEND_FILE_MAX_AGE_DEFAULT' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return _make_timedelta(self.config["SEND_FILE_MAX_AGE_DEFAULT"])
|
||||||
|
|
||||||
|
@send_file_max_age_default.setter
|
||||||
|
def send_file_max_age_default(self, value: t.Union[int, timedelta, None]) -> None:
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'send_file_max_age_default' is deprecated and will be removed in Flask"
|
||||||
|
" 2.3. Use 'SEND_FILE_MAX_AGE_DEFAULT' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
self.config["SEND_FILE_MAX_AGE_DEFAULT"] = _make_timedelta(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def use_x_sendfile(self) -> bool:
|
||||||
|
"""Enable this to use the ``X-Sendfile`` feature, assuming the server supports
|
||||||
|
it, from :func:`~flask.send_file`.
|
||||||
|
|
||||||
|
.. deprecated:: 2.2
|
||||||
|
Will be removed in Flask 2.3. Use ``app.config["USE_X_SENDFILE"]`` instead.
|
||||||
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'use_x_sendfile' is deprecated and will be removed in Flask 2.3. Use"
|
||||||
|
" 'USE_X_SENDFILE' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
return self.config["USE_X_SENDFILE"]
|
||||||
|
|
||||||
|
@use_x_sendfile.setter
|
||||||
|
def use_x_sendfile(self, value: bool) -> None:
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'use_x_sendfile' is deprecated and will be removed in Flask 2.3. Use"
|
||||||
|
" 'USE_X_SENDFILE' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
self.config["USE_X_SENDFILE"] = value
|
||||||
|
|
||||||
#: The JSON encoder class to use. Defaults to
|
#: The JSON encoder class to use. Defaults to
|
||||||
#: :class:`~flask.json.JSONEncoder`.
|
#: :class:`~flask.json.JSONEncoder`.
|
||||||
|
@ -624,8 +689,18 @@ class Flask(Scaffold):
|
||||||
"""Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration
|
"""Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration
|
||||||
value in case it's set, otherwise a sensible default is returned.
|
value in case it's set, otherwise a sensible default is returned.
|
||||||
|
|
||||||
|
.. deprecated:: 2.2
|
||||||
|
Will be removed in Flask 2.3.
|
||||||
|
|
||||||
.. versionadded:: 0.7
|
.. versionadded:: 0.7
|
||||||
"""
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'propagate_exceptions' is deprecated and will be removed in Flask 2.3.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
rv = self.config["PROPAGATE_EXCEPTIONS"]
|
rv = self.config["PROPAGATE_EXCEPTIONS"]
|
||||||
if rv is not None:
|
if rv is not None:
|
||||||
return rv
|
return rv
|
||||||
|
@ -734,20 +809,37 @@ class Flask(Scaffold):
|
||||||
@property
|
@property
|
||||||
def templates_auto_reload(self) -> bool:
|
def templates_auto_reload(self) -> bool:
|
||||||
"""Reload templates when they are changed. Used by
|
"""Reload templates when they are changed. Used by
|
||||||
:meth:`create_jinja_environment`.
|
:meth:`create_jinja_environment`. It is enabled by default in debug mode.
|
||||||
|
|
||||||
This attribute can be configured with :data:`TEMPLATES_AUTO_RELOAD`. If
|
.. deprecated:: 2.2
|
||||||
not set, it will be enabled in debug mode.
|
Will be removed in Flask 2.3. Use ``app.config["TEMPLATES_AUTO_RELOAD"]``
|
||||||
|
instead.
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
This property was added but the underlying config and behavior
|
This property was added but the underlying config and behavior
|
||||||
already existed.
|
already existed.
|
||||||
"""
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'templates_auto_reload' is deprecated and will be removed in Flask 2.3."
|
||||||
|
" Use 'TEMPLATES_AUTO_RELOAD' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
rv = self.config["TEMPLATES_AUTO_RELOAD"]
|
rv = self.config["TEMPLATES_AUTO_RELOAD"]
|
||||||
return rv if rv is not None else self.debug
|
return rv if rv is not None else self.debug
|
||||||
|
|
||||||
@templates_auto_reload.setter
|
@templates_auto_reload.setter
|
||||||
def templates_auto_reload(self, value: bool) -> None:
|
def templates_auto_reload(self, value: bool) -> None:
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"'templates_auto_reload' is deprecated and will be removed in Flask 2.3."
|
||||||
|
" Use 'TEMPLATES_AUTO_RELOAD' in 'app.config' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
self.config["TEMPLATES_AUTO_RELOAD"] = value
|
self.config["TEMPLATES_AUTO_RELOAD"] = value
|
||||||
|
|
||||||
def create_jinja_environment(self) -> Environment:
|
def create_jinja_environment(self) -> Environment:
|
||||||
|
@ -768,7 +860,12 @@ class Flask(Scaffold):
|
||||||
options["autoescape"] = self.select_jinja_autoescape
|
options["autoescape"] = self.select_jinja_autoescape
|
||||||
|
|
||||||
if "auto_reload" not in options:
|
if "auto_reload" not in options:
|
||||||
options["auto_reload"] = self.templates_auto_reload
|
auto_reload = self.config["TEMPLATES_AUTO_RELOAD"]
|
||||||
|
|
||||||
|
if auto_reload is None:
|
||||||
|
auto_reload = self.debug
|
||||||
|
|
||||||
|
options["auto_reload"] = auto_reload
|
||||||
|
|
||||||
rv = self.jinja_environment(self, **options)
|
rv = self.jinja_environment(self, **options)
|
||||||
rv.globals.update(
|
rv.globals.update(
|
||||||
|
@ -898,7 +995,9 @@ class Flask(Scaffold):
|
||||||
@debug.setter
|
@debug.setter
|
||||||
def debug(self, value: bool) -> None:
|
def debug(self, value: bool) -> None:
|
||||||
self.config["DEBUG"] = value
|
self.config["DEBUG"] = value
|
||||||
self.jinja_env.auto_reload = self.templates_auto_reload
|
|
||||||
|
if self.config["TEMPLATES_AUTO_RELOAD"] is None:
|
||||||
|
self.jinja_env.auto_reload = value
|
||||||
|
|
||||||
def run(
|
def run(
|
||||||
self,
|
self,
|
||||||
|
@ -1541,8 +1640,12 @@ class Flask(Scaffold):
|
||||||
"""
|
"""
|
||||||
exc_info = sys.exc_info()
|
exc_info = sys.exc_info()
|
||||||
got_request_exception.send(self, exception=e)
|
got_request_exception.send(self, exception=e)
|
||||||
|
propagate = self.config["PROPAGATE_EXCEPTIONS"]
|
||||||
|
|
||||||
if self.propagate_exceptions:
|
if propagate is None:
|
||||||
|
propagate = self.testing or self.debug
|
||||||
|
|
||||||
|
if propagate:
|
||||||
# Re-raise if called with an active exception, otherwise
|
# Re-raise if called with an active exception, otherwise
|
||||||
# raise the passed in exception.
|
# raise the passed in exception.
|
||||||
if exc_info[1] is e:
|
if exc_info[1] is e:
|
||||||
|
|
|
@ -414,7 +414,7 @@ def _prepare_send_file_kwargs(**kwargs: t.Any) -> t.Dict[str, t.Any]:
|
||||||
|
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
environ=request.environ,
|
environ=request.environ,
|
||||||
use_x_sendfile=current_app.use_x_sendfile,
|
use_x_sendfile=current_app.config["USE_X_SENDFILE"],
|
||||||
response_class=current_app.response_class,
|
response_class=current_app.response_class,
|
||||||
_root_path=current_app.root_path, # type: ignore
|
_root_path=current_app.root_path, # type: ignore
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import pkgutil
|
||||||
import sys
|
import sys
|
||||||
import typing as t
|
import typing as t
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from datetime import timedelta
|
||||||
from functools import update_wrapper
|
from functools import update_wrapper
|
||||||
|
|
||||||
from jinja2 import FileSystemLoader
|
from jinja2 import FileSystemLoader
|
||||||
|
@ -302,13 +303,16 @@ class Scaffold:
|
||||||
|
|
||||||
.. versionadded:: 0.9
|
.. versionadded:: 0.9
|
||||||
"""
|
"""
|
||||||
value = current_app.send_file_max_age_default
|
value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"]
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if isinstance(value, timedelta):
|
||||||
return int(value.total_seconds())
|
return int(value.total_seconds())
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
def send_static_file(self, filename: str) -> "Response":
|
def send_static_file(self, filename: str) -> "Response":
|
||||||
"""The view function used to serve files from
|
"""The view function used to serve files from
|
||||||
:attr:`static_folder`. A route is automatically registered for
|
:attr:`static_folder`. A route is automatically registered for
|
||||||
|
|
|
@ -177,11 +177,8 @@ class SessionInterface:
|
||||||
return isinstance(obj, self.null_session_class)
|
return isinstance(obj, self.null_session_class)
|
||||||
|
|
||||||
def get_cookie_name(self, app: "Flask") -> str:
|
def get_cookie_name(self, app: "Flask") -> str:
|
||||||
"""Returns the name of the session cookie.
|
"""The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``."""
|
||||||
|
return app.config["SESSION_COOKIE_NAME"]
|
||||||
Uses ``app.session_cookie_name`` which is set to ``SESSION_COOKIE_NAME``
|
|
||||||
"""
|
|
||||||
return app.session_cookie_name
|
|
||||||
|
|
||||||
def get_cookie_domain(self, app: "Flask") -> t.Optional[str]:
|
def get_cookie_domain(self, app: "Flask") -> t.Optional[str]:
|
||||||
"""Returns the domain that should be set for the session cookie.
|
"""Returns the domain that should be set for the session cookie.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import textwrap
|
import textwrap
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -207,14 +206,6 @@ def test_session_lifetime():
|
||||||
assert app.permanent_session_lifetime.seconds == 42
|
assert app.permanent_session_lifetime.seconds == 42
|
||||||
|
|
||||||
|
|
||||||
def test_send_file_max_age():
|
|
||||||
app = flask.Flask(__name__)
|
|
||||||
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 3600
|
|
||||||
assert app.send_file_max_age_default.seconds == 3600
|
|
||||||
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = timedelta(hours=2)
|
|
||||||
assert app.send_file_max_age_default.seconds == 7200
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_namespace():
|
def test_get_namespace():
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.config["FOO_OPTION_1"] = "foo option 1"
|
app.config["FOO_OPTION_1"] = "foo option 1"
|
||||||
|
|
|
@ -397,11 +397,9 @@ def test_templates_auto_reload_debug_run(app, monkeypatch):
|
||||||
monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
|
monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
assert not app.templates_auto_reload
|
|
||||||
assert not app.jinja_env.auto_reload
|
assert not app.jinja_env.auto_reload
|
||||||
|
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
assert app.templates_auto_reload
|
|
||||||
assert app.jinja_env.auto_reload
|
assert app.jinja_env.auto_reload
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue