remove uses of LocalStack
This commit is contained in:
parent
d597db67de
commit
82c2e0366c
13 changed files with 114 additions and 131 deletions
|
|
@ -38,10 +38,11 @@ from .config import ConfigAttribute
|
|||
from .ctx import _AppCtxGlobals
|
||||
from .ctx import AppContext
|
||||
from .ctx import RequestContext
|
||||
from .globals import _app_ctx_stack
|
||||
from .globals import _request_ctx_stack
|
||||
from .globals import _cv_app
|
||||
from .globals import _cv_req
|
||||
from .globals import g
|
||||
from .globals import request
|
||||
from .globals import request_ctx
|
||||
from .globals import session
|
||||
from .helpers import _split_blueprint_path
|
||||
from .helpers import get_debug_flag
|
||||
|
|
@ -1554,10 +1555,10 @@ class Flask(Scaffold):
|
|||
This no longer does the exception handling, this code was
|
||||
moved to the new :meth:`full_dispatch_request`.
|
||||
"""
|
||||
req = _request_ctx_stack.top.request
|
||||
req = request_ctx.request
|
||||
if req.routing_exception is not None:
|
||||
self.raise_routing_exception(req)
|
||||
rule = req.url_rule
|
||||
rule: Rule = req.url_rule # type: ignore[assignment]
|
||||
# if we provide automatic options for this URL and the
|
||||
# request came with the OPTIONS method, reply automatically
|
||||
if (
|
||||
|
|
@ -1566,7 +1567,8 @@ class Flask(Scaffold):
|
|||
):
|
||||
return self.make_default_options_response()
|
||||
# otherwise dispatch to the handler for that endpoint
|
||||
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
|
||||
view_args: t.Dict[str, t.Any] = req.view_args # type: ignore[assignment]
|
||||
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
|
||||
|
||||
def full_dispatch_request(self) -> Response:
|
||||
"""Dispatches the request and on top of that performs request
|
||||
|
|
@ -1631,8 +1633,8 @@ class Flask(Scaffold):
|
|||
|
||||
.. versionadded:: 0.7
|
||||
"""
|
||||
adapter = _request_ctx_stack.top.url_adapter
|
||||
methods = adapter.allowed_methods()
|
||||
adapter = request_ctx.url_adapter
|
||||
methods = adapter.allowed_methods() # type: ignore[union-attr]
|
||||
rv = self.response_class()
|
||||
rv.allow.update(methods)
|
||||
return rv
|
||||
|
|
@ -1740,7 +1742,7 @@ class Flask(Scaffold):
|
|||
.. versionadded:: 2.2
|
||||
Moved from ``flask.url_for``, which calls this method.
|
||||
"""
|
||||
req_ctx = _request_ctx_stack.top
|
||||
req_ctx = _cv_req.get(None)
|
||||
|
||||
if req_ctx is not None:
|
||||
url_adapter = req_ctx.url_adapter
|
||||
|
|
@ -1759,7 +1761,7 @@ class Flask(Scaffold):
|
|||
if _external is None:
|
||||
_external = _scheme is not None
|
||||
else:
|
||||
app_ctx = _app_ctx_stack.top
|
||||
app_ctx = _cv_app.get(None)
|
||||
|
||||
# If called by helpers.url_for, an app context is active,
|
||||
# use its url_adapter. Otherwise, app.url_for was called
|
||||
|
|
@ -1790,7 +1792,7 @@ class Flask(Scaffold):
|
|||
self.inject_url_defaults(endpoint, values)
|
||||
|
||||
try:
|
||||
rv = url_adapter.build(
|
||||
rv = url_adapter.build( # type: ignore[union-attr]
|
||||
endpoint,
|
||||
values,
|
||||
method=_method,
|
||||
|
|
@ -2099,7 +2101,7 @@ class Flask(Scaffold):
|
|||
:return: a new response object or the same, has to be an
|
||||
instance of :attr:`response_class`.
|
||||
"""
|
||||
ctx = _request_ctx_stack.top
|
||||
ctx = request_ctx._get_current_object() # type: ignore[attr-defined]
|
||||
|
||||
for func in ctx._after_request_functions:
|
||||
response = self.ensure_sync(func)(response)
|
||||
|
|
@ -2305,8 +2307,8 @@ class Flask(Scaffold):
|
|||
return response(environ, start_response)
|
||||
finally:
|
||||
if "werkzeug.debug.preserve_context" in environ:
|
||||
environ["werkzeug.debug.preserve_context"](_app_ctx_stack.top)
|
||||
environ["werkzeug.debug.preserve_context"](_request_ctx_stack.top)
|
||||
environ["werkzeug.debug.preserve_context"](_cv_app.get())
|
||||
environ["werkzeug.debug.preserve_context"](_cv_req.get())
|
||||
|
||||
if error is not None and self.should_ignore_error(error):
|
||||
error = None
|
||||
|
|
|
|||
|
|
@ -1051,13 +1051,11 @@ def shell_command() -> None:
|
|||
without having to manually configure the application.
|
||||
"""
|
||||
import code
|
||||
from .globals import _app_ctx_stack
|
||||
|
||||
app = _app_ctx_stack.top.app
|
||||
banner = (
|
||||
f"Python {sys.version} on {sys.platform}\n"
|
||||
f"App: {app.import_name} [{app.env}]\n"
|
||||
f"Instance: {app.instance_path}"
|
||||
f"App: {current_app.import_name} [{current_app.env}]\n"
|
||||
f"Instance: {current_app.instance_path}"
|
||||
)
|
||||
ctx: dict = {}
|
||||
|
||||
|
|
@ -1068,7 +1066,7 @@ def shell_command() -> None:
|
|||
with open(startup) as f:
|
||||
eval(compile(f.read(), startup, "exec"), ctx)
|
||||
|
||||
ctx.update(app.make_shell_context())
|
||||
ctx.update(current_app.make_shell_context())
|
||||
|
||||
# Site, customize, or startup script can set a hook to call when
|
||||
# entering interactive mode. The default one sets up readline with
|
||||
|
|
|
|||
|
|
@ -7,10 +7,8 @@ from types import TracebackType
|
|||
from werkzeug.exceptions import HTTPException
|
||||
|
||||
from . import typing as ft
|
||||
from .globals import _app_ctx_stack
|
||||
from .globals import _cv_app
|
||||
from .globals import _cv_req
|
||||
from .globals import _request_ctx_stack
|
||||
from .signals import appcontext_popped
|
||||
from .signals import appcontext_pushed
|
||||
|
||||
|
|
@ -106,9 +104,9 @@ class _AppCtxGlobals:
|
|||
return iter(self.__dict__)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
top = _app_ctx_stack.top
|
||||
if top is not None:
|
||||
return f"<flask.g of {top.app.name!r}>"
|
||||
ctx = _cv_app.get(None)
|
||||
if ctx is not None:
|
||||
return f"<flask.g of '{ctx.app.name}'>"
|
||||
return object.__repr__(self)
|
||||
|
||||
|
||||
|
|
@ -133,15 +131,15 @@ def after_this_request(f: ft.AfterRequestCallable) -> ft.AfterRequestCallable:
|
|||
|
||||
.. versionadded:: 0.9
|
||||
"""
|
||||
top = _request_ctx_stack.top
|
||||
ctx = _cv_req.get(None)
|
||||
|
||||
if top is None:
|
||||
if ctx is None:
|
||||
raise RuntimeError(
|
||||
"This decorator can only be used when a request context is"
|
||||
" active, such as within a view function."
|
||||
"'after_this_request' can only be used when a request"
|
||||
" context is active, such as in a view function."
|
||||
)
|
||||
|
||||
top._after_request_functions.append(f)
|
||||
ctx._after_request_functions.append(f)
|
||||
return f
|
||||
|
||||
|
||||
|
|
@ -169,19 +167,19 @@ def copy_current_request_context(f: t.Callable) -> t.Callable:
|
|||
|
||||
.. versionadded:: 0.10
|
||||
"""
|
||||
top = _request_ctx_stack.top
|
||||
ctx = _cv_req.get(None)
|
||||
|
||||
if top is None:
|
||||
if ctx is None:
|
||||
raise RuntimeError(
|
||||
"This decorator can only be used when a request context is"
|
||||
" active, such as within a view function."
|
||||
"'copy_current_request_context' can only be used when a"
|
||||
" request context is active, such as in a view function."
|
||||
)
|
||||
|
||||
reqctx = top.copy()
|
||||
ctx = ctx.copy()
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
with reqctx:
|
||||
return reqctx.app.ensure_sync(f)(*args, **kwargs)
|
||||
with ctx:
|
||||
return ctx.app.ensure_sync(f)(*args, **kwargs)
|
||||
|
||||
return update_wrapper(wrapper, f)
|
||||
|
||||
|
|
@ -240,7 +238,7 @@ class AppContext:
|
|||
def __init__(self, app: "Flask") -> None:
|
||||
self.app = app
|
||||
self.url_adapter = app.create_url_adapter(None)
|
||||
self.g = app.app_ctx_globals_class()
|
||||
self.g: _AppCtxGlobals = app.app_ctx_globals_class()
|
||||
self._cv_tokens: t.List[contextvars.Token] = []
|
||||
|
||||
def push(self) -> None:
|
||||
|
|
@ -311,14 +309,14 @@ class RequestContext:
|
|||
self.app = app
|
||||
if request is None:
|
||||
request = app.request_class(environ)
|
||||
self.request = request
|
||||
self.request: Request = request
|
||||
self.url_adapter = None
|
||||
try:
|
||||
self.url_adapter = app.create_url_adapter(self.request)
|
||||
except HTTPException as e:
|
||||
self.request.routing_exception = e
|
||||
self.flashes = None
|
||||
self.session = session
|
||||
self.flashes: t.Optional[t.List[t.Tuple[str, str]]] = None
|
||||
self.session: t.Optional["SessionMixin"] = session
|
||||
# Functions that should be executed after the request on the response
|
||||
# object. These will be called before the regular "after_request"
|
||||
# functions.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import typing as t
|
|||
|
||||
from .app import Flask
|
||||
from .blueprints import Blueprint
|
||||
from .globals import _request_ctx_stack
|
||||
from .globals import request_ctx
|
||||
|
||||
|
||||
class UnexpectedUnicodeError(AssertionError, UnicodeError):
|
||||
|
|
@ -116,9 +116,8 @@ def explain_template_loading_attempts(app: Flask, template, attempts) -> None:
|
|||
info = [f"Locating template {template!r}:"]
|
||||
total_found = 0
|
||||
blueprint = None
|
||||
reqctx = _request_ctx_stack.top
|
||||
if reqctx is not None and reqctx.request.blueprint is not None:
|
||||
blueprint = reqctx.request.blueprint
|
||||
if request_ctx and request_ctx.request.blueprint is not None:
|
||||
blueprint = request_ctx.request.blueprint
|
||||
|
||||
for idx, (loader, srcobj, triple) in enumerate(attempts):
|
||||
if isinstance(srcobj, Flask):
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ import werkzeug.utils
|
|||
from werkzeug.exceptions import abort as _wz_abort
|
||||
from werkzeug.utils import redirect as _wz_redirect
|
||||
|
||||
from .globals import _request_ctx_stack
|
||||
from .globals import _cv_req
|
||||
from .globals import current_app
|
||||
from .globals import request
|
||||
from .globals import request_ctx
|
||||
from .globals import session
|
||||
from .signals import message_flashed
|
||||
|
||||
|
|
@ -110,11 +111,11 @@ def stream_with_context(
|
|||
return update_wrapper(decorator, generator_or_function) # type: ignore
|
||||
|
||||
def generator() -> t.Generator:
|
||||
ctx = _request_ctx_stack.top
|
||||
ctx = _cv_req.get(None)
|
||||
if ctx is None:
|
||||
raise RuntimeError(
|
||||
"Attempted to stream with context but "
|
||||
"there was no context in the first place to keep around."
|
||||
"'stream_with_context' can only be used when a request"
|
||||
" context is active, such as in a view function."
|
||||
)
|
||||
with ctx:
|
||||
# Dummy sentinel. Has to be inside the context block or we're
|
||||
|
|
@ -377,11 +378,10 @@ def get_flashed_messages(
|
|||
:param category_filter: filter of categories to limit return values. Only
|
||||
categories in the list will be returned.
|
||||
"""
|
||||
flashes = _request_ctx_stack.top.flashes
|
||||
flashes = request_ctx.flashes
|
||||
if flashes is None:
|
||||
_request_ctx_stack.top.flashes = flashes = (
|
||||
session.pop("_flashes") if "_flashes" in session else []
|
||||
)
|
||||
flashes = session.pop("_flashes") if "_flashes" in session else []
|
||||
request_ctx.flashes = flashes
|
||||
if category_filter:
|
||||
flashes = list(filter(lambda f: f[0] in category_filter, flashes))
|
||||
if not with_categories:
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ from jinja2 import Environment as BaseEnvironment
|
|||
from jinja2 import Template
|
||||
from jinja2 import TemplateNotFound
|
||||
|
||||
from .globals import _app_ctx_stack
|
||||
from .globals import _request_ctx_stack
|
||||
from .globals import _cv_app
|
||||
from .globals import _cv_req
|
||||
from .globals import current_app
|
||||
from .globals import request
|
||||
from .helpers import stream_with_context
|
||||
|
|
@ -22,9 +22,9 @@ def _default_template_ctx_processor() -> t.Dict[str, t.Any]:
|
|||
"""Default template context processor. Injects `request`,
|
||||
`session` and `g`.
|
||||
"""
|
||||
reqctx = _request_ctx_stack.top
|
||||
appctx = _app_ctx_stack.top
|
||||
rv = {}
|
||||
appctx = _cv_app.get(None)
|
||||
reqctx = _cv_req.get(None)
|
||||
rv: t.Dict[str, t.Any] = {}
|
||||
if appctx is not None:
|
||||
rv["g"] = appctx.g
|
||||
if reqctx is not None:
|
||||
|
|
@ -124,7 +124,8 @@ class DispatchingJinjaLoader(BaseLoader):
|
|||
return list(result)
|
||||
|
||||
|
||||
def _render(template: Template, context: dict, app: "Flask") -> str:
|
||||
def _render(app: "Flask", template: Template, context: t.Dict[str, t.Any]) -> str:
|
||||
app.update_template_context(context)
|
||||
before_render_template.send(app, template=template, context=context)
|
||||
rv = template.render(context)
|
||||
template_rendered.send(app, template=template, context=context)
|
||||
|
|
@ -135,36 +136,27 @@ def render_template(
|
|||
template_name_or_list: t.Union[str, Template, t.List[t.Union[str, Template]]],
|
||||
**context: t.Any
|
||||
) -> str:
|
||||
"""Renders a template from the template folder with the given
|
||||
context.
|
||||
"""Render a template by name with the given context.
|
||||
|
||||
:param template_name_or_list: the name of the template to be
|
||||
rendered, or an iterable with template names
|
||||
the first one existing will be rendered
|
||||
:param context: the variables that should be available in the
|
||||
context of the template.
|
||||
:param template_name_or_list: The name of the template to render. If
|
||||
a list is given, the first name to exist will be rendered.
|
||||
:param context: The variables to make available in the template.
|
||||
"""
|
||||
ctx = _app_ctx_stack.top
|
||||
ctx.app.update_template_context(context)
|
||||
return _render(
|
||||
ctx.app.jinja_env.get_or_select_template(template_name_or_list),
|
||||
context,
|
||||
ctx.app,
|
||||
)
|
||||
app = current_app._get_current_object() # type: ignore[attr-defined]
|
||||
template = app.jinja_env.get_or_select_template(template_name_or_list)
|
||||
return _render(app, template, context)
|
||||
|
||||
|
||||
def render_template_string(source: str, **context: t.Any) -> str:
|
||||
"""Renders a template from the given template source string
|
||||
with the given context. Template variables will be autoescaped.
|
||||
"""Render a template from the given source string with the given
|
||||
context.
|
||||
|
||||
:param source: the source code of the template to be
|
||||
rendered
|
||||
:param context: the variables that should be available in the
|
||||
context of the template.
|
||||
:param source: The source code of the template to render.
|
||||
:param context: The variables to make available in the template.
|
||||
"""
|
||||
ctx = _app_ctx_stack.top
|
||||
ctx.app.update_template_context(context)
|
||||
return _render(ctx.app.jinja_env.from_string(source), context, ctx.app)
|
||||
app = current_app._get_current_object() # type: ignore[attr-defined]
|
||||
template = app.jinja_env.from_string(source)
|
||||
return _render(app, template, context)
|
||||
|
||||
|
||||
def _stream(
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class FlaskClient(Client):
|
|||
# behavior. It's important to not use the push and pop
|
||||
# methods of the actual request context object since that would
|
||||
# mean that cleanup handlers are called
|
||||
token = _cv_req.set(outer_reqctx)
|
||||
token = _cv_req.set(outer_reqctx) # type: ignore[arg-type]
|
||||
try:
|
||||
yield sess
|
||||
finally:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue