Spaces:
Running
Running
ChatBot-UI-With-API
/
venv
/lib
/python3.11
/site-packages
/werkzeug
/datastructures
/cache_control.py
from __future__ import annotations | |
import collections.abc as cabc | |
import typing as t | |
from inspect import cleandoc | |
from .mixins import ImmutableDictMixin | |
from .structures import CallbackDict | |
def cache_control_property( | |
key: str, empty: t.Any, type: type[t.Any] | None, *, doc: str | None = None | |
) -> t.Any: | |
"""Return a new property object for a cache header. Useful if you | |
want to add support for a cache extension in a subclass. | |
:param key: The attribute name present in the parsed cache-control header dict. | |
:param empty: The value to use if the key is present without a value. | |
:param type: The type to convert the string value to instead of a string. If | |
conversion raises a ``ValueError``, the returned value is ``None``. | |
:param doc: The docstring for the property. If not given, it is generated | |
based on the other params. | |
.. versionchanged:: 3.1 | |
Added the ``doc`` param. | |
.. versionchanged:: 2.0 | |
Renamed from ``cache_property``. | |
""" | |
if doc is None: | |
parts = [f"The ``{key}`` attribute."] | |
if type is bool: | |
parts.append("A ``bool``, either present or not.") | |
else: | |
if type is None: | |
parts.append("A ``str``,") | |
else: | |
parts.append(f"A ``{type.__name__}``,") | |
if empty is not None: | |
parts.append(f"``{empty!r}`` if present with no value,") | |
parts.append("or ``None`` if not present.") | |
doc = " ".join(parts) | |
return property( | |
lambda x: x._get_cache_value(key, empty, type), | |
lambda x, v: x._set_cache_value(key, v, type), | |
lambda x: x._del_cache_value(key), | |
doc=cleandoc(doc), | |
) | |
class _CacheControl(CallbackDict[str, t.Optional[str]]): | |
"""Subclass of a dict that stores values for a Cache-Control header. It | |
has accessors for all the cache-control directives specified in RFC 2616. | |
The class does not differentiate between request and response directives. | |
Because the cache-control directives in the HTTP header use dashes the | |
python descriptors use underscores for that. | |
To get a header of the :class:`CacheControl` object again you can convert | |
the object into a string or call the :meth:`to_header` method. If you plan | |
to subclass it and add your own items have a look at the sourcecode for | |
that class. | |
.. versionchanged:: 3.1 | |
Dict values are always ``str | None``. Setting properties will | |
convert the value to a string. Setting a non-bool property to | |
``False`` is equivalent to setting it to ``None``. Getting typed | |
properties will return ``None`` if conversion raises | |
``ValueError``, rather than the string. | |
.. versionchanged:: 2.1 | |
Setting int properties such as ``max_age`` will convert the | |
value to an int. | |
.. versionchanged:: 0.4 | |
Setting ``no_cache`` or ``private`` to ``True`` will set the | |
implicit value ``"*"``. | |
""" | |
no_store: bool = cache_control_property("no-store", None, bool) | |
max_age: int | None = cache_control_property("max-age", None, int) | |
no_transform: bool = cache_control_property("no-transform", None, bool) | |
stale_if_error: int | None = cache_control_property("stale-if-error", None, int) | |
def __init__( | |
self, | |
values: cabc.Mapping[str, t.Any] | cabc.Iterable[tuple[str, t.Any]] | None = (), | |
on_update: cabc.Callable[[_CacheControl], None] | None = None, | |
): | |
super().__init__(values, on_update) | |
self.provided = values is not None | |
def _get_cache_value( | |
self, key: str, empty: t.Any, type: type[t.Any] | None | |
) -> t.Any: | |
"""Used internally by the accessor properties.""" | |
if type is bool: | |
return key in self | |
if key not in self: | |
return None | |
if (value := self[key]) is None: | |
return empty | |
if type is not None: | |
try: | |
value = type(value) | |
except ValueError: | |
return None | |
return value | |
def _set_cache_value( | |
self, key: str, value: t.Any, type: type[t.Any] | None | |
) -> None: | |
"""Used internally by the accessor properties.""" | |
if type is bool: | |
if value: | |
self[key] = None | |
else: | |
self.pop(key, None) | |
elif value is None or value is False: | |
self.pop(key, None) | |
elif value is True: | |
self[key] = None | |
else: | |
if type is not None: | |
value = type(value) | |
self[key] = str(value) | |
def _del_cache_value(self, key: str) -> None: | |
"""Used internally by the accessor properties.""" | |
if key in self: | |
del self[key] | |
def to_header(self) -> str: | |
"""Convert the stored values into a cache control header.""" | |
return http.dump_header(self) | |
def __str__(self) -> str: | |
return self.to_header() | |
def __repr__(self) -> str: | |
kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items())) | |
return f"<{type(self).__name__} {kv_str}>" | |
cache_property = staticmethod(cache_control_property) | |
class RequestCacheControl(ImmutableDictMixin[str, t.Optional[str]], _CacheControl): # type: ignore[misc] | |
"""A cache control for requests. This is immutable and gives access | |
to all the request-relevant cache control headers. | |
To get a header of the :class:`RequestCacheControl` object again you can | |
convert the object into a string or call the :meth:`to_header` method. If | |
you plan to subclass it and add your own items have a look at the sourcecode | |
for that class. | |
.. versionchanged:: 3.1 | |
Dict values are always ``str | None``. Setting properties will | |
convert the value to a string. Setting a non-bool property to | |
``False`` is equivalent to setting it to ``None``. Getting typed | |
properties will return ``None`` if conversion raises | |
``ValueError``, rather than the string. | |
.. versionchanged:: 3.1 | |
``max_age`` is ``None`` if present without a value, rather | |
than ``-1``. | |
.. versionchanged:: 3.1 | |
``no_cache`` is a boolean, it is ``True`` instead of ``"*"`` | |
when present. | |
.. versionchanged:: 3.1 | |
``max_stale`` is ``True`` if present without a value, rather | |
than ``"*"``. | |
.. versionchanged:: 3.1 | |
``no_transform`` is a boolean. Previously it was mistakenly | |
always ``None``. | |
.. versionchanged:: 3.1 | |
``min_fresh`` is ``None`` if present without a value, rather | |
than ``"*"``. | |
.. versionchanged:: 2.1 | |
Setting int properties such as ``max_age`` will convert the | |
value to an int. | |
.. versionadded:: 0.5 | |
Response-only properties are not present on this request class. | |
""" | |
no_cache: bool = cache_control_property("no-cache", None, bool) | |
max_stale: int | t.Literal[True] | None = cache_control_property( | |
"max-stale", | |
True, | |
int, | |
) | |
min_fresh: int | None = cache_control_property("min-fresh", None, int) | |
only_if_cached: bool = cache_control_property("only-if-cached", None, bool) | |
class ResponseCacheControl(_CacheControl): | |
"""A cache control for responses. Unlike :class:`RequestCacheControl` | |
this is mutable and gives access to response-relevant cache control | |
headers. | |
To get a header of the :class:`ResponseCacheControl` object again you can | |
convert the object into a string or call the :meth:`to_header` method. If | |
you plan to subclass it and add your own items have a look at the sourcecode | |
for that class. | |
.. versionchanged:: 3.1 | |
Dict values are always ``str | None``. Setting properties will | |
convert the value to a string. Setting a non-bool property to | |
``False`` is equivalent to setting it to ``None``. Getting typed | |
properties will return ``None`` if conversion raises | |
``ValueError``, rather than the string. | |
.. versionchanged:: 3.1 | |
``no_cache`` is ``True`` if present without a value, rather than | |
``"*"``. | |
.. versionchanged:: 3.1 | |
``private`` is ``True`` if present without a value, rather than | |
``"*"``. | |
.. versionchanged:: 3.1 | |
``no_transform`` is a boolean. Previously it was mistakenly | |
always ``None``. | |
.. versionchanged:: 3.1 | |
Added the ``must_understand``, ``stale_while_revalidate``, and | |
``stale_if_error`` properties. | |
.. versionchanged:: 2.1.1 | |
``s_maxage`` converts the value to an int. | |
.. versionchanged:: 2.1 | |
Setting int properties such as ``max_age`` will convert the | |
value to an int. | |
.. versionadded:: 0.5 | |
Request-only properties are not present on this response class. | |
""" | |
no_cache: str | t.Literal[True] | None = cache_control_property( | |
"no-cache", True, None | |
) | |
public: bool = cache_control_property("public", None, bool) | |
private: str | t.Literal[True] | None = cache_control_property( | |
"private", True, None | |
) | |
must_revalidate: bool = cache_control_property("must-revalidate", None, bool) | |
proxy_revalidate: bool = cache_control_property("proxy-revalidate", None, bool) | |
s_maxage: int | None = cache_control_property("s-maxage", None, int) | |
immutable: bool = cache_control_property("immutable", None, bool) | |
must_understand: bool = cache_control_property("must-understand", None, bool) | |
stale_while_revalidate: int | None = cache_control_property( | |
"stale-while-revalidate", None, int | |
) | |
# circular dependencies | |
from .. import http | |