]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/werkzeug/local.py
1 from __future__
import annotations
7 from contextvars
import ContextVar
8 from functools
import partial
9 from functools
import update_wrapper
10 from operator
import attrgetter
12 from .wsgi
import ClosingIterator
15 from _typeshed
.wsgi
import StartResponse
16 from _typeshed
.wsgi
import WSGIApplication
17 from _typeshed
.wsgi
import WSGIEnvironment
20 F
= t
.TypeVar("F", bound
=t
.Callable
[..., t
.Any
])
23 def release_local(local
: Local | LocalStack
) -> None:
24 """Release the data for the current context in a :class:`Local` or
25 :class:`LocalStack` without using a :class:`LocalManager`.
27 This should not be needed for modern use cases, and may be removed
30 .. versionadded:: 0.6.1
32 local
.__release
_local
__()
36 """Create a namespace of context-local data. This wraps a
37 :class:`ContextVar` containing a :class:`dict` value.
39 This may incur a performance penalty compared to using individual
40 context vars, as it has to copy data to avoid mutating the dict
41 between nested contexts.
43 :param context_var: The :class:`~contextvars.ContextVar` to use as
44 storage for this local. If not given, one will be created.
45 Context vars not created at the global scope may interfere with
48 .. versionchanged:: 2.0
49 Uses ``ContextVar`` instead of a custom storage implementation.
52 __slots__
= ("__storage",)
54 def __init__(self
, context_var
: ContextVar
[dict[str, t
.Any
]] |
None = None) -> None:
55 if context_var
is None:
56 # A ContextVar not created at global scope interferes with
57 # Python's garbage collection. However, a local only makes
58 # sense defined at the global scope as well, in which case
59 # the GC issue doesn't seem relevant.
60 context_var
= ContextVar(f
"werkzeug.Local<{id(self)}>.storage")
62 object.__setattr
__(self
, "_Local__storage", context_var
)
64 def __iter__(self
) -> t
.Iterator
[tuple[str, t
.Any
]]:
65 return iter(self
.__storage
.get({}).items())
67 def __call__(self
, name
: str, *, unbound_message
: str |
None = None) -> LocalProxy
:
68 """Create a :class:`LocalProxy` that access an attribute on this
71 :param name: Proxy this attribute.
72 :param unbound_message: The error message that the proxy will
73 show if the attribute isn't set.
75 return LocalProxy(self
, name
, unbound_message
=unbound_message
)
77 def __release_local__(self
) -> None:
78 self
.__storage
.set({})
80 def __getattr__(self
, name
: str) -> t
.Any
:
81 values
= self
.__storage
.get({})
86 raise AttributeError(name
)
88 def __setattr__(self
, name
: str, value
: t
.Any
) -> None:
89 values
= self
.__storage
.get({}).copy()
91 self
.__storage
.set(values
)
93 def __delattr__(self
, name
: str) -> None:
94 values
= self
.__storage
.get({})
97 values
= values
.copy()
99 self
.__storage
.set(values
)
101 raise AttributeError(name
)
104 class LocalStack(t
.Generic
[T
]):
105 """Create a stack of context-local data. This wraps a
106 :class:`ContextVar` containing a :class:`list` value.
108 This may incur a performance penalty compared to using individual
109 context vars, as it has to copy data to avoid mutating the list
110 between nested contexts.
112 :param context_var: The :class:`~contextvars.ContextVar` to use as
113 storage for this local. If not given, one will be created.
114 Context vars not created at the global scope may interfere with
117 .. versionchanged:: 2.0
118 Uses ``ContextVar`` instead of a custom storage implementation.
120 .. versionadded:: 0.6.1
123 __slots__
= ("_storage",)
125 def __init__(self
, context_var
: ContextVar
[list[T
]] |
None = None) -> None:
126 if context_var
is None:
127 # A ContextVar not created at global scope interferes with
128 # Python's garbage collection. However, a local only makes
129 # sense defined at the global scope as well, in which case
130 # the GC issue doesn't seem relevant.
131 context_var
= ContextVar(f
"werkzeug.LocalStack<{id(self)}>.storage")
133 self
._storage
= context_var
135 def __release_local__(self
) -> None:
136 self
._storage
.set([])
138 def push(self
, obj
: T
) -> list[T
]:
139 """Add a new item to the top of the stack."""
140 stack
= self
._storage
.get([]).copy()
142 self
._storage
.set(stack
)
145 def pop(self
) -> T |
None:
146 """Remove the top item from the stack and return it. If the
147 stack is empty, return ``None``.
149 stack
= self
._storage
.get([])
155 self
._storage
.set(stack
[:-1])
159 def top(self
) -> T |
None:
160 """The topmost item on the stack. If the stack is empty,
163 stack
= self
._storage
.get([])
171 self
, name
: str |
None = None, *, unbound_message
: str |
None = None
173 """Create a :class:`LocalProxy` that accesses the top of this
176 :param name: If given, the proxy access this attribute of the
177 top item, rather than the item itself.
178 :param unbound_message: The error message that the proxy will
179 show if the stack is empty.
181 return LocalProxy(self
, name
, unbound_message
=unbound_message
)
185 """Manage releasing the data for the current context in one or more
186 :class:`Local` and :class:`LocalStack` objects.
188 This should not be needed for modern use cases, and may be removed
191 :param locals: A local or list of locals to manage.
193 .. versionchanged:: 2.1
194 The ``ident_func`` was removed.
196 .. versionchanged:: 0.7
197 The ``ident_func`` parameter was added.
199 .. versionchanged:: 0.6.1
200 The :func:`release_local` function can be used instead of a
204 __slots__
= ("locals",)
208 locals: None |
(Local | LocalStack | t
.Iterable
[Local | LocalStack
]) = None,
212 elif isinstance(locals, Local
):
213 self
.locals = [locals]
215 self
.locals = list(locals) # type: ignore[arg-type]
217 def cleanup(self
) -> None:
218 """Release the data in the locals for this context. Call this at
219 the end of each request or use :meth:`make_middleware`.
221 for local
in self
.locals:
224 def make_middleware(self
, app
: WSGIApplication
) -> WSGIApplication
:
225 """Wrap a WSGI application so that local data is released
226 automatically after the response has been sent for a request.
230 environ
: WSGIEnvironment
, start_response
: StartResponse
231 ) -> t
.Iterable
[bytes]:
232 return ClosingIterator(app(environ
, start_response
), self
.cleanup
)
236 def middleware(self
, func
: WSGIApplication
) -> WSGIApplication
:
237 """Like :meth:`make_middleware` but used as a decorator on the
238 WSGI application function.
240 .. code-block:: python
243 def application(environ, start_response):
246 return update_wrapper(self
.make_middleware(func
), func
)
248 def __repr__(self
) -> str:
249 return f
"<{type(self).__name__} storages: {len(self.locals)}>"
253 """Descriptor that handles proxied attribute lookup for
256 :param f: The built-in function this attribute is accessed through.
257 Instead of looking up the special method, the function call
258 is redone on the object.
259 :param fallback: Return this function if the proxy is unbound
260 instead of raising a :exc:`RuntimeError`.
261 :param is_attr: This proxied name is an attribute, not a function.
262 Call the fallback immediately to get the value.
263 :param class_value: Value to return when accessed from the
264 ``LocalProxy`` class directly. Used for ``__doc__`` so building
268 __slots__
= ("bind_f", "fallback", "is_attr", "class_value", "name")
272 f
: t
.Callable |
None = None,
273 fallback
: t
.Callable |
None = None,
274 class_value
: t
.Any |
None = None,
275 is_attr
: bool = False,
277 bind_f
: t
.Callable
[[LocalProxy
, t
.Any
], t
.Callable
] |
None
279 if hasattr(f
, "__get__"):
280 # A Python function, can be turned into a bound method.
282 def bind_f(instance
: LocalProxy
, obj
: t
.Any
) -> t
.Callable
:
283 return f
.__get
__(obj
, type(obj
)) # type: ignore
286 # A C function, use partial to bind the first argument.
288 def bind_f(instance
: LocalProxy
, obj
: t
.Any
) -> t
.Callable
:
289 return partial(f
, obj
)
292 # Use getattr, which will produce a bound method.
296 self
.fallback
= fallback
297 self
.class_value
= class_value
298 self
.is_attr
= is_attr
300 def __set_name__(self
, owner
: LocalProxy
, name
: str) -> None:
303 def __get__(self
, instance
: LocalProxy
, owner
: type |
None = None) -> t
.Any
:
305 if self
.class_value
is not None:
306 return self
.class_value
311 obj
= instance
._get
_current
_object
()
313 if self
.fallback
is None:
316 fallback
= self
.fallback
.__get
__(instance
, owner
)
319 # __class__ and __doc__ are attributes, not methods.
320 # Call the fallback to get the value.
325 if self
.bind_f
is not None:
326 return self
.bind_f(instance
, obj
)
328 return getattr(obj
, self
.name
)
330 def __repr__(self
) -> str:
331 return f
"proxy {self.name}"
333 def __call__(self
, instance
: LocalProxy
, *args
: t
.Any
, **kwargs
: t
.Any
) -> t
.Any
:
334 """Support calling unbound methods from the class. For example,
335 this happens with ``copy.copy``, which does
336 ``type(x).__copy__(x)``. ``type(x)`` can't be proxied, so it
337 returns the proxy type and descriptor.
339 return self
.__get
__(instance
, type(instance
))(*args
, **kwargs
)
342 class _ProxyIOp(_ProxyLookup
):
343 """Look up an augmented assignment method on a proxied object. The
344 method is wrapped to return the proxy instead of the object.
350 self
, f
: t
.Callable |
None = None, fallback
: t
.Callable |
None = None
352 super().__init
__(f
, fallback
)
354 def bind_f(instance
: LocalProxy
, obj
: t
.Any
) -> t
.Callable
:
355 def i_op(self
: t
.Any
, other
: t
.Any
) -> LocalProxy
:
356 f(self
, other
) # type: ignore
359 return i_op
.__get
__(obj
, type(obj
)) # type: ignore
364 def _l_to_r_op(op
: F
) -> F
:
365 """Swap the argument order to turn an l-op into an r-op."""
367 def r_op(obj
: t
.Any
, other
: t
.Any
) -> t
.Any
:
368 return op(other
, obj
)
370 return t
.cast(F
, r_op
)
373 def _identity(o
: T
) -> T
:
377 class LocalProxy(t
.Generic
[T
]):
378 """A proxy to the object bound to a context-local object. All
379 operations on the proxy are forwarded to the bound object. If no
380 object is bound, a ``RuntimeError`` is raised.
382 :param local: The context-local object that provides the proxied
384 :param name: Proxy this attribute from the proxied object.
385 :param unbound_message: The error message to show if the
386 context-local object is unbound.
388 Proxy a :class:`~contextvars.ContextVar` to make it easier to
389 access. Pass a name to proxy that attribute.
391 .. code-block:: python
393 _request_var = ContextVar("request")
394 request = LocalProxy(_request_var)
395 session = LocalProxy(_request_var, "session")
397 Proxy an attribute on a :class:`Local` namespace by calling the
398 local with the attribute name:
400 .. code-block:: python
405 Proxy the top item on a :class:`LocalStack` by calling the local.
406 Pass a name to proxy that attribute.
410 app_stack = LocalStack()
411 current_app = app_stack()
414 Pass a function to proxy the return value from that function. This
415 was previously used to access attributes of local objects before
416 that was supported directly.
418 .. code-block:: python
420 session = LocalProxy(lambda: request.session)
422 ``__repr__`` and ``__class__`` are proxied, so ``repr(x)`` and
423 ``isinstance(x, cls)`` will look like the proxied object. Use
424 ``issubclass(type(x), LocalProxy)`` to check if an object is a
427 .. code-block:: python
429 repr(user) # <User admin>
430 isinstance(user, User) # True
431 issubclass(type(user), LocalProxy) # True
433 .. versionchanged:: 2.2.2
434 ``__wrapped__`` is set when wrapping an object, not only when
435 wrapping a function, to prevent doctest from failing.
437 .. versionchanged:: 2.2
438 Can proxy a ``ContextVar`` or ``LocalStack`` directly.
440 .. versionchanged:: 2.2
441 The ``name`` parameter can be used with any proxied object, not
444 .. versionchanged:: 2.2
445 Added the ``unbound_message`` parameter.
447 .. versionchanged:: 2.0
448 Updated proxied attributes and methods to reflect the current
451 .. versionchanged:: 0.6.1
452 The class can be instantiated with a callable.
455 __slots__
= ("__wrapped", "_get_current_object")
457 _get_current_object
: t
.Callable
[[], T
]
458 """Return the current object this proxy is bound to. If the proxy is
459 unbound, this raises a ``RuntimeError``.
461 This should be used if you need to pass the object to something that
462 doesn't understand the proxy. It can also be useful for performance
463 if you are accessing the object multiple times in a function, rather
464 than going through the proxy multiple times.
469 local
: ContextVar
[T
] | Local | LocalStack
[T
] | t
.Callable
[[], T
],
470 name
: str |
None = None,
472 unbound_message
: str |
None = None,
477 get_name
= attrgetter(name
) # type: ignore[assignment]
479 if unbound_message
is None:
480 unbound_message
= "object is not bound"
482 if isinstance(local
, Local
):
484 raise TypeError("'name' is required when proxying a 'Local' object.")
486 def _get_current_object() -> T
:
488 return get_name(local
) # type: ignore[return-value]
489 except AttributeError:
490 raise RuntimeError(unbound_message
) from None
492 elif isinstance(local
, LocalStack
):
494 def _get_current_object() -> T
:
498 raise RuntimeError(unbound_message
)
502 elif isinstance(local
, ContextVar
):
504 def _get_current_object() -> T
:
508 raise RuntimeError(unbound_message
) from None
512 elif callable(local
):
514 def _get_current_object() -> T
:
515 return get_name(local())
518 raise TypeError(f
"Don't know how to proxy '{type(local)}'.")
520 object.__setattr
__(self
, "_LocalProxy__wrapped", local
)
521 object.__setattr
__(self
, "_get_current_object", _get_current_object
)
523 __doc__
= _ProxyLookup( # type: ignore
524 class_value
=__doc__
, fallback
=lambda self
: type(self
).__doc
__, is_attr
=True
526 __wrapped__
= _ProxyLookup(
527 fallback
=lambda self
: self
._LocalProxy
__wrapped
, is_attr
=True
529 # __del__ should only delete the proxy
530 __repr__
= _ProxyLookup( # type: ignore
531 repr, fallback
=lambda self
: f
"<{type(self).__name__} unbound>"
533 __str__
= _ProxyLookup(str) # type: ignore
534 __bytes__
= _ProxyLookup(bytes)
535 __format__
= _ProxyLookup() # type: ignore
536 __lt__
= _ProxyLookup(operator
.lt
)
537 __le__
= _ProxyLookup(operator
.le
)
538 __eq__
= _ProxyLookup(operator
.eq
) # type: ignore
539 __ne__
= _ProxyLookup(operator
.ne
) # type: ignore
540 __gt__
= _ProxyLookup(operator
.gt
)
541 __ge__
= _ProxyLookup(operator
.ge
)
542 __hash__
= _ProxyLookup(hash) # type: ignore
543 __bool__
= _ProxyLookup(bool, fallback
=lambda self
: False)
544 __getattr__
= _ProxyLookup(getattr)
545 # __getattribute__ triggered through __getattr__
546 __setattr__
= _ProxyLookup(setattr) # type: ignore
547 __delattr__
= _ProxyLookup(delattr) # type: ignore
548 __dir__
= _ProxyLookup(dir, fallback
=lambda self
: []) # type: ignore
549 # __get__ (proxying descriptor not supported)
550 # __set__ (descriptor)
551 # __delete__ (descriptor)
552 # __set_name__ (descriptor)
553 # __objclass__ (descriptor)
554 # __slots__ used by proxy itself
555 # __dict__ (__getattr__)
556 # __weakref__ (__getattr__)
557 # __init_subclass__ (proxying metaclass not supported)
558 # __prepare__ (metaclass)
559 __class__
= _ProxyLookup(
560 fallback
=lambda self
: type(self
), is_attr
=True
562 __instancecheck__
= _ProxyLookup(lambda self
, other
: isinstance(other
, self
))
563 __subclasscheck__
= _ProxyLookup(lambda self
, other
: issubclass(other
, self
))
564 # __class_getitem__ triggered through __getitem__
565 __call__
= _ProxyLookup(lambda self
, *args
, **kwargs
: self(*args
, **kwargs
))
566 __len__
= _ProxyLookup(len)
567 __length_hint__
= _ProxyLookup(operator
.length_hint
)
568 __getitem__
= _ProxyLookup(operator
.getitem
)
569 __setitem__
= _ProxyLookup(operator
.setitem
)
570 __delitem__
= _ProxyLookup(operator
.delitem
)
571 # __missing__ triggered through __getitem__
572 __iter__
= _ProxyLookup(iter)
573 __next__
= _ProxyLookup(next
)
574 __reversed__
= _ProxyLookup(reversed)
575 __contains__
= _ProxyLookup(operator
.contains
)
576 __add__
= _ProxyLookup(operator
.add
)
577 __sub__
= _ProxyLookup(operator
.sub
)
578 __mul__
= _ProxyLookup(operator
.mul
)
579 __matmul__
= _ProxyLookup(operator
.matmul
)
580 __truediv__
= _ProxyLookup(operator
.truediv
)
581 __floordiv__
= _ProxyLookup(operator
.floordiv
)
582 __mod__
= _ProxyLookup(operator
.mod
)
583 __divmod__
= _ProxyLookup(divmod)
584 __pow__
= _ProxyLookup(pow)
585 __lshift__
= _ProxyLookup(operator
.lshift
)
586 __rshift__
= _ProxyLookup(operator
.rshift
)
587 __and__
= _ProxyLookup(operator
.and_
)
588 __xor__
= _ProxyLookup(operator
.xor
)
589 __or__
= _ProxyLookup(operator
.or_
)
590 __radd__
= _ProxyLookup(_l_to_r_op(operator
.add
))
591 __rsub__
= _ProxyLookup(_l_to_r_op(operator
.sub
))
592 __rmul__
= _ProxyLookup(_l_to_r_op(operator
.mul
))
593 __rmatmul__
= _ProxyLookup(_l_to_r_op(operator
.matmul
))
594 __rtruediv__
= _ProxyLookup(_l_to_r_op(operator
.truediv
))
595 __rfloordiv__
= _ProxyLookup(_l_to_r_op(operator
.floordiv
))
596 __rmod__
= _ProxyLookup(_l_to_r_op(operator
.mod
))
597 __rdivmod__
= _ProxyLookup(_l_to_r_op(divmod))
598 __rpow__
= _ProxyLookup(_l_to_r_op(pow))
599 __rlshift__
= _ProxyLookup(_l_to_r_op(operator
.lshift
))
600 __rrshift__
= _ProxyLookup(_l_to_r_op(operator
.rshift
))
601 __rand__
= _ProxyLookup(_l_to_r_op(operator
.and_
))
602 __rxor__
= _ProxyLookup(_l_to_r_op(operator
.xor
))
603 __ror__
= _ProxyLookup(_l_to_r_op(operator
.or_
))
604 __iadd__
= _ProxyIOp(operator
.iadd
)
605 __isub__
= _ProxyIOp(operator
.isub
)
606 __imul__
= _ProxyIOp(operator
.imul
)
607 __imatmul__
= _ProxyIOp(operator
.imatmul
)
608 __itruediv__
= _ProxyIOp(operator
.itruediv
)
609 __ifloordiv__
= _ProxyIOp(operator
.ifloordiv
)
610 __imod__
= _ProxyIOp(operator
.imod
)
611 __ipow__
= _ProxyIOp(operator
.ipow
)
612 __ilshift__
= _ProxyIOp(operator
.ilshift
)
613 __irshift__
= _ProxyIOp(operator
.irshift
)
614 __iand__
= _ProxyIOp(operator
.iand
)
615 __ixor__
= _ProxyIOp(operator
.ixor
)
616 __ior__
= _ProxyIOp(operator
.ior
)
617 __neg__
= _ProxyLookup(operator
.neg
)
618 __pos__
= _ProxyLookup(operator
.pos
)
619 __abs__
= _ProxyLookup(abs)
620 __invert__
= _ProxyLookup(operator
.invert
)
621 __complex__
= _ProxyLookup(complex)
622 __int__
= _ProxyLookup(int)
623 __float__
= _ProxyLookup(float)
624 __index__
= _ProxyLookup(operator
.index
)
625 __round__
= _ProxyLookup(round)
626 __trunc__
= _ProxyLookup(math
.trunc
)
627 __floor__
= _ProxyLookup(math
.floor
)
628 __ceil__
= _ProxyLookup(math
.ceil
)
629 __enter__
= _ProxyLookup()
630 __exit__
= _ProxyLookup()
631 __await__
= _ProxyLookup()
632 __aiter__
= _ProxyLookup()
633 __anext__
= _ProxyLookup()
634 __aenter__
= _ProxyLookup()
635 __aexit__
= _ProxyLookup()
636 __copy__
= _ProxyLookup(copy
.copy
)
637 __deepcopy__
= _ProxyLookup(copy
.deepcopy
)
638 # __getnewargs_ex__ (pickle through proxy not supported)
639 # __getnewargs__ (pickle)
640 # __getstate__ (pickle)
641 # __setstate__ (pickle)
642 # __reduce__ (pickle)
643 # __reduce_ex__ (pickle)