Coverage for fastblocks/decorators.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-09 00:47 -0700

1import functools 

2import typing as t 

3from collections.abc import Sequence 

4from typing import TypeVar 

5 

6from starlette.types import ASGIApp 

7 

8from .caching import CacheDirectives, Rule 

9from .middleware import CacheControlMiddleware, CacheMiddleware 

10 

11_P = t.ParamSpec("_P") 

12T = TypeVar("T", bound=ASGIApp) 

13_T = t.TypeVar("_T", bound=ASGIApp) 

14 

15 

16class _MiddlewareFactory(t.Protocol[_P]): 

17 def __call__( 

18 self, 

19 app: ASGIApp, 

20 *args: _P.args, 

21 **kwargs: _P.kwargs, 

22 ) -> ASGIApp: ... 

23 

24 

25def _wrap_in_middleware[T: ASGIApp](app: T, middleware: ASGIApp) -> T: 

26 return t.cast(T, functools.wraps(app, updated=())(middleware)) 

27 

28 

29class _CacheMiddlewareDecorator: 

30 def __call__( 

31 self, 

32 *, 

33 cache: t.Any, 

34 rules: Sequence[Rule] | None = None, 

35 ) -> t.Callable[[_T], _T]: 

36 def wrap(app: _T) -> _T: 

37 middleware = CacheMiddleware(app, cache=cache, rules=rules) 

38 return _wrap_in_middleware(app, middleware) 

39 

40 return wrap 

41 

42 

43class _CacheControlMiddlewareDecorator: 

44 def __call__(self, **kwargs: t.Unpack[CacheDirectives]) -> t.Callable[[_T], _T]: 

45 def wrap(app: _T) -> _T: 

46 middleware = CacheControlMiddleware(app, **kwargs) 

47 return _wrap_in_middleware(app, middleware) 

48 

49 return wrap 

50 

51 

52cached = _CacheMiddlewareDecorator() 

53cache_control = _CacheControlMiddlewareDecorator() 

54__all__ = ["_MiddlewareFactory", "cache_control", "cached"]