Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
cache_control.py274 linesDownload Raw Back to datastructures
1from __future__ import annotations2 3import collections.abc as cabc4import typing as t5from inspect import cleandoc6 7from .mixins import ImmutableDictMixin8from .structures import CallbackDict9 10 11def cache_control_property(12    key: str, empty: t.Any, type: type[t.Any] | None, *, doc: str | None = None13) -> t.Any:14    """Return a new property object for a cache header. Useful if you15    want to add support for a cache extension in a subclass.16 17    :param key: The attribute name present in the parsed cache-control header dict.18    :param empty: The value to use if the key is present without a value.19    :param type: The type to convert the string value to instead of a string. If20        conversion raises a ``ValueError``, the returned value is ``None``.21    :param doc: The docstring for the property. If not given, it is generated22        based on the other params.23 24    .. versionchanged:: 3.125        Added the ``doc`` param.26 27    .. versionchanged:: 2.028        Renamed from ``cache_property``.29    """30    if doc is None:31        parts = [f"The ``{key}`` attribute."]32 33        if type is bool:34            parts.append("A ``bool``, either present or not.")35        else:36            if type is None:37                parts.append("A ``str``,")38            else:39                parts.append(f"A ``{type.__name__}``,")40 41            if empty is not None:42                parts.append(f"``{empty!r}`` if present with no value,")43 44            parts.append("or ``None`` if not present.")45 46        doc = " ".join(parts)47 48    return property(49        lambda x: x._get_cache_value(key, empty, type),50        lambda x, v: x._set_cache_value(key, v, type),51        lambda x: x._del_cache_value(key),52        doc=cleandoc(doc),53    )54 55 56class _CacheControl(CallbackDict[str, t.Optional[str]]):57    """Subclass of a dict that stores values for a Cache-Control header.  It58    has accessors for all the cache-control directives specified in RFC 2616.59    The class does not differentiate between request and response directives.60 61    Because the cache-control directives in the HTTP header use dashes the62    python descriptors use underscores for that.63 64    To get a header of the :class:`CacheControl` object again you can convert65    the object into a string or call the :meth:`to_header` method.  If you plan66    to subclass it and add your own items have a look at the sourcecode for67    that class.68 69    .. versionchanged:: 3.170        Dict values are always ``str | None``. Setting properties will71        convert the value to a string. Setting a non-bool property to72        ``False`` is equivalent to setting it to ``None``. Getting typed73        properties will return ``None`` if conversion raises74        ``ValueError``, rather than the string.75 76    .. versionchanged:: 2.177        Setting int properties such as ``max_age`` will convert the78        value to an int.79 80    .. versionchanged:: 0.481       Setting ``no_cache`` or ``private`` to ``True`` will set the82       implicit value ``"*"``.83    """84 85    no_store: bool = cache_control_property("no-store", None, bool)86    max_age: int | None = cache_control_property("max-age", None, int)87    no_transform: bool = cache_control_property("no-transform", None, bool)88    stale_if_error: int | None = cache_control_property("stale-if-error", None, int)89 90    def __init__(91        self,92        values: cabc.Mapping[str, t.Any] | cabc.Iterable[tuple[str, t.Any]] | None = (),93        on_update: cabc.Callable[[_CacheControl], None] | None = None,94    ):95        super().__init__(values, on_update)96        self.provided = values is not None97 98    def _get_cache_value(99        self, key: str, empty: t.Any, type: type[t.Any] | None100    ) -> t.Any:101        """Used internally by the accessor properties."""102        if type is bool:103            return key in self104 105        if key not in self:106            return None107 108        if (value := self[key]) is None:109            return empty110 111        if type is not None:112            try:113                value = type(value)114            except ValueError:115                return None116 117        return value118 119    def _set_cache_value(120        self, key: str, value: t.Any, type: type[t.Any] | None121    ) -> None:122        """Used internally by the accessor properties."""123        if type is bool:124            if value:125                self[key] = None126            else:127                self.pop(key, None)128        elif value is None or value is False:129            self.pop(key, None)130        elif value is True:131            self[key] = None132        else:133            if type is not None:134                value = type(value)135 136            self[key] = str(value)137 138    def _del_cache_value(self, key: str) -> None:139        """Used internally by the accessor properties."""140        if key in self:141            del self[key]142 143    def to_header(self) -> str:144        """Convert the stored values into a cache control header."""145        return http.dump_header(self)146 147    def __str__(self) -> str:148        return self.to_header()149 150    def __repr__(self) -> str:151        kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items()))152        return f"<{type(self).__name__} {kv_str}>"153 154    cache_property = staticmethod(cache_control_property)155 156 157class RequestCacheControl(ImmutableDictMixin[str, t.Optional[str]], _CacheControl):  # type: ignore[misc]158    """A cache control for requests.  This is immutable and gives access159    to all the request-relevant cache control headers.160 161    To get a header of the :class:`RequestCacheControl` object again you can162    convert the object into a string or call the :meth:`to_header` method.  If163    you plan to subclass it and add your own items have a look at the sourcecode164    for that class.165 166    .. versionchanged:: 3.1167        Dict values are always ``str | None``. Setting properties will168        convert the value to a string. Setting a non-bool property to169        ``False`` is equivalent to setting it to ``None``. Getting typed170        properties will return ``None`` if conversion raises171        ``ValueError``, rather than the string.172 173    .. versionchanged:: 3.1174       ``max_age`` is ``None`` if present without a value, rather175       than ``-1``.176 177    .. versionchanged:: 3.1178        ``no_cache`` is a boolean, it is ``True`` instead of ``"*"``179        when present.180 181    .. versionchanged:: 3.1182        ``max_stale`` is ``True`` if present without a value, rather183        than ``"*"``.184 185    .. versionchanged:: 3.1186       ``no_transform`` is a boolean. Previously it was mistakenly187       always ``None``.188 189    .. versionchanged:: 3.1190       ``min_fresh`` is ``None`` if present without a value, rather191       than ``"*"``.192 193    .. versionchanged:: 2.1194        Setting int properties such as ``max_age`` will convert the195        value to an int.196 197    .. versionadded:: 0.5198        Response-only properties are not present on this request class.199    """200 201    no_cache: bool = cache_control_property("no-cache", None, bool)202    max_stale: int | t.Literal[True] | None = cache_control_property(203        "max-stale",204        True,205        int,206    )207    min_fresh: int | None = cache_control_property("min-fresh", None, int)208    only_if_cached: bool = cache_control_property("only-if-cached", None, bool)209 210 211class ResponseCacheControl(_CacheControl):212    """A cache control for responses.  Unlike :class:`RequestCacheControl`213    this is mutable and gives access to response-relevant cache control214    headers.215 216    To get a header of the :class:`ResponseCacheControl` object again you can217    convert the object into a string or call the :meth:`to_header` method.  If218    you plan to subclass it and add your own items have a look at the sourcecode219    for that class.220 221    .. versionchanged:: 3.1222        Dict values are always ``str | None``. Setting properties will223        convert the value to a string. Setting a non-bool property to224        ``False`` is equivalent to setting it to ``None``. Getting typed225        properties will return ``None`` if conversion raises226        ``ValueError``, rather than the string.227 228    .. versionchanged:: 3.1229        ``no_cache`` is ``True`` if present without a value, rather than230        ``"*"``.231 232    .. versionchanged:: 3.1233        ``private`` is ``True`` if present without a value, rather than234        ``"*"``.235 236    .. versionchanged:: 3.1237       ``no_transform`` is a boolean. Previously it was mistakenly238       always ``None``.239 240    .. versionchanged:: 3.1241        Added the ``must_understand``, ``stale_while_revalidate``, and242        ``stale_if_error`` properties.243 244    .. versionchanged:: 2.1.1245        ``s_maxage`` converts the value to an int.246 247    .. versionchanged:: 2.1248        Setting int properties such as ``max_age`` will convert the249        value to an int.250 251    .. versionadded:: 0.5252       Request-only properties are not present on this response class.253    """254 255    no_cache: str | t.Literal[True] | None = cache_control_property(256        "no-cache", True, None257    )258    public: bool = cache_control_property("public", None, bool)259    private: str | t.Literal[True] | None = cache_control_property(260        "private", True, None261    )262    must_revalidate: bool = cache_control_property("must-revalidate", None, bool)263    proxy_revalidate: bool = cache_control_property("proxy-revalidate", None, bool)264    s_maxage: int | None = cache_control_property("s-maxage", None, int)265    immutable: bool = cache_control_property("immutable", None, bool)266    must_understand: bool = cache_control_property("must-understand", None, bool)267    stale_while_revalidate: int | None = cache_control_property(268        "stale-while-revalidate", None, int269    )270 271 272# circular dependencies273from .. import http  # noqa: E402274 
codekingpro/portable-devtools · Team Ai