rust-py-cache 0.1.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.
- rust_py_cache-0.1.1/.github/workflows/ci.yml +77 -0
- rust_py_cache-0.1.1/.github/workflows/release.yml +57 -0
- rust_py_cache-0.1.1/.gitignore +7 -0
- rust_py_cache-0.1.1/Cargo.lock +283 -0
- rust_py_cache-0.1.1/Cargo.toml +32 -0
- rust_py_cache-0.1.1/PKG-INFO +136 -0
- rust_py_cache-0.1.1/PUBLISHING.md +71 -0
- rust_py_cache-0.1.1/README.md +117 -0
- rust_py_cache-0.1.1/examples/django_example.py +63 -0
- rust_py_cache-0.1.1/examples/fastapi_example.py +62 -0
- rust_py_cache-0.1.1/pyproject.toml +33 -0
- rust_py_cache-0.1.1/python/rust_py_cache/__init__.py +22 -0
- rust_py_cache-0.1.1/python/rust_py_cache/decorators.py +64 -0
- rust_py_cache-0.1.1/src/cache.rs +226 -0
- rust_py_cache-0.1.1/src/entry.rs +47 -0
- rust_py_cache-0.1.1/src/lib.rs +181 -0
- rust_py_cache-0.1.1/src/stats.rs +69 -0
- rust_py_cache-0.1.1/src/ttl.rs +35 -0
- rust_py_cache-0.1.1/tests/test_cache_basic.py +23 -0
- rust_py_cache-0.1.1/tests/test_delete.py +33 -0
- rust_py_cache-0.1.1/tests/test_features.py +104 -0
- rust_py_cache-0.1.1/tests/test_set_get.py +65 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: cargo test + pytest
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest]
|
|
16
|
+
python-version: ["3.10", "3.12", "3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Set up Rust
|
|
26
|
+
uses: dtolnay/rust-toolchain@stable
|
|
27
|
+
|
|
28
|
+
- name: Cache cargo
|
|
29
|
+
uses: Swatinem/rust-cache@v2
|
|
30
|
+
|
|
31
|
+
# Testes do core Rust (puro, sem Python).
|
|
32
|
+
- name: cargo test
|
|
33
|
+
run: cargo test --verbose
|
|
34
|
+
|
|
35
|
+
# maturin develop exige um virtualenv ativo. O setup-python não cria um,
|
|
36
|
+
# então criamos o .venv e o exportamos para os próximos steps via
|
|
37
|
+
# GITHUB_ENV/GITHUB_PATH (cada step roda num shell novo).
|
|
38
|
+
- name: Create virtualenv
|
|
39
|
+
run: |
|
|
40
|
+
python -m venv .venv
|
|
41
|
+
echo "VIRTUAL_ENV=$PWD/.venv" >> "$GITHUB_ENV"
|
|
42
|
+
echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
|
|
43
|
+
|
|
44
|
+
- name: Install Python deps
|
|
45
|
+
run: |
|
|
46
|
+
python -m pip install --upgrade pip
|
|
47
|
+
pip install maturin pytest
|
|
48
|
+
|
|
49
|
+
# Compila a extensão e instala no .venv.
|
|
50
|
+
- name: maturin develop
|
|
51
|
+
run: maturin develop
|
|
52
|
+
|
|
53
|
+
- name: pytest
|
|
54
|
+
run: pytest -q
|
|
55
|
+
|
|
56
|
+
build-wheels:
|
|
57
|
+
name: build wheels (abi3)
|
|
58
|
+
runs-on: ${{ matrix.os }}
|
|
59
|
+
needs: test
|
|
60
|
+
strategy:
|
|
61
|
+
matrix:
|
|
62
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
- uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- name: Build wheels
|
|
69
|
+
uses: PyO3/maturin-action@v1
|
|
70
|
+
with:
|
|
71
|
+
command: build
|
|
72
|
+
args: --release --out dist
|
|
73
|
+
- name: Upload artifacts
|
|
74
|
+
uses: actions/upload-artifact@v4
|
|
75
|
+
with:
|
|
76
|
+
name: wheels-${{ matrix.os }}
|
|
77
|
+
path: dist
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Dispara ao publicar uma tag de versão (ex.: v0.1.0). Constrói as wheels para
|
|
4
|
+
# todas as plataformas + sdist e publica no PyPI via Trusted Publishing (OIDC),
|
|
5
|
+
# sem precisar guardar um token no repositório.
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags: ["v*"]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
name: build (${{ matrix.os }})
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
- name: Build wheels
|
|
26
|
+
uses: PyO3/maturin-action@v1
|
|
27
|
+
with:
|
|
28
|
+
command: build
|
|
29
|
+
args: --release --out dist
|
|
30
|
+
- name: Build sdist
|
|
31
|
+
if: matrix.os == 'ubuntu-latest'
|
|
32
|
+
uses: PyO3/maturin-action@v1
|
|
33
|
+
with:
|
|
34
|
+
command: sdist
|
|
35
|
+
args: --out dist
|
|
36
|
+
- uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: dist-${{ matrix.os }}
|
|
39
|
+
path: dist
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
name: publish to PyPI
|
|
43
|
+
needs: build
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
environment: pypi
|
|
46
|
+
permissions:
|
|
47
|
+
id-token: write # necessário para o Trusted Publishing (OIDC)
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/download-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
pattern: dist-*
|
|
52
|
+
merge-multiple: true
|
|
53
|
+
path: dist
|
|
54
|
+
- name: Publish
|
|
55
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
56
|
+
with:
|
|
57
|
+
packages-dir: dist
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "bitflags"
|
|
13
|
+
version = "2.13.0"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "cfg-if"
|
|
19
|
+
version = "1.0.4"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "crossbeam-utils"
|
|
25
|
+
version = "0.8.21"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "dashmap"
|
|
31
|
+
version = "6.2.1"
|
|
32
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
33
|
+
checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c"
|
|
34
|
+
dependencies = [
|
|
35
|
+
"cfg-if",
|
|
36
|
+
"crossbeam-utils",
|
|
37
|
+
"hashbrown",
|
|
38
|
+
"lock_api",
|
|
39
|
+
"once_cell",
|
|
40
|
+
"parking_lot_core",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[package]]
|
|
44
|
+
name = "hashbrown"
|
|
45
|
+
version = "0.14.5"
|
|
46
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
47
|
+
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
48
|
+
|
|
49
|
+
[[package]]
|
|
50
|
+
name = "heck"
|
|
51
|
+
version = "0.5.0"
|
|
52
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
53
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
54
|
+
|
|
55
|
+
[[package]]
|
|
56
|
+
name = "indoc"
|
|
57
|
+
version = "2.0.7"
|
|
58
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
59
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
60
|
+
dependencies = [
|
|
61
|
+
"rustversion",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "libc"
|
|
66
|
+
version = "0.2.186"
|
|
67
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "lock_api"
|
|
72
|
+
version = "0.4.14"
|
|
73
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
74
|
+
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
|
75
|
+
dependencies = [
|
|
76
|
+
"scopeguard",
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
[[package]]
|
|
80
|
+
name = "memoffset"
|
|
81
|
+
version = "0.9.1"
|
|
82
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
83
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
84
|
+
dependencies = [
|
|
85
|
+
"autocfg",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[[package]]
|
|
89
|
+
name = "once_cell"
|
|
90
|
+
version = "1.21.4"
|
|
91
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
92
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
93
|
+
|
|
94
|
+
[[package]]
|
|
95
|
+
name = "parking_lot_core"
|
|
96
|
+
version = "0.9.12"
|
|
97
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
98
|
+
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
|
99
|
+
dependencies = [
|
|
100
|
+
"cfg-if",
|
|
101
|
+
"libc",
|
|
102
|
+
"redox_syscall",
|
|
103
|
+
"smallvec",
|
|
104
|
+
"windows-link",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[[package]]
|
|
108
|
+
name = "portable-atomic"
|
|
109
|
+
version = "1.13.1"
|
|
110
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
111
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
112
|
+
|
|
113
|
+
[[package]]
|
|
114
|
+
name = "proc-macro2"
|
|
115
|
+
version = "1.0.106"
|
|
116
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
117
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
118
|
+
dependencies = [
|
|
119
|
+
"unicode-ident",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[[package]]
|
|
123
|
+
name = "pyo3"
|
|
124
|
+
version = "0.24.2"
|
|
125
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
126
|
+
checksum = "e5203598f366b11a02b13aa20cab591229ff0a89fd121a308a5df751d5fc9219"
|
|
127
|
+
dependencies = [
|
|
128
|
+
"cfg-if",
|
|
129
|
+
"indoc",
|
|
130
|
+
"libc",
|
|
131
|
+
"memoffset",
|
|
132
|
+
"once_cell",
|
|
133
|
+
"portable-atomic",
|
|
134
|
+
"pyo3-build-config",
|
|
135
|
+
"pyo3-ffi",
|
|
136
|
+
"pyo3-macros",
|
|
137
|
+
"unindent",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
[[package]]
|
|
141
|
+
name = "pyo3-build-config"
|
|
142
|
+
version = "0.24.2"
|
|
143
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
144
|
+
checksum = "99636d423fa2ca130fa5acde3059308006d46f98caac629418e53f7ebb1e9999"
|
|
145
|
+
dependencies = [
|
|
146
|
+
"once_cell",
|
|
147
|
+
"target-lexicon",
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
[[package]]
|
|
151
|
+
name = "pyo3-ffi"
|
|
152
|
+
version = "0.24.2"
|
|
153
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
154
|
+
checksum = "78f9cf92ba9c409279bc3305b5409d90db2d2c22392d443a87df3a1adad59e33"
|
|
155
|
+
dependencies = [
|
|
156
|
+
"libc",
|
|
157
|
+
"pyo3-build-config",
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
[[package]]
|
|
161
|
+
name = "pyo3-macros"
|
|
162
|
+
version = "0.24.2"
|
|
163
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
164
|
+
checksum = "0b999cb1a6ce21f9a6b147dcf1be9ffedf02e0043aec74dc390f3007047cecd9"
|
|
165
|
+
dependencies = [
|
|
166
|
+
"proc-macro2",
|
|
167
|
+
"pyo3-macros-backend",
|
|
168
|
+
"quote",
|
|
169
|
+
"syn",
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
[[package]]
|
|
173
|
+
name = "pyo3-macros-backend"
|
|
174
|
+
version = "0.24.2"
|
|
175
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
176
|
+
checksum = "822ece1c7e1012745607d5cf0bcb2874769f0f7cb34c4cde03b9358eb9ef911a"
|
|
177
|
+
dependencies = [
|
|
178
|
+
"heck",
|
|
179
|
+
"proc-macro2",
|
|
180
|
+
"pyo3-build-config",
|
|
181
|
+
"quote",
|
|
182
|
+
"syn",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "quote"
|
|
187
|
+
version = "1.0.45"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"proc-macro2",
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[[package]]
|
|
195
|
+
name = "redox_syscall"
|
|
196
|
+
version = "0.5.18"
|
|
197
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
198
|
+
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
|
199
|
+
dependencies = [
|
|
200
|
+
"bitflags",
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[[package]]
|
|
204
|
+
name = "rust_py_cache"
|
|
205
|
+
version = "0.1.1"
|
|
206
|
+
dependencies = [
|
|
207
|
+
"dashmap",
|
|
208
|
+
"pyo3",
|
|
209
|
+
"thiserror",
|
|
210
|
+
]
|
|
211
|
+
|
|
212
|
+
[[package]]
|
|
213
|
+
name = "rustversion"
|
|
214
|
+
version = "1.0.22"
|
|
215
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
216
|
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
217
|
+
|
|
218
|
+
[[package]]
|
|
219
|
+
name = "scopeguard"
|
|
220
|
+
version = "1.2.0"
|
|
221
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
222
|
+
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
223
|
+
|
|
224
|
+
[[package]]
|
|
225
|
+
name = "smallvec"
|
|
226
|
+
version = "1.15.2"
|
|
227
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
228
|
+
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
|
229
|
+
|
|
230
|
+
[[package]]
|
|
231
|
+
name = "syn"
|
|
232
|
+
version = "2.0.118"
|
|
233
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
234
|
+
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
|
235
|
+
dependencies = [
|
|
236
|
+
"proc-macro2",
|
|
237
|
+
"quote",
|
|
238
|
+
"unicode-ident",
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
[[package]]
|
|
242
|
+
name = "target-lexicon"
|
|
243
|
+
version = "0.13.5"
|
|
244
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
245
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
246
|
+
|
|
247
|
+
[[package]]
|
|
248
|
+
name = "thiserror"
|
|
249
|
+
version = "2.0.18"
|
|
250
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
251
|
+
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
|
252
|
+
dependencies = [
|
|
253
|
+
"thiserror-impl",
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
[[package]]
|
|
257
|
+
name = "thiserror-impl"
|
|
258
|
+
version = "2.0.18"
|
|
259
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
260
|
+
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
|
261
|
+
dependencies = [
|
|
262
|
+
"proc-macro2",
|
|
263
|
+
"quote",
|
|
264
|
+
"syn",
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
[[package]]
|
|
268
|
+
name = "unicode-ident"
|
|
269
|
+
version = "1.0.24"
|
|
270
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
271
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
272
|
+
|
|
273
|
+
[[package]]
|
|
274
|
+
name = "unindent"
|
|
275
|
+
version = "0.2.4"
|
|
276
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
277
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
|
278
|
+
|
|
279
|
+
[[package]]
|
|
280
|
+
name = "windows-link"
|
|
281
|
+
version = "0.2.1"
|
|
282
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
283
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "rust_py_cache"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
|
|
7
|
+
# Biblioteca de extensão para Python:
|
|
8
|
+
# - crate-type = ["cdylib"] -> gera um .so/.dylib carregável pelo Python
|
|
9
|
+
# - name = "_rust_py_cache" -> nome do módulo nativo (importado pelo __init__.py)
|
|
10
|
+
[lib]
|
|
11
|
+
name = "_rust_py_cache"
|
|
12
|
+
crate-type = ["cdylib"]
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
# abi3-py310: compila contra a Stable ABI do CPython 3.10+, gerando uma única
|
|
16
|
+
# wheel compatível com 3.10, 3.11, 3.12, 3.13...
|
|
17
|
+
# extension-module: não linka o binário do Python (o interpretador resolve em runtime).
|
|
18
|
+
pyo3 = { version = "0.24", features = ["abi3-py310", "extension-module"] }
|
|
19
|
+
|
|
20
|
+
# DashMap: HashMap concorrente (lock por shard). Permite get/set de várias threads
|
|
21
|
+
# Python sem um Mutex global no caminho crítico. Usado pelo RustCache (Etapa 4).
|
|
22
|
+
dashmap = "6"
|
|
23
|
+
|
|
24
|
+
# thiserror: deriva o trait std::error::Error para nossos erros (errors.rs),
|
|
25
|
+
# que depois convertemos em exceções Python.
|
|
26
|
+
thiserror = "2"
|
|
27
|
+
|
|
28
|
+
# --- Reservado para a v0.2 (NÃO incluso ainda para evitar dependência morta) ---
|
|
29
|
+
# serde = { version = "1", features = ["derive"] } # serializer JSON
|
|
30
|
+
# serde_json = "1" # serializer JSON
|
|
31
|
+
# No MVP o TTL usa std::time::SystemTime (epoch em ms), então o crate `time`
|
|
32
|
+
# também não é necessário ainda.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rust-py-cache
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
9
|
+
Classifier: Topic :: Database
|
|
10
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
11
|
+
Summary: An ultra-fast local cache for Python, powered by Rust.
|
|
12
|
+
Keywords: cache,rust,pyo3,ttl,performance
|
|
13
|
+
Author-email: Roberto Lima <robertolima.izphera@gmail.com>
|
|
14
|
+
License: MIT
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Homepage, https://github.com/robertolima/rust-py-cache
|
|
18
|
+
|
|
19
|
+
# rust-py-cache
|
|
20
|
+
|
|
21
|
+
> **An ultra-fast local cache for Python, powered by Rust.**
|
|
22
|
+
|
|
23
|
+
A local, in-memory, thread-safe cache with TTL, lazy expiration, and metrics. The
|
|
24
|
+
core is written in Rust (PyO3 + maturin) on top of a concurrent `DashMap`; the
|
|
25
|
+
Python API is minimal. Think of it as a "mini Redis" living **inside** your Python
|
|
26
|
+
process.
|
|
27
|
+
|
|
28
|
+
[](https://pypi.org/project/rust-py-cache/)
|
|
29
|
+
[](https://pypi.org/project/rust-py-cache/)
|
|
30
|
+
[](./LICENSE)
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install rust-py-cache
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To work on it locally (requires Rust + maturin):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
python -m venv .venv && source .venv/bin/activate
|
|
42
|
+
pip install maturin pytest
|
|
43
|
+
maturin develop # compiles the Rust core and installs into the venv
|
|
44
|
+
pytest # runs the tests
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from rust_py_cache import Cache
|
|
51
|
+
|
|
52
|
+
cache = Cache()
|
|
53
|
+
|
|
54
|
+
cache.set("user:1", {"name": "Roberto"}, ttl=60) # ttl in seconds
|
|
55
|
+
user = cache.get("user:1") # {"name": "Roberto"}
|
|
56
|
+
cache.get("missing", default=0) # 0
|
|
57
|
+
|
|
58
|
+
cache.exists("user:1") # True (honors TTL)
|
|
59
|
+
cache.delete("user:1") # True if removed, False if absent
|
|
60
|
+
cache.len() # approximate size
|
|
61
|
+
cache.keys() # list of keys
|
|
62
|
+
cache.cleanup_expired() # remove expired entries; returns the count
|
|
63
|
+
cache.clear() # remove everything (keeps counters)
|
|
64
|
+
cache.stats() # {'hits', 'misses', 'sets', 'deletes', 'expired', 'size'}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Memoization decorator
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
@cache.cached(ttl=60)
|
|
71
|
+
def add(a, b):
|
|
72
|
+
return a + b
|
|
73
|
+
|
|
74
|
+
add(2, 3) # runs and caches
|
|
75
|
+
add(2, 3) # served from cache
|
|
76
|
+
|
|
77
|
+
# custom key (fixed string or callable):
|
|
78
|
+
@cache.cached(ttl=300, key=lambda user_id: f"user:{user_id}")
|
|
79
|
+
def load_user(user_id):
|
|
80
|
+
...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
See full examples under [`examples/`](./examples) (FastAPI and Django).
|
|
84
|
+
|
|
85
|
+
## API
|
|
86
|
+
|
|
87
|
+
| Method | Description |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `set(key, value, ttl=None)` | Store a value. `ttl` in seconds (`int`/`float`); `None` = no expiration; `ttl <= 0` → `ValueError`. Overwrites. |
|
|
90
|
+
| `get(key, default=None)` | The value, or `default` if missing/expired (expired entries are removed). |
|
|
91
|
+
| `delete(key)` | `True` if removed, `False` if it didn't exist. |
|
|
92
|
+
| `exists(key)` | `True`/`False`, honoring TTL. |
|
|
93
|
+
| `keys()` | List of keys (may include expired-but-not-yet-collected ones). |
|
|
94
|
+
| `len()` / `len(cache)` | Approximate size. |
|
|
95
|
+
| `clear()` | Remove everything (does not reset counters). |
|
|
96
|
+
| `cleanup_expired()` | Remove expired entries; returns how many. |
|
|
97
|
+
| `stats()` | `dict` with `hits, misses, sets, deletes, expired, size`. |
|
|
98
|
+
| `@cache.cached(ttl=None, key=None)` | Memoization decorator. |
|
|
99
|
+
|
|
100
|
+
## How it works
|
|
101
|
+
|
|
102
|
+
- **Serialization:** in the MVP, values are serialized with `pickle` (on the Python
|
|
103
|
+
side, via PyO3) and stored as opaque bytes (`Vec<u8>`) in the Rust core.
|
|
104
|
+
- **Concurrency:** `DashMap` (a HashMap with per-shard locks) plus `AtomicU64`
|
|
105
|
+
counters, with no global lock on the hot path. Thread-safe, no busy loop.
|
|
106
|
+
- **TTL:** expiration is **lazy** — an expired key is removed when accessed
|
|
107
|
+
(`get`/`exists`) or via `cleanup_expired()`. There is no background thread in the MVP.
|
|
108
|
+
|
|
109
|
+
## Limitations
|
|
110
|
+
|
|
111
|
+
- The cache is **process-local**: multiple workers = multiple independent caches.
|
|
112
|
+
- It does **not** replace Redis for distributed caching.
|
|
113
|
+
- Data is **lost** when the process restarts.
|
|
114
|
+
- `pickle` must **not** be used to deserialize untrusted data.
|
|
115
|
+
- Lazy TTL: expired items may linger until accessed or until `cleanup_expired()`.
|
|
116
|
+
|
|
117
|
+
## Development
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
cargo test # Rust core tests
|
|
121
|
+
maturin develop # rebuild and install
|
|
122
|
+
pytest # Python tests
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> If `maturin develop` complains about both `VIRTUAL_ENV` and `CONDA_PREFIX` being
|
|
126
|
+
> set, run `conda deactivate` first, or use `env -u CONDA_PREFIX maturin develop`.
|
|
127
|
+
|
|
128
|
+
## Roadmap
|
|
129
|
+
|
|
130
|
+
Stages and next steps (LRU/LFU eviction, background expiration, configurable
|
|
131
|
+
serializer, namespaces, etc.) are in [ROADMAP.md](./ROADMAP.md).
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|
|
136
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Publicação — TestPyPI e PyPI (Etapas 22 e 23)
|
|
2
|
+
|
|
3
|
+
> Estas etapas exigem **suas credenciais** e publicam artefatos externos. Por isso
|
|
4
|
+
> ficam documentadas aqui e **não** são executadas automaticamente. Rode você,
|
|
5
|
+
> conscientemente, quando a v0.1 estiver pronta.
|
|
6
|
+
|
|
7
|
+
## Pré-requisitos
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install maturin twine
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Tenha contas em https://test.pypi.org e https://pypi.org e gere um **API token**
|
|
14
|
+
em cada uma (Account settings → API tokens).
|
|
15
|
+
|
|
16
|
+
## 1. Build dos artefatos
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# wheel(s) abi3 + sdist na pasta dist/
|
|
20
|
+
maturin build --release --out dist
|
|
21
|
+
maturin sdist --out dist
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 2. Publicar no TestPyPI (Etapa 22 — ensaio)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
twine upload --repository testpypi dist/*
|
|
28
|
+
# usuário: __token__ | senha: o token do TestPyPI (começa com "pypi-")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Teste a instalação a partir do TestPyPI num venv limpo:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install --index-url https://test.pypi.org/simple/ \
|
|
35
|
+
--extra-index-url https://pypi.org/simple/ \
|
|
36
|
+
rust-py-cache
|
|
37
|
+
python -c "from rust_py_cache import Cache; c=Cache(); c.set('k',1); print(c.get('k'))"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 3. Publicar no PyPI (Etapa 23 — produção)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
twine upload dist/*
|
|
44
|
+
# usuário: __token__ | senha: o token do PyPI
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Alternativa recomendada: release automático por tag
|
|
48
|
+
|
|
49
|
+
O workflow [`.github/workflows/release.yml`](.github/workflows/release.yml) já faz
|
|
50
|
+
build multi-plataforma e publica no PyPI via **Trusted Publishing (OIDC)** — sem
|
|
51
|
+
token no repositório. Para usar:
|
|
52
|
+
|
|
53
|
+
1. Em https://pypi.org → projeto → *Publishing*, registre o publisher confiável
|
|
54
|
+
(owner/repo, workflow `release.yml`, environment `pypi`).
|
|
55
|
+
2. Bump da versão em `Cargo.toml` **e** `pyproject.toml` (manter iguais).
|
|
56
|
+
3. Crie e publique a tag:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git tag v0.1.0
|
|
60
|
+
git push origin v0.1.0
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
O workflow constrói as wheels (Linux/macOS/Windows) + sdist e publica.
|
|
64
|
+
|
|
65
|
+
## Checklist de versão
|
|
66
|
+
|
|
67
|
+
- [ ] `version` igual em `Cargo.toml` e `pyproject.toml`
|
|
68
|
+
- [ ] `__version__` em `python/rust_py_cache/__init__.py`
|
|
69
|
+
- [ ] `cargo test` e `pytest` verdes
|
|
70
|
+
- [ ] README atualizado
|
|
71
|
+
- [ ] Tag `vX.Y.Z` criada
|