hishel 1.1.4__py3-none-any.whl → 1.1.6__py3-none-any.whl
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.
- hishel/_core/_spec.py +38 -1
- hishel/_core/_storages/_async_sqlite.py +14 -11
- hishel/_core/_storages/_sync_sqlite.py +14 -11
- {hishel-1.1.4.dist-info → hishel-1.1.6.dist-info}/METADATA +24 -1
- {hishel-1.1.4.dist-info → hishel-1.1.6.dist-info}/RECORD +7 -7
- {hishel-1.1.4.dist-info → hishel-1.1.6.dist-info}/WHEEL +0 -0
- {hishel-1.1.4.dist-info → hishel-1.1.6.dist-info}/licenses/LICENSE +0 -0
hishel/_core/_spec.py
CHANGED
|
@@ -1207,6 +1207,7 @@ class IdleClient(State):
|
|
|
1207
1207
|
- Unsafe methods (POST, PUT, DELETE, etc.) are written through to origin
|
|
1208
1208
|
- Multiple matching responses are sorted by Date header (most recent first)
|
|
1209
1209
|
- Age header is updated when serving from cache
|
|
1210
|
+
- Request no-cache directive forces revalidation of cached responses
|
|
1210
1211
|
|
|
1211
1212
|
Examples:
|
|
1212
1213
|
--------
|
|
@@ -1229,6 +1230,18 @@ class IdleClient(State):
|
|
|
1229
1230
|
>>> next_state = idle.next(get_request, [cached_pair])
|
|
1230
1231
|
>>> isinstance(next_state, NeedRevalidation)
|
|
1231
1232
|
True
|
|
1233
|
+
|
|
1234
|
+
>>> # Need revalidation - request no-cache forces validation of fresh response
|
|
1235
|
+
>>> idle = IdleClient(options=default_options)
|
|
1236
|
+
>>> no_cache_request = Request(
|
|
1237
|
+
... method="GET",
|
|
1238
|
+
... url="https://example.com",
|
|
1239
|
+
... headers=Headers({"cache-control": "no-cache"})
|
|
1240
|
+
... )
|
|
1241
|
+
>>> cached_pair = CompletePair(no_cache_request, fresh_response)
|
|
1242
|
+
>>> next_state = idle.next(no_cache_request, [cached_pair])
|
|
1243
|
+
>>> isinstance(next_state, NeedRevalidation)
|
|
1244
|
+
True
|
|
1232
1245
|
"""
|
|
1233
1246
|
|
|
1234
1247
|
# ============================================================================
|
|
@@ -1388,7 +1401,31 @@ class IdleClient(State):
|
|
|
1388
1401
|
ready_to_use, need_revalidation = partition(filtered_pairs, fresh_or_allowed_stale)
|
|
1389
1402
|
|
|
1390
1403
|
# ============================================================================
|
|
1391
|
-
# STEP 7:
|
|
1404
|
+
# STEP 7: Handle Request no-cache Directive
|
|
1405
|
+
# ============================================================================
|
|
1406
|
+
# RFC 9111 Section 5.2.1.4: no-cache Request Directive
|
|
1407
|
+
# https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.4
|
|
1408
|
+
#
|
|
1409
|
+
# "The no-cache request directive indicates that a cache MUST NOT use a
|
|
1410
|
+
# stored response to satisfy the request without successful validation on
|
|
1411
|
+
# the origin server."
|
|
1412
|
+
#
|
|
1413
|
+
# When a client sends Cache-Control: no-cache in the request, it's explicitly
|
|
1414
|
+
# requesting that the cache not use any stored response without first validating
|
|
1415
|
+
# it with the origin server. This is different from the response no-cache directive,
|
|
1416
|
+
# which applies to how responses should be cached.
|
|
1417
|
+
request_cache_control = parse_cache_control(request.headers.get("cache-control"))
|
|
1418
|
+
|
|
1419
|
+
if request_cache_control.no_cache is True:
|
|
1420
|
+
# Move all fresh responses to the revalidation queue
|
|
1421
|
+
# This ensures that even fresh cached responses will be validated
|
|
1422
|
+
# with the origin server via conditional requests (If-None-Match,
|
|
1423
|
+
# If-Modified-Since) before being served to the client.
|
|
1424
|
+
need_revalidation.extend(ready_to_use)
|
|
1425
|
+
ready_to_use = []
|
|
1426
|
+
|
|
1427
|
+
# ============================================================================
|
|
1428
|
+
# STEP 8: Determine Next State Based on Available Responses
|
|
1392
1429
|
# ============================================================================
|
|
1393
1430
|
|
|
1394
1431
|
if ready_to_use:
|
|
@@ -161,8 +161,19 @@ try:
|
|
|
161
161
|
for row in await cursor.fetchall():
|
|
162
162
|
pair_data = unpack(row[1], kind="pair")
|
|
163
163
|
|
|
164
|
+
if pair_data is None:
|
|
165
|
+
continue
|
|
166
|
+
|
|
164
167
|
# Skip entries without a response (incomplete)
|
|
165
|
-
if not
|
|
168
|
+
if not await self._is_stream_complete(pair_data.id, cursor=cursor):
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
# Skip expired entries
|
|
172
|
+
if await self._is_pair_expired(pair_data, cursor=cursor):
|
|
173
|
+
continue
|
|
174
|
+
|
|
175
|
+
# Skip soft-deleted entries
|
|
176
|
+
if self.is_soft_deleted(pair_data):
|
|
166
177
|
continue
|
|
167
178
|
|
|
168
179
|
final_pairs.append(pair_data)
|
|
@@ -329,16 +340,8 @@ try:
|
|
|
329
340
|
await connection.commit()
|
|
330
341
|
|
|
331
342
|
async def _is_corrupted(self, pair: Entry, cursor: anysqlite.Cursor) -> bool:
|
|
332
|
-
# if entry was created more than 1 hour ago and still has no response
|
|
333
|
-
if pair.meta.created_at + 3600 < time.time() and pair.
|
|
334
|
-
return True
|
|
335
|
-
|
|
336
|
-
# Check if response stream is complete for Entry with response
|
|
337
|
-
if (
|
|
338
|
-
isinstance(pair, Entry)
|
|
339
|
-
and pair.response is not None
|
|
340
|
-
and not await self._is_stream_complete(pair.id, cursor)
|
|
341
|
-
):
|
|
343
|
+
# if entry was created more than 1 hour ago and still has no full response data
|
|
344
|
+
if pair.meta.created_at + 3600 < time.time() and not (await self._is_stream_complete(pair.id, cursor)):
|
|
342
345
|
return True
|
|
343
346
|
return False
|
|
344
347
|
|
|
@@ -161,8 +161,19 @@ try:
|
|
|
161
161
|
for row in cursor.fetchall():
|
|
162
162
|
pair_data = unpack(row[1], kind="pair")
|
|
163
163
|
|
|
164
|
+
if pair_data is None:
|
|
165
|
+
continue
|
|
166
|
+
|
|
164
167
|
# Skip entries without a response (incomplete)
|
|
165
|
-
if not
|
|
168
|
+
if not self._is_stream_complete(pair_data.id, cursor=cursor):
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
# Skip expired entries
|
|
172
|
+
if self._is_pair_expired(pair_data, cursor=cursor):
|
|
173
|
+
continue
|
|
174
|
+
|
|
175
|
+
# Skip soft-deleted entries
|
|
176
|
+
if self.is_soft_deleted(pair_data):
|
|
166
177
|
continue
|
|
167
178
|
|
|
168
179
|
final_pairs.append(pair_data)
|
|
@@ -329,16 +340,8 @@ try:
|
|
|
329
340
|
connection.commit()
|
|
330
341
|
|
|
331
342
|
def _is_corrupted(self, pair: Entry, cursor: sqlite3.Cursor) -> bool:
|
|
332
|
-
# if entry was created more than 1 hour ago and still has no response
|
|
333
|
-
if pair.meta.created_at + 3600 < time.time() and pair.
|
|
334
|
-
return True
|
|
335
|
-
|
|
336
|
-
# Check if response stream is complete for Entry with response
|
|
337
|
-
if (
|
|
338
|
-
isinstance(pair, Entry)
|
|
339
|
-
and pair.response is not None
|
|
340
|
-
and not self._is_stream_complete(pair.id, cursor)
|
|
341
|
-
):
|
|
343
|
+
# if entry was created more than 1 hour ago and still has no full response data
|
|
344
|
+
if pair.meta.created_at + 3600 < time.time() and not (self._is_stream_complete(pair.id, cursor)):
|
|
342
345
|
return True
|
|
343
346
|
return False
|
|
344
347
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hishel
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.6
|
|
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
|
|
@@ -406,6 +406,29 @@ Hishel is inspired by and builds upon the excellent work in the Python HTTP ecos
|
|
|
406
406
|
<strong>Made with ❤️ by <a href="https://github.com/karpetrosyan">Kar Petrosyan</a></strong>
|
|
407
407
|
</p>
|
|
408
408
|
|
|
409
|
+
## What's Changed in 1.1.6
|
|
410
|
+
### 📚 Documentation
|
|
411
|
+
|
|
412
|
+
* remove some stale httpx configs by @karpetrosyan
|
|
413
|
+
### 🚀 Features
|
|
414
|
+
|
|
415
|
+
* Add support for request no-cache directive by @karpetrosyan in [#416](https://github.com/karpetrosyan/hishel/pull/416)
|
|
416
|
+
|
|
417
|
+
### Contributors
|
|
418
|
+
* @karpetrosyan
|
|
419
|
+
|
|
420
|
+
**Full Changelog**: https://github.com/karpetrosyan/hishel/compare/1.1.5...1.1.6
|
|
421
|
+
|
|
422
|
+
## What's Changed in 1.1.5
|
|
423
|
+
### 🐛 Bug Fixes
|
|
424
|
+
|
|
425
|
+
* filter out soft-deleted, expired and incomplete entries in `get_entries` by @karpetrosyan
|
|
426
|
+
|
|
427
|
+
### Contributors
|
|
428
|
+
* @karpetrosyan
|
|
429
|
+
|
|
430
|
+
**Full Changelog**: https://github.com/karpetrosyan/hishel/compare/1.1.4...1.1.5
|
|
431
|
+
|
|
409
432
|
## What's Changed in 1.1.4
|
|
410
433
|
### 🐛 Bug Fixes
|
|
411
434
|
|
|
@@ -11,14 +11,14 @@ hishel/httpx.py,sha256=99a8X9COPiPHSgGW61O2uMWMZB7dY93Ty9DTCJ9C18Q,467
|
|
|
11
11
|
hishel/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
hishel/requests.py,sha256=F3BntFGeesm19NmWFgGoBg-rfkcIs9OTpXDass73t6w,6819
|
|
13
13
|
hishel/_core/_headers.py,sha256=hGaT6o1F-gs1pm5RpdGb0IMQL3uJYDH1xpwJLy28Cys,17514
|
|
14
|
-
hishel/_core/_spec.py,sha256=
|
|
14
|
+
hishel/_core/_spec.py,sha256=26mrK0MFSN_03ZecKem0asHYCXqzJ0tmcVmJXG7VHeI,105016
|
|
15
15
|
hishel/_core/models.py,sha256=EabP2qnjYVzhPWhQer3QFmdDE6TDbqEBEqPHzv25VnA,7978
|
|
16
16
|
hishel/_core/_storages/_async_base.py,sha256=iZ6Mb30P0ho5h4UU5bgOrcsSMZ1427j9tht-tupZs68,2106
|
|
17
|
-
hishel/_core/_storages/_async_sqlite.py,sha256=
|
|
17
|
+
hishel/_core/_storages/_async_sqlite.py,sha256=IDMbtmbQ8e12HUlNJGyn6SIYColupuIbtvGfNl47_pM,15916
|
|
18
18
|
hishel/_core/_storages/_packing.py,sha256=mC8LMFQ5uPfFOgingKm2WKFO_DwcZ1OjTgI6xc0hfJI,3708
|
|
19
19
|
hishel/_core/_storages/_sync_base.py,sha256=qfOvcFY5qvrzSh4ztV2Trlxft-BF7An5SFsLlEb8EeE,2075
|
|
20
|
-
hishel/_core/_storages/_sync_sqlite.py,sha256=
|
|
21
|
-
hishel-1.1.
|
|
22
|
-
hishel-1.1.
|
|
23
|
-
hishel-1.1.
|
|
24
|
-
hishel-1.1.
|
|
20
|
+
hishel/_core/_storages/_sync_sqlite.py,sha256=MidCVhhzlf2bZQ2_UzZzh0r_14HGZpFEomkGU5POjuk,15385
|
|
21
|
+
hishel-1.1.6.dist-info/METADATA,sha256=xQuRX_gSxX_sqXkwKnH7Mtsft7tUfym5L05CfbKeog4,20803
|
|
22
|
+
hishel-1.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
hishel-1.1.6.dist-info/licenses/LICENSE,sha256=1qQj7pE0V2O9OIedvyOgLGLvZLaPd3nFEup3IBEOZjQ,1493
|
|
24
|
+
hishel-1.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|