hishel 0.1.2__py3-none-any.whl → 0.1.3__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/__init__.py CHANGED
@@ -14,4 +14,4 @@ def install_cache() -> None: # pragma: no cover
14
14
  httpx.Client = CacheClient # type: ignore
15
15
 
16
16
 
17
- __version__ = "0.1.2"
17
+ __version__ = "0.1.3"
@@ -159,7 +159,7 @@ class AsyncFileStorage(AsyncBaseStorage):
159
159
 
160
160
  async with self._lock:
161
161
  if response_path.exists():
162
- response_path.unlink()
162
+ response_path.unlink(missing_ok=True)
163
163
 
164
164
  async def update_metadata(self, key: str, response: Response, request: Request, metadata: Metadata) -> None:
165
165
  """
@@ -222,7 +222,7 @@ class AsyncFileStorage(AsyncBaseStorage):
222
222
  if response_path.is_file():
223
223
  age = time.time() - response_path.stat().st_mtime
224
224
  if age > self._ttl:
225
- response_path.unlink()
225
+ response_path.unlink(missing_ok=True)
226
226
  return
227
227
 
228
228
  self._last_cleaned = time.monotonic()
@@ -507,7 +507,7 @@ class AsyncRedisStorage(AsyncBaseStorage):
507
507
  return self._serializer.loads(cached_response)
508
508
 
509
509
  async def aclose(self) -> None: # pragma: no cover
510
- await self._client.close()
510
+ await self._client.aclose()
511
511
 
512
512
 
513
513
  class AsyncInMemoryStorage(AsyncBaseStorage):
@@ -654,6 +654,8 @@ class AsyncS3Storage(AsyncBaseStorage): # pragma: no cover
654
654
  :type check_ttl_every: tp.Union[int, float]
655
655
  :param client: A client for S3, defaults to None
656
656
  :type client: tp.Optional[tp.Any], optional
657
+ :param path_prefix: A path prefix to use for S3 object keys, defaults to "hishel-"
658
+ :type path_prefix: str, optional
657
659
  """
658
660
 
659
661
  def __init__(
@@ -663,6 +665,7 @@ class AsyncS3Storage(AsyncBaseStorage): # pragma: no cover
663
665
  ttl: tp.Optional[tp.Union[int, float]] = None,
664
666
  check_ttl_every: tp.Union[int, float] = 60,
665
667
  client: tp.Optional[tp.Any] = None,
668
+ path_prefix: str = "hishel-",
666
669
  ) -> None:
667
670
  super().__init__(serializer, ttl)
668
671
 
@@ -680,6 +683,7 @@ class AsyncS3Storage(AsyncBaseStorage): # pragma: no cover
680
683
  bucket_name=bucket_name,
681
684
  is_binary=self._serializer.is_binary,
682
685
  check_ttl_every=check_ttl_every,
686
+ path_prefix=path_prefix,
683
687
  )
684
688
  self._lock = AsyncLock()
685
689
 
hishel/_s3.py CHANGED
@@ -11,16 +11,22 @@ def get_timestamp_in_ms() -> float:
11
11
 
12
12
  class S3Manager:
13
13
  def __init__(
14
- self, client: tp.Any, bucket_name: str, check_ttl_every: tp.Union[int, float], is_binary: bool = False
14
+ self,
15
+ client: tp.Any,
16
+ bucket_name: str,
17
+ check_ttl_every: tp.Union[int, float],
18
+ is_binary: bool = False,
19
+ path_prefix: str = "hishel-",
15
20
  ):
16
21
  self._client = client
17
22
  self._bucket_name = bucket_name
18
23
  self._is_binary = is_binary
19
24
  self._last_cleaned = time.monotonic()
20
25
  self._check_ttl_every = check_ttl_every
26
+ self._path_prefix = path_prefix
21
27
 
22
28
  def write_to(self, path: str, data: tp.Union[bytes, str], only_metadata: bool = False) -> None:
23
- path = "hishel-" + path
29
+ path = self._path_prefix + path
24
30
  if isinstance(data, str):
25
31
  data = data.encode("utf-8")
26
32
 
@@ -43,7 +49,7 @@ class S3Manager:
43
49
  )
44
50
 
45
51
  def read_from(self, path: str) -> tp.Union[bytes, str]:
46
- path = "hishel-" + path
52
+ path = self._path_prefix + path
47
53
  response = self._client.get_object(
48
54
  Bucket=self._bucket_name,
49
55
  Key=path,
@@ -57,7 +63,7 @@ class S3Manager:
57
63
  return tp.cast(str, content.decode("utf-8"))
58
64
 
59
65
  def remove_expired(self, ttl: int, key: str) -> None:
60
- path = "hishel-" + key
66
+ path = self._path_prefix + key
61
67
 
62
68
  if time.monotonic() - self._last_cleaned < self._check_ttl_every:
63
69
  try:
@@ -72,7 +78,7 @@ class S3Manager:
72
78
 
73
79
  self._last_cleaned = time.monotonic()
74
80
  for obj in self._client.list_objects(Bucket=self._bucket_name).get("Contents", []):
75
- if not obj["Key"].startswith("hishel-"): # pragma: no cover
81
+ if not obj["Key"].startswith(self._path_prefix): # pragma: no cover
76
82
  continue
77
83
 
78
84
  try:
@@ -88,15 +94,20 @@ class S3Manager:
88
94
  self._client.delete_object(Bucket=self._bucket_name, Key=obj["Key"])
89
95
 
90
96
  def remove_entry(self, key: str) -> None:
91
- path = "hishel-" + key
97
+ path = self._path_prefix + key
92
98
  self._client.delete_object(Bucket=self._bucket_name, Key=path)
93
99
 
94
100
 
95
101
  class AsyncS3Manager: # pragma: no cover
96
102
  def __init__(
97
- self, client: tp.Any, bucket_name: str, check_ttl_every: tp.Union[int, float], is_binary: bool = False
103
+ self,
104
+ client: tp.Any,
105
+ bucket_name: str,
106
+ check_ttl_every: tp.Union[int, float],
107
+ is_binary: bool = False,
108
+ path_prefix: str = "hishel-",
98
109
  ):
99
- self._sync_manager = S3Manager(client, bucket_name, check_ttl_every, is_binary)
110
+ self._sync_manager = S3Manager(client, bucket_name, check_ttl_every, is_binary, path_prefix)
100
111
 
101
112
  async def write_to(self, path: str, data: tp.Union[bytes, str], only_metadata: bool = False) -> None:
102
113
  return await to_thread.run_sync(self._sync_manager.write_to, path, data, only_metadata)
hishel/_sync/_storages.py CHANGED
@@ -159,7 +159,7 @@ class FileStorage(BaseStorage):
159
159
 
160
160
  with self._lock:
161
161
  if response_path.exists():
162
- response_path.unlink()
162
+ response_path.unlink(missing_ok=True)
163
163
 
164
164
  def update_metadata(self, key: str, response: Response, request: Request, metadata: Metadata) -> None:
165
165
  """
@@ -222,7 +222,7 @@ class FileStorage(BaseStorage):
222
222
  if response_path.is_file():
223
223
  age = time.time() - response_path.stat().st_mtime
224
224
  if age > self._ttl:
225
- response_path.unlink()
225
+ response_path.unlink(missing_ok=True)
226
226
  return
227
227
 
228
228
  self._last_cleaned = time.monotonic()
@@ -654,6 +654,8 @@ class S3Storage(BaseStorage): # pragma: no cover
654
654
  :type check_ttl_every: tp.Union[int, float]
655
655
  :param client: A client for S3, defaults to None
656
656
  :type client: tp.Optional[tp.Any], optional
657
+ :param path_prefix: A path prefix to use for S3 object keys, defaults to "hishel-"
658
+ :type path_prefix: str, optional
657
659
  """
658
660
 
659
661
  def __init__(
@@ -663,6 +665,7 @@ class S3Storage(BaseStorage): # pragma: no cover
663
665
  ttl: tp.Optional[tp.Union[int, float]] = None,
664
666
  check_ttl_every: tp.Union[int, float] = 60,
665
667
  client: tp.Optional[tp.Any] = None,
668
+ path_prefix: str = "hishel-",
666
669
  ) -> None:
667
670
  super().__init__(serializer, ttl)
668
671
 
@@ -680,6 +683,7 @@ class S3Storage(BaseStorage): # pragma: no cover
680
683
  bucket_name=bucket_name,
681
684
  is_binary=self._serializer.is_binary,
682
685
  check_ttl_every=check_ttl_every,
686
+ path_prefix=path_prefix,
683
687
  )
684
688
  self._lock = Lock()
685
689
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hishel
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Persistent cache implementation for httpx and httpcore
5
5
  Project-URL: Homepage, https://hishel.com
6
6
  Project-URL: Source, https://github.com/karpetrosyan/hishel
@@ -25,14 +25,14 @@ Classifier: Topic :: Internet :: WWW/HTTP
25
25
  Requires-Python: >=3.9
26
26
  Requires-Dist: httpx>=0.28.0
27
27
  Provides-Extra: redis
28
- Requires-Dist: redis==5.0.4; extra == 'redis'
28
+ Requires-Dist: redis==6.2.0; extra == 'redis'
29
29
  Provides-Extra: s3
30
30
  Requires-Dist: boto3<=1.15.3,>=1.15.0; (python_version < '3.12') and extra == 's3'
31
31
  Requires-Dist: boto3>=1.15.3; (python_version >= '3.12') and extra == 's3'
32
32
  Provides-Extra: sqlite
33
33
  Requires-Dist: anysqlite>=0.0.5; extra == 'sqlite'
34
34
  Provides-Extra: yaml
35
- Requires-Dist: pyyaml==6.0.1; extra == 'yaml'
35
+ Requires-Dist: pyyaml==6.0.2; extra == 'yaml'
36
36
  Description-Content-Type: text/markdown
37
37
 
38
38
  <p align="center" class="logo">
@@ -181,6 +181,13 @@ Help us grow and continue developing good software for you ❤️
181
181
 
182
182
  # Changelog
183
183
 
184
+ ## 0.1.3 (1st July, 2025)
185
+
186
+ - Remove `types-redis` from dev dependencies (#336)
187
+ - Bump redis to 6.0.0 and address async `.close()` deprecation warning (#336)
188
+ - Avoid race condition when unlinking files in `FileStorage`. (#334)
189
+ - Allow prodiving a `path_prefix` in `S3Storage` and `AsyncS3Storage`. (#342)
190
+
184
191
  ## 0.1.2 (5th April, 2025)
185
192
 
186
193
  - Add check for fips compliant python. (#325)
@@ -1,10 +1,10 @@
1
- hishel/__init__.py,sha256=R91Ika4Y8yXeuWLIrpbrXHUPASzYa-ZlaC2r7cX7L74,368
1
+ hishel/__init__.py,sha256=b-mInXgxD6YLLyk5l1YV1B1nZdzSchPoI48Lwa4hMLc,368
2
2
  hishel/_controller.py,sha256=be1_eL34Gue6a1px_eLFWWxViPQbYENMvtZmv8gFRhA,24636
3
3
  hishel/_exceptions.py,sha256=qbg55RNlzwhv5JreWY9Zog_zmmiKdn5degtqJKijuRs,198
4
4
  hishel/_files.py,sha256=7J5uX7Nnzd7QQWfYuDGh8v6XGLG3eUDBjoJZ4aTaY1c,2228
5
5
  hishel/_headers.py,sha256=BPvas0LQgwbz-HZhFykZiHEIeNgnY-E33U__oskYzJw,7323
6
6
  hishel/_lfu_cache.py,sha256=GBxToQI8u_a9TzYnLlZMLhgZ8Lb83boPHzTvIgqV6pA,2707
7
- hishel/_s3.py,sha256=HDS3-3HM8xmIb-1_p2VRKJk9EwfzoxgTT0F1Kryl8sU,4087
7
+ hishel/_s3.py,sha256=HkmWYjYWAiWgEMp1_Jl79hG5aUpMcD0NDXjj8VHRmQE,4322
8
8
  hishel/_serializers.py,sha256=gepVb8JC4aBkGw9kLcbAsyo-1XgK_lzTssLr_8av4SQ,11640
9
9
  hishel/_synchronization.py,sha256=xOmU9_8KAWTAv3r8EpqPISrtSF3slyh1J0Sc7ZQO1rg,897
10
10
  hishel/_utils.py,sha256=7HhJlomBCqbhBv01ZuK5WfG8dCtGONLFFF7ujIvBBWQ,3277
@@ -13,15 +13,15 @@ hishel/_async/__init__.py,sha256=_oAltH4emAtUF7_9SSxz_KKGYzSXL34o_EGgGvoPG7E,187
13
13
  hishel/_async/_client.py,sha256=AkVSSbNTTHmK0gX6PRYVQ-3aDbuCX2Im4VKbLkwLiBU,1101
14
14
  hishel/_async/_mock.py,sha256=995v9p5xiw3svGSOJATkLMqwodlhZhcwmGygLHM2VFw,1515
15
15
  hishel/_async/_pool.py,sha256=xCcSAl4bHI5eVsZyPap7iHDpxzzgfMqYE_txcjQJ1Hs,8195
16
- hishel/_async/_storages.py,sha256=tJXwov37HOvwYwXyjFtf-uRn7y7wR8RZs49F_Urj570,28744
16
+ hishel/_async/_storages.py,sha256=pc1u9pmOLzN2bizOzvqecky7GAZWpI5k5jLqzQ3sd5s,28974
17
17
  hishel/_async/_transports.py,sha256=BhtEj8SHxu0YKHWDDP5mfCabIWgrAM7lMLJ1-TwWigw,11203
18
18
  hishel/_sync/__init__.py,sha256=_oAltH4emAtUF7_9SSxz_KKGYzSXL34o_EGgGvoPG7E,187
19
19
  hishel/_sync/_client.py,sha256=O-gwm9DsveKtSFUfqdbBB-3I1FmXr5rE-uQ7X5frwDA,1060
20
20
  hishel/_sync/_mock.py,sha256=im88tZr-XhP9BpzvIt3uOjndAlNcJvFP7Puv3H-6lKU,1430
21
21
  hishel/_sync/_pool.py,sha256=U2b9ZGYUltwTjI2q2KHZwmj4boIqUExJ_rUKWuLmYSs,7960
22
- hishel/_sync/_storages.py,sha256=NhIIAoWdpFECcexz121rfYLFRCk3C1iBazVXwoDVoSU,27954
22
+ hishel/_sync/_storages.py,sha256=Hal5BujHvCH49hv79chpIrFjVQsk_5rU51IX415REes,28183
23
23
  hishel/_sync/_transports.py,sha256=cQQgdJSy1zfmIa14ycADPek9Tobpa33nqBHA614_6kc,10875
24
- hishel-0.1.2.dist-info/METADATA,sha256=aqgCs4WIdawt1s7MUa6kVR32jEWG9Zeu3yTGJUL9ah4,12583
25
- hishel-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- hishel-0.1.2.dist-info/licenses/LICENSE,sha256=1qQj7pE0V2O9OIedvyOgLGLvZLaPd3nFEup3IBEOZjQ,1493
27
- hishel-0.1.2.dist-info/RECORD,,
24
+ hishel-0.1.3.dist-info/METADATA,sha256=DLnpaHpXbtsuIjPOsNrJuts1997dz3XGHhKywucUh-s,12890
25
+ hishel-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
+ hishel-0.1.3.dist-info/licenses/LICENSE,sha256=1qQj7pE0V2O9OIedvyOgLGLvZLaPd3nFEup3IBEOZjQ,1493
27
+ hishel-0.1.3.dist-info/RECORD,,
File without changes