From a411a2434b09d9cbaa4074232b2c247d591bb655 Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 19 Feb 2026 08:35:48 -0800 Subject: [PATCH] add back opening session on context push --- src/flask/ctx.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/flask/ctx.py b/src/flask/ctx.py index ac1422c7..8876efd0 100644 --- a/src/flask/ctx.py +++ b/src/flask/ctx.py @@ -377,12 +377,8 @@ class AppContext: return self._request - @property - def session(self) -> SessionMixin: - """The session object associated with this context. Accessed through - :data:`.session`. Only available in request contexts, otherwise raises - :exc:`RuntimeError`. Accessing this sets :attr:`.SessionMixin.accessed`. - """ + def _get_session(self) -> SessionMixin: + """Open the session if it is not already open for this request context.""" if self._request is None: raise RuntimeError("There is no request in this context.") @@ -393,9 +389,18 @@ class AppContext: if self._session is None: self._session = si.make_null_session(self.app) - self._session.accessed = True return self._session + @property + def session(self) -> SessionMixin: + """The session object associated with this context. Accessed through + :data:`.session`. Only available in request contexts, otherwise raises + :exc:`RuntimeError`. Accessing this sets :attr:`.SessionMixin.accessed`. + """ + session = self._get_session() + session.accessed = True + return session + def match_request(self) -> None: """Apply routing to the current request, storing either the matched endpoint and args, or a routing exception. @@ -427,8 +432,15 @@ class AppContext: self._cv_token = _cv_app.set(self) appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync) - if self._request is not None and self.url_adapter is not None: - self.match_request() + if self._request is not None: + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + self._get_session() + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() def pop(self, exc: BaseException | None = None) -> None: """Pop this context so that it is no longer the active context. Then