hishel 1.0.0.dev2__tar.gz → 1.0.0.dev3__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.
Files changed (29) hide show
  1. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/CHANGELOG.md +23 -0
  2. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/PKG-INFO +100 -6
  3. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/README.md +74 -5
  4. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/__init__.py +15 -14
  5. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_async_cache.py +42 -36
  6. hishel-1.0.0.dev3/hishel/_async_httpx.py +243 -0
  7. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_core/_headers.py +11 -1
  8. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_core/_spec.py +88 -84
  9. hishel-1.0.0.dev3/hishel/_core/_storages/_async_base.py +71 -0
  10. hishel-1.0.0.dev2/hishel/_core/_async/_storages/_sqlite.py → hishel-1.0.0.dev3/hishel/_core/_storages/_async_sqlite.py +95 -132
  11. hishel-1.0.0.dev3/hishel/_core/_storages/_packing.py +144 -0
  12. hishel-1.0.0.dev3/hishel/_core/_storages/_sync_base.py +71 -0
  13. hishel-1.0.0.dev2/hishel/_core/_sync/_storages/_sqlite.py → hishel-1.0.0.dev3/hishel/_core/_storages/_sync_sqlite.py +95 -132
  14. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_core/models.py +6 -22
  15. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_sync_cache.py +42 -36
  16. hishel-1.0.0.dev3/hishel/_sync_httpx.py +243 -0
  17. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/_utils.py +49 -2
  18. hishel-1.0.0.dev3/hishel/asgi.py +400 -0
  19. hishel-1.0.0.dev3/hishel/fastapi.py +263 -0
  20. hishel-1.0.0.dev3/hishel/httpx.py +12 -0
  21. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/requests.py +25 -17
  22. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/pyproject.toml +11 -2
  23. hishel-1.0.0.dev2/hishel/_core/__init__.py +0 -59
  24. hishel-1.0.0.dev2/hishel/_core/_base/_storages/_base.py +0 -272
  25. hishel-1.0.0.dev2/hishel/_core/_base/_storages/_packing.py +0 -165
  26. hishel-1.0.0.dev2/hishel/httpx.py +0 -335
  27. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/.gitignore +0 -0
  28. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/LICENSE +0 -0
  29. {hishel-1.0.0.dev2 → hishel-1.0.0.dev3}/hishel/py.typed +0 -0
@@ -2,10 +2,33 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 1.0.0.dev3 - 2025-10-26
6
+ ### ♻️ Refactoring
7
+ - Replace pairs with entries, simplify storage API
8
+ - Automatically generate httpx sync integration from async
9
+
10
+ ### ⚙️ Miscellaneous Tasks
11
+ - Simplify metadata docs
12
+ - Add custom integrations docs
13
+ - More robust compressed response caching
14
+
15
+ ### 🐛 Bug Fixes
16
+ - Add missing permissions into `publish.yml`
17
+ - Raise on consumed httpx streams, which we can't store as is (it's already decoded)
18
+ - Fix compressed data caching for requests
19
+ - Handle httpx iterable usage instead of iterator correctly
20
+ - Add date header for proper age calculation
21
+
22
+ ### 🚀 Features
23
+ - Add integrations with fastapi and asgi
24
+ - Add blacksheep integration examples
25
+ - Add logging for asgi
26
+
5
27
  ## 1.0.0.dev2 - 2025-10-21
6
28
  ### ⚙️ Miscellaneous Tasks
7
29
  - Remove redundant utils and tests
8
30
  - Add import without extras check in ci
31
+ - Fix time travel date, explicitly specify the timezone
9
32
 
10
33
  ### 🐛 Bug Fixes
11
34
  - Fix check for storing auth requests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hishel
3
- Version: 1.0.0.dev2
3
+ Version: 1.0.0.dev3
4
4
  Summary: Elegant HTTP Caching for Python
5
5
  Project-URL: Homepage, https://hishel.com
6
6
  Project-URL: Source, https://github.com/karpetrosyan/hishel
@@ -29,6 +29,8 @@ Requires-Dist: typing-extensions>=4.14.1
29
29
  Provides-Extra: async
30
30
  Requires-Dist: anyio>=4.9.0; extra == 'async'
31
31
  Requires-Dist: anysqlite>=0.0.5; extra == 'async'
32
+ Provides-Extra: fastapi
33
+ Requires-Dist: fastapi>=0.119.1; extra == 'fastapi'
32
34
  Provides-Extra: httpx
33
35
  Requires-Dist: anyio>=4.9.0; extra == 'httpx'
34
36
  Requires-Dist: anysqlite>=0.0.5; extra == 'httpx'
@@ -37,6 +39,7 @@ Provides-Extra: requests
37
39
  Requires-Dist: requests>=2.32.5; extra == 'requests'
38
40
  Description-Content-Type: text/markdown
39
41
 
42
+
40
43
  <p align="center">
41
44
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_yellow.png#gh-dark-mode-only">
42
45
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_black.png#gh-light-mode-only">
@@ -73,14 +76,15 @@ Description-Content-Type: text/markdown
73
76
  ## ✨ Features
74
77
 
75
78
  - 🎯 **RFC 9111 Compliant** - Fully compliant with the latest HTTP caching specification
76
- - 🔌 **Easy Integration** - Drop-in support for HTTPX and Requests
79
+ - 🔌 **Easy Integration** - Drop-in support for HTTPX, Requests, ASGI, FastAPI, and BlackSheep
77
80
  - 💾 **Flexible Storage** - SQLite backend with more coming soon
78
81
  - ⚡ **High Performance** - Efficient caching with minimal overhead
79
82
  - 🔄 **Async & Sync** - Full support for both synchronous and asynchronous workflows
80
83
  - 🎨 **Type Safe** - Fully typed with comprehensive type hints
81
84
  - 🧪 **Well Tested** - Extensive test coverage and battle-tested
82
85
  - 🎛️ **Configurable** - Fine-grained control over caching behavior
83
- - 🌐 **Future Ready** - Designed for easy integration with any HTTP client/server
86
+ - **Memory Efficient** - Streaming support prevents loading large payloads into memory
87
+ - 🌐 **Universal** - Works with any ASGI application (Starlette, Litestar, BlackSheep, etc.)
84
88
 
85
89
  ## 📦 Installation
86
90
 
@@ -90,19 +94,23 @@ pip install hishel
90
94
 
91
95
  ### Optional Dependencies
92
96
 
93
- Install with specific HTTP client support:
97
+ Install with specific integration support:
94
98
 
95
99
  ```bash
96
100
  pip install hishel[httpx] # For HTTPX support
97
101
  pip install hishel[requests] # For Requests support
102
+ pip install hishel[fastapi] # For FastAPI support (includes ASGI)
98
103
  ```
99
104
 
100
- Or install both:
105
+ Or install multiple:
101
106
 
102
107
  ```bash
103
- pip install hishel[httpx,requests]
108
+ pip install hishel[httpx,requests,fastapi]
104
109
  ```
105
110
 
111
+ > [!NOTE]
112
+ > ASGI middleware has no extra dependencies - it's included in the base installation.
113
+
106
114
  ## 🚀 Quick Start
107
115
 
108
116
  ### With HTTPX
@@ -156,6 +164,65 @@ response = session.get("https://api.example.com/data")
156
164
  print(response.headers.get("X-Hishel-From-Cache")) # "True"
157
165
  ```
158
166
 
167
+ ### With ASGI Applications
168
+
169
+ Add caching middleware to any ASGI application:
170
+
171
+ ```python
172
+ from hishel.asgi import ASGICacheMiddleware
173
+
174
+ # Wrap your ASGI app
175
+ app = ASGICacheMiddleware(app)
176
+
177
+ # Or configure with options
178
+ from hishel import AsyncSqliteStorage, CacheOptions
179
+
180
+ app = ASGICacheMiddleware(
181
+ app,
182
+ storage=AsyncSqliteStorage(),
183
+ cache_options=CacheOptions(shared=True)
184
+ )
185
+ ```
186
+
187
+ ### With FastAPI
188
+
189
+ Add Cache-Control headers using the `cache()` dependency:
190
+
191
+ ```python
192
+ from fastapi import FastAPI
193
+ from hishel.fastapi import cache
194
+
195
+ app = FastAPI()
196
+
197
+ @app.get("/api/data", dependencies=[cache(max_age=300, public=True)])
198
+ async def get_data():
199
+ # Cache-Control: public, max-age=300
200
+ return {"data": "cached for 5 minutes"}
201
+
202
+ # Optionally wrap with ASGI middleware for local caching according to specified rules
203
+ from hishel.asgi import ASGICacheMiddleware
204
+ from hishel import AsyncSqliteStorage
205
+
206
+ app = ASGICacheMiddleware(app, storage=AsyncSqliteStorage())
207
+ ```
208
+
209
+ ### With BlackSheep
210
+
211
+ Use BlackSheep's native `cache_control` decorator with Hishel's ASGI middleware:
212
+
213
+ ```python
214
+ from blacksheep import Application, get
215
+ from blacksheep.server.headers.cache import cache_control
216
+
217
+ app = Application()
218
+
219
+ @get("/api/data")
220
+ @cache_control(max_age=300, public=True)
221
+ async def get_data():
222
+ # Cache-Control: public, max-age=300
223
+ return {"data": "cached for 5 minutes"}
224
+ ```
225
+
159
226
  ## 🎛️ Advanced Configuration
160
227
 
161
228
  ### Custom Cache Options
@@ -214,7 +281,11 @@ Comprehensive documentation is available at [https://hishel.com/dev](https://his
214
281
  - [Getting Started](https://hishel.com)
215
282
  - [HTTPX Integration](https://hishel.com/dev/integrations/httpx)
216
283
  - [Requests Integration](https://hishel.com/dev/integrations/requests)
284
+ - [ASGI Integration](https://hishel.com/dev/asgi)
285
+ - [FastAPI Integration](https://hishel.com/dev/fastapi)
286
+ - [BlackSheep Integration](https://hishel.com/dev/integrations/blacksheep)
217
287
  - [Storage Backends](https://hishel.com/dev/storages)
288
+ - [Request/Response Metadata](https://hishel.com/dev/metadata)
218
289
  - [RFC 9111 Specification](https://hishel.com/dev/specification)
219
290
 
220
291
  ## 🤝 Contributing
@@ -255,10 +326,33 @@ Hishel is inspired by and builds upon the excellent work in the Python HTTP ecos
255
326
 
256
327
  All notable changes to this project will be documented in this file.
257
328
 
329
+ ## 1.0.0.dev3 - 2025-10-26
330
+ ### ♻️ Refactoring
331
+ - Replace pairs with entries, simplify storage API
332
+ - Automatically generate httpx sync integration from async
333
+
334
+ ### ⚙️ Miscellaneous Tasks
335
+ - Simplify metadata docs
336
+ - Add custom integrations docs
337
+ - More robust compressed response caching
338
+
339
+ ### 🐛 Bug Fixes
340
+ - Add missing permissions into `publish.yml`
341
+ - Raise on consumed httpx streams, which we can't store as is (it's already decoded)
342
+ - Fix compressed data caching for requests
343
+ - Handle httpx iterable usage instead of iterator correctly
344
+ - Add date header for proper age calculation
345
+
346
+ ### 🚀 Features
347
+ - Add integrations with fastapi and asgi
348
+ - Add blacksheep integration examples
349
+ - Add logging for asgi
350
+
258
351
  ## 1.0.0.dev2 - 2025-10-21
259
352
  ### ⚙️ Miscellaneous Tasks
260
353
  - Remove redundant utils and tests
261
354
  - Add import without extras check in ci
355
+ - Fix time travel date, explicitly specify the timezone
262
356
 
263
357
  ### 🐛 Bug Fixes
264
358
  - Fix check for storing auth requests
@@ -1,3 +1,4 @@
1
+
1
2
  <p align="center">
2
3
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_yellow.png#gh-dark-mode-only">
3
4
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_black.png#gh-light-mode-only">
@@ -34,14 +35,15 @@
34
35
  ## ✨ Features
35
36
 
36
37
  - 🎯 **RFC 9111 Compliant** - Fully compliant with the latest HTTP caching specification
37
- - 🔌 **Easy Integration** - Drop-in support for HTTPX and Requests
38
+ - 🔌 **Easy Integration** - Drop-in support for HTTPX, Requests, ASGI, FastAPI, and BlackSheep
38
39
  - 💾 **Flexible Storage** - SQLite backend with more coming soon
39
40
  - ⚡ **High Performance** - Efficient caching with minimal overhead
40
41
  - 🔄 **Async & Sync** - Full support for both synchronous and asynchronous workflows
41
42
  - 🎨 **Type Safe** - Fully typed with comprehensive type hints
42
43
  - 🧪 **Well Tested** - Extensive test coverage and battle-tested
43
44
  - 🎛️ **Configurable** - Fine-grained control over caching behavior
44
- - 🌐 **Future Ready** - Designed for easy integration with any HTTP client/server
45
+ - **Memory Efficient** - Streaming support prevents loading large payloads into memory
46
+ - 🌐 **Universal** - Works with any ASGI application (Starlette, Litestar, BlackSheep, etc.)
45
47
 
46
48
  ## 📦 Installation
47
49
 
@@ -51,19 +53,23 @@ pip install hishel
51
53
 
52
54
  ### Optional Dependencies
53
55
 
54
- Install with specific HTTP client support:
56
+ Install with specific integration support:
55
57
 
56
58
  ```bash
57
59
  pip install hishel[httpx] # For HTTPX support
58
60
  pip install hishel[requests] # For Requests support
61
+ pip install hishel[fastapi] # For FastAPI support (includes ASGI)
59
62
  ```
60
63
 
61
- Or install both:
64
+ Or install multiple:
62
65
 
63
66
  ```bash
64
- pip install hishel[httpx,requests]
67
+ pip install hishel[httpx,requests,fastapi]
65
68
  ```
66
69
 
70
+ > [!NOTE]
71
+ > ASGI middleware has no extra dependencies - it's included in the base installation.
72
+
67
73
  ## 🚀 Quick Start
68
74
 
69
75
  ### With HTTPX
@@ -117,6 +123,65 @@ response = session.get("https://api.example.com/data")
117
123
  print(response.headers.get("X-Hishel-From-Cache")) # "True"
118
124
  ```
119
125
 
126
+ ### With ASGI Applications
127
+
128
+ Add caching middleware to any ASGI application:
129
+
130
+ ```python
131
+ from hishel.asgi import ASGICacheMiddleware
132
+
133
+ # Wrap your ASGI app
134
+ app = ASGICacheMiddleware(app)
135
+
136
+ # Or configure with options
137
+ from hishel import AsyncSqliteStorage, CacheOptions
138
+
139
+ app = ASGICacheMiddleware(
140
+ app,
141
+ storage=AsyncSqliteStorage(),
142
+ cache_options=CacheOptions(shared=True)
143
+ )
144
+ ```
145
+
146
+ ### With FastAPI
147
+
148
+ Add Cache-Control headers using the `cache()` dependency:
149
+
150
+ ```python
151
+ from fastapi import FastAPI
152
+ from hishel.fastapi import cache
153
+
154
+ app = FastAPI()
155
+
156
+ @app.get("/api/data", dependencies=[cache(max_age=300, public=True)])
157
+ async def get_data():
158
+ # Cache-Control: public, max-age=300
159
+ return {"data": "cached for 5 minutes"}
160
+
161
+ # Optionally wrap with ASGI middleware for local caching according to specified rules
162
+ from hishel.asgi import ASGICacheMiddleware
163
+ from hishel import AsyncSqliteStorage
164
+
165
+ app = ASGICacheMiddleware(app, storage=AsyncSqliteStorage())
166
+ ```
167
+
168
+ ### With BlackSheep
169
+
170
+ Use BlackSheep's native `cache_control` decorator with Hishel's ASGI middleware:
171
+
172
+ ```python
173
+ from blacksheep import Application, get
174
+ from blacksheep.server.headers.cache import cache_control
175
+
176
+ app = Application()
177
+
178
+ @get("/api/data")
179
+ @cache_control(max_age=300, public=True)
180
+ async def get_data():
181
+ # Cache-Control: public, max-age=300
182
+ return {"data": "cached for 5 minutes"}
183
+ ```
184
+
120
185
  ## 🎛️ Advanced Configuration
121
186
 
122
187
  ### Custom Cache Options
@@ -175,7 +240,11 @@ Comprehensive documentation is available at [https://hishel.com/dev](https://his
175
240
  - [Getting Started](https://hishel.com)
176
241
  - [HTTPX Integration](https://hishel.com/dev/integrations/httpx)
177
242
  - [Requests Integration](https://hishel.com/dev/integrations/requests)
243
+ - [ASGI Integration](https://hishel.com/dev/asgi)
244
+ - [FastAPI Integration](https://hishel.com/dev/fastapi)
245
+ - [BlackSheep Integration](https://hishel.com/dev/integrations/blacksheep)
178
246
  - [Storage Backends](https://hishel.com/dev/storages)
247
+ - [Request/Response Metadata](https://hishel.com/dev/metadata)
179
248
  - [RFC 9111 Specification](https://hishel.com/dev/specification)
180
249
 
181
250
  ## 🤝 Contributing
@@ -1,8 +1,7 @@
1
- from hishel._core._async._storages._sqlite import AsyncSqliteStorage
2
- from hishel._core._base._storages._base import (
3
- AsyncBaseStorage as AsyncBaseStorage,
4
- SyncBaseStorage as SyncBaseStorage,
5
- )
1
+ from hishel._core._storages._async_sqlite import AsyncSqliteStorage
2
+ from hishel._core._storages._async_base import AsyncBaseStorage
3
+ from hishel._core._storages._sync_sqlite import SyncSqliteStorage
4
+ from hishel._core._storages._sync_base import SyncBaseStorage
6
5
  from hishel._core._headers import Headers as Headers
7
6
  from hishel._core._spec import (
8
7
  AnyState as AnyState,
@@ -11,21 +10,21 @@ from hishel._core._spec import (
11
10
  CouldNotBeStored as CouldNotBeStored,
12
11
  FromCache as FromCache,
13
12
  IdleClient as IdleClient,
13
+ InvalidateEntries,
14
14
  NeedRevalidation as NeedRevalidation,
15
15
  NeedToBeUpdated as NeedToBeUpdated,
16
16
  State as State,
17
17
  StoreAndUse as StoreAndUse,
18
18
  create_idle_state as create_idle_state,
19
19
  )
20
- from hishel._core._sync._storages._sqlite import SyncSqliteStorage
21
20
  from hishel._core.models import (
22
- CompletePair as CompletePair,
23
- IncompletePair as IncompletePair,
24
- Pair as Pair,
25
- PairMeta as PairMeta,
21
+ Entry as Entry,
22
+ EntryMeta as EntryMeta,
26
23
  Request as Request,
27
24
  Response,
28
25
  )
26
+ from hishel._async_cache import AsyncCacheProxy as AsyncCacheProxy
27
+ from hishel._sync_cache import SyncCacheProxy as SyncCacheProxy
29
28
 
30
29
  __all__ = (
31
30
  # New API
@@ -41,14 +40,13 @@ __all__ = (
41
40
  "State",
42
41
  "StoreAndUse",
43
42
  "CouldNotBeStored",
43
+ "InvalidateEntries",
44
44
  "create_idle_state",
45
45
  ## Models
46
46
  "Request",
47
47
  "Response",
48
- "Pair",
49
- "IncompletePair",
50
- "CompletePair",
51
- "PairMeta",
48
+ "Entry",
49
+ "EntryMeta",
52
50
  ## Headers
53
51
  "Headers",
54
52
  ## Storages
@@ -56,4 +54,7 @@ __all__ = (
56
54
  "AsyncBaseStorage",
57
55
  "SyncSqliteStorage",
58
56
  "AsyncSqliteStorage",
57
+ # Proxy
58
+ "AsyncCacheProxy",
59
+ "SyncCacheProxy",
59
60
  )
@@ -4,7 +4,7 @@ import hashlib
4
4
  import logging
5
5
  import time
6
6
  from dataclasses import replace
7
- from typing import AsyncIterator, Awaitable, Callable
7
+ from typing import AsyncIterable, AsyncIterator, Awaitable, Callable
8
8
 
9
9
  from typing_extensions import assert_never
10
10
 
@@ -24,8 +24,9 @@ from hishel import (
24
24
  StoreAndUse,
25
25
  create_idle_state,
26
26
  )
27
- from hishel._core._spec import InvalidatePairs, vary_headers_match
28
- from hishel._core.models import CompletePair, ResponseMetadata
27
+ from hishel._core._spec import InvalidateEntries, vary_headers_match
28
+ from hishel._core.models import Entry, ResponseMetadata
29
+ from hishel._utils import make_async_iterator
29
30
 
30
31
  logger = logging.getLogger("hishel.integrations.clients")
31
32
 
@@ -42,12 +43,12 @@ class AsyncCacheProxy:
42
43
 
43
44
  def __init__(
44
45
  self,
45
- send_request: Callable[[Request], Awaitable[Response]],
46
+ request_sender: Callable[[Request], Awaitable[Response]],
46
47
  storage: AsyncBaseStorage | None = None,
47
48
  cache_options: CacheOptions | None = None,
48
49
  ignore_specification: bool = False,
49
50
  ) -> None:
50
- self.send_request = send_request
51
+ self.send_request = request_sender
51
52
  self.storage = storage if storage is not None else AsyncSqliteStorage()
52
53
  self.cache_options = cache_options if cache_options is not None else CacheOptions()
53
54
  self.ignore_specification = ignore_specification
@@ -59,26 +60,30 @@ class AsyncCacheProxy:
59
60
 
60
61
  async def _get_key_for_request(self, request: Request) -> str:
61
62
  if request.metadata.get("hishel_body_key"):
62
- assert isinstance(request.stream, AsyncIterator)
63
+ assert isinstance(request.stream, (AsyncIterator, AsyncIterable))
63
64
  collected = b"".join([chunk async for chunk in request.stream])
64
65
  hash_ = hashlib.sha256(collected).hexdigest()
66
+ request.stream = make_async_iterator([collected])
65
67
  return f"{str(request.url)}-{hash_}"
66
- return str(request.url)
68
+ return hashlib.sha256(str(request.url).encode("utf-8")).hexdigest()
67
69
 
68
- async def _maybe_refresh_pair_ttl(self, pair: CompletePair) -> None:
70
+ async def _maybe_refresh_pair_ttl(self, pair: Entry) -> None:
69
71
  if pair.request.metadata.get("hishel_refresh_ttl_on_access"):
70
- await self.storage.update_pair(
72
+ await self.storage.update_entry(
71
73
  pair.id,
72
- lambda complete_pair: replace(complete_pair, meta=replace(complete_pair.meta, created_at=time.time())),
74
+ lambda complete_pair: replace(
75
+ complete_pair,
76
+ meta=replace(complete_pair.meta, created_at=time.time()),
77
+ ),
73
78
  )
74
79
 
75
80
  async def _handle_request_ignoring_spec(self, request: Request) -> Response:
76
81
  logger.debug("Trying to get cached response ignoring specification")
77
- pairs = await self.storage.get_pairs(await self._get_key_for_request(request))
82
+ entries = await self.storage.get_entries(await self._get_key_for_request(request))
78
83
 
79
- logger.debug(f"Found {len(pairs)} cached pairs for the request")
84
+ logger.debug(f"Found {len(entries)} cached entries for the request")
80
85
 
81
- for pair in pairs:
86
+ for pair in entries:
82
87
  if (
83
88
  str(pair.request.url) == str(request.url)
84
89
  and pair.request.method == request.method
@@ -101,16 +106,15 @@ class AsyncCacheProxy:
101
106
  await self._maybe_refresh_pair_ttl(pair)
102
107
  return pair.response
103
108
 
104
- incomplete_pair = await self.storage.create_pair(
105
- request,
106
- )
107
- response = await self.send_request(incomplete_pair.request)
109
+ response = await self.send_request(request)
108
110
 
109
111
  logger.debug("Storing response in cache ignoring specification")
110
- complete_pair = await self.storage.add_response(
111
- incomplete_pair.id, response, await self._get_key_for_request(request)
112
+ entry = await self.storage.create_entry(
113
+ request,
114
+ response,
115
+ await self._get_key_for_request(request),
112
116
  )
113
- return complete_pair.response
117
+ return entry.response
114
118
 
115
119
  async def _handle_request_respecting_spec(self, request: Request) -> Response:
116
120
  state: AnyState = create_idle_state("client", self.cache_options)
@@ -132,25 +136,26 @@ class AsyncCacheProxy:
132
136
  return state.pair.response
133
137
  elif isinstance(state, NeedToBeUpdated):
134
138
  state = await self._handle_update(state)
135
- elif isinstance(state, InvalidatePairs):
136
- state = await self._handle_invalidate_pairs(state)
139
+ elif isinstance(state, InvalidateEntries):
140
+ state = await self._handle_invalidate_entries(state)
137
141
  else:
138
142
  assert_never(state)
139
143
 
140
144
  raise RuntimeError("Unreachable")
141
145
 
142
146
  async def _handle_idle_state(self, state: IdleClient, request: Request) -> AnyState:
143
- stored_pairs = await self.storage.get_pairs(await self._get_key_for_request(request))
144
- return state.next(request, stored_pairs)
147
+ stored_entries = await self.storage.get_entries(await self._get_key_for_request(request))
148
+ return state.next(request, stored_entries)
145
149
 
146
150
  async def _handle_cache_miss(self, state: CacheMiss) -> AnyState:
147
- incomplete_pair = await self.storage.create_pair(state.request)
148
- response = await self.send_request(incomplete_pair.request)
149
- return state.next(response, incomplete_pair.id)
151
+ response = await self.send_request(state.request)
152
+ return state.next(response)
150
153
 
151
154
  async def _handle_store_and_use(self, state: StoreAndUse, request: Request) -> Response:
152
- complete_pair = await self.storage.add_response(
153
- state.pair_id, state.response, await self._get_key_for_request(request)
155
+ complete_pair = await self.storage.create_entry(
156
+ request,
157
+ state.response,
158
+ await self._get_key_for_request(request),
154
159
  )
155
160
  return complete_pair.response
156
161
 
@@ -159,16 +164,17 @@ class AsyncCacheProxy:
159
164
  return state.next(revalidation_response)
160
165
 
161
166
  async def _handle_update(self, state: NeedToBeUpdated) -> AnyState:
162
- for pair in state.updating_pairs:
163
- await self.storage.update_pair(
164
- pair.id,
167
+ for entry in state.updating_entries:
168
+ await self.storage.update_entry(
169
+ entry.id,
165
170
  lambda complete_pair: replace(
166
- complete_pair, response=replace(pair.response, headers=pair.response.headers)
171
+ complete_pair,
172
+ response=replace(entry.response, headers=entry.response.headers),
167
173
  ),
168
174
  )
169
175
  return state.next()
170
176
 
171
- async def _handle_invalidate_pairs(self, state: InvalidatePairs) -> AnyState:
172
- for pair_id in state.pair_ids:
173
- await self.storage.remove(pair_id)
177
+ async def _handle_invalidate_entries(self, state: InvalidateEntries) -> AnyState:
178
+ for entry_id in state.entry_ids:
179
+ await self.storage.remove_entry(entry_id)
174
180
  return state.next()