radixor 4.1.0__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.
- radixor-4.1.0/Cargo.lock +254 -0
- radixor-4.1.0/Cargo.toml +21 -0
- radixor-4.1.0/LICENSE +28 -0
- radixor-4.1.0/PKG-INFO +298 -0
- radixor-4.1.0/README.md +253 -0
- radixor-4.1.0/pyproject.toml +82 -0
- radixor-4.1.0/radixor/__init__.py +398 -0
- radixor-4.1.0/radixor/py.typed +0 -0
- radixor-4.1.0/scripts/assemble_release.py +171 -0
- radixor-4.1.0/scripts/build_standard_distribution.py +129 -0
- radixor-4.1.0/scripts/build_standard_models.py +285 -0
- radixor-4.1.0/scripts/prepare_release_tree.py +132 -0
- radixor-4.1.0/scripts/update_simple_index.py +173 -0
- radixor-4.1.0/scripts/verify_distributions.py +598 -0
- radixor-4.1.0/src/builder.rs +682 -0
- radixor-4.1.0/src/dict.rs +122 -0
- radixor-4.1.0/src/encoder.rs +349 -0
- radixor-4.1.0/src/lib.rs +346 -0
- radixor-4.1.0/src/patch.rs +494 -0
- radixor-4.1.0/src/serial.rs +450 -0
- radixor-4.1.0/src/trie.rs +294 -0
radixor-4.1.0/Cargo.lock
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "adler2"
|
|
7
|
+
version = "2.0.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "autocfg"
|
|
13
|
+
version = "1.5.1"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
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 = "crc32fast"
|
|
25
|
+
version = "1.5.0"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
|
28
|
+
dependencies = [
|
|
29
|
+
"cfg-if",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "flate2"
|
|
34
|
+
version = "1.1.9"
|
|
35
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
36
|
+
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
|
37
|
+
dependencies = [
|
|
38
|
+
"crc32fast",
|
|
39
|
+
"miniz_oxide",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "heck"
|
|
44
|
+
version = "0.5.0"
|
|
45
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
47
|
+
|
|
48
|
+
[[package]]
|
|
49
|
+
name = "indoc"
|
|
50
|
+
version = "2.0.7"
|
|
51
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
52
|
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
|
53
|
+
dependencies = [
|
|
54
|
+
"rustversion",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[[package]]
|
|
58
|
+
name = "libc"
|
|
59
|
+
version = "0.2.189"
|
|
60
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
61
|
+
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
|
62
|
+
|
|
63
|
+
[[package]]
|
|
64
|
+
name = "memoffset"
|
|
65
|
+
version = "0.9.1"
|
|
66
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
67
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
68
|
+
dependencies = [
|
|
69
|
+
"autocfg",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[[package]]
|
|
73
|
+
name = "miniz_oxide"
|
|
74
|
+
version = "0.8.9"
|
|
75
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
76
|
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
|
77
|
+
dependencies = [
|
|
78
|
+
"adler2",
|
|
79
|
+
"simd-adler32",
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
[[package]]
|
|
83
|
+
name = "once_cell"
|
|
84
|
+
version = "1.21.4"
|
|
85
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
86
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
87
|
+
|
|
88
|
+
[[package]]
|
|
89
|
+
name = "portable-atomic"
|
|
90
|
+
version = "1.14.0"
|
|
91
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
92
|
+
checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3"
|
|
93
|
+
|
|
94
|
+
[[package]]
|
|
95
|
+
name = "proc-macro2"
|
|
96
|
+
version = "1.0.107"
|
|
97
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
98
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
99
|
+
dependencies = [
|
|
100
|
+
"unicode-ident",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "pyo3"
|
|
105
|
+
version = "0.22.6"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884"
|
|
108
|
+
dependencies = [
|
|
109
|
+
"cfg-if",
|
|
110
|
+
"indoc",
|
|
111
|
+
"libc",
|
|
112
|
+
"memoffset",
|
|
113
|
+
"once_cell",
|
|
114
|
+
"portable-atomic",
|
|
115
|
+
"pyo3-build-config",
|
|
116
|
+
"pyo3-ffi",
|
|
117
|
+
"pyo3-macros",
|
|
118
|
+
"unindent",
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
[[package]]
|
|
122
|
+
name = "pyo3-build-config"
|
|
123
|
+
version = "0.22.6"
|
|
124
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
125
|
+
checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38"
|
|
126
|
+
dependencies = [
|
|
127
|
+
"once_cell",
|
|
128
|
+
"target-lexicon",
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
[[package]]
|
|
132
|
+
name = "pyo3-ffi"
|
|
133
|
+
version = "0.22.6"
|
|
134
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
135
|
+
checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636"
|
|
136
|
+
dependencies = [
|
|
137
|
+
"libc",
|
|
138
|
+
"pyo3-build-config",
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
[[package]]
|
|
142
|
+
name = "pyo3-macros"
|
|
143
|
+
version = "0.22.6"
|
|
144
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
145
|
+
checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453"
|
|
146
|
+
dependencies = [
|
|
147
|
+
"proc-macro2",
|
|
148
|
+
"pyo3-macros-backend",
|
|
149
|
+
"quote",
|
|
150
|
+
"syn",
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
[[package]]
|
|
154
|
+
name = "pyo3-macros-backend"
|
|
155
|
+
version = "0.22.6"
|
|
156
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
157
|
+
checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe"
|
|
158
|
+
dependencies = [
|
|
159
|
+
"heck",
|
|
160
|
+
"proc-macro2",
|
|
161
|
+
"pyo3-build-config",
|
|
162
|
+
"quote",
|
|
163
|
+
"syn",
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
[[package]]
|
|
167
|
+
name = "quote"
|
|
168
|
+
version = "1.0.47"
|
|
169
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
170
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
171
|
+
dependencies = [
|
|
172
|
+
"proc-macro2",
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "radixor"
|
|
177
|
+
version = "4.1.0"
|
|
178
|
+
dependencies = [
|
|
179
|
+
"flate2",
|
|
180
|
+
"pyo3",
|
|
181
|
+
"unicode-general-category",
|
|
182
|
+
"unicode-normalization",
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
[[package]]
|
|
186
|
+
name = "rustversion"
|
|
187
|
+
version = "1.0.23"
|
|
188
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
189
|
+
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
|
190
|
+
|
|
191
|
+
[[package]]
|
|
192
|
+
name = "simd-adler32"
|
|
193
|
+
version = "0.3.10"
|
|
194
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
195
|
+
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
|
196
|
+
|
|
197
|
+
[[package]]
|
|
198
|
+
name = "syn"
|
|
199
|
+
version = "2.0.119"
|
|
200
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
201
|
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
|
202
|
+
dependencies = [
|
|
203
|
+
"proc-macro2",
|
|
204
|
+
"quote",
|
|
205
|
+
"unicode-ident",
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
[[package]]
|
|
209
|
+
name = "target-lexicon"
|
|
210
|
+
version = "0.12.16"
|
|
211
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
212
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
213
|
+
|
|
214
|
+
[[package]]
|
|
215
|
+
name = "tinyvec"
|
|
216
|
+
version = "1.12.0"
|
|
217
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
218
|
+
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
|
|
219
|
+
dependencies = [
|
|
220
|
+
"tinyvec_macros",
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
[[package]]
|
|
224
|
+
name = "tinyvec_macros"
|
|
225
|
+
version = "0.1.1"
|
|
226
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
227
|
+
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|
228
|
+
|
|
229
|
+
[[package]]
|
|
230
|
+
name = "unicode-general-category"
|
|
231
|
+
version = "0.6.0"
|
|
232
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
233
|
+
checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7"
|
|
234
|
+
|
|
235
|
+
[[package]]
|
|
236
|
+
name = "unicode-ident"
|
|
237
|
+
version = "1.0.24"
|
|
238
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
239
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
240
|
+
|
|
241
|
+
[[package]]
|
|
242
|
+
name = "unicode-normalization"
|
|
243
|
+
version = "0.1.25"
|
|
244
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
245
|
+
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
|
246
|
+
dependencies = [
|
|
247
|
+
"tinyvec",
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
[[package]]
|
|
251
|
+
name = "unindent"
|
|
252
|
+
version = "0.2.4"
|
|
253
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
254
|
+
checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
|
radixor-4.1.0/Cargo.toml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "radixor"
|
|
3
|
+
version = "4.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
|
|
7
|
+
[lib]
|
|
8
|
+
name = "_radixor"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
pyo3 = { version = "0.22", features = ["extension-module", "abi3-py39"] }
|
|
13
|
+
flate2 = "1.0"
|
|
14
|
+
unicode-normalization = "0.1"
|
|
15
|
+
unicode-general-category = "0.6"
|
|
16
|
+
|
|
17
|
+
[profile.release]
|
|
18
|
+
lto = true
|
|
19
|
+
codegen-units = 1
|
|
20
|
+
opt-level = 3
|
|
21
|
+
strip = true
|
radixor-4.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Copyright (C) 2026, Leo Galambos
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
15
|
+
may be used to endorse or promote products derived from this software
|
|
16
|
+
without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
21
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
22
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
23
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
24
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
25
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
26
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
27
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
28
|
+
POSSIBILITY OF SUCH DAMAGE.
|
radixor-4.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: radixor
|
|
3
|
+
Version: 4.1.0
|
|
4
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: Natural Language :: Czech
|
|
7
|
+
Classifier: Natural Language :: Danish
|
|
8
|
+
Classifier: Natural Language :: Dutch
|
|
9
|
+
Classifier: Natural Language :: English
|
|
10
|
+
Classifier: Natural Language :: Finnish
|
|
11
|
+
Classifier: Natural Language :: French
|
|
12
|
+
Classifier: Natural Language :: German
|
|
13
|
+
Classifier: Natural Language :: Hebrew
|
|
14
|
+
Classifier: Natural Language :: Hungarian
|
|
15
|
+
Classifier: Natural Language :: Italian
|
|
16
|
+
Classifier: Natural Language :: Norwegian
|
|
17
|
+
Classifier: Natural Language :: Persian
|
|
18
|
+
Classifier: Natural Language :: Polish
|
|
19
|
+
Classifier: Natural Language :: Portuguese
|
|
20
|
+
Classifier: Natural Language :: Russian
|
|
21
|
+
Classifier: Natural Language :: Spanish
|
|
22
|
+
Classifier: Natural Language :: Swedish
|
|
23
|
+
Classifier: Natural Language :: Ukrainian
|
|
24
|
+
Classifier: Natural Language :: Yiddish
|
|
25
|
+
Classifier: Programming Language :: Python
|
|
26
|
+
Classifier: Programming Language :: Python :: 3
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
30
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
31
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
33
|
+
Classifier: Programming Language :: Rust
|
|
34
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
35
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
36
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
37
|
+
Requires-Dist: radixor-models-standard>=1.0,<2.0
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Summary: Radixor stemmer – fastest stemming for Python, backed by Rust
|
|
40
|
+
Keywords: python,information retrieval,language processing,morphology,stemming algorithms,stemmers,nlp,rust
|
|
41
|
+
License-Expression: BSD-3-Clause
|
|
42
|
+
Requires-Python: >=3.9
|
|
43
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
44
|
+
|
|
45
|
+
# radixor — Fastest Stemming for Python
|
|
46
|
+
|
|
47
|
+
**radixor** is a Python extension for the [Radixor](https://github.com/leogalambos/Radixor) stemmer library, built on a Rust core via [PyO3](https://pyo3.rs/). It provides sub-microsecond per-word stemming with a batch API that amortises the Python↔Rust bridge overhead across thousands of words at once.
|
|
48
|
+
|
|
49
|
+
## Why radixor?
|
|
50
|
+
|
|
51
|
+
| Library | Approach | Batch API |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| **radixor** | Compiled patch-command trie in Rust | ✅ `stem_batch()` |
|
|
54
|
+
| PyStemmer (Snowball) | C extension (`libstemmer`) | ✅ `stemWords()` |
|
|
55
|
+
| snowballstemmer | Pure-Python Snowball | ✅ (Python loop) |
|
|
56
|
+
| NLTK Porter / CISTEM | Pure Python | ❌ |
|
|
57
|
+
|
|
58
|
+
**Performance.** On the shared UniMorph gold-standard corpus, measuring runtime
|
|
59
|
+
stemming only (construction excluded) and with a fair, cache-disabled,
|
|
60
|
+
same-input methodology, radixor won all **18 / 18** direct comparisons with
|
|
61
|
+
PyStemmer 3.1.0 (Snowball's C `libstemmer`) in the published 2026-08-08 run.
|
|
62
|
+
At batch size 100, the geometric-mean speedup was **1.67×**. The complete
|
|
63
|
+
machine metadata and current results are in the [Python performance
|
|
64
|
+
documentation](../docs/python/performance.md); benchmark implementation and
|
|
65
|
+
fairness notes are in [`benchmarks/`](benchmarks/README.md).
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
From PyPI, once publication is enabled:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m pip install --only-binary=:all: radixor
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The GitHub Releases-backed index is the independent alternative:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
python -m pip install --only-binary=:all: \
|
|
79
|
+
--index-url https://leogalambos.github.io/Radixor/python/simple/ radixor
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The GitHub command becomes usable after the first model and native releases
|
|
83
|
+
populate that index. See the [installation guide](../docs/python/installation.md)
|
|
84
|
+
for current availability and source-checkout builds.
|
|
85
|
+
|
|
86
|
+
Wheels are provided for Linux, macOS, and Windows (Python 3.9+). The install
|
|
87
|
+
also resolves the mandatory pure `radixor-models-standard` dependency
|
|
88
|
+
with 20 precompiled standard models. Building the native source distribution
|
|
89
|
+
requires Rust ≥ 1.75 and [maturin](https://www.maturin.rs/).
|
|
90
|
+
|
|
91
|
+
## Quick start
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from radixor import Stemmer
|
|
95
|
+
|
|
96
|
+
s = Stemmer("en") # English (us-uk-default model)
|
|
97
|
+
s.stem("running") # → "run"
|
|
98
|
+
s.stem("cats") # → "cat"
|
|
99
|
+
s.stem("unknown_word") # → None
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Batch API — the fast path
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
words = ["running", "cats", "stemming", "quickly"]
|
|
106
|
+
|
|
107
|
+
# Amortises the Python→Rust bridge cost across all words at once
|
|
108
|
+
stems = s.stem_batch(words)
|
|
109
|
+
# → ["run", "cat", "stem", "quick"]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For large corpora (tens of thousands of words) the batch call is the recommended interface. It avoids per-call Python frame overhead and keeps the hot loop entirely inside Rust.
|
|
113
|
+
|
|
114
|
+
## Migrating from PyStemmer
|
|
115
|
+
|
|
116
|
+
Radixor provides PyStemmer's `stemWord` and `stemWords` method names. These
|
|
117
|
+
compatibility methods also follow PyStemmer's fallback behavior: when the trie
|
|
118
|
+
has no patch command, they return the original word instead of `None`.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# PyStemmer: import Stemmer
|
|
122
|
+
import radixor as Stemmer
|
|
123
|
+
|
|
124
|
+
stemmer = Stemmer.Stemmer("english")
|
|
125
|
+
stemmer.stemWord("running") # → "run"
|
|
126
|
+
stemmer.stemWord("unknown_word") # → "unknown_word"
|
|
127
|
+
stemmer.stemWords(["running", "unknown"]) # → ["run", "unknown"]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The original Radixor methods remain unchanged: `stem` and `stem_batch` return
|
|
131
|
+
`None` for words without a matching patch command. Radixor accepts PyStemmer's
|
|
132
|
+
full language names for the languages represented by its bundled models, as
|
|
133
|
+
well as its existing two-letter codes and model IDs.
|
|
134
|
+
|
|
135
|
+
## Supported languages
|
|
136
|
+
|
|
137
|
+
| Code | Language | Model ID |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `cs` | Czech | `cs-cz-default` |
|
|
140
|
+
| `da` | Danish | `da-dk-default` |
|
|
141
|
+
| `de` | German | `de-de-default` |
|
|
142
|
+
| `en` | English | `us-uk-default` |
|
|
143
|
+
| `es` | Spanish | `es-es-default` |
|
|
144
|
+
| `fa` | Persian | `fa-ir-default` |
|
|
145
|
+
| `fi` | Finnish | `fi-fi-default` |
|
|
146
|
+
| `fr` | French | `fr-fr-default` |
|
|
147
|
+
| `he` | Hebrew | `he-il-default` |
|
|
148
|
+
| `hu` | Hungarian | `hu-hu-default` |
|
|
149
|
+
| `it` | Italian | `it-it-default` |
|
|
150
|
+
| `nb` | Norwegian Bokmål | `nb-no-default` |
|
|
151
|
+
| `nl` | Dutch | `nl-nl-default` |
|
|
152
|
+
| `nn` | Norwegian Nynorsk | `nn-no-default` |
|
|
153
|
+
| `pl` | Polish | `pl-pl-unimorph` |
|
|
154
|
+
| `pt` | Portuguese | `pt-pt-default` |
|
|
155
|
+
| `ru` | Russian | `ru-ru-default` |
|
|
156
|
+
| `sv` | Swedish | `sv-se-default` |
|
|
157
|
+
| `uk` | Ukrainian | `uk-ua-default` |
|
|
158
|
+
| `yi` | Yiddish | `yi-default` |
|
|
159
|
+
|
|
160
|
+
## API reference
|
|
161
|
+
|
|
162
|
+
### `Stemmer(language=None, *, path=None, compiled=None, backward=None, store_original=True, lowercase=True, cache_size=10_000)`
|
|
163
|
+
|
|
164
|
+
Create a stemmer for the given language code, model ID, custom textual
|
|
165
|
+
dictionary, or previously compiled version 7 trie. Textual dictionaries are
|
|
166
|
+
compiled in Rust; `compiled=` loads a prepared binary directly.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
s = Stemmer("de") # by language code
|
|
170
|
+
s = Stemmer("de-de-default") # by model ID
|
|
171
|
+
s = Stemmer(path="/data/custom.gz") # custom gzipped dictionary
|
|
172
|
+
s = Stemmer(compiled="/data/custom.rxc") # prepared v7 binary
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`backward` selects the traversal direction; when left as `None` it is derived
|
|
176
|
+
from the language (BACKWARD, except right-to-left `fa`/`he`/`yi` which use
|
|
177
|
+
FORWARD). `store_original` (default `True`) maps each canonical stem to a no-op
|
|
178
|
+
patch so the stem itself is recognised. `lowercase=False` skips runtime
|
|
179
|
+
lowercasing for already-normalized input, and `cache_size` enables the bounded
|
|
180
|
+
result cache. The default holds up to 10,000 entries, matching PyStemmer;
|
|
181
|
+
`cache_size=0` disables it. One cache is shared by `stem()`, `stemWord()`,
|
|
182
|
+
`stem_batch()`, and `stemWords()`; the `stem_all*()` methods are not cached.
|
|
183
|
+
|
|
184
|
+
### `stem(word: str) → str | None`
|
|
185
|
+
|
|
186
|
+
Return the stem, or `None` when the compiled trie finds no applicable patch
|
|
187
|
+
command. This does not mean that lookup is restricted to exact training words.
|
|
188
|
+
|
|
189
|
+
### `stem_batch(words: list[str]) → list[str | None]`
|
|
190
|
+
|
|
191
|
+
Stem an entire list. Preferred for large inputs.
|
|
192
|
+
|
|
193
|
+
### `stemWord(word: str) → str`
|
|
194
|
+
|
|
195
|
+
PyStemmer-compatible scalar method. Return the original word if it cannot be
|
|
196
|
+
stemmed.
|
|
197
|
+
|
|
198
|
+
### `stemWords(words: list[str]) → list[str]`
|
|
199
|
+
|
|
200
|
+
PyStemmer-compatible batch method. Return each unrecognized word unchanged.
|
|
201
|
+
|
|
202
|
+
### `stem_all(word: str) → list[str]`
|
|
203
|
+
|
|
204
|
+
Return all stems ordered by descending corpus frequency. Useful when multiple valid stems exist.
|
|
205
|
+
|
|
206
|
+
### `stem_all_batch(words: list[str]) → list[list[str]]`
|
|
207
|
+
|
|
208
|
+
Return all stems for each word in a batch.
|
|
209
|
+
|
|
210
|
+
## Compiling a model (compile once, load instantly)
|
|
211
|
+
|
|
212
|
+
Compiling the trie from a textual dictionary takes time for large languages
|
|
213
|
+
(seconds). You can compile it **once** to Radixor's binary format and then load
|
|
214
|
+
it near-instantly — the same workflow Java users have:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
import radixor
|
|
218
|
+
radixor.compile("stemmer.gz", "en.rxc", language="en") # or backward=True/False
|
|
219
|
+
s = radixor.Stemmer(compiled="en.rxc") # instant load, no re-compile
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The compiled file uses Radixor's **v7 trie format and is byte-compatible with
|
|
223
|
+
the Java `StemmerPatchTrieBinaryIO`** (the inner stream is identical), so a file
|
|
224
|
+
compiled by Java can be loaded by Python and vice versa. `Stemmer(path=...)`
|
|
225
|
+
auto-detects whether it was given a compiled trie or a textual dictionary.
|
|
226
|
+
|
|
227
|
+
## Using a custom model
|
|
228
|
+
|
|
229
|
+
Provide your own gzipped source dictionary (tab-separated
|
|
230
|
+
`stem<TAB>variant1<TAB>variant2…` per line, `#` / `//` line remarks allowed) and
|
|
231
|
+
load it directly:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
s = Stemmer(path="my_dictionary.gz") # BACKWARD by default
|
|
235
|
+
s = Stemmer(path="my_rtl_dictionary.gz", backward=False) # right-to-left
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The dictionary is compiled to a patch-command trie in Rust at construction time.
|
|
239
|
+
|
|
240
|
+
## Building from source
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
cd Radixor/
|
|
244
|
+
pip install maturin build setuptools wheel pytest
|
|
245
|
+
./gradlew pythonBuildStandardModels
|
|
246
|
+
pip install --no-deps build/python/dist/standard/radixor_models_standard-0.0.0-py3-none-any.whl
|
|
247
|
+
cd python/
|
|
248
|
+
maturin develop --release # editable install with release optimisations
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
From the repository root, Gradle builds the native wheel/sdist and pure
|
|
252
|
+
standard-model wheel/sdist without installing them globally:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
./gradlew pythonBuild
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The convenience tasks `pythonBuildLinux`, `pythonBuildWindows`, and
|
|
259
|
+
`pythonBuildMacos` use the host build when the requested platform matches the
|
|
260
|
+
current system. Other platforms are cross-compiled with the corresponding Rust
|
|
261
|
+
target and therefore require that target and its linker/SDK to be installed.
|
|
262
|
+
Override a default target with, for example,
|
|
263
|
+
`-PpythonWindowsTarget=x86_64-pc-windows-gnu`. Build artifacts are written below
|
|
264
|
+
`build/python/dist/`.
|
|
265
|
+
|
|
266
|
+
The complete batch benchmark runs Radixor for all bundled languages and every
|
|
267
|
+
available comparison engine for the languages it supports, using batch sizes
|
|
268
|
+
10, 20, 50, and 100:
|
|
269
|
+
|
|
270
|
+
Comparison engines are auto-detected in the environment of `pythonExecutable`.
|
|
271
|
+
Install `python/benchmarks/requirements-bench.txt` there to enable the complete
|
|
272
|
+
comparison set.
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
./gradlew pythonBenchmarkAllLanguagesBatch
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Use `pythonBenchmarkWords`, `pythonBenchmarkRepeats`, and
|
|
279
|
+
`pythonBenchmarkWarmup` Gradle properties to tune the run. CSV and JSON reports
|
|
280
|
+
are written below `build/reports/python-benchmarks/`.
|
|
281
|
+
|
|
282
|
+
Neither runtime distribution contains textual dictionaries. The standard data
|
|
283
|
+
sdist contains build-ready gzip v7 `.rxc` files, a checksummed provenance
|
|
284
|
+
manifest, and per-model CC BY-SA 3.0 notices. They are generated below `build/`
|
|
285
|
+
from canonical `models/*/src/modelInput/stemmer.gz` inputs and are never stored
|
|
286
|
+
in Git. `./gradlew regeneratePythonStandardModels` performs this deterministic
|
|
287
|
+
generation; repository topology selects the 20 defaults and excludes optional
|
|
288
|
+
`pl-pl-polimorf`.
|
|
289
|
+
|
|
290
|
+
`radixor` requires `radixor-models-standard>=1.0,<2.0`. The Python distribution
|
|
291
|
+
version is independent of its `2026.1` Java model-catalog identity and of the
|
|
292
|
+
individual model versions recorded in the manifest.
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
The native/API package is BSD-3-Clause — see [LICENSE](LICENSE). Model data
|
|
297
|
+
is separately licensed under CC BY-SA 3.0 in its packaged notices.
|
|
298
|
+
|