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
|
||||
mode. Debug mode should be controlled directly using the ``--debug``
|
||||
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
|
||||
previously global behaviors.
|
||||
|
||||
|
|
|
@ -125,10 +125,9 @@ implementation that Flask is using.
|
|||
|
||||
.. admonition:: Notice
|
||||
|
||||
The ``PERMANENT_SESSION_LIFETIME`` config key can also be an integer
|
||||
starting with Flask 0.8. Either catch this down yourself or use
|
||||
the :attr:`~flask.Flask.permanent_session_lifetime` attribute on the
|
||||
app which converts the result to an integer automatically.
|
||||
The :data:`PERMANENT_SESSION_LIFETIME` config can be an integer or ``timedelta``.
|
||||
The :attr:`~flask.Flask.permanent_session_lifetime` attribute is always a
|
||||
``timedelta``.
|
||||
|
||||
|
||||
Test Client
|
||||
|
|
171
src/flask/app.py
171
src/flask/app.py
|
@ -99,7 +99,7 @@ else:
|
|||
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):
|
||||
return value
|
||||
|
||||
|
@ -273,11 +273,35 @@ class Flask(Scaffold):
|
|||
#: :data:`SECRET_KEY` configuration key. Defaults to ``None``.
|
||||
secret_key = ConfigAttribute("SECRET_KEY")
|
||||
|
||||
#: The secure cookie uses this for the name of the session cookie.
|
||||
#:
|
||||
#: This attribute can also be configured from the config with the
|
||||
#: ``SESSION_COOKIE_NAME`` configuration key. Defaults to ``'session'``
|
||||
session_cookie_name = ConfigAttribute("SESSION_COOKIE_NAME")
|
||||
@property
|
||||
def session_cookie_name(self) -> str:
|
||||
"""The name of the cookie set by the session interface.
|
||||
|
||||
.. 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
|
||||
#: 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
|
||||
)
|
||||
|
||||
#: A :class:`~datetime.timedelta` or number of seconds which is used
|
||||
#: as the default ``max_age`` for :func:`send_file`. The default 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
|
||||
)
|
||||
@property
|
||||
def send_file_max_age_default(self) -> t.Optional[timedelta]:
|
||||
"""The default value for ``max_age`` for :func:`~flask.send_file`. The default
|
||||
is ``None``, which tells the browser to use conditional requests instead of a
|
||||
timed cache.
|
||||
|
||||
#: Enable this if you want to use the X-Sendfile feature. Keep in
|
||||
#: mind that the server has to support this. This only affects files
|
||||
#: sent with the :func:`send_file` method.
|
||||
#:
|
||||
#: .. versionadded:: 0.2
|
||||
#:
|
||||
#: This attribute can also be configured from the config with the
|
||||
#: ``USE_X_SENDFILE`` configuration key. Defaults to ``False``.
|
||||
use_x_sendfile = ConfigAttribute("USE_X_SENDFILE")
|
||||
.. deprecated:: 2.2
|
||||
Will be removed in Flask 2.3. Use
|
||||
``app.config["SEND_FILE_MAX_AGE_DEFAULT"]`` instead.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
Defaults to ``None`` instead of 12 hours.
|
||||
"""
|
||||
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,
|
||||
)
|
||||
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
|
||||
#: :class:`~flask.json.JSONEncoder`.
|
||||
|
@ -624,8 +689,18 @@ class Flask(Scaffold):
|
|||
"""Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration
|
||||
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
|
||||
"""
|
||||
import warnings
|
||||
|
||||
warnings.warn(
|
||||
"'propagate_exceptions' is deprecated and will be removed in Flask 2.3.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
rv = self.config["PROPAGATE_EXCEPTIONS"]
|
||||
if rv is not None:
|
||||
return rv
|
||||
|
@ -734,20 +809,37 @@ class Flask(Scaffold):
|
|||
@property
|
||||
def templates_auto_reload(self) -> bool:
|
||||
"""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
|
||||
not set, it will be enabled in debug mode.
|
||||
.. deprecated:: 2.2
|
||||
Will be removed in Flask 2.3. Use ``app.config["TEMPLATES_AUTO_RELOAD"]``
|
||||
instead.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
This property was added but the underlying config and behavior
|
||||
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"]
|
||||
return rv if rv is not None else self.debug
|
||||
|
||||
@templates_auto_reload.setter
|
||||
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
|
||||
|
||||
def create_jinja_environment(self) -> Environment:
|
||||
|
@ -768,7 +860,12 @@ class Flask(Scaffold):
|
|||
options["autoescape"] = self.select_jinja_autoescape
|
||||
|
||||
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.globals.update(
|
||||
|
@ -898,7 +995,9 @@ class Flask(Scaffold):
|
|||
@debug.setter
|
||||
def debug(self, value: bool) -> None:
|
||||
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(
|
||||
self,
|
||||
|
@ -1541,8 +1640,12 @@ class Flask(Scaffold):
|
|||
"""
|
||||
exc_info = sys.exc_info()
|
||||
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
|
||||
# raise the passed in exception.
|
||||
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(
|
||||
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,
|
||||
_root_path=current_app.root_path, # type: ignore
|
||||
)
|
||||
|
|
|
@ -5,6 +5,7 @@ import pkgutil
|
|||
import sys
|
||||
import typing as t
|
||||
from collections import defaultdict
|
||||
from datetime import timedelta
|
||||
from functools import update_wrapper
|
||||
|
||||
from jinja2 import FileSystemLoader
|
||||
|
@ -302,12 +303,15 @@ class Scaffold:
|
|||
|
||||
.. versionadded:: 0.9
|
||||
"""
|
||||
value = current_app.send_file_max_age_default
|
||||
value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"]
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
return int(value.total_seconds())
|
||||
if isinstance(value, timedelta):
|
||||
return int(value.total_seconds())
|
||||
|
||||
return value
|
||||
|
||||
def send_static_file(self, filename: str) -> "Response":
|
||||
"""The view function used to serve files from
|
||||
|
|
|
@ -177,11 +177,8 @@ class SessionInterface:
|
|||
return isinstance(obj, self.null_session_class)
|
||||
|
||||
def get_cookie_name(self, app: "Flask") -> str:
|
||||
"""Returns the name of the session cookie.
|
||||
|
||||
Uses ``app.session_cookie_name`` which is set to ``SESSION_COOKIE_NAME``
|
||||
"""
|
||||
return app.session_cookie_name
|
||||
"""The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``."""
|
||||
return app.config["SESSION_COOKIE_NAME"]
|
||||
|
||||
def get_cookie_domain(self, app: "Flask") -> t.Optional[str]:
|
||||
"""Returns the domain that should be set for the session cookie.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import json
|
||||
import os
|
||||
import textwrap
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -207,14 +206,6 @@ def test_session_lifetime():
|
|||
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():
|
||||
app = flask.Flask(__name__)
|
||||
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)
|
||||
|
||||
app.run()
|
||||
assert not app.templates_auto_reload
|
||||
assert not app.jinja_env.auto_reload
|
||||
|
||||
app.run(debug=True)
|
||||
assert app.templates_auto_reload
|
||||
assert app.jinja_env.auto_reload
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue