globals.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import typing as t
  2. from contextvars import ContextVar
  3. from werkzeug.local import LocalProxy
  4. if t.TYPE_CHECKING: # pragma: no cover
  5. from .app import Flask
  6. from .ctx import _AppCtxGlobals
  7. from .ctx import AppContext
  8. from .ctx import RequestContext
  9. from .sessions import SessionMixin
  10. from .wrappers import Request
  11. class _FakeStack:
  12. def __init__(self, name: str, cv: ContextVar[t.Any]) -> None:
  13. self.name = name
  14. self.cv = cv
  15. def _warn(self):
  16. import warnings
  17. warnings.warn(
  18. f"'_{self.name}_ctx_stack' is deprecated and will be"
  19. " removed in Flask 2.3. Use 'g' to store data, or"
  20. f" '{self.name}_ctx' to access the current context.",
  21. DeprecationWarning,
  22. stacklevel=3,
  23. )
  24. def push(self, obj: t.Any) -> None:
  25. self._warn()
  26. self.cv.set(obj)
  27. def pop(self) -> t.Any:
  28. self._warn()
  29. ctx = self.cv.get(None)
  30. self.cv.set(None)
  31. return ctx
  32. @property
  33. def top(self) -> t.Optional[t.Any]:
  34. self._warn()
  35. return self.cv.get(None)
  36. _no_app_msg = """\
  37. Working outside of application context.
  38. This typically means that you attempted to use functionality that needed
  39. the current application. To solve this, set up an application context
  40. with app.app_context(). See the documentation for more information.\
  41. """
  42. _cv_app: ContextVar["AppContext"] = ContextVar("flask.app_ctx")
  43. __app_ctx_stack = _FakeStack("app", _cv_app)
  44. app_ctx: "AppContext" = LocalProxy( # type: ignore[assignment]
  45. _cv_app, unbound_message=_no_app_msg
  46. )
  47. current_app: "Flask" = LocalProxy( # type: ignore[assignment]
  48. _cv_app, "app", unbound_message=_no_app_msg
  49. )
  50. g: "_AppCtxGlobals" = LocalProxy( # type: ignore[assignment]
  51. _cv_app, "g", unbound_message=_no_app_msg
  52. )
  53. _no_req_msg = """\
  54. Working outside of request context.
  55. This typically means that you attempted to use functionality that needed
  56. an active HTTP request. Consult the documentation on testing for
  57. information about how to avoid this problem.\
  58. """
  59. _cv_request: ContextVar["RequestContext"] = ContextVar("flask.request_ctx")
  60. __request_ctx_stack = _FakeStack("request", _cv_request)
  61. request_ctx: "RequestContext" = LocalProxy( # type: ignore[assignment]
  62. _cv_request, unbound_message=_no_req_msg
  63. )
  64. request: "Request" = LocalProxy( # type: ignore[assignment]
  65. _cv_request, "request", unbound_message=_no_req_msg
  66. )
  67. session: "SessionMixin" = LocalProxy( # type: ignore[assignment]
  68. _cv_request, "session", unbound_message=_no_req_msg
  69. )
  70. def __getattr__(name: str) -> t.Any:
  71. if name == "_app_ctx_stack":
  72. import warnings
  73. warnings.warn(
  74. "'_app_ctx_stack' is deprecated and will be remoevd in Flask 2.3.",
  75. DeprecationWarning,
  76. stacklevel=2,
  77. )
  78. return __app_ctx_stack
  79. if name == "_request_ctx_stack":
  80. import warnings
  81. warnings.warn(
  82. "'_request_ctx_stack' is deprecated and will be remoevd in Flask 2.3.",
  83. DeprecationWarning,
  84. stacklevel=2,
  85. )
  86. return __request_ctx_stack
  87. raise AttributeError(name)