cachebox 6.2.5__tar.gz → 6.2.7__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.2.5 → cachebox-6.2.7}/.github/workflows/CI.yml +29 -21
- {cachebox-6.2.5 → cachebox-6.2.7}/.github/workflows/docs.yml +1 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/.github/workflows/python-test.yml +3 -3
- {cachebox-6.2.5 → cachebox-6.2.7}/Cargo.lock +13 -13
- {cachebox-6.2.5 → cachebox-6.2.7}/Cargo.toml +1 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/PKG-INFO +1 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/cachebox/_cachebox.py +18 -16
- {cachebox-6.2.5 → cachebox-6.2.7}/cachebox/_wrappers.py +20 -18
- {cachebox-6.2.5 → cachebox-6.2.7}/cachebox/utils.py +22 -30
- cachebox-6.2.7/docs/docs/algorithms.md +280 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/docs/docs/api/impls.md +10 -2
- cachebox-6.2.7/docs/docs/api/index.md +71 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/docs/docs/api/utils.md +20 -0
- cachebox-6.2.7/docs/docs/faq.md +164 -0
- cachebox-6.2.7/docs/docs/getting-started.md +421 -0
- cachebox-6.2.7/docs/docs/index.md +94 -0
- cachebox-6.2.7/docs/docs/installation.md +58 -0
- cachebox-6.2.7/docs/docs/migration.md +156 -0
- cachebox-6.2.7/docs/docs/tips.md +361 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/docs/mkdocs.yml +4 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/fifopolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/lfupolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/lrupolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/nopolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/rrpolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/traits.rs +1 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/ttlpolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/vttlpolicy.rs +2 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/wrapped.rs +12 -2
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/cache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/fifocache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/lfucache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/lrucache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/rrcache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/ttlcache.rs +3 -1
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/vttlcache.rs +3 -1
- cachebox-6.2.7/tests/__init__.py +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/tests/mixins.py +92 -10
- {cachebox-6.2.5 → cachebox-6.2.7}/typos.toml +1 -7
- cachebox-6.2.5/docs/docs/api/index.md +0 -4
- cachebox-6.2.5/docs/docs/getting-started.md +0 -322
- cachebox-6.2.5/docs/docs/index.md +0 -76
- cachebox-6.2.5/docs/docs/installation.md +0 -32
- cachebox-6.2.5/docs/docs/migration.md +0 -140
- cachebox-6.2.5/docs/docs/tips.md +0 -310
- {cachebox-6.2.5 → cachebox-6.2.7}/.github/dependabot.yaml +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/.gitignore +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/LICENSE +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/LICENSE-THIRD-PARTY +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/README.md +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/build.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/cachebox/__init__.py +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/cachebox/_core.pyi +0 -0
- /cachebox-6.2.5/tests/__init__.py → /cachebox-6.2.7/cachebox/py.typed +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/pyproject.toml +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/rust-toolchain.toml +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/rustfmt.toml +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/alloc.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/bitmask.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/group/generic.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/group/lsx.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/group/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/group/neon.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/group/sse2.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/control/tag.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/raw.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/scopeguard.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/hashbrown/util.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/alias.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/lazyheap.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/linked_list.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/onceinit.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/pickle.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/internal/utils.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/lib.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/macro_rules.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/common.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/policies/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/base.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/pyclasses/mod.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/src/typeref.rs +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/tests/conftest.py +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/tests/test_impls.py +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/tests/test_utils.py +0 -0
- {cachebox-6.2.5 → cachebox-6.2.7}/uv.lock +0 -0
|
@@ -16,6 +16,7 @@ concurrency:
|
|
|
16
16
|
env:
|
|
17
17
|
(^_^): &interpreters "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t pypy3.11"
|
|
18
18
|
○_○: &interpreters_without_pypy "3.10 3.11 3.12 3.13 3.14 3.14t 3.15 3.15t"
|
|
19
|
+
(o_o): &interpreters_win_arm64 "3.11 3.12 3.13 3.14 3.14t 3.15 3.15t"
|
|
19
20
|
|
|
20
21
|
jobs:
|
|
21
22
|
tools:
|
|
@@ -41,7 +42,7 @@ jobs:
|
|
|
41
42
|
python-version: "3.14"
|
|
42
43
|
|
|
43
44
|
- name: "Install uv"
|
|
44
|
-
uses: astral-sh/setup-uv@
|
|
45
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
45
46
|
with:
|
|
46
47
|
# zizmor: ignore[cache-poisoning]
|
|
47
48
|
enable-cache: ${{ github.event_name == 'pull_request' }}
|
|
@@ -57,21 +58,24 @@ jobs:
|
|
|
57
58
|
strategy:
|
|
58
59
|
matrix:
|
|
59
60
|
platform:
|
|
60
|
-
- { target: x86_64, interpreter: *interpreters }
|
|
61
|
-
- { target: x86, interpreter: *interpreters }
|
|
62
|
-
- { target: aarch64, interpreter: *interpreters }
|
|
63
|
-
- { target: armv7, interpreter: *interpreters }
|
|
64
|
-
- { target: s390x, interpreter: *interpreters }
|
|
65
|
-
- { target: ppc64le, interpreter: *interpreters }
|
|
61
|
+
- { target: x86_64-unknown-linux-gnu, arch: x86_64, interpreter: *interpreters }
|
|
62
|
+
- { target: i686-unknown-linux-gnu, arch: x86, interpreter: *interpreters }
|
|
63
|
+
- { target: aarch64-unknown-linux-gnu, arch: aarch64, interpreter: *interpreters }
|
|
64
|
+
- { target: armv7-unknown-linux-gnueabihf, arch: armv7, interpreter: *interpreters }
|
|
65
|
+
- { target: s390x-unknown-linux-gnu, arch: s390x, interpreter: *interpreters }
|
|
66
|
+
- { target: powerpc64le-unknown-linux-gnu, arch: ppc64le, interpreter: *interpreters }
|
|
67
|
+
- { target: riscv64gc-unknown-linux-gnu, arch: riscv64, interpreter: *interpreters }
|
|
66
68
|
|
|
67
69
|
steps:
|
|
68
70
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
69
71
|
with:
|
|
70
72
|
persist-credentials: false
|
|
71
73
|
|
|
72
|
-
- uses:
|
|
74
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
73
75
|
with:
|
|
74
|
-
|
|
76
|
+
activate-environment: true
|
|
77
|
+
enable-cache: false
|
|
78
|
+
python-version: "3"
|
|
75
79
|
|
|
76
80
|
- uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
|
|
77
81
|
# zizmor: ignore[cache-poisoning]
|
|
@@ -87,7 +91,7 @@ jobs:
|
|
|
87
91
|
|
|
88
92
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
89
93
|
with:
|
|
90
|
-
name: wheels-linux-${{ matrix.platform.
|
|
94
|
+
name: wheels-linux-${{ matrix.platform.arch }}
|
|
91
95
|
path: dist
|
|
92
96
|
|
|
93
97
|
build-musllinux:
|
|
@@ -95,19 +99,22 @@ jobs:
|
|
|
95
99
|
strategy:
|
|
96
100
|
matrix:
|
|
97
101
|
platform:
|
|
98
|
-
- { target: x86_64, interpreter: *interpreters }
|
|
99
|
-
- { target: x86, interpreter: *interpreters }
|
|
100
|
-
- { target: aarch64, interpreter: *interpreters }
|
|
101
|
-
- { target: armv7, interpreter: *interpreters }
|
|
102
|
+
- { target: x86_64-unknown-linux-musl, arch: x86_64, interpreter: *interpreters }
|
|
103
|
+
- { target: i686-unknown-linux-musl, arch: x86, interpreter: *interpreters }
|
|
104
|
+
- { target: aarch64-unknown-linux-musl, arch: aarch64, interpreter: *interpreters }
|
|
105
|
+
- { target: armv7-unknown-linux-musleabihf, arch: armv7, interpreter: *interpreters }
|
|
106
|
+
- { target: riscv64gc-unknown-linux-musl, arch: riscv64, interpreter: *interpreters }
|
|
102
107
|
|
|
103
108
|
steps:
|
|
104
109
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
105
110
|
with:
|
|
106
111
|
persist-credentials: false
|
|
107
112
|
|
|
108
|
-
- uses:
|
|
113
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
109
114
|
with:
|
|
110
|
-
|
|
115
|
+
activate-environment: true
|
|
116
|
+
enable-cache: false
|
|
117
|
+
python-version: "3"
|
|
111
118
|
|
|
112
119
|
- uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
|
|
113
120
|
# zizmor: ignore[cache-poisoning]
|
|
@@ -123,16 +130,17 @@ jobs:
|
|
|
123
130
|
|
|
124
131
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
125
132
|
with:
|
|
126
|
-
name: wheels-musllinux-${{ matrix.platform.
|
|
133
|
+
name: wheels-musllinux-${{ matrix.platform.arch }}
|
|
127
134
|
path: dist
|
|
128
135
|
|
|
129
136
|
build-windows:
|
|
130
|
-
runs-on:
|
|
137
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
131
138
|
strategy:
|
|
132
139
|
matrix:
|
|
133
140
|
platform:
|
|
134
|
-
- { target: x64, interpreter: *interpreters }
|
|
135
|
-
- { target: x86, interpreter: *interpreters_without_pypy }
|
|
141
|
+
- { runner: windows-latest, target: x64, arch: x64, interpreter: *interpreters }
|
|
142
|
+
- { runner: windows-latest, target: x86, arch: x86, interpreter: *interpreters_without_pypy }
|
|
143
|
+
- { runner: windows-11-arm, target: aarch64, arch: arm64, interpreter: *interpreters_win_arm64 }
|
|
136
144
|
|
|
137
145
|
steps:
|
|
138
146
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
@@ -142,7 +150,7 @@ jobs:
|
|
|
142
150
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
143
151
|
with:
|
|
144
152
|
python-version: "3.x"
|
|
145
|
-
architecture: ${{ matrix.platform.
|
|
153
|
+
architecture: ${{ matrix.platform.arch }}
|
|
146
154
|
|
|
147
155
|
- uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
|
|
148
156
|
# zizmor: ignore[cache-poisoning]
|
|
@@ -40,7 +40,7 @@ jobs:
|
|
|
40
40
|
|
|
41
41
|
- uses: dtolnay/rust-toolchain@stable # zizmor: ignore[unpinned-uses]
|
|
42
42
|
|
|
43
|
-
- uses: Swatinem/rust-cache@
|
|
43
|
+
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
44
44
|
if: github.event_name == 'pull_request' && github.run_attempt == 1
|
|
45
45
|
with:
|
|
46
46
|
lookup-only: false # zizmor: ignore[cache-poisoning]
|
|
@@ -52,7 +52,7 @@ jobs:
|
|
|
52
52
|
allow-prereleases: true
|
|
53
53
|
|
|
54
54
|
- name: "Install uv"
|
|
55
|
-
uses: astral-sh/setup-uv@
|
|
55
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
56
56
|
with:
|
|
57
57
|
enable-cache: false
|
|
58
58
|
|
|
@@ -93,7 +93,7 @@ jobs:
|
|
|
93
93
|
python-version: "3.13"
|
|
94
94
|
|
|
95
95
|
- name: "Install uv"
|
|
96
|
-
uses: astral-sh/setup-uv@
|
|
96
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
97
97
|
with:
|
|
98
98
|
enable-cache: false
|
|
99
99
|
|
|
@@ -37,7 +37,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
|
37
37
|
|
|
38
38
|
[[package]]
|
|
39
39
|
name = "cachebox"
|
|
40
|
-
version = "6.2.
|
|
40
|
+
version = "6.2.7"
|
|
41
41
|
dependencies = [
|
|
42
42
|
"allocator-api2",
|
|
43
43
|
"cfg-if",
|
|
@@ -50,9 +50,9 @@ dependencies = [
|
|
|
50
50
|
|
|
51
51
|
[[package]]
|
|
52
52
|
name = "cc"
|
|
53
|
-
version = "1.4.
|
|
53
|
+
version = "1.4.4"
|
|
54
54
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
55
|
-
checksum = "
|
|
55
|
+
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
|
|
56
56
|
dependencies = [
|
|
57
57
|
"find-msvc-tools",
|
|
58
58
|
"shlex",
|
|
@@ -91,27 +91,27 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
|
|
91
91
|
|
|
92
92
|
[[package]]
|
|
93
93
|
name = "find-msvc-tools"
|
|
94
|
-
version = "0.1.
|
|
94
|
+
version = "0.1.11"
|
|
95
95
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
96
|
-
checksum = "
|
|
96
|
+
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
|
|
97
97
|
|
|
98
98
|
[[package]]
|
|
99
99
|
name = "futures-core"
|
|
100
|
-
version = "0.3.
|
|
100
|
+
version = "0.3.34"
|
|
101
101
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
102
|
-
checksum = "
|
|
102
|
+
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
|
103
103
|
|
|
104
104
|
[[package]]
|
|
105
105
|
name = "futures-task"
|
|
106
|
-
version = "0.3.
|
|
106
|
+
version = "0.3.34"
|
|
107
107
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
108
|
-
checksum = "
|
|
108
|
+
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
|
109
109
|
|
|
110
110
|
[[package]]
|
|
111
111
|
name = "futures-util"
|
|
112
|
-
version = "0.3.
|
|
112
|
+
version = "0.3.34"
|
|
113
113
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
114
|
-
checksum = "
|
|
114
|
+
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
|
115
115
|
dependencies = [
|
|
116
116
|
"futures-core",
|
|
117
117
|
"futures-task",
|
|
@@ -177,9 +177,9 @@ dependencies = [
|
|
|
177
177
|
|
|
178
178
|
[[package]]
|
|
179
179
|
name = "log"
|
|
180
|
-
version = "0.4.
|
|
180
|
+
version = "0.4.34"
|
|
181
181
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
182
|
-
checksum = "
|
|
182
|
+
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
|
183
183
|
|
|
184
184
|
[[package]]
|
|
185
185
|
name = "num-traits"
|
|
@@ -161,16 +161,15 @@ class TTLCache(_CoreTTLCache[KT, VT]):
|
|
|
161
161
|
)
|
|
162
162
|
|
|
163
163
|
self._thread: threading.Thread | None = None
|
|
164
|
-
self.
|
|
164
|
+
self._stop_event = threading.Event()
|
|
165
165
|
|
|
166
166
|
if sweep_interval is not None:
|
|
167
167
|
if isinstance(sweep_interval, timedelta):
|
|
168
168
|
sweep_interval = sweep_interval.total_seconds()
|
|
169
169
|
|
|
170
170
|
if sweep_interval < 1:
|
|
171
|
-
raise ValueError("sweep_interval must be
|
|
171
|
+
raise ValueError("sweep_interval must be at least 1 second.")
|
|
172
172
|
|
|
173
|
-
self._thread_is_running = True
|
|
174
173
|
self._thread = threading.Thread(
|
|
175
174
|
target=self._sweeper_thread,
|
|
176
175
|
args=(sweep_interval,),
|
|
@@ -185,17 +184,19 @@ class TTLCache(_CoreTTLCache[KT, VT]):
|
|
|
185
184
|
"""The configured ``sweep_interval`` in seconds."""
|
|
186
185
|
return self._sweep_interval
|
|
187
186
|
|
|
188
|
-
def _sweeper_thread(self, interval: float):
|
|
189
|
-
while self.
|
|
190
|
-
time.sleep(interval)
|
|
187
|
+
def _sweeper_thread(self, interval: float) -> None:
|
|
188
|
+
while not self._stop_event.wait(interval):
|
|
191
189
|
self.expire()
|
|
192
190
|
|
|
193
191
|
def stop_sweeper(self) -> None:
|
|
194
192
|
"""Signals the background sweeper thread to stop, if one is active."""
|
|
195
|
-
self.
|
|
193
|
+
self._stop_event.set()
|
|
196
194
|
|
|
197
195
|
def __del__(self) -> None:
|
|
198
|
-
|
|
196
|
+
# If super().__init__ raises for any reason (bad arguments, type error, ...),
|
|
197
|
+
# the assignment to self._stop_event never happens.
|
|
198
|
+
if hasattr(self, "_stop_event"):
|
|
199
|
+
self.stop_sweeper()
|
|
199
200
|
|
|
200
201
|
|
|
201
202
|
class VTTLCache(_CoreVTTLCache[KT, VT]):
|
|
@@ -333,16 +334,15 @@ class VTTLCache(_CoreVTTLCache[KT, VT]):
|
|
|
333
334
|
)
|
|
334
335
|
|
|
335
336
|
self._thread: threading.Thread | None = None
|
|
336
|
-
self.
|
|
337
|
+
self._stop_event = threading.Event()
|
|
337
338
|
|
|
338
339
|
if sweep_interval is not None:
|
|
339
340
|
if isinstance(sweep_interval, timedelta):
|
|
340
341
|
sweep_interval = sweep_interval.total_seconds()
|
|
341
342
|
|
|
342
343
|
if sweep_interval < 1:
|
|
343
|
-
raise ValueError("sweep_interval must be
|
|
344
|
+
raise ValueError("sweep_interval must be at least 1 second.")
|
|
344
345
|
|
|
345
|
-
self._thread_is_running = True
|
|
346
346
|
self._thread = threading.Thread(
|
|
347
347
|
target=self._sweeper_thread,
|
|
348
348
|
args=(sweep_interval,),
|
|
@@ -357,14 +357,16 @@ class VTTLCache(_CoreVTTLCache[KT, VT]):
|
|
|
357
357
|
"""The configured ``sweep_interval`` in seconds."""
|
|
358
358
|
return self._sweep_interval
|
|
359
359
|
|
|
360
|
-
def _sweeper_thread(self, interval: float):
|
|
361
|
-
while self.
|
|
362
|
-
time.sleep(interval)
|
|
360
|
+
def _sweeper_thread(self, interval: float) -> None:
|
|
361
|
+
while not self._stop_event.wait(interval):
|
|
363
362
|
self.expire()
|
|
364
363
|
|
|
365
364
|
def stop_sweeper(self) -> None:
|
|
366
365
|
"""Signals the background sweeper thread to stop, if one is active."""
|
|
367
|
-
self.
|
|
366
|
+
self._stop_event.set()
|
|
368
367
|
|
|
369
368
|
def __del__(self) -> None:
|
|
370
|
-
|
|
369
|
+
# If super().__init__ raises for any reason (bad arguments, type error, ...),
|
|
370
|
+
# the assignment to self._stop_event never happens.
|
|
371
|
+
if hasattr(self, "_stop_event"):
|
|
372
|
+
self.stop_sweeper()
|
|
@@ -2,12 +2,14 @@ import inspect
|
|
|
2
2
|
import typing
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
5
|
+
from collections.abc import Callable, Hashable
|
|
5
6
|
|
|
6
7
|
from cachebox._core import BaseCacheImpl, Cache
|
|
7
8
|
|
|
8
|
-
_PostProcess: typing.TypeAlias =
|
|
9
|
-
_Callback: typing.TypeAlias =
|
|
10
|
-
|
|
9
|
+
_PostProcess: typing.TypeAlias = Callable[[typing.Any], typing.Any]
|
|
10
|
+
_Callback: typing.TypeAlias = Callable[
|
|
11
|
+
[int, typing.Any, typing.Any], typing.Any
|
|
12
|
+
]
|
|
11
13
|
|
|
12
14
|
class _Lock:
|
|
13
15
|
__slots__ = ("_lock", "waiters")
|
|
@@ -65,10 +67,10 @@ def _create_cache_info(cache, hits, misses) -> CacheInfo:
|
|
|
65
67
|
|
|
66
68
|
def _cached_wrapper_without_lock(
|
|
67
69
|
func,
|
|
68
|
-
cache: BaseCacheImpl |
|
|
69
|
-
key_maker:
|
|
70
|
+
cache: BaseCacheImpl | Callable,
|
|
71
|
+
key_maker: Callable[[tuple, dict], Hashable],
|
|
70
72
|
clear_reuse: bool,
|
|
71
|
-
callback:
|
|
73
|
+
callback: Callable[[int, typing.Any, typing.Any], None] | None,
|
|
72
74
|
postprocess: _PostProcess | None,
|
|
73
75
|
):
|
|
74
76
|
cache_is_fn = callable(cache)
|
|
@@ -139,10 +141,10 @@ async def _call_async_callback(callback, event, key, result):
|
|
|
139
141
|
|
|
140
142
|
def _async_cached_wrapper_without_lock(
|
|
141
143
|
func,
|
|
142
|
-
cache: BaseCacheImpl |
|
|
143
|
-
key_maker:
|
|
144
|
+
cache: BaseCacheImpl | Callable,
|
|
145
|
+
key_maker: Callable[[tuple, dict], Hashable],
|
|
144
146
|
clear_reuse: bool,
|
|
145
|
-
callback:
|
|
147
|
+
callback: Callable[[int, typing.Any, typing.Any], None] | None,
|
|
146
148
|
postprocess: _PostProcess | None,
|
|
147
149
|
):
|
|
148
150
|
cache_is_fn = callable(cache)
|
|
@@ -179,7 +181,7 @@ def _async_cached_wrapper_without_lock(
|
|
|
179
181
|
|
|
180
182
|
result = await func(*args, **kwds)
|
|
181
183
|
_cache.insert(key, result)
|
|
182
|
-
|
|
184
|
+
misses += 1
|
|
183
185
|
await _call_async_callback(callback, EVENT_MISS, key, result)
|
|
184
186
|
|
|
185
187
|
return postprocess(result) if postprocess is not None else result
|
|
@@ -202,12 +204,12 @@ def _async_cached_wrapper_without_lock(
|
|
|
202
204
|
|
|
203
205
|
def _cached_wrapper(
|
|
204
206
|
func,
|
|
205
|
-
cache: BaseCacheImpl |
|
|
206
|
-
key_maker:
|
|
207
|
+
cache: BaseCacheImpl | Callable,
|
|
208
|
+
key_maker: Callable[[tuple, dict], Hashable],
|
|
207
209
|
clear_reuse: bool,
|
|
208
|
-
callback:
|
|
210
|
+
callback: Callable[[int, typing.Any, typing.Any], None] | None,
|
|
209
211
|
postprocess: _PostProcess | None,
|
|
210
|
-
lock_type:
|
|
212
|
+
lock_type: type[AbstractContextManager],
|
|
211
213
|
):
|
|
212
214
|
cache_is_fn = callable(cache)
|
|
213
215
|
|
|
@@ -221,8 +223,8 @@ def _cached_wrapper(
|
|
|
221
223
|
hits = 0
|
|
222
224
|
misses = 0
|
|
223
225
|
|
|
224
|
-
locks: Cache[
|
|
225
|
-
pending_errors: dict[
|
|
226
|
+
locks: Cache[Hashable, _Lock] = Cache(0)
|
|
227
|
+
pending_errors: dict[Hashable, BaseException] = {}
|
|
226
228
|
|
|
227
229
|
def _wrapped(*args, **kwds):
|
|
228
230
|
nonlocal hits, misses
|
|
@@ -308,12 +310,12 @@ def _cached_wrapper(
|
|
|
308
310
|
|
|
309
311
|
def _async_cached_wrapper(
|
|
310
312
|
func,
|
|
311
|
-
cache: BaseCacheImpl |
|
|
313
|
+
cache: BaseCacheImpl | Callable,
|
|
312
314
|
key_maker: typing.Callable[..., typing.Hashable],
|
|
313
315
|
clear_reuse: bool,
|
|
314
316
|
callback: _Callback | None,
|
|
315
317
|
postprocess: _PostProcess | None,
|
|
316
|
-
lock_type:
|
|
318
|
+
lock_type: type[AbstractAsyncContextManager],
|
|
317
319
|
):
|
|
318
320
|
cache_is_fn = callable(cache)
|
|
319
321
|
_make_key = (
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import _thread
|
|
2
|
+
import asyncio
|
|
1
3
|
import functools
|
|
2
4
|
import inspect
|
|
5
|
+
import threading
|
|
3
6
|
import typing
|
|
7
|
+
from collections.abc import Callable, Hashable
|
|
8
|
+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
4
9
|
from copy import copy as _shallow_copy
|
|
5
10
|
from copy import deepcopy as _deep_copy
|
|
6
11
|
|
|
7
12
|
from ._cachebox import BaseCacheImpl, LRUCache
|
|
8
13
|
from ._wrappers import (
|
|
9
|
-
AbstractAsyncContextManager,
|
|
10
|
-
AbstractContextManager,
|
|
11
14
|
CacheInfo,
|
|
12
15
|
_async_cached_wrapper,
|
|
13
16
|
_async_cached_wrapper_without_lock,
|
|
@@ -23,7 +26,7 @@ if typing.TYPE_CHECKING:
|
|
|
23
26
|
KT = typing.TypeVar("KT")
|
|
24
27
|
VT = typing.TypeVar("VT")
|
|
25
28
|
DT = typing.TypeVar("DT")
|
|
26
|
-
FT = typing.TypeVar("FT", bound=
|
|
29
|
+
FT = typing.TypeVar("FT", bound=Callable[..., typing.Any])
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
_COPY_TYPES = frozenset((dict, list, set))
|
|
@@ -63,7 +66,7 @@ _KWDS_MARK = object()
|
|
|
63
66
|
_FAST_TYPES = frozenset((int, str))
|
|
64
67
|
|
|
65
68
|
|
|
66
|
-
def make_key(*args, **kwds) ->
|
|
69
|
+
def make_key(*args: typing.Any, **kwds: typing.Any) -> Hashable:
|
|
67
70
|
"""
|
|
68
71
|
Default cache key.
|
|
69
72
|
|
|
@@ -83,7 +86,7 @@ def make_key(*args, **kwds) -> typing.Hashable:
|
|
|
83
86
|
return key
|
|
84
87
|
|
|
85
88
|
|
|
86
|
-
def make_hash_key(*args, **kwds) -> int:
|
|
89
|
+
def make_hash_key(*args: typing.Any, **kwds: typing.Any) -> int:
|
|
87
90
|
"""
|
|
88
91
|
Key as the hash of all positional and keyword arguments.
|
|
89
92
|
|
|
@@ -98,7 +101,7 @@ def make_hash_key(*args, **kwds) -> int:
|
|
|
98
101
|
return hash(key)
|
|
99
102
|
|
|
100
103
|
|
|
101
|
-
def make_typed_key(*args, **kwds) -> tuple:
|
|
104
|
+
def make_typed_key(*args: typing.Any, **kwds: typing.Any) -> tuple[typing.Any, ...]:
|
|
102
105
|
"""
|
|
103
106
|
Key that includes the runtime type of every argument.
|
|
104
107
|
|
|
@@ -183,7 +186,7 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
183
186
|
return self.__cache.maxsize
|
|
184
187
|
|
|
185
188
|
@property
|
|
186
|
-
def getsizeof(self) ->
|
|
189
|
+
def getsizeof(self) -> Callable[[KT, VT], int] | None:
|
|
187
190
|
"""Callable or None: The configured ``getsizeof`` function."""
|
|
188
191
|
return self.__cache.getsizeof
|
|
189
192
|
|
|
@@ -271,7 +274,7 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
271
274
|
value: VT,
|
|
272
275
|
*args: typing.Any,
|
|
273
276
|
**kwargs: typing.Any,
|
|
274
|
-
) ->
|
|
277
|
+
) -> VT | None:
|
|
275
278
|
return self._guard()
|
|
276
279
|
|
|
277
280
|
def __setitem__(self, key: KT, value: VT) -> None:
|
|
@@ -285,7 +288,7 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
285
288
|
) -> None:
|
|
286
289
|
return self._guard()
|
|
287
290
|
|
|
288
|
-
def get(self, key: KT, default:
|
|
291
|
+
def get(self, key: KT, default: DT | None = None) -> VT | DT:
|
|
289
292
|
return self.__cache.get(key, default)
|
|
290
293
|
|
|
291
294
|
def __getitem__(self, key: KT) -> VT:
|
|
@@ -294,13 +297,13 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
294
297
|
def setdefault(
|
|
295
298
|
self,
|
|
296
299
|
key: KT,
|
|
297
|
-
default:
|
|
300
|
+
default: DT | None = None,
|
|
298
301
|
*args: typing.Any,
|
|
299
302
|
**kwargs: typing.Any,
|
|
300
|
-
) ->
|
|
303
|
+
) -> VT | DT | None:
|
|
301
304
|
return self._guard()
|
|
302
305
|
|
|
303
|
-
def pop(self, key: KT, default: DT = None) ->
|
|
306
|
+
def pop(self, key: KT, default: DT | None = None) -> VT | DT:
|
|
304
307
|
"""
|
|
305
308
|
Removes the specified key and returns the corresponding value.
|
|
306
309
|
|
|
@@ -319,7 +322,7 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
319
322
|
def __delitem__(self, key: KT) -> None:
|
|
320
323
|
return self._guard()
|
|
321
324
|
|
|
322
|
-
def popitem(self) ->
|
|
325
|
+
def popitem(self) -> tuple[KT, VT]:
|
|
323
326
|
return self._guard() # type: ignore[return-value]
|
|
324
327
|
|
|
325
328
|
def drain(self, n: int) -> int:
|
|
@@ -348,7 +351,7 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
348
351
|
"""
|
|
349
352
|
return self._guard()
|
|
350
353
|
|
|
351
|
-
def items(self) -> typing.Iterable[
|
|
354
|
+
def items(self) -> typing.Iterable[tuple[KT, VT]]:
|
|
352
355
|
return self.__cache.items()
|
|
353
356
|
|
|
354
357
|
def values(self) -> typing.Iterable[VT]:
|
|
@@ -373,20 +376,9 @@ class Frozen(BaseCacheImpl[KT, VT]): # pragma: no cover
|
|
|
373
376
|
def _cast_lock(
|
|
374
377
|
iscoroutinefunction: bool,
|
|
375
378
|
lock: (
|
|
376
|
-
|
|
377
|
-
| typing.Type[AbstractAsyncContextManager]
|
|
378
|
-
| bool
|
|
379
|
-
| None
|
|
379
|
+
type[AbstractContextManager] | type[AbstractAsyncContextManager] | bool | None
|
|
380
380
|
) = True,
|
|
381
|
-
) ->
|
|
382
|
-
typing.Type[AbstractContextManager]
|
|
383
|
-
| typing.Type[AbstractAsyncContextManager]
|
|
384
|
-
| None
|
|
385
|
-
):
|
|
386
|
-
import _thread
|
|
387
|
-
import asyncio
|
|
388
|
-
import threading
|
|
389
|
-
|
|
381
|
+
) -> type[AbstractContextManager] | type[AbstractAsyncContextManager] | None:
|
|
390
382
|
if lock is None or lock is False:
|
|
391
383
|
return None
|
|
392
384
|
|
|
@@ -416,8 +408,8 @@ def _cast_lock(
|
|
|
416
408
|
|
|
417
409
|
|
|
418
410
|
def cached(
|
|
419
|
-
cache: BaseCacheImpl | dict |
|
|
420
|
-
key_maker:
|
|
411
|
+
cache: BaseCacheImpl | dict | Callable[..., BaseCacheImpl] | None = None,
|
|
412
|
+
key_maker: Callable[..., Hashable] = make_key,
|
|
421
413
|
clear_reuse: bool = False,
|
|
422
414
|
callback: _Callback | None = None,
|
|
423
415
|
copy_level: int = 1,
|
|
@@ -428,7 +420,7 @@ def cached(
|
|
|
428
420
|
| bool
|
|
429
421
|
| None
|
|
430
422
|
) = True,
|
|
431
|
-
) ->
|
|
423
|
+
) -> Callable[[FT], FT]:
|
|
432
424
|
"""
|
|
433
425
|
Decorator to memoize function/method results.
|
|
434
426
|
|