fastapi-cachex 0.1.5__tar.gz → 0.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fastapi-cachex might be problematic. Click here for more details.

Files changed (28) hide show
  1. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/PKG-INFO +55 -16
  2. fastapi_cachex-0.1.6/README.md +142 -0
  3. fastapi_cachex-0.1.6/fastapi_cachex/backends/__init__.py +11 -0
  4. fastapi_cachex-0.1.6/fastapi_cachex/backends/redis.py +137 -0
  5. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex.egg-info/PKG-INFO +55 -16
  6. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex.egg-info/SOURCES.txt +1 -0
  7. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex.egg-info/requires.txt +4 -1
  8. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/pyproject.toml +9 -4
  9. fastapi_cachex-0.1.5/README.md +0 -105
  10. fastapi_cachex-0.1.5/fastapi_cachex/backends/__init__.py +0 -3
  11. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/LICENSE +0 -0
  12. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/__init__.py +0 -0
  13. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/backends/base.py +0 -0
  14. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/backends/memcached.py +0 -0
  15. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/backends/memory.py +0 -0
  16. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/cache.py +0 -0
  17. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/dependencies.py +0 -0
  18. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/directives.py +0 -0
  19. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/exceptions.py +0 -0
  20. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/proxy.py +0 -0
  21. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/py.typed +0 -0
  22. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex/types.py +0 -0
  23. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex.egg-info/dependency_links.txt +0 -0
  24. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/fastapi_cachex.egg-info/top_level.txt +0 -0
  25. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/setup.cfg +0 -0
  26. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/tests/test_cache.py +0 -0
  27. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/tests/test_dependencies.py +0 -0
  28. {fastapi_cachex-0.1.5 → fastapi_cachex-0.1.6}/tests/test_proxybackend.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-cachex
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: A caching library for FastAPI with support for Cache-Control, ETag, and multiple backends.
5
5
  Author-email: Allen <s96016641@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -24,9 +24,11 @@ Requires-Python: >=3.10
24
24
  Description-Content-Type: text/markdown
25
25
  License-File: LICENSE
26
26
  Requires-Dist: fastapi
27
- Requires-Dist: httpx
28
27
  Provides-Extra: memcache
29
28
  Requires-Dist: pymemcache; extra == "memcache"
29
+ Provides-Extra: redis
30
+ Requires-Dist: redis[hiredis]; extra == "redis"
31
+ Requires-Dist: orjson; extra == "redis"
30
32
  Dynamic: license-file
31
33
 
32
34
  # FastAPI-Cache X
@@ -34,7 +36,7 @@ Dynamic: license-file
34
36
  [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
35
37
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
36
38
  [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
37
- [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
39
+ [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/coverage.yml)
38
40
 
39
41
  [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
40
42
  [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
@@ -60,6 +62,24 @@ A high-performance caching extension for FastAPI, providing comprehensive HTTP c
60
62
  - Complete Cache-Control directive implementation
61
63
  - Easy-to-use `@cache` decorator
62
64
 
65
+ ### Cache-Control Directives
66
+
67
+ | Directive | Supported | Description |
68
+ |--------------------------|--------------------|---------------------------------------------------------------------------------------------------------|
69
+ | `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. |
70
+ | `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. |
71
+ | `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. |
72
+ | `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. |
73
+ | `no-transform` | :x: | Instructs caches not to transform the response content. |
74
+ | `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. |
75
+ | `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. |
76
+ | `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. |
77
+ | `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. |
78
+ | `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. |
79
+ | `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. |
80
+ | `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. |
81
+ | `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. |
82
+
63
83
  ## Installation
64
84
 
65
85
  ### Using pip
@@ -78,31 +98,44 @@ uv pip install fastapi-cachex
78
98
 
79
99
  ```python
80
100
  from fastapi import FastAPI
81
- from fastapi_cachex import cache, BackendProxy
82
- from fastapi_cachex.backends import MemoryBackend, MemcachedBackend
101
+ from fastapi_cachex import cache
102
+ from fastapi_cachex import CacheBackend
83
103
 
84
104
  app = FastAPI()
85
105
 
86
- # Configure your cache backend
87
- memory_backend = MemoryBackend() # In-memory cache
88
- # or
89
- memcached_backend = MemcachedBackend(servers=["localhost:11211"]) # Memcached
90
-
91
- # Set the backend you want to use
92
- BackendProxy.set_backend(memory_backend) # or memcached_backend
93
-
94
106
 
95
107
  @app.get("/")
96
108
  @cache(ttl=60) # Cache for 60 seconds
97
109
  async def read_root():
98
110
  return {"Hello": "World"}
111
+
112
+
113
+ @app.get("/no-cache")
114
+ @cache(no_cache=True) # Mark this endpoint as non-cacheable
115
+ async def non_cache_endpoint():
116
+ return {"Hello": "World"}
117
+
118
+
119
+ @app.get("/no-store")
120
+ @cache(no_store=True) # Mark this endpoint as non-cacheable
121
+ async def non_store_endpoint():
122
+ return {"Hello": "World"}
123
+
124
+
125
+ @app.get("/clear_cache")
126
+ async def remove_cache(cache: CacheBackend):
127
+ await cache.clear_path("/path/to/clear") # Clear cache for a specific path
128
+ await cache.clear_pattern("/path/to/clear/*") # Clear cache for a specific pattern
99
129
  ```
100
130
 
101
131
  ## Backend Configuration
102
132
 
103
133
  FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
104
134
 
105
- ### In-Memory Cache
135
+ ### In-Memory Cache (default)
136
+
137
+ If you don't specify a backend, FastAPI-CacheX will use the in-memory cache by default.
138
+ This is suitable for development and testing purposes.
106
139
 
107
140
  ```python
108
141
  from fastapi_cachex.backends import MemoryBackend
@@ -122,9 +155,15 @@ backend = MemcachedBackend(servers=["localhost:11211"])
122
155
  BackendProxy.set_backend(backend)
123
156
  ```
124
157
 
125
- ### Redis (Coming Soon)
158
+ ### Redis
159
+
160
+ ```python
161
+ from fastapi_cachex.backends import AsyncRedisCacheBackend
162
+ from fastapi_cachex import BackendProxy
126
163
 
127
- Redis support is under development and will be available in future releases.
164
+ backend = AsyncRedisCacheBackend(host="127.0.1", port=6379, db=0)
165
+ BackendProxy.set_backend(backend)
166
+ ```
128
167
 
129
168
  ## Documentation
130
169
 
@@ -0,0 +1,142 @@
1
+ # FastAPI-Cache X
2
+
3
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
+ [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
6
+ [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/coverage.yml)
7
+
8
+ [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
9
+ [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
10
+ [![Monthly downloads](https://static.pepy.tech/badge/fastapi-cachex/month)](https://pepy.tech/project/fastapi-cachex)
11
+
12
+ [![PyPI version](https://img.shields.io/pypi/v/fastapi-cachex.svg?logo=pypi&logoColor=gold&label=PyPI)](https://pypi.org/project/fastapi-cachex)
13
+ [![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-cachex.svg?logo=python&label=Python&logoColor=gold)](https://pypi.org/project/fastapi-cachex/)
14
+
15
+ [English](README.md) | [繁體中文](docs/README.zh-TW.md)
16
+
17
+ A high-performance caching extension for FastAPI, providing comprehensive HTTP caching support.
18
+
19
+ ## Features
20
+
21
+ - Support for HTTP caching headers
22
+ - `Cache-Control`
23
+ - `ETag`
24
+ - `If-None-Match`
25
+ - Multiple backend cache support
26
+ - Redis
27
+ - Memcached
28
+ - In-memory cache
29
+ - Complete Cache-Control directive implementation
30
+ - Easy-to-use `@cache` decorator
31
+
32
+ ### Cache-Control Directives
33
+
34
+ | Directive | Supported | Description |
35
+ |--------------------------|--------------------|---------------------------------------------------------------------------------------------------------|
36
+ | `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. |
37
+ | `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. |
38
+ | `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. |
39
+ | `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. |
40
+ | `no-transform` | :x: | Instructs caches not to transform the response content. |
41
+ | `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. |
42
+ | `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. |
43
+ | `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. |
44
+ | `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. |
45
+ | `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. |
46
+ | `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. |
47
+ | `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. |
48
+ | `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. |
49
+
50
+ ## Installation
51
+
52
+ ### Using pip
53
+
54
+ ```bash
55
+ pip install fastapi-cachex
56
+ ```
57
+
58
+ ### Using uv (recommended)
59
+
60
+ ```bash
61
+ uv pip install fastapi-cachex
62
+ ```
63
+
64
+ ## Quick Start
65
+
66
+ ```python
67
+ from fastapi import FastAPI
68
+ from fastapi_cachex import cache
69
+ from fastapi_cachex import CacheBackend
70
+
71
+ app = FastAPI()
72
+
73
+
74
+ @app.get("/")
75
+ @cache(ttl=60) # Cache for 60 seconds
76
+ async def read_root():
77
+ return {"Hello": "World"}
78
+
79
+
80
+ @app.get("/no-cache")
81
+ @cache(no_cache=True) # Mark this endpoint as non-cacheable
82
+ async def non_cache_endpoint():
83
+ return {"Hello": "World"}
84
+
85
+
86
+ @app.get("/no-store")
87
+ @cache(no_store=True) # Mark this endpoint as non-cacheable
88
+ async def non_store_endpoint():
89
+ return {"Hello": "World"}
90
+
91
+
92
+ @app.get("/clear_cache")
93
+ async def remove_cache(cache: CacheBackend):
94
+ await cache.clear_path("/path/to/clear") # Clear cache for a specific path
95
+ await cache.clear_pattern("/path/to/clear/*") # Clear cache for a specific pattern
96
+ ```
97
+
98
+ ## Backend Configuration
99
+
100
+ FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
101
+
102
+ ### In-Memory Cache (default)
103
+
104
+ If you don't specify a backend, FastAPI-CacheX will use the in-memory cache by default.
105
+ This is suitable for development and testing purposes.
106
+
107
+ ```python
108
+ from fastapi_cachex.backends import MemoryBackend
109
+ from fastapi_cachex import BackendProxy
110
+
111
+ backend = MemoryBackend()
112
+ BackendProxy.set_backend(backend)
113
+ ```
114
+
115
+ ### Memcached
116
+
117
+ ```python
118
+ from fastapi_cachex.backends import MemcachedBackend
119
+ from fastapi_cachex import BackendProxy
120
+
121
+ backend = MemcachedBackend(servers=["localhost:11211"])
122
+ BackendProxy.set_backend(backend)
123
+ ```
124
+
125
+ ### Redis
126
+
127
+ ```python
128
+ from fastapi_cachex.backends import AsyncRedisCacheBackend
129
+ from fastapi_cachex import BackendProxy
130
+
131
+ backend = AsyncRedisCacheBackend(host="127.0.1", port=6379, db=0)
132
+ BackendProxy.set_backend(backend)
133
+ ```
134
+
135
+ ## Documentation
136
+
137
+ - [Development Guide](docs/DEVELOPMENT.md)
138
+ - [Contributing Guidelines](docs/CONTRIBUTING.md)
139
+
140
+ ## License
141
+
142
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,11 @@
1
+ from fastapi_cachex.backends.base import BaseCacheBackend
2
+ from fastapi_cachex.backends.memcached import MemcachedBackend
3
+ from fastapi_cachex.backends.memory import MemoryBackend
4
+ from fastapi_cachex.backends.redis import AsyncRedisCacheBackend
5
+
6
+ __all__ = [
7
+ "AsyncRedisCacheBackend",
8
+ "BaseCacheBackend",
9
+ "MemcachedBackend",
10
+ "MemoryBackend",
11
+ ]
@@ -0,0 +1,137 @@
1
+ from typing import TYPE_CHECKING
2
+ from typing import Any
3
+ from typing import Literal
4
+ from typing import Optional
5
+
6
+ from fastapi_cachex.backends.base import BaseCacheBackend
7
+ from fastapi_cachex.exceptions import CacheXError
8
+ from fastapi_cachex.types import ETagContent
9
+
10
+ if TYPE_CHECKING:
11
+ from redis.asyncio import Redis as AsyncRedis
12
+
13
+ try:
14
+ import orjson as json
15
+
16
+ except ImportError: # pragma: no cover
17
+ import json # type: ignore[no-redef]
18
+
19
+
20
+ class AsyncRedisCacheBackend(BaseCacheBackend):
21
+ """Async Redis cache backend implementation."""
22
+
23
+ client: "AsyncRedis[str]"
24
+
25
+ def __init__(
26
+ self,
27
+ host: str = "127.0.0.1",
28
+ port: int = 6379,
29
+ password: Optional[str] = None,
30
+ db: int = 0,
31
+ encoding: str = "utf-8",
32
+ decode_responses: Literal[True] = True,
33
+ socket_timeout: float = 1.0,
34
+ socket_connect_timeout: float = 1.0,
35
+ **kwargs: Any,
36
+ ) -> None:
37
+ """Initialize async Redis cache backend.
38
+
39
+ Args:
40
+ host: Redis host
41
+ port: Redis port
42
+ password: Redis password
43
+ db: Redis database number
44
+ encoding: Character encoding to use
45
+ decode_responses: Whether to decode response automatically
46
+ socket_timeout: Timeout for socket operations (in seconds)
47
+ socket_connect_timeout: Timeout for socket connection (in seconds)
48
+ **kwargs: Additional arguments to pass to Redis client
49
+ """
50
+ try:
51
+ from redis.asyncio import Redis as AsyncRedis
52
+ except ImportError:
53
+ raise CacheXError(
54
+ "redis[hiredis] is not installed. Please install it with 'pip install \"redis[hiredis]\"'"
55
+ )
56
+
57
+ self.client = AsyncRedis(
58
+ host=host,
59
+ port=port,
60
+ password=password,
61
+ db=db,
62
+ encoding=encoding,
63
+ decode_responses=decode_responses,
64
+ socket_timeout=socket_timeout,
65
+ socket_connect_timeout=socket_connect_timeout,
66
+ **kwargs,
67
+ )
68
+
69
+ def _serialize(self, value: ETagContent) -> str:
70
+ """Serialize ETagContent to JSON string."""
71
+ serialized = json.dumps(
72
+ {
73
+ "etag": value.etag,
74
+ "content": value.content.decode()
75
+ if isinstance(value.content, bytes)
76
+ else value.content,
77
+ }
78
+ )
79
+
80
+ if isinstance(serialized, bytes):
81
+ # If using orjson, it returns bytes
82
+ return serialized.decode()
83
+
84
+ return serialized # type: ignore[unreachable]
85
+
86
+ def _deserialize(self, value: Optional[str]) -> Optional[ETagContent]:
87
+ """Deserialize JSON string to ETagContent."""
88
+ if value is None:
89
+ return None
90
+ try:
91
+ data = json.loads(value)
92
+ return ETagContent(
93
+ etag=data["etag"],
94
+ content=data["content"].encode()
95
+ if isinstance(data["content"], str)
96
+ else data["content"],
97
+ )
98
+ except (json.JSONDecodeError, KeyError):
99
+ return None
100
+
101
+ async def get(self, key: str) -> Optional[ETagContent]:
102
+ """Retrieve a cached response."""
103
+ result = await self.client.get(key)
104
+ return self._deserialize(result)
105
+
106
+ async def set(
107
+ self, key: str, value: ETagContent, ttl: Optional[int] = None
108
+ ) -> None:
109
+ """Store a response in the cache."""
110
+ serialized = self._serialize(value)
111
+ if ttl is not None:
112
+ await self.client.setex(key, ttl, serialized)
113
+ else:
114
+ await self.client.set(key, serialized)
115
+
116
+ async def delete(self, key: str) -> None:
117
+ """Remove a response from the cache."""
118
+ await self.client.delete(key)
119
+
120
+ async def clear(self) -> None:
121
+ """Clear all cached responses."""
122
+ await self.client.flushdb()
123
+
124
+ async def clear_path(self, path: str, include_params: bool = False) -> int:
125
+ """Clear cached responses for a specific path."""
126
+ pattern = f"{path}*" if include_params else path
127
+ keys = await self.client.keys(pattern)
128
+ if keys:
129
+ return await self.client.delete(*keys)
130
+ return 0
131
+
132
+ async def clear_pattern(self, pattern: str) -> int:
133
+ """Clear cached responses matching a pattern."""
134
+ keys = await self.client.keys(pattern)
135
+ if keys:
136
+ return await self.client.delete(*keys)
137
+ return 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-cachex
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: A caching library for FastAPI with support for Cache-Control, ETag, and multiple backends.
5
5
  Author-email: Allen <s96016641@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -24,9 +24,11 @@ Requires-Python: >=3.10
24
24
  Description-Content-Type: text/markdown
25
25
  License-File: LICENSE
26
26
  Requires-Dist: fastapi
27
- Requires-Dist: httpx
28
27
  Provides-Extra: memcache
29
28
  Requires-Dist: pymemcache; extra == "memcache"
29
+ Provides-Extra: redis
30
+ Requires-Dist: redis[hiredis]; extra == "redis"
31
+ Requires-Dist: orjson; extra == "redis"
30
32
  Dynamic: license-file
31
33
 
32
34
  # FastAPI-Cache X
@@ -34,7 +36,7 @@ Dynamic: license-file
34
36
  [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
35
37
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
36
38
  [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
37
- [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
39
+ [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/coverage.yml)
38
40
 
39
41
  [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
40
42
  [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
@@ -60,6 +62,24 @@ A high-performance caching extension for FastAPI, providing comprehensive HTTP c
60
62
  - Complete Cache-Control directive implementation
61
63
  - Easy-to-use `@cache` decorator
62
64
 
65
+ ### Cache-Control Directives
66
+
67
+ | Directive | Supported | Description |
68
+ |--------------------------|--------------------|---------------------------------------------------------------------------------------------------------|
69
+ | `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. |
70
+ | `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. |
71
+ | `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. |
72
+ | `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. |
73
+ | `no-transform` | :x: | Instructs caches not to transform the response content. |
74
+ | `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. |
75
+ | `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. |
76
+ | `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. |
77
+ | `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. |
78
+ | `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. |
79
+ | `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. |
80
+ | `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. |
81
+ | `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. |
82
+
63
83
  ## Installation
64
84
 
65
85
  ### Using pip
@@ -78,31 +98,44 @@ uv pip install fastapi-cachex
78
98
 
79
99
  ```python
80
100
  from fastapi import FastAPI
81
- from fastapi_cachex import cache, BackendProxy
82
- from fastapi_cachex.backends import MemoryBackend, MemcachedBackend
101
+ from fastapi_cachex import cache
102
+ from fastapi_cachex import CacheBackend
83
103
 
84
104
  app = FastAPI()
85
105
 
86
- # Configure your cache backend
87
- memory_backend = MemoryBackend() # In-memory cache
88
- # or
89
- memcached_backend = MemcachedBackend(servers=["localhost:11211"]) # Memcached
90
-
91
- # Set the backend you want to use
92
- BackendProxy.set_backend(memory_backend) # or memcached_backend
93
-
94
106
 
95
107
  @app.get("/")
96
108
  @cache(ttl=60) # Cache for 60 seconds
97
109
  async def read_root():
98
110
  return {"Hello": "World"}
111
+
112
+
113
+ @app.get("/no-cache")
114
+ @cache(no_cache=True) # Mark this endpoint as non-cacheable
115
+ async def non_cache_endpoint():
116
+ return {"Hello": "World"}
117
+
118
+
119
+ @app.get("/no-store")
120
+ @cache(no_store=True) # Mark this endpoint as non-cacheable
121
+ async def non_store_endpoint():
122
+ return {"Hello": "World"}
123
+
124
+
125
+ @app.get("/clear_cache")
126
+ async def remove_cache(cache: CacheBackend):
127
+ await cache.clear_path("/path/to/clear") # Clear cache for a specific path
128
+ await cache.clear_pattern("/path/to/clear/*") # Clear cache for a specific pattern
99
129
  ```
100
130
 
101
131
  ## Backend Configuration
102
132
 
103
133
  FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
104
134
 
105
- ### In-Memory Cache
135
+ ### In-Memory Cache (default)
136
+
137
+ If you don't specify a backend, FastAPI-CacheX will use the in-memory cache by default.
138
+ This is suitable for development and testing purposes.
106
139
 
107
140
  ```python
108
141
  from fastapi_cachex.backends import MemoryBackend
@@ -122,9 +155,15 @@ backend = MemcachedBackend(servers=["localhost:11211"])
122
155
  BackendProxy.set_backend(backend)
123
156
  ```
124
157
 
125
- ### Redis (Coming Soon)
158
+ ### Redis
159
+
160
+ ```python
161
+ from fastapi_cachex.backends import AsyncRedisCacheBackend
162
+ from fastapi_cachex import BackendProxy
126
163
 
127
- Redis support is under development and will be available in future releases.
164
+ backend = AsyncRedisCacheBackend(host="127.0.1", port=6379, db=0)
165
+ BackendProxy.set_backend(backend)
166
+ ```
128
167
 
129
168
  ## Documentation
130
169
 
@@ -18,6 +18,7 @@ fastapi_cachex/backends/__init__.py
18
18
  fastapi_cachex/backends/base.py
19
19
  fastapi_cachex/backends/memcached.py
20
20
  fastapi_cachex/backends/memory.py
21
+ fastapi_cachex/backends/redis.py
21
22
  tests/test_cache.py
22
23
  tests/test_dependencies.py
23
24
  tests/test_proxybackend.py
@@ -1,5 +1,8 @@
1
1
  fastapi
2
- httpx
3
2
 
4
3
  [memcache]
5
4
  pymemcache
5
+
6
+ [redis]
7
+ redis[hiredis]
8
+ orjson
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-cachex"
3
- version = "0.1.5" # Initial release version
3
+ version = "0.1.6" # Initial release version
4
4
  description = "A caching library for FastAPI with support for Cache-Control, ETag, and multiple backends."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -25,7 +25,6 @@ classifiers = [
25
25
  keywords = ["fastapi", "cache", "etag", "cache-control", "redis", "memcached", "in-memory"]
26
26
  dependencies = [
27
27
  "fastapi",
28
- "httpx",
29
28
  ]
30
29
 
31
30
  [project.urls]
@@ -36,25 +35,31 @@ Issues = "https://github.com/allen0099/FastAPI-CacheX/issues"
36
35
  [dependency-groups]
37
36
  dev = [
38
37
  "coverage>=7.8.0",
38
+ "httpx>=0.28.1",
39
39
  "mypy>=1.15.0",
40
+ "orjson>=3.10.16",
40
41
  "pre-commit>=4.2.0",
41
42
  "pymemcache>=4.0.0",
42
43
  "pytest>=8.3.5",
43
44
  "pytest-asyncio>=0.26.0",
44
45
  "pytest-cov>=6.1.0",
46
+ "redis[hiredis]>=5.2.1",
45
47
  "ruff>=0.11.2",
46
48
  "tox>=4.25.0",
49
+ "types-orjson>=3.6.2",
50
+ "types-redis>=4.6.0.20241004",
47
51
  ]
48
52
 
49
53
  [project.optional-dependencies]
50
54
  memcache = ["pymemcache"]
55
+ redis = ["redis[hiredis]", "orjson"]
51
56
 
52
57
  [tool.setuptools]
53
- package-data = {"fastapi_cachex" = ["py.typed"]}
58
+ package-data = { "fastapi_cachex" = ["py.typed"] }
54
59
 
55
60
  [tool.pytest.ini_options]
56
61
  pythonpath = [
57
- "."
62
+ "."
58
63
  ]
59
64
  asyncio_default_fixture_loop_scope = "function"
60
65
 
@@ -1,105 +0,0 @@
1
- # FastAPI-Cache X
2
-
3
- [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
- [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
- [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
6
- [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
7
-
8
- [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
9
- [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
10
- [![Monthly downloads](https://static.pepy.tech/badge/fastapi-cachex/month)](https://pepy.tech/project/fastapi-cachex)
11
-
12
- [![PyPI version](https://img.shields.io/pypi/v/fastapi-cachex.svg?logo=pypi&logoColor=gold&label=PyPI)](https://pypi.org/project/fastapi-cachex)
13
- [![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-cachex.svg?logo=python&label=Python&logoColor=gold)](https://pypi.org/project/fastapi-cachex/)
14
-
15
- [English](README.md) | [繁體中文](docs/README.zh-TW.md)
16
-
17
- A high-performance caching extension for FastAPI, providing comprehensive HTTP caching support.
18
-
19
- ## Features
20
-
21
- - Support for HTTP caching headers
22
- - `Cache-Control`
23
- - `ETag`
24
- - `If-None-Match`
25
- - Multiple backend cache support
26
- - Redis
27
- - Memcached
28
- - In-memory cache
29
- - Complete Cache-Control directive implementation
30
- - Easy-to-use `@cache` decorator
31
-
32
- ## Installation
33
-
34
- ### Using pip
35
-
36
- ```bash
37
- pip install fastapi-cachex
38
- ```
39
-
40
- ### Using uv (recommended)
41
-
42
- ```bash
43
- uv pip install fastapi-cachex
44
- ```
45
-
46
- ## Quick Start
47
-
48
- ```python
49
- from fastapi import FastAPI
50
- from fastapi_cachex import cache, BackendProxy
51
- from fastapi_cachex.backends import MemoryBackend, MemcachedBackend
52
-
53
- app = FastAPI()
54
-
55
- # Configure your cache backend
56
- memory_backend = MemoryBackend() # In-memory cache
57
- # or
58
- memcached_backend = MemcachedBackend(servers=["localhost:11211"]) # Memcached
59
-
60
- # Set the backend you want to use
61
- BackendProxy.set_backend(memory_backend) # or memcached_backend
62
-
63
-
64
- @app.get("/")
65
- @cache(ttl=60) # Cache for 60 seconds
66
- async def read_root():
67
- return {"Hello": "World"}
68
- ```
69
-
70
- ## Backend Configuration
71
-
72
- FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
73
-
74
- ### In-Memory Cache
75
-
76
- ```python
77
- from fastapi_cachex.backends import MemoryBackend
78
- from fastapi_cachex import BackendProxy
79
-
80
- backend = MemoryBackend()
81
- BackendProxy.set_backend(backend)
82
- ```
83
-
84
- ### Memcached
85
-
86
- ```python
87
- from fastapi_cachex.backends import MemcachedBackend
88
- from fastapi_cachex import BackendProxy
89
-
90
- backend = MemcachedBackend(servers=["localhost:11211"])
91
- BackendProxy.set_backend(backend)
92
- ```
93
-
94
- ### Redis (Coming Soon)
95
-
96
- Redis support is under development and will be available in future releases.
97
-
98
- ## Documentation
99
-
100
- - [Development Guide](docs/DEVELOPMENT.md)
101
- - [Contributing Guidelines](docs/CONTRIBUTING.md)
102
-
103
- ## License
104
-
105
- This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
@@ -1,3 +0,0 @@
1
- from .base import BaseCacheBackend as BaseCacheBackend
2
- from .memcached import MemcachedBackend as MemcachedBackend
3
- from .memory import MemoryBackend as MemoryBackend
File without changes
File without changes