cachebox 6.1.2__tar.gz → 6.2.1__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.
- {cachebox-6.1.2 → cachebox-6.2.1}/.github/workflows/CI.yml +4 -6
- {cachebox-6.1.2 → cachebox-6.2.1}/.github/workflows/python-test.yml +12 -9
- {cachebox-6.1.2 → cachebox-6.2.1}/Cargo.lock +8 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/Cargo.toml +2 -2
- {cachebox-6.1.2 → cachebox-6.2.1}/PKG-INFO +2 -2
- {cachebox-6.1.2 → cachebox-6.2.1}/README.md +1 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/cachebox/_core.pyi +209 -23
- {cachebox-6.1.2 → cachebox-6.2.1}/cachebox/_wrappers.py +40 -13
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/api/impls.md +8 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/requirements-dev.txt +1 -0
- cachebox-6.2.1/src/hashbrown/alloc.rs +21 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/raw.rs +4 -5
- cachebox-6.2.1/src/hashbrown/util.rs +23 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/lazyheap.rs +1 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/linked_list.rs +1 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/onceinit.rs +1 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/utils.rs +1 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/lib.rs +4 -8
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/fifopolicy.rs +2 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/ttlpolicy.rs +4 -7
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/wrapped.rs +12 -1
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/cache.rs +46 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/fifocache.rs +46 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/lfucache.rs +47 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/lrucache.rs +46 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/rrcache.rs +46 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/ttlcache.rs +47 -4
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/vttlcache.rs +38 -2
- {cachebox-6.1.2 → cachebox-6.2.1}/tests/mixins.py +61 -8
- {cachebox-6.1.2 → cachebox-6.2.1}/tests/test_impls.py +25 -6
- {cachebox-6.1.2 → cachebox-6.2.1}/tests/test_utils.py +3 -3
- cachebox-6.1.2/src/hashbrown/alloc.rs +0 -13
- cachebox-6.1.2/src/hashbrown/util.rs +0 -9
- {cachebox-6.1.2 → cachebox-6.2.1}/.github/workflows/docs.yml +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/.gitignore +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/LICENSE +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/LICENSE-THIRD-PARTY +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/build.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/cachebox/__init__.py +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/cachebox/_cachebox.py +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/cachebox/utils.py +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/api/index.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/api/utils.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/getting-started.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/index.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/installation.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/migration.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/docs/tips.md +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/docs/mkdocs.yml +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/pyproject.toml +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/rustfmt.toml +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/bitmask.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/group/generic.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/group/lsx.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/group/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/group/neon.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/group/sse2.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/control/tag.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/hashbrown/scopeguard.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/alias.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/internal/pickle.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/macro_rules.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/common.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/lfupolicy.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/lrupolicy.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/nopolicy.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/rrpolicy.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/traits.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/policies/vttlpolicy.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/base.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/pyclasses/mod.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/src/typeref.rs +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/tests/__init__.py +0 -0
- {cachebox-6.1.2 → cachebox-6.2.1}/tests/conftest.py +0 -0
|
@@ -57,7 +57,6 @@ jobs:
|
|
|
57
57
|
args: --release --out dist --interpreter ${{ matrix.platform.interpreter }}
|
|
58
58
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
59
59
|
manylinux: auto
|
|
60
|
-
rust-toolchain: nightly
|
|
61
60
|
|
|
62
61
|
- uses: actions/upload-artifact@v7.0.1
|
|
63
62
|
with:
|
|
@@ -101,7 +100,6 @@ jobs:
|
|
|
101
100
|
args: --release --out dist --interpreter ${{ matrix.platform.interpreter }}
|
|
102
101
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
103
102
|
manylinux: musllinux_1_2
|
|
104
|
-
rust-toolchain: nightly
|
|
105
103
|
|
|
106
104
|
- uses: actions/upload-artifact@v7.0.1
|
|
107
105
|
with:
|
|
@@ -117,7 +115,10 @@ jobs:
|
|
|
117
115
|
target: x64,
|
|
118
116
|
interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11",
|
|
119
117
|
}
|
|
120
|
-
- {
|
|
118
|
+
- {
|
|
119
|
+
target: x86,
|
|
120
|
+
interpreter: "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t",
|
|
121
|
+
}
|
|
121
122
|
|
|
122
123
|
steps:
|
|
123
124
|
- uses: actions/checkout@v6.0.2
|
|
@@ -134,7 +135,6 @@ jobs:
|
|
|
134
135
|
target: ${{ matrix.platform.target }}
|
|
135
136
|
args: --release --out dist --interpreter ${{ matrix.platform.interpreter }}
|
|
136
137
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
137
|
-
rust-toolchain: nightly
|
|
138
138
|
|
|
139
139
|
- uses: actions/upload-artifact@v7.0.1
|
|
140
140
|
with:
|
|
@@ -169,7 +169,6 @@ jobs:
|
|
|
169
169
|
target: ${{ matrix.platform.target }}
|
|
170
170
|
args: --release --out dist --interpreter ${{ matrix.platform.interpreter }}
|
|
171
171
|
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
172
|
-
rust-toolchain: nightly
|
|
173
172
|
|
|
174
173
|
- uses: actions/upload-artifact@v7.0.1
|
|
175
174
|
with:
|
|
@@ -188,7 +187,6 @@ jobs:
|
|
|
188
187
|
with:
|
|
189
188
|
command: sdist
|
|
190
189
|
args: --out dist
|
|
191
|
-
rust-toolchain: nightly
|
|
192
190
|
|
|
193
191
|
- name: Upload sdist
|
|
194
192
|
uses: actions/upload-artifact@v7.0.1
|
|
@@ -16,7 +16,7 @@ env:
|
|
|
16
16
|
|
|
17
17
|
jobs:
|
|
18
18
|
test-python:
|
|
19
|
-
name:
|
|
19
|
+
name: ${{ matrix.python-version }}
|
|
20
20
|
runs-on: ubuntu-latest
|
|
21
21
|
continue-on-error: ${{ endsWith(matrix.python-version, 't') }}
|
|
22
22
|
strategy:
|
|
@@ -36,22 +36,24 @@ jobs:
|
|
|
36
36
|
steps:
|
|
37
37
|
- uses: actions/checkout@v6.0.2
|
|
38
38
|
|
|
39
|
-
- uses: dtolnay/rust-toolchain@
|
|
39
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
40
40
|
|
|
41
41
|
- uses: actions/setup-python@v6.2.0
|
|
42
42
|
with:
|
|
43
43
|
python-version: ${{ matrix.python-version }}
|
|
44
44
|
allow-prereleases: true
|
|
45
45
|
|
|
46
|
-
- run: pip install virtualenv
|
|
46
|
+
- run: pip install virtualenv
|
|
47
|
+
- run: pip install -r requirements-dev.txt
|
|
47
48
|
- run: virtualenv --no-vcs-ignore .venv
|
|
49
|
+
|
|
48
50
|
- run: maturin develop --features use-small-offset
|
|
49
|
-
- run: pytest -v
|
|
51
|
+
- run: pytest -v -n auto
|
|
50
52
|
env:
|
|
51
53
|
HYPOTHESIS_PROFILE: slow
|
|
52
54
|
|
|
53
55
|
test-os:
|
|
54
|
-
name:
|
|
56
|
+
name: ${{ matrix.os }}
|
|
55
57
|
runs-on: ${{ matrix.os }}-latest
|
|
56
58
|
strategy:
|
|
57
59
|
fail-fast: false
|
|
@@ -61,16 +63,17 @@ jobs:
|
|
|
61
63
|
steps:
|
|
62
64
|
- uses: actions/checkout@v6.0.2
|
|
63
65
|
|
|
64
|
-
- uses: dtolnay/rust-toolchain@
|
|
66
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
65
67
|
|
|
66
68
|
- uses: actions/setup-python@v6.2.0
|
|
67
69
|
with:
|
|
68
70
|
python-version: "3.13"
|
|
69
|
-
allow-prereleases: true
|
|
70
71
|
|
|
71
|
-
- run: pip install virtualenv
|
|
72
|
+
- run: pip install virtualenv
|
|
73
|
+
- run: pip install -r requirements-dev.txt
|
|
72
74
|
- run: virtualenv --no-vcs-ignore .venv
|
|
75
|
+
|
|
73
76
|
- run: maturin develop --features use-small-offset
|
|
74
|
-
- run: pytest -v
|
|
77
|
+
- run: pytest -v -n auto
|
|
75
78
|
env:
|
|
76
79
|
HYPOTHESIS_PROFILE: slow
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
3
|
version = 4
|
|
4
4
|
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "allocator-api2"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "c880a97d28a3681c0267bd29cff89621202715b065127cd445fa0f0fe0aa2880"
|
|
10
|
+
|
|
5
11
|
[[package]]
|
|
6
12
|
name = "android_system_properties"
|
|
7
13
|
version = "0.1.5"
|
|
@@ -31,8 +37,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
|
31
37
|
|
|
32
38
|
[[package]]
|
|
33
39
|
name = "cachebox"
|
|
34
|
-
version = "6.1
|
|
40
|
+
version = "6.2.1"
|
|
35
41
|
dependencies = [
|
|
42
|
+
"allocator-api2",
|
|
36
43
|
"cfg-if",
|
|
37
44
|
"chrono",
|
|
38
45
|
"fastrand",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "cachebox"
|
|
3
|
-
version = "6.1
|
|
3
|
+
version = "6.2.1"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "The fastest memoizing and caching Python library written in Rust"
|
|
6
6
|
readme = "README.md"
|
|
@@ -22,12 +22,12 @@ panic = "abort"
|
|
|
22
22
|
strip = true
|
|
23
23
|
|
|
24
24
|
[dependencies]
|
|
25
|
+
allocator-api2 = "0.4.0"
|
|
25
26
|
cfg-if = "1.0.4"
|
|
26
27
|
chrono = "0.4.44"
|
|
27
28
|
fastrand = "2.4.1"
|
|
28
29
|
parking_lot = {version="0.12.5", default-features=false}
|
|
29
30
|
pyo3 = {version="0.29", default-features=false, features=["macros", "chrono"]}
|
|
30
|
-
# tokio = {version="1.52.3", default-features=false, features=["sync"]}
|
|
31
31
|
|
|
32
32
|
[build-dependencies]
|
|
33
33
|
pyo3-build-config = {version="0.29", default-features=false, features=["resolve-config"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachebox
|
|
3
|
-
Version: 6.1
|
|
3
|
+
Version: 6.2.1
|
|
4
4
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -161,7 +161,7 @@ assert cache.get("key") == "value"
|
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
## Learn more
|
|
164
|
-
Read the documentation for full information and learn more: [**Documentation**](https://awolverp.github.
|
|
164
|
+
Read the documentation for full information and learn more: [**Documentation**](https://awolverp.github.io/cachebox/)
|
|
165
165
|
|
|
166
166
|
## License
|
|
167
167
|
This repository is licensed under the [MIT License](LICENSE)
|
|
@@ -130,7 +130,7 @@ assert cache.get("key") == "value"
|
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
## Learn more
|
|
133
|
-
Read the documentation for full information and learn more: [**Documentation**](https://awolverp.github.
|
|
133
|
+
Read the documentation for full information and learn more: [**Documentation**](https://awolverp.github.io/cachebox/)
|
|
134
134
|
|
|
135
135
|
## License
|
|
136
136
|
This repository is licensed under the [MIT License](LICENSE)
|
|
@@ -157,7 +157,9 @@ class BaseCacheImpl(typing.Generic[KT, VT]):
|
|
|
157
157
|
*args: typing.Any,
|
|
158
158
|
**kwargs: typing.Any,
|
|
159
159
|
) -> None: ...
|
|
160
|
-
def get(
|
|
160
|
+
def get(
|
|
161
|
+
self, key: KT, default: typing.Optional[DT] = None
|
|
162
|
+
) -> typing.Union[VT, DT]: ...
|
|
161
163
|
def __getitem__(self, key: KT) -> VT: ...
|
|
162
164
|
def setdefault(
|
|
163
165
|
self,
|
|
@@ -166,6 +168,13 @@ class BaseCacheImpl(typing.Generic[KT, VT]):
|
|
|
166
168
|
*args: typing.Any,
|
|
167
169
|
**kwargs: typing.Any,
|
|
168
170
|
) -> typing.Optional[VT | DT]: ...
|
|
171
|
+
def setdefault_with(
|
|
172
|
+
self,
|
|
173
|
+
key: KT,
|
|
174
|
+
factory: typing.Callable[[], DT],
|
|
175
|
+
*args: typing.Any,
|
|
176
|
+
**kwargs: typing.Any,
|
|
177
|
+
) -> VT | DT: ...
|
|
169
178
|
def pop(self, key: KT, default: DT = ...) -> typing.Union[VT, DT]:
|
|
170
179
|
"""
|
|
171
180
|
Removes the specified key and returns the corresponding value.
|
|
@@ -352,15 +361,40 @@ class Cache(BaseCacheImpl[KT, VT]):
|
|
|
352
361
|
default: typing.Optional[DT] = None,
|
|
353
362
|
) -> typing.Optional[VT | DT]:
|
|
354
363
|
"""
|
|
355
|
-
|
|
364
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
365
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
366
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
356
367
|
|
|
357
368
|
Args:
|
|
358
369
|
key: The key to look up or insert.
|
|
359
370
|
default: The value to insert if ``key`` is not in the cache.
|
|
360
371
|
Defaults to ``None``.
|
|
361
372
|
|
|
362
|
-
|
|
363
|
-
|
|
373
|
+
Note:
|
|
374
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
375
|
+
effectes.
|
|
376
|
+
"""
|
|
377
|
+
...
|
|
378
|
+
|
|
379
|
+
def setdefault_with(
|
|
380
|
+
self,
|
|
381
|
+
key: KT,
|
|
382
|
+
factory: typing.Callable[[], DT],
|
|
383
|
+
) -> VT | DT:
|
|
384
|
+
"""
|
|
385
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
386
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
387
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
388
|
+
result is inserted and returned.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
key: The key to look up or insert.
|
|
392
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
393
|
+
|
|
394
|
+
Warning:
|
|
395
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
396
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
397
|
+
propagates.
|
|
364
398
|
"""
|
|
365
399
|
...
|
|
366
400
|
|
|
@@ -508,15 +542,40 @@ class FIFOCache(BaseCacheImpl[KT, VT]):
|
|
|
508
542
|
default: typing.Optional[DT] = None,
|
|
509
543
|
) -> typing.Optional[VT | DT]:
|
|
510
544
|
"""
|
|
511
|
-
|
|
545
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
546
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
547
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
512
548
|
|
|
513
549
|
Args:
|
|
514
550
|
key: The key to look up or insert.
|
|
515
551
|
default: The value to insert if ``key`` is not in the cache.
|
|
516
552
|
Defaults to ``None``.
|
|
517
553
|
|
|
518
|
-
|
|
519
|
-
|
|
554
|
+
Note:
|
|
555
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
556
|
+
effectes.
|
|
557
|
+
"""
|
|
558
|
+
...
|
|
559
|
+
|
|
560
|
+
def setdefault_with(
|
|
561
|
+
self,
|
|
562
|
+
key: KT,
|
|
563
|
+
factory: typing.Callable[[], DT],
|
|
564
|
+
) -> VT | DT:
|
|
565
|
+
"""
|
|
566
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
567
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
568
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
569
|
+
result is inserted and returned.
|
|
570
|
+
|
|
571
|
+
Args:
|
|
572
|
+
key: The key to look up or insert.
|
|
573
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
574
|
+
|
|
575
|
+
Warning:
|
|
576
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
577
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
578
|
+
propagates.
|
|
520
579
|
"""
|
|
521
580
|
...
|
|
522
581
|
|
|
@@ -697,15 +756,40 @@ class RRCache(BaseCacheImpl[KT, VT]):
|
|
|
697
756
|
default: typing.Optional[DT] = None,
|
|
698
757
|
) -> typing.Optional[VT | DT]:
|
|
699
758
|
"""
|
|
700
|
-
|
|
759
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
760
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
761
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
701
762
|
|
|
702
763
|
Args:
|
|
703
764
|
key: The key to look up or insert.
|
|
704
765
|
default: The value to insert if ``key`` is not in the cache.
|
|
705
766
|
Defaults to ``None``.
|
|
706
767
|
|
|
707
|
-
|
|
708
|
-
|
|
768
|
+
Note:
|
|
769
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
770
|
+
effectes.
|
|
771
|
+
"""
|
|
772
|
+
...
|
|
773
|
+
|
|
774
|
+
def setdefault_with(
|
|
775
|
+
self,
|
|
776
|
+
key: KT,
|
|
777
|
+
factory: typing.Callable[[], DT],
|
|
778
|
+
) -> VT | DT:
|
|
779
|
+
"""
|
|
780
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
781
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
782
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
783
|
+
result is inserted and returned.
|
|
784
|
+
|
|
785
|
+
Args:
|
|
786
|
+
key: The key to look up or insert.
|
|
787
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
788
|
+
|
|
789
|
+
Warning:
|
|
790
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
791
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
792
|
+
propagates.
|
|
709
793
|
"""
|
|
710
794
|
...
|
|
711
795
|
|
|
@@ -879,15 +963,40 @@ class LRUCache(BaseCacheImpl[KT, VT]):
|
|
|
879
963
|
default: typing.Optional[DT] = None,
|
|
880
964
|
) -> typing.Optional[VT | DT]:
|
|
881
965
|
"""
|
|
882
|
-
|
|
966
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
967
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
968
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
883
969
|
|
|
884
970
|
Args:
|
|
885
971
|
key: The key to look up or insert.
|
|
886
972
|
default: The value to insert if ``key`` is not in the cache.
|
|
887
973
|
Defaults to ``None``.
|
|
888
974
|
|
|
889
|
-
|
|
890
|
-
|
|
975
|
+
Note:
|
|
976
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
977
|
+
effectes.
|
|
978
|
+
"""
|
|
979
|
+
...
|
|
980
|
+
|
|
981
|
+
def setdefault_with(
|
|
982
|
+
self,
|
|
983
|
+
key: KT,
|
|
984
|
+
factory: typing.Callable[[], DT],
|
|
985
|
+
) -> VT | DT:
|
|
986
|
+
"""
|
|
987
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
988
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
989
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
990
|
+
result is inserted and returned.
|
|
991
|
+
|
|
992
|
+
Args:
|
|
993
|
+
key: The key to look up or insert.
|
|
994
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
995
|
+
|
|
996
|
+
Warning:
|
|
997
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
998
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
999
|
+
propagates.
|
|
891
1000
|
"""
|
|
892
1001
|
...
|
|
893
1002
|
|
|
@@ -1102,15 +1211,40 @@ class LFUCache(BaseCacheImpl[KT, VT]):
|
|
|
1102
1211
|
default: typing.Optional[DT] = None,
|
|
1103
1212
|
) -> typing.Optional[VT | DT]:
|
|
1104
1213
|
"""
|
|
1105
|
-
|
|
1214
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
1215
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
1216
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
1106
1217
|
|
|
1107
1218
|
Args:
|
|
1108
1219
|
key: The key to look up or insert.
|
|
1109
1220
|
default: The value to insert if ``key`` is not in the cache.
|
|
1110
1221
|
Defaults to ``None``.
|
|
1111
1222
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1223
|
+
Note:
|
|
1224
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
1225
|
+
effectes.
|
|
1226
|
+
"""
|
|
1227
|
+
...
|
|
1228
|
+
|
|
1229
|
+
def setdefault_with(
|
|
1230
|
+
self,
|
|
1231
|
+
key: KT,
|
|
1232
|
+
factory: typing.Callable[[], DT],
|
|
1233
|
+
) -> VT | DT:
|
|
1234
|
+
"""
|
|
1235
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
1236
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
1237
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
1238
|
+
result is inserted and returned.
|
|
1239
|
+
|
|
1240
|
+
Args:
|
|
1241
|
+
key: The key to look up or insert.
|
|
1242
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
1243
|
+
|
|
1244
|
+
Warning:
|
|
1245
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
1246
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
1247
|
+
propagates.
|
|
1114
1248
|
"""
|
|
1115
1249
|
...
|
|
1116
1250
|
|
|
@@ -1284,15 +1418,40 @@ class TTLCache(BaseCacheImpl[KT, VT]):
|
|
|
1284
1418
|
default: typing.Optional[DT] = None,
|
|
1285
1419
|
) -> typing.Optional[VT | DT]:
|
|
1286
1420
|
"""
|
|
1287
|
-
|
|
1421
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
1422
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
1423
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
1288
1424
|
|
|
1289
1425
|
Args:
|
|
1290
1426
|
key: The key to look up or insert.
|
|
1291
1427
|
default: The value to insert if ``key`` is not in the cache.
|
|
1292
1428
|
Defaults to ``None``.
|
|
1293
1429
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1430
|
+
Note:
|
|
1431
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
1432
|
+
effectes.
|
|
1433
|
+
"""
|
|
1434
|
+
...
|
|
1435
|
+
|
|
1436
|
+
def setdefault_with(
|
|
1437
|
+
self,
|
|
1438
|
+
key: KT,
|
|
1439
|
+
factory: typing.Callable[[], DT],
|
|
1440
|
+
) -> VT | DT:
|
|
1441
|
+
"""
|
|
1442
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
1443
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
1444
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
1445
|
+
result is inserted and returned.
|
|
1446
|
+
|
|
1447
|
+
Args:
|
|
1448
|
+
key: The key to look up or insert.
|
|
1449
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
1450
|
+
|
|
1451
|
+
Warning:
|
|
1452
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
1453
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
1454
|
+
propagates.
|
|
1296
1455
|
"""
|
|
1297
1456
|
...
|
|
1298
1457
|
|
|
@@ -1524,16 +1683,43 @@ class VTTLCache(BaseCacheImpl[KT, VT]):
|
|
|
1524
1683
|
ttl: float | timedelta | datetime | None = None,
|
|
1525
1684
|
) -> typing.Optional[VT | DT]:
|
|
1526
1685
|
"""
|
|
1527
|
-
|
|
1686
|
+
Get `key`s value, or atomatically insert `default` and return it.
|
|
1687
|
+
If `key` exists, its current value is returned and `default` is ignored.
|
|
1688
|
+
Otherwise `default` is inserted for `key` and returned.
|
|
1689
|
+
|
|
1690
|
+
Note:
|
|
1691
|
+
Use `setdefault_with`, if computing the value is expensive or has side
|
|
1692
|
+
effectes.
|
|
1528
1693
|
|
|
1529
1694
|
Args:
|
|
1530
1695
|
key: The key to look up or insert.
|
|
1531
1696
|
default: The value to insert if ``key`` is not in the cache.
|
|
1532
1697
|
Defaults to ``None``.
|
|
1533
|
-
ttl: An optional time-to-live duration for
|
|
1698
|
+
ttl: An optional time-to-live duration for item.
|
|
1699
|
+
"""
|
|
1700
|
+
...
|
|
1534
1701
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1702
|
+
def setdefault_with(
|
|
1703
|
+
self,
|
|
1704
|
+
key: KT,
|
|
1705
|
+
factory: typing.Callable[[], DT],
|
|
1706
|
+
ttl: float | timedelta | datetime | None = None,
|
|
1707
|
+
) -> VT | DT:
|
|
1708
|
+
"""
|
|
1709
|
+
Get `key`s value, or atomatically create and insert one via `factory`.
|
|
1710
|
+
If `key` exists, its current value is returned and `factory` is not called.
|
|
1711
|
+
Otherwise `factory` is called exactly once under an internal lock, its
|
|
1712
|
+
result is inserted and returned.
|
|
1713
|
+
|
|
1714
|
+
Args:
|
|
1715
|
+
key: The key to look up or insert.
|
|
1716
|
+
factory: The factory to call and get default value from if ``key`` is not in the cache.
|
|
1717
|
+
ttl: An optional time-to-live duration for item.
|
|
1718
|
+
|
|
1719
|
+
Warning:
|
|
1720
|
+
`factory` must not call back into this cache (deadlock risk) or block
|
|
1721
|
+
for long. If `factory` raises, nothing is inserted and the exception
|
|
1722
|
+
propagates.
|
|
1537
1723
|
"""
|
|
1538
1724
|
...
|
|
1539
1725
|
|
|
@@ -3,7 +3,7 @@ import typing
|
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
5
5
|
|
|
6
|
-
from cachebox import BaseCacheImpl
|
|
6
|
+
from cachebox._core import BaseCacheImpl, Cache
|
|
7
7
|
|
|
8
8
|
_PostProcess: typing.TypeAlias = typing.Callable[[typing.Any], typing.Any]
|
|
9
9
|
_Callback: typing.TypeAlias = typing.Callable[[int, typing.Any, typing.Any], typing.Any]
|
|
@@ -71,7 +71,9 @@ def _cached_wrapper_without_lock(
|
|
|
71
71
|
|
|
72
72
|
# Per-instance caches receive `self` as args[0]; exclude it from the ke
|
|
73
73
|
_make_key = (
|
|
74
|
-
(lambda a, k: key_maker(*a[1:], **k))
|
|
74
|
+
(lambda a, k: key_maker(*a[1:], **k))
|
|
75
|
+
if cache_is_fn
|
|
76
|
+
else (lambda a, k: key_maker(*a, **k))
|
|
75
77
|
)
|
|
76
78
|
|
|
77
79
|
hits = 0
|
|
@@ -143,7 +145,9 @@ def _async_cached_wrapper_without_lock(
|
|
|
143
145
|
|
|
144
146
|
# Per-instance caches receive `self` as args[0]; exclude it from the ke
|
|
145
147
|
_make_key = (
|
|
146
|
-
(lambda a, k: key_maker(*a[1:], **k))
|
|
148
|
+
(lambda a, k: key_maker(*a[1:], **k))
|
|
149
|
+
if cache_is_fn
|
|
150
|
+
else (lambda a, k: key_maker(*a, **k))
|
|
147
151
|
)
|
|
148
152
|
|
|
149
153
|
hits = 0
|
|
@@ -205,13 +209,15 @@ def _cached_wrapper(
|
|
|
205
209
|
|
|
206
210
|
# Per-instance caches receive `self` as args[0]; exclude it from the key
|
|
207
211
|
_make_key = (
|
|
208
|
-
(lambda a, k: key_maker(*a[1:], **k))
|
|
212
|
+
(lambda a, k: key_maker(*a[1:], **k))
|
|
213
|
+
if cache_is_fn
|
|
214
|
+
else (lambda a, k: key_maker(*a, **k))
|
|
209
215
|
)
|
|
210
216
|
|
|
211
217
|
hits = 0
|
|
212
218
|
misses = 0
|
|
213
219
|
|
|
214
|
-
locks:
|
|
220
|
+
locks: Cache[typing.Hashable, _Lock] = Cache(0)
|
|
215
221
|
pending_errors: dict[typing.Hashable, BaseException] = {}
|
|
216
222
|
|
|
217
223
|
def _wrapped(*args, **kwds):
|
|
@@ -237,9 +243,7 @@ def _cached_wrapper(
|
|
|
237
243
|
except KeyError:
|
|
238
244
|
pass
|
|
239
245
|
|
|
240
|
-
lock = locks.
|
|
241
|
-
if lock is None:
|
|
242
|
-
locks[key] = lock = _Lock(lock_type())
|
|
246
|
+
lock = locks.setdefault_with(key, lambda: _Lock(lock_type()))
|
|
243
247
|
|
|
244
248
|
# Acquire the per-key lock so that only one task computes the value
|
|
245
249
|
# while the rest wait.
|
|
@@ -307,12 +311,37 @@ def _async_cached_wrapper(
|
|
|
307
311
|
):
|
|
308
312
|
cache_is_fn = callable(cache)
|
|
309
313
|
_make_key = (
|
|
310
|
-
(lambda a, k: key_maker(*a[1:], **k))
|
|
314
|
+
(lambda a, k: key_maker(*a[1:], **k))
|
|
315
|
+
if cache_is_fn
|
|
316
|
+
else (lambda a, k: key_maker(*a, **k))
|
|
311
317
|
)
|
|
312
318
|
|
|
313
319
|
hits = 0
|
|
314
320
|
misses = 0
|
|
315
|
-
|
|
321
|
+
|
|
322
|
+
# See _cached_wrapper
|
|
323
|
+
locks: Cache[typing.Hashable, _AsyncLock] = Cache(0)
|
|
324
|
+
|
|
325
|
+
# if lock_type is asyncio.Lock:
|
|
326
|
+
|
|
327
|
+
# async def _get_lock(key: typing.Hashable):
|
|
328
|
+
# return locks.setdefault(key, _AsyncLock(lock_type()))
|
|
329
|
+
|
|
330
|
+
# else:
|
|
331
|
+
# _lock_creation_guard = asyncio.Lock()
|
|
332
|
+
|
|
333
|
+
# async def _get_lock(key: typing.Hashable):
|
|
334
|
+
# lock = locks.get(key)
|
|
335
|
+
# if lock is not None:
|
|
336
|
+
# return lock
|
|
337
|
+
|
|
338
|
+
# async with _lock_creation_guard:
|
|
339
|
+
# lock = locks.get(key)
|
|
340
|
+
# if lock is None:
|
|
341
|
+
# locks[key] = lock = _AsyncLock(lock_type())
|
|
342
|
+
|
|
343
|
+
# return lock
|
|
344
|
+
|
|
316
345
|
pending_errors: dict[typing.Hashable, BaseException] = {}
|
|
317
346
|
|
|
318
347
|
async def _wrapped(*args, **kwds):
|
|
@@ -335,9 +364,7 @@ def _async_cached_wrapper(
|
|
|
335
364
|
except KeyError:
|
|
336
365
|
pass
|
|
337
366
|
|
|
338
|
-
lock = locks.
|
|
339
|
-
if lock is None:
|
|
340
|
-
locks[key] = lock = _AsyncLock(lock_type())
|
|
367
|
+
lock = locks.setdefault_with(key, lambda: _AsyncLock(lock_type()))
|
|
341
368
|
|
|
342
369
|
async with lock:
|
|
343
370
|
err = pending_errors.get(key)
|