Merge pull request #4621 from pallets/deprecate-before_first_request

deprecate before_first_request
This commit is contained in:
David Lord 2022-06-06 10:11:00 -07:00 committed by GitHub
commit aab1d9935e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 33 deletions

View file

@ -20,6 +20,8 @@ Unreleased
registering the blueprint will show a warning. In the next version,
this will become an error just like the application setup methods.
:issue:`4571`
- ``before_first_request`` is deprecated. Run setup code when creating
the application instead. :issue:`4605`
Version 2.1.3
@ -1032,8 +1034,7 @@ Released 2011-09-29, codename Rakija
earlier feedback when users forget to import view code ahead of
time.
- Added the ability to register callbacks that are only triggered once
at the beginning of the first request.
(:meth:`Flask.before_first_request`)
at the beginning of the first request. (``before_first_request``)
- Malformed JSON data will now trigger a bad request HTTP exception
instead of a value error which usually would result in a 500
internal server error if not handled. This is a backwards

View file

@ -451,6 +451,10 @@ class Flask(Scaffold):
#: first request to this instance. To register a function, use the
#: :meth:`before_first_request` decorator.
#:
#: .. deprecated:: 2.2
#: Will be removed in Flask 2.3. Run setup code when
#: creating the application instead.
#:
#: .. versionadded:: 0.8
self.before_first_request_funcs: t.List[ft.BeforeFirstRequestCallable] = []
@ -1255,8 +1259,21 @@ class Flask(Scaffold):
The function will be called without any arguments and its return
value is ignored.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Run setup code when creating
the application instead.
.. versionadded:: 0.8
"""
import warnings
warnings.warn(
"'before_first_request' is deprecated and will be removed"
" in Flask 2.3. Run setup code while creating the"
" application instead.",
DeprecationWarning,
stacklevel=2,
)
self.before_first_request_funcs.append(f)
return f
@ -1552,7 +1569,17 @@ class Flask(Scaffold):
.. versionadded:: 0.7
"""
self.try_trigger_before_first_request_functions()
# Run before_first_request functions if this is the thread's first request.
# Inlined to avoid a method call on subsequent requests.
# This is deprecated, will be removed in Flask 2.3.
if not self._got_first_request:
with self._before_request_lock:
if not self._got_first_request:
for func in self.before_first_request_funcs:
self.ensure_sync(func)()
self._got_first_request = True
try:
request_started.send(self)
rv = self.preprocess_request()
@ -1591,22 +1618,6 @@ class Flask(Scaffold):
)
return response
def try_trigger_before_first_request_functions(self) -> None:
"""Called before each request and will ensure that it triggers
the :attr:`before_first_request_funcs` and only exactly once per
application instance (which means process usually).
:internal:
"""
if self._got_first_request:
return
with self._before_request_lock:
if self._got_first_request:
return
for func in self.before_first_request_funcs:
self.ensure_sync(func)()
self._got_first_request = True
def make_default_options_response(self) -> Response:
"""This method is called to create the default ``OPTIONS`` response.
This can be changed through subclassing to change the default

View file

@ -543,7 +543,20 @@ class Blueprint(Scaffold):
) -> ft.BeforeFirstRequestCallable:
"""Like :meth:`Flask.before_first_request`. Such a function is
executed before the first request to the application.
.. deprecated:: 2.2
Will be removed in Flask 2.3. Run setup code when creating
the application instead.
"""
import warnings
warnings.warn(
"'before_app_first_request' is deprecated and will be"
" removed in Flask 2.3. Use 'record_once' instead to run"
" setup code when registering the blueprint.",
DeprecationWarning,
stacklevel=2,
)
self.record_once(lambda s: s.app.before_first_request_funcs.append(f))
return f

View file

@ -107,10 +107,12 @@ def test_async_before_after_request():
def index():
return ""
@app.before_first_request
async def before_first():
nonlocal app_first_called
app_first_called = True
with pytest.deprecated_call():
@app.before_first_request
async def before_first():
nonlocal app_first_called
app_first_called = True
@app.before_request
async def before():

View file

@ -1684,9 +1684,11 @@ def test_no_setup_after_first_request(app, client):
def test_before_first_request_functions(app, client):
got = []
@app.before_first_request
def foo():
got.append(42)
with pytest.deprecated_call():
@app.before_first_request
def foo():
got.append(42)
client.get("/")
assert got == [42]
@ -1698,10 +1700,12 @@ def test_before_first_request_functions(app, client):
def test_before_first_request_functions_concurrent(app, client):
got = []
@app.before_first_request
def foo():
time.sleep(0.2)
got.append(42)
with pytest.deprecated_call():
@app.before_first_request
def foo():
time.sleep(0.2)
got.append(42)
def get_and_assert():
client.get("/")

View file

@ -722,9 +722,11 @@ def test_app_request_processing(app, client):
bp = flask.Blueprint("bp", __name__)
evts = []
@bp.before_app_first_request
def before_first_request():
evts.append("first")
with pytest.deprecated_call():
@bp.before_app_first_request
def before_first_request():
evts.append("first")
@bp.before_app_request
def before_app():