pycedar 0.2.2__tar.gz → 0.3.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.
Files changed (28) hide show
  1. {pycedar-0.2.2 → pycedar-0.3.0}/CHANGELOG.md +24 -1
  2. {pycedar-0.2.2/pycedar.egg-info → pycedar-0.3.0}/PKG-INFO +31 -9
  3. {pycedar-0.2.2 → pycedar-0.3.0}/README.ja.md +29 -8
  4. {pycedar-0.2.2 → pycedar-0.3.0}/README.md +30 -8
  5. pycedar-0.3.0/pycedar/VERSION +1 -0
  6. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/pycedar.cpp +2340 -1978
  7. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/pycedar.pyx +22 -1
  8. {pycedar-0.2.2 → pycedar-0.3.0/pycedar.egg-info}/PKG-INFO +31 -9
  9. {pycedar-0.2.2 → pycedar-0.3.0}/tests/test_pycedar.py +56 -29
  10. {pycedar-0.2.2 → pycedar-0.3.0}/tests/test_trie_api.py +23 -0
  11. pycedar-0.2.2/pycedar/VERSION +0 -1
  12. {pycedar-0.2.2 → pycedar-0.3.0}/MANIFEST.in +0 -0
  13. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/AUTHORS +0 -0
  14. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/BSD +0 -0
  15. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/COPYING +0 -0
  16. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/GPL +0 -0
  17. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/LGPL +0 -0
  18. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/README.md +0 -0
  19. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/THANKS +0 -0
  20. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/core/cedar/src/cedarpp.h +0 -0
  21. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar/pycedar.pxd +0 -0
  22. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar.egg-info/SOURCES.txt +0 -0
  23. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar.egg-info/dependency_links.txt +0 -0
  24. {pycedar-0.2.2 → pycedar-0.3.0}/pycedar.egg-info/top_level.txt +0 -0
  25. {pycedar-0.2.2 → pycedar-0.3.0}/pyproject.toml +0 -0
  26. {pycedar-0.2.2 → pycedar-0.3.0}/setup.cfg +0 -0
  27. {pycedar-0.2.2 → pycedar-0.3.0}/setup.py +0 -0
  28. {pycedar-0.2.2 → pycedar-0.3.0}/tests/test_readme.py +0 -0
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-09-16
11
+
12
+ ### Changed
13
+
14
+ - **Breaking**: storing `-1` or `-2` now raises `ValueError`. They are cedar's
15
+ sentinels, `base_trie.NO_VALUE` and `base_trie.NO_PATH`, and accepting them
16
+ silently corrupted the trie: `-1` made a key invisible to `in`, `get()` and
17
+ `d[key]` while leaving it visible to iteration, and `-2` terminated every
18
+ traversal early, hiding each key stored after it. Anyone affected was already
19
+ unable to read those values back, so the exception replaces silent data loss
20
+ rather than working behaviour.
21
+
22
+ The check lives in the writers shared by both layers, so `d[key] = value`,
23
+ `set()`, `setdefault()` and the trie level `set()` all enforce it.
24
+ `update()` validates the resulting value instead of the delta, because an
25
+ ordinary delta can still land on a sentinel; when it does, the delta is
26
+ rolled back and the stored value is left untouched. A key created by such a
27
+ rejected `update()` is left registered with the value `0`.
28
+
29
+ As a consequence, `get()` returning `NO_VALUE` is now unambiguous: no stored
30
+ value can collide with it.
31
+
10
32
  ## [0.2.2] - 2026-09-16
11
33
 
12
34
  ### Added
@@ -166,7 +188,8 @@ records; the corresponding tags were added retroactively.
166
188
 
167
189
  - Build failure with clang on macOS.
168
190
 
169
- [Unreleased]: https://github.com/akivajp/pycedar/compare/v0.2.2...HEAD
191
+ [Unreleased]: https://github.com/akivajp/pycedar/compare/v0.3.0...HEAD
192
+ [0.3.0]: https://github.com/akivajp/pycedar/compare/v0.2.2...v0.3.0
170
193
  [0.2.2]: https://github.com/akivajp/pycedar/compare/v0.2.1...v0.2.2
171
194
  [0.2.1]: https://github.com/akivajp/pycedar/compare/v0.2.0...v0.2.1
172
195
  [0.2.0]: https://github.com/akivajp/pycedar/compare/v0.1.3...v0.2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycedar
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: Python binding of cedar (implementation of efficiently-updatable double-array trie) using Cython
5
5
  Home-page: https://github.com/akivajp/pycedar
6
6
  Author: Akiva Miura
@@ -332,16 +332,38 @@ A ``dict``-like façade over a trie. ``pycedar.dict(key_type)`` accepts ``str``
332
332
  Values are stored as C ``int``, so they must fit in ``-2**31 .. 2**31-1``;
333
333
  anything larger raises ``OverflowError``.
334
334
 
335
- Two values collide with cedar's sentinels and must not be stored:
335
+ ``-1`` and ``-2`` are cedar's sentinels — ``base_trie.NO_VALUE`` and
336
+ ``base_trie.NO_PATH`` — and every writer rejects them:
336
337
 
337
- * **``-1`` (``NO_VALUE``)** — the key is stored and appears during iteration,
338
- but ``in``, ``get()`` and ``d[key]`` all report it as absent.
339
- * **``-2`` (``NO_PATH``)** — this value terminates traversal, so ``items()``,
340
- ``keys()``, ``values()``, ``find()`` and friends silently stop at that key and
341
- never reach the rest of the trie.
338
+ ```python
339
+ >>> limited = pycedar.dict()
340
+ >>> limited['key'] = -1
341
+ Traceback (most recent call last):
342
+ ...
343
+ ValueError: -1 is reserved and cannot be stored: ...
344
+ ```
345
+
346
+ ``update()`` checks the resulting value rather than the delta, because a
347
+ perfectly ordinary delta can still land on a sentinel. When it does, the delta
348
+ is rolled back and the stored value is left untouched:
349
+
350
+ ```python
351
+ >>> limited['counter'] = 1
352
+ >>> limited.update('counter', -3) # 1 + (-3) == -2
353
+ Traceback (most recent call last):
354
+ ...
355
+ ValueError: -2 is reserved and cannot be stored: ...
356
+ >>> limited['counter']
357
+ 1
358
+ ```
359
+
360
+ Every other value round trips, negative ones included.
342
361
 
343
- Storing non-negative values avoids both problems. Every other value, including
344
- other negative numbers, round trips normally.
362
+ Before 0.3.0 these two were accepted and silently corrupted the trie: ``-1``
363
+ made a key invisible to ``in``, ``get()`` and ``d[key]`` while leaving it
364
+ visible to iteration, and ``-2`` ended every traversal early, hiding each key
365
+ that came after it. If you are upgrading and were storing either, the values
366
+ were not being read back correctly in the first place.
345
367
 
346
368
  ### The serialization format is platform-dependent and unauthenticated
347
369
 
@@ -291,16 +291,37 @@ applet 2
291
291
  値は C の ``int`` として格納されるため、``-2**31 .. 2**31-1`` に収まる必要が
292
292
  あります。これを超えると ``OverflowError`` になります。
293
293
 
294
- 次の 2 つの値は cedar の番兵値と衝突するため、格納してはいけません。
294
+ ``-1`` と ``-2`` は cedar の番兵値(``base_trie.NO_VALUE`` と
295
+ ``base_trie.NO_PATH``)であり、すべての書き込み経路が拒否します。
295
296
 
296
- * **``-1``(``NO_VALUE``)** — キーは格納され走査にも現れますが、``in``、
297
- ``get()``、``d[key]`` のいずれからも「存在しない」と報告されます。
298
- * **``-2``(``NO_PATH``)** — この値は走査の終端条件そのものであるため、
299
- ``items()``、``keys()``、``values()``、``find()`` などが**そのキーで静かに停止し、
300
- それ以降のトライに到達しなくなります**。
297
+ ```python
298
+ >>> limited = pycedar.dict()
299
+ >>> limited['key'] = -1
300
+ Traceback (most recent call last):
301
+ ...
302
+ ValueError: -1 is reserved and cannot be stored: ...
303
+ ```
304
+
305
+ ``update()`` はデルタではなく**加算結果**を検査します。ごく普通のデルタでも
306
+ 結果が番兵値に着地しうるためです。着地した場合はデルタを巻き戻すので、
307
+ 格納されている値は変化しません。
308
+
309
+ ```python
310
+ >>> limited['counter'] = 1
311
+ >>> limited.update('counter', -3) # 1 + (-3) == -2
312
+ Traceback (most recent call last):
313
+ ...
314
+ ValueError: -2 is reserved and cannot be stored: ...
315
+ >>> limited['counter']
316
+ 1
317
+ ```
318
+
319
+ これ以外の値は、負数を含めて通常どおり往復します。
301
320
 
302
- 値を非負に限れば、いずれの問題も回避できます。それ以外の値は、負数を含めて
303
- 通常どおり往復します。
321
+ 0.3.0 より前はこの 2 つを受け付けてしまい、トライを静かに壊していました。
322
+ ``-1`` はキーを ``in`` / ``get()`` / ``d[key]`` から不可視にする一方で走査には
323
+ 現れ、``-2`` は走査をそこで打ち切って以降のキーをすべて隠していました。
324
+ いずれかを格納していた場合、そもそも正しく読み出せていなかったことになります。
304
325
 
305
326
  ### シリアライズ形式はプラットフォーム依存であり、検証機構を持たない
306
327
 
@@ -294,16 +294,38 @@ A ``dict``-like façade over a trie. ``pycedar.dict(key_type)`` accepts ``str``
294
294
  Values are stored as C ``int``, so they must fit in ``-2**31 .. 2**31-1``;
295
295
  anything larger raises ``OverflowError``.
296
296
 
297
- Two values collide with cedar's sentinels and must not be stored:
297
+ ``-1`` and ``-2`` are cedar's sentinels — ``base_trie.NO_VALUE`` and
298
+ ``base_trie.NO_PATH`` — and every writer rejects them:
298
299
 
299
- * **``-1`` (``NO_VALUE``)** — the key is stored and appears during iteration,
300
- but ``in``, ``get()`` and ``d[key]`` all report it as absent.
301
- * **``-2`` (``NO_PATH``)** — this value terminates traversal, so ``items()``,
302
- ``keys()``, ``values()``, ``find()`` and friends silently stop at that key and
303
- never reach the rest of the trie.
300
+ ```python
301
+ >>> limited = pycedar.dict()
302
+ >>> limited['key'] = -1
303
+ Traceback (most recent call last):
304
+ ...
305
+ ValueError: -1 is reserved and cannot be stored: ...
306
+ ```
307
+
308
+ ``update()`` checks the resulting value rather than the delta, because a
309
+ perfectly ordinary delta can still land on a sentinel. When it does, the delta
310
+ is rolled back and the stored value is left untouched:
311
+
312
+ ```python
313
+ >>> limited['counter'] = 1
314
+ >>> limited.update('counter', -3) # 1 + (-3) == -2
315
+ Traceback (most recent call last):
316
+ ...
317
+ ValueError: -2 is reserved and cannot be stored: ...
318
+ >>> limited['counter']
319
+ 1
320
+ ```
321
+
322
+ Every other value round trips, negative ones included.
304
323
 
305
- Storing non-negative values avoids both problems. Every other value, including
306
- other negative numbers, round trips normally.
324
+ Before 0.3.0 these two were accepted and silently corrupted the trie: ``-1``
325
+ made a key invisible to ``in``, ``get()`` and ``d[key]`` while leaving it
326
+ visible to iteration, and ``-2`` ended every traversal early, hiding each key
327
+ that came after it. If you are upgrading and were storing either, the values
328
+ were not being read back correctly in the first place.
307
329
 
308
330
  ### The serialization format is platform-dependent and unauthenticated
309
331
 
@@ -0,0 +1 @@
1
+ 0.3.0