cultcache-py: read the slot-nil vector; changelog for the store lock and msgpack
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (pull_request) Has been cancelled
CultNet cross-runtime interop / C# / TypeScript / Rust / Python / Kotlin (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (pull_request) Has been cancelled
CultNet cross-runtime interop / C# / TypeScript / Rust / Python / Kotlin (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
tests/vectors/slot-nil was read by TS only. The Python reader accepts the same 15 rows and refuses the same 2 as the C# reference and rewrites the reference's bytes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b2434fc7fc
commit
00ecdcf9e6
2 changed files with 59 additions and 0 deletions
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- `msgpack` is a hard dependency, as `pyproject.toml` declared it. The optional-import fallbacks and the `cultcache-py[msgpack]` extra they named (which never existed) are gone: a missing msgpack is an `ImportError` at import.
|
||||
- The single-file store's `push`, `push_all` and `delete` take the cross-process lock on `<path>.lock` (flock; LockFileEx over the whole file on Windows) across the read and the replace, waiting up to `lock_timeout` seconds (30 by default, `TimeoutError` after), and exclude the C#, Rust and TypeScript runtimes' writers. The staged file is `<path>.tmp-<pid>-<uuid>`, fsynced before the replace, with a directory fsync after it off Windows. A fixed `<path>.tmp` is no longer used.
|
||||
|
||||
### Breaking
|
||||
|
||||
- A single-file store written as `cultcache.store.v3` is read and written: a record that holds an element id (an owned list element with an `[CultElementId]` member, carried through every write) marks the store v3, and a v3 store is carried through a rewrite with its ids. A runtime from before this change refuses a v3 store by name.
|
||||
|
|
|
|||
54
packages/cultcache-py/tests/test_slot_nil.py
Normal file
54
packages/cultcache-py/tests/test_slot_nil.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
import msgpack
|
||||
|
||||
from cultcache_py import database_entry_field, define_database_entry_type, define_record_codec, leaves as t
|
||||
|
||||
# tests/vectors/slot-nil is written only by the C# reference (SlotNilVectorTests): what it reads and rewrites for a nil, a
|
||||
# str in a byte[] slot, and a record short of its last slots. This runtime accepts what the reference accepts and rewrites
|
||||
# the same bytes.
|
||||
VECTORS = Path(__file__).resolve().parents[3] / "tests" / "vectors" / "slot-nil"
|
||||
|
||||
|
||||
def _probe():
|
||||
inner = define_record_codec("SlotNilInner", [database_entry_field("x", 0, default="", codec=t.string)])
|
||||
return define_database_entry_type(
|
||||
"tests.slot-nil",
|
||||
[
|
||||
database_entry_field("s", 0, default="", codec=t.nullable(t.string)),
|
||||
database_entry_field("i", 1, default=0, codec=t.int32),
|
||||
database_entry_field("b", 2, default=b"", codec=t.nullable(t.bytes)),
|
||||
database_entry_field("r", 3, default=None, codec=t.nullable(inner)),
|
||||
database_entry_field("l", 4, default=[], codec=t.nullable(t.list(t.string))),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class SlotNilVectorTests(unittest.TestCase):
|
||||
def test_slots_read_and_rewrite_exactly_what_the_reference_does_for_nil_str_in_bytes_and_short_records(self) -> None:
|
||||
rows = msgpack.unpackb((VECTORS / "reads.msgpack").read_bytes(), raw=False)
|
||||
probe = _probe()
|
||||
self.assertEqual(17, len(rows))
|
||||
accepted = 0
|
||||
for name, payload, was_accepted, rewritten in rows:
|
||||
with self.subTest(name):
|
||||
if was_accepted:
|
||||
self.assertEqual(rewritten.hex(), probe.encode_payload(probe.decode_payload(payload)).hex())
|
||||
accepted += 1
|
||||
else:
|
||||
with self.assertRaises(Exception):
|
||||
probe.decode_payload(payload)
|
||||
self.assertEqual(15, accepted)
|
||||
|
||||
def test_a_character_outside_the_bmp_is_four_utf8_bytes(self) -> None:
|
||||
rows = {name: (payload, rewritten) for name, payload, _, rewritten in msgpack.unpackb((VECTORS / "reads.msgpack").read_bytes(), raw=False)}
|
||||
probe = _probe()
|
||||
self.assertEqual("\U0001F600", probe.decode_payload(rows["string-astral"][0])["s"])
|
||||
self.assertEqual(b"\xf0\x9f\x98\x80", probe.decode_payload(rows["bytes-str-astral"][0])["b"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Reference in a new issue