Skip to content

Commit

Permalink
deprecate before_first_request
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Jun 6, 2022
1 parent 7a2d5fb commit 893d183
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 33 deletions.
6 changes: 4 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ 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 and will be removed in Flask
2.3. Run setup code when creating the application instead.
:issue:`4605`


Version 2.1.3
Expand Down Expand Up @@ -1032,8 +1035,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
Expand Down
45 changes: 28 additions & 17 deletions src/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,10 @@ def __init__(
#: 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] = []

Expand Down Expand Up @@ -1255,8 +1259,21 @@ def before_first_request(
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

Expand Down Expand Up @@ -1552,7 +1569,17 @@ def full_dispatch_request(self) -> Response:
.. 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()
Expand Down Expand Up @@ -1591,22 +1618,6 @@ def finalize_request(
)
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
Expand Down
13 changes: 13 additions & 0 deletions src/flask/blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,20 @@ def before_app_first_request(
) -> 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

Expand Down
10 changes: 6 additions & 4 deletions tests/test_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down
18 changes: 11 additions & 7 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1684,9 +1684,11 @@ def index():
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]
Expand All @@ -1698,10 +1700,12 @@ def foo():
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("/")
Expand Down
8 changes: 5 additions & 3 deletions tests/test_blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down

0 comments on commit 893d183

Please sign in to comment.