sharedbox 0.4.0__tar.gz → 0.5.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.
- sharedbox-0.5.0/.github/dependabot.yml +23 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.github/workflows/check-docs.yaml +2 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.github/workflows/ci.yaml +15 -15
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.github/workflows/codspeed.yml +1 -1
- sharedbox-0.5.0/.github/workflows/contention.yaml +45 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.github/workflows/publish-docs.yaml +2 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/CHANGELOG.md +54 -1
- {sharedbox-0.4.0 → sharedbox-0.5.0}/CLAUDE.md +13 -7
- {sharedbox-0.4.0 → sharedbox-0.5.0}/PKG-INFO +37 -11
- {sharedbox-0.4.0 → sharedbox-0.5.0}/README.md +36 -10
- {sharedbox-0.4.0 → sharedbox-0.5.0}/benchmarks/test_bench_box.py +41 -0
- sharedbox-0.5.0/docs/diagrams/style.d2 +61 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/store_arrays.py +12 -0
- sharedbox-0.5.0/docs/explanation/checking-a-process-is-alive.md +89 -0
- sharedbox-0.5.0/docs/explanation/closing-and-lifetime.md +242 -0
- sharedbox-0.5.0/docs/explanation/field-types.md +141 -0
- sharedbox-0.5.0/docs/explanation/glossary.md +130 -0
- sharedbox-0.5.0/docs/explanation/how-a-box-is-stored.md +214 -0
- sharedbox-0.5.0/docs/explanation/how-the-module-is-built.md +96 -0
- sharedbox-0.5.0/docs/explanation/index.md +44 -0
- sharedbox-0.5.0/docs/explanation/limits.md +74 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/explanation/performance.md +14 -10
- sharedbox-0.5.0/docs/explanation/reading-and-writing.md +272 -0
- sharedbox-0.5.0/docs/explanation/references.md +154 -0
- sharedbox-0.5.0/docs/explanation/waiting-for-changes.md +268 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/explanation/when-to-use-sharedbox.md +11 -6
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/accept-a-box-in-c.md +30 -18
- sharedbox-0.5.0/docs/how-to/accept-a-box-in-cpp.md +192 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/build-docs.md +3 -0
- sharedbox-0.5.0/docs/how-to/change-several-fields-at-once.md +60 -0
- sharedbox-0.5.0/docs/how-to/clean-up-segments.md +93 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/commits-and-prs.md +4 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/contribute.md +3 -2
- sharedbox-0.5.0/docs/how-to/follow-a-whole-reference-graph.md +73 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/index.md +6 -5
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/install-sharedbox.md +9 -8
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/make-a-release.md +3 -2
- sharedbox-0.5.0/docs/how-to/name-a-box.md +83 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/open-a-box-from-a-program.md +13 -11
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/run-benchmarks.md +34 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/run-commit-checks.md +5 -4
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/run-tests.md +7 -2
- sharedbox-0.5.0/docs/how-to/send-a-box-to-another-process.md +127 -0
- sharedbox-0.5.0/docs/how-to/set-defaults-and-check-values.md +84 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/set-up-development.md +3 -1
- sharedbox-0.5.0/docs/how-to/store-arrays.md +175 -0
- sharedbox-0.5.0/docs/how-to/store-collections.md +71 -0
- sharedbox-0.5.0/docs/how-to/store-records.md +79 -0
- sharedbox-0.5.0/docs/how-to/store-text-and-bytes.md +68 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/write-docs.md +68 -6
- sharedbox-0.5.0/docs/index.md +185 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/cpp-and-c-api.md +9 -6
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/index.md +4 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/segment-layout.md +11 -7
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/tutorials/index.md +6 -4
- sharedbox-0.5.0/docs/tutorials/react-to-changes.md +149 -0
- sharedbox-0.5.0/docs/tutorials/refer-to-another-box.md +104 -0
- sharedbox-0.5.0/docs/tutorials/share-a-record.md +131 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/include/sharedbox/sharedbox.hpp +34 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/pyproject.toml +1 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_box.py +93 -10
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_events.py +45 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_layout.py +6 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/codec.cpp +8 -4
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/module.cpp +173 -7
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/segment.cpp +44 -1
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/segment.hpp +31 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/types.cpp +130 -21
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/types.hpp +17 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native.pyi +56 -2
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_types.py +34 -1
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_version.py +3 -3
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/_app.py +37 -1
- sharedbox-0.5.0/src/sharedbox/benchmarks/contention.py +324 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/ops.py +9 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/stubtest-allowlist.txt +5 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/CMakeLists.txt +1 -1
- sharedbox-0.5.0/tests/cpp/test_write_in_place.cpp +83 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/forged_open.py +6 -2
- sharedbox-0.5.0/tests/stress/test_stress_read_into.py +61 -0
- sharedbox-0.5.0/tests/test_benchbox_contention.py +15 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_box.py +5 -4
- sharedbox-0.5.0/tests/test_exit.py +53 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_fork.py +34 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_properties_stateful.py +12 -1
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_properties_types.py +5 -2
- sharedbox-0.5.0/tests/test_read_into.py +197 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_arrays_bfloat16.py +21 -0
- sharedbox-0.5.0/tests/test_types_records_attrs.py +83 -0
- sharedbox-0.5.0/tests/test_types_records_msgspec.py +92 -0
- sharedbox-0.5.0/tests/test_value_reuse.py +446 -0
- sharedbox-0.5.0/tests/test_writing.py +171 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/type_checks/box_types.py +21 -1
- {sharedbox-0.4.0 → sharedbox-0.5.0}/uv.lock +32 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/zensical.toml +1 -1
- sharedbox-0.4.0/docs/explanation/checking-a-process-is-alive.md +0 -63
- sharedbox-0.4.0/docs/explanation/closing-and-lifetime.md +0 -136
- sharedbox-0.4.0/docs/explanation/field-types.md +0 -91
- sharedbox-0.4.0/docs/explanation/glossary.md +0 -114
- sharedbox-0.4.0/docs/explanation/how-a-box-is-stored.md +0 -145
- sharedbox-0.4.0/docs/explanation/how-the-module-is-built.md +0 -68
- sharedbox-0.4.0/docs/explanation/index.md +0 -44
- sharedbox-0.4.0/docs/explanation/limits.md +0 -63
- sharedbox-0.4.0/docs/explanation/reading-and-writing.md +0 -121
- sharedbox-0.4.0/docs/explanation/references.md +0 -79
- sharedbox-0.4.0/docs/explanation/waiting-for-changes.md +0 -184
- sharedbox-0.4.0/docs/how-to/accept-a-box-in-cpp.md +0 -174
- sharedbox-0.4.0/docs/how-to/change-several-fields-at-once.md +0 -59
- sharedbox-0.4.0/docs/how-to/clean-up-segments.md +0 -82
- sharedbox-0.4.0/docs/how-to/follow-a-whole-reference-graph.md +0 -70
- sharedbox-0.4.0/docs/how-to/name-a-box.md +0 -76
- sharedbox-0.4.0/docs/how-to/send-a-box-to-another-process.md +0 -69
- sharedbox-0.4.0/docs/how-to/set-defaults-and-check-values.md +0 -75
- sharedbox-0.4.0/docs/how-to/store-arrays.md +0 -58
- sharedbox-0.4.0/docs/how-to/store-collections.md +0 -59
- sharedbox-0.4.0/docs/how-to/store-records.md +0 -68
- sharedbox-0.4.0/docs/how-to/store-text-and-bytes.md +0 -66
- sharedbox-0.4.0/docs/index.md +0 -63
- sharedbox-0.4.0/docs/tutorials/react-to-changes.md +0 -130
- sharedbox-0.4.0/docs/tutorials/refer-to-another-box.md +0 -92
- sharedbox-0.4.0/docs/tutorials/share-a-record.md +0 -115
- sharedbox-0.4.0/tests/test_types_records_attrs.py +0 -21
- sharedbox-0.4.0/tests/test_types_records_msgspec.py +0 -35
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.clang-format +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.claude/settings.json +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/.gitignore +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/CMakeLists.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/LICENSE +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/cmake/sharedbox-config.cmake +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/cmake/sharedbox-require-cxx.cmake +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/assets/benchmarks/ops-dark.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/assets/benchmarks/ops-light.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/assets/benchmarks/roundtrip-dark.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/assets/benchmarks/roundtrip-light.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/change_several_fields_at_once.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/clean_up_segments.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/follow_a_whole_reference_graph.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/name_a_box.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/send_a_box_to_another_process.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/set_defaults_and_check_values.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/store_collections.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/store_records.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/examples/store_text_and_bytes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/how-to/ai-contribution-policy.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/arrays.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/box.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/errors.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/events.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/library-authors.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/api/references.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/reference/changelog.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/docs/tutorials/motor.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/include/sharedbox/sharedbox_c.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/include/sharedbox/sharedbox_c.h +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/includes/abbreviations.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/prek.toml +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/scripts/check_xrefs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/scripts/vscode_setup.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/__init__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_arrays.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/codec.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/scalars.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_native/scalars.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/_refs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/__init__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/__main__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/cli.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/plot.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/roundtrip.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/size.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/benchmarks/size_diff.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/src/sharedbox/py.typed +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/conftest.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/compile_fail.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/consumer/CMakeLists.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/consumer/consumer.c +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/table_builder.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_atomics.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_c_smoke.c +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_c_smoke_box.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_fork.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_layout2.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_lock.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_mapping.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_result.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_slots.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_small_shm.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_types.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_values.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_wait.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/test_windows_h.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/cpp/unique.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/crossproc.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/forged_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/refs_future.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/stress_helpers.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_contention.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_crashes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_lock_timeout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_memory.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_waiters.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/stress/test_stress_watchers.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_benchbox_plot.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_capsule.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_doc_examples.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_doc_tutorials.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_events_async.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_events_bytes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_events_signals.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_events_sync.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_fields.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_layout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_layout_v1.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_codec.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_liveness.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_segment.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_wait.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_native_waiters.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_properties_codec.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_properties_forged.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_properties_layout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_refs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_refs_lazy.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_arrays.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_arrays_torch.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_choices.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_collections.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_records.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_scalars.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/test_types_unions.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.5.0}/tests/type_checks/events_types.py +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
commit-message:
|
|
8
|
+
prefix: ci
|
|
9
|
+
groups:
|
|
10
|
+
actions:
|
|
11
|
+
patterns:
|
|
12
|
+
- "*"
|
|
13
|
+
- package-ecosystem: uv
|
|
14
|
+
directory: /
|
|
15
|
+
schedule:
|
|
16
|
+
interval: weekly
|
|
17
|
+
commit-message:
|
|
18
|
+
prefix: build
|
|
19
|
+
include: scope
|
|
20
|
+
groups:
|
|
21
|
+
python:
|
|
22
|
+
patterns:
|
|
23
|
+
- "*"
|
|
@@ -8,7 +8,7 @@ jobs:
|
|
|
8
8
|
name: Build and check cross-references
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
steps:
|
|
11
|
-
- uses: actions/checkout@
|
|
11
|
+
- uses: actions/checkout@v7
|
|
12
12
|
|
|
13
13
|
- name: Install uv
|
|
14
14
|
uses: astral-sh/setup-uv@v7
|
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
# the publish job deploys this artifact rather than building again,
|
|
24
24
|
# so what reaches Pages is what was checked
|
|
25
25
|
- name: Store the built site
|
|
26
|
-
uses: actions/upload-artifact@
|
|
26
|
+
uses: actions/upload-artifact@v7
|
|
27
27
|
with:
|
|
28
28
|
name: docs-site
|
|
29
29
|
path: site/
|
|
@@ -14,7 +14,7 @@ jobs:
|
|
|
14
14
|
name: Lint
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
18
|
|
|
19
19
|
# local hooks in prek.toml call `uv run --locked --only-group lint ...`
|
|
20
20
|
- uses: astral-sh/setup-uv@v7
|
|
@@ -62,7 +62,7 @@ jobs:
|
|
|
62
62
|
ASAN_OPTIONS: detect_leaks=1
|
|
63
63
|
UBSAN_OPTIONS: print_stacktrace=1
|
|
64
64
|
steps:
|
|
65
|
-
- uses: actions/checkout@
|
|
65
|
+
- uses: actions/checkout@v7
|
|
66
66
|
with:
|
|
67
67
|
fetch-depth: 0
|
|
68
68
|
|
|
@@ -108,13 +108,13 @@ jobs:
|
|
|
108
108
|
- { os: ubuntu-latest, python: cp314t, platform_id: musllinux_x86_64 }
|
|
109
109
|
|
|
110
110
|
steps:
|
|
111
|
-
- uses: actions/checkout@
|
|
111
|
+
- uses: actions/checkout@v7
|
|
112
112
|
with:
|
|
113
113
|
fetch-depth: 0
|
|
114
114
|
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }}
|
|
115
115
|
|
|
116
116
|
- name: Build wheels
|
|
117
|
-
uses: pypa/cibuildwheel@
|
|
117
|
+
uses: pypa/cibuildwheel@v4.2.1
|
|
118
118
|
env:
|
|
119
119
|
CIBW_BUILD: ${{ matrix.python }}-${{ matrix.platform_id }}
|
|
120
120
|
CIBW_CONTAINER_ENGINE: "docker; create_args: --shm-size=1g"
|
|
@@ -125,7 +125,7 @@ jobs:
|
|
|
125
125
|
output-dir: wheelhouse
|
|
126
126
|
|
|
127
127
|
- name: Upload wheel artifacts
|
|
128
|
-
uses: actions/upload-artifact@
|
|
128
|
+
uses: actions/upload-artifact@v7
|
|
129
129
|
with:
|
|
130
130
|
name: cibw-wheels-${{ matrix.python }}-${{ matrix.platform_id }}
|
|
131
131
|
path: ./wheelhouse/*.whl
|
|
@@ -139,7 +139,7 @@ jobs:
|
|
|
139
139
|
python src/sharedbox/benchmarks/size.py wheelhouse/*.whl --json wheelhouse/sizes.json --markdown >> "$GITHUB_STEP_SUMMARY"
|
|
140
140
|
|
|
141
141
|
- name: Upload size artifact
|
|
142
|
-
uses: actions/upload-artifact@
|
|
142
|
+
uses: actions/upload-artifact@v7
|
|
143
143
|
with:
|
|
144
144
|
name: wheel-sizes-${{ matrix.python }}-${{ matrix.platform_id }}
|
|
145
145
|
path: wheelhouse/sizes.json
|
|
@@ -153,10 +153,10 @@ jobs:
|
|
|
153
153
|
actions: read
|
|
154
154
|
continue-on-error: true
|
|
155
155
|
steps:
|
|
156
|
-
- uses: actions/checkout@
|
|
156
|
+
- uses: actions/checkout@v7
|
|
157
157
|
|
|
158
158
|
- name: Download this run's size artifacts
|
|
159
|
-
uses: actions/download-artifact@
|
|
159
|
+
uses: actions/download-artifact@v8
|
|
160
160
|
with:
|
|
161
161
|
pattern: wheel-sizes-*
|
|
162
162
|
path: sizes/this
|
|
@@ -173,7 +173,7 @@ jobs:
|
|
|
173
173
|
- name: Download the baseline's size artifacts
|
|
174
174
|
if: steps.baseline.outputs.run_id != ''
|
|
175
175
|
continue-on-error: true
|
|
176
|
-
uses: actions/download-artifact@
|
|
176
|
+
uses: actions/download-artifact@v8
|
|
177
177
|
with:
|
|
178
178
|
pattern: wheel-sizes-*
|
|
179
179
|
path: sizes/main
|
|
@@ -199,11 +199,11 @@ jobs:
|
|
|
199
199
|
- { os: ubuntu-latest, wheel: cibw-wheels-cp312-manylinux_x86_64 }
|
|
200
200
|
- { os: windows-latest, wheel: cibw-wheels-cp312-win_amd64 }
|
|
201
201
|
steps:
|
|
202
|
-
- uses: actions/checkout@
|
|
202
|
+
- uses: actions/checkout@v7
|
|
203
203
|
|
|
204
204
|
- uses: astral-sh/setup-uv@v7
|
|
205
205
|
|
|
206
|
-
- uses: actions/download-artifact@
|
|
206
|
+
- uses: actions/download-artifact@v8
|
|
207
207
|
with:
|
|
208
208
|
name: ${{ matrix.wheel }}
|
|
209
209
|
path: wheelhouse
|
|
@@ -218,7 +218,7 @@ jobs:
|
|
|
218
218
|
"$python" -m pytest -m stress -q -p no:cacheprovider
|
|
219
219
|
"$python" -m pytest tests/test_properties_codec.py tests/test_properties_layout.py tests/test_properties_forged.py tests/test_properties_stateful.py -q -p no:cacheprovider --hypothesis-profile=thorough
|
|
220
220
|
|
|
221
|
-
- uses: actions/upload-artifact@
|
|
221
|
+
- uses: actions/upload-artifact@v7
|
|
222
222
|
if: always()
|
|
223
223
|
with:
|
|
224
224
|
name: stress-${{ matrix.os }}
|
|
@@ -243,7 +243,7 @@ jobs:
|
|
|
243
243
|
*) [ "$PRERELEASE" = "false" ] || { echo "::error::$TAG must not be marked pre-release"; exit 1; } ;;
|
|
244
244
|
esac
|
|
245
245
|
|
|
246
|
-
- uses: actions/checkout@
|
|
246
|
+
- uses: actions/checkout@v7
|
|
247
247
|
with:
|
|
248
248
|
fetch-depth: 0
|
|
249
249
|
ref: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }}
|
|
@@ -256,7 +256,7 @@ jobs:
|
|
|
256
256
|
TAG: ${{ github.event.release.tag_name }}
|
|
257
257
|
run: test -f "dist/sharedbox-${TAG#v}.tar.gz"
|
|
258
258
|
|
|
259
|
-
- uses: actions/upload-artifact@
|
|
259
|
+
- uses: actions/upload-artifact@v7
|
|
260
260
|
with:
|
|
261
261
|
name: cibw-sdist
|
|
262
262
|
path: dist/*.tar.gz
|
|
@@ -272,7 +272,7 @@ jobs:
|
|
|
272
272
|
id-token: write
|
|
273
273
|
if: github.event_name == 'release' && github.event.action == 'published'
|
|
274
274
|
steps:
|
|
275
|
-
- uses: actions/download-artifact@
|
|
275
|
+
- uses: actions/download-artifact@v8
|
|
276
276
|
with:
|
|
277
277
|
# unpacks all CIBW artifacts into dist/
|
|
278
278
|
pattern: cibw-*
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Contention
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
paths:
|
|
7
|
+
- include/sharedbox/**
|
|
8
|
+
- src/sharedbox/_native/**
|
|
9
|
+
- src/sharedbox/benchmarks/contention.py
|
|
10
|
+
- .github/workflows/contention.yaml
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
contention:
|
|
18
|
+
name: Contention on ${{ matrix.os }}
|
|
19
|
+
runs-on: ${{ matrix.os }}
|
|
20
|
+
timeout-minutes: 30
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ ubuntu-latest, windows-latest ]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
with:
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
|
|
30
|
+
- uses: astral-sh/setup-uv@v7
|
|
31
|
+
|
|
32
|
+
- name: Install the project
|
|
33
|
+
run: uv sync --frozen --python 3.12
|
|
34
|
+
|
|
35
|
+
- name: Run benchbox contention
|
|
36
|
+
shell: bash
|
|
37
|
+
run: |
|
|
38
|
+
cores=$(uv run --no-sync python -c "import os; print(os.cpu_count())")
|
|
39
|
+
echo "### Contention on ${{ matrix.os }}, $cores logical cores" >> "$GITHUB_STEP_SUMMARY"
|
|
40
|
+
uv run --no-sync benchbox contention --json contention.json --markdown >> "$GITHUB_STEP_SUMMARY"
|
|
41
|
+
|
|
42
|
+
- uses: actions/upload-artifact@v7
|
|
43
|
+
with:
|
|
44
|
+
name: contention-${{ matrix.os }}
|
|
45
|
+
path: contention.json
|
|
@@ -10,10 +10,10 @@ jobs:
|
|
|
10
10
|
permissions:
|
|
11
11
|
contents: write
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
13
|
+
- uses: actions/checkout@v7
|
|
14
14
|
|
|
15
15
|
- name: Download the built site
|
|
16
|
-
uses: actions/download-artifact@
|
|
16
|
+
uses: actions/download-artifact@v8
|
|
17
17
|
with:
|
|
18
18
|
name: docs-site
|
|
19
19
|
path: site/
|
|
@@ -9,6 +9,57 @@ Dates are marked as `DD-MM-YYYY`
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.5.0] - 09-10-2026
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `SharedBox.read_into`: copies an array field into an array the caller
|
|
17
|
+
passes and returns it, without allocating a new array.
|
|
18
|
+
- `SharedBox.writing`: a context manager that holds the box's write lock
|
|
19
|
+
and yields an array field as an array to fill in place.
|
|
20
|
+
- `benchbox contention`: times writes and reads of an `int` while several
|
|
21
|
+
writer and reader processes share it, for a box, `mp.Value` and
|
|
22
|
+
`SharedMemory` with a `Lock`.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- `SharedBox`: a field named `read_into` raises `TypeError`.
|
|
27
|
+
- `SharedBox`: a field named `writing` raises `TypeError`.
|
|
28
|
+
- `SharedBox`: reading a collection, tuple or record field whose members
|
|
29
|
+
are `bool`, `int`, `float` or `str` takes less time: about 90 ns less
|
|
30
|
+
for a list of 16 `float` on Windows.
|
|
31
|
+
- `SharedBox`: reading a field whose value cannot be changed (a frozen
|
|
32
|
+
dataclass, attrs class or msgspec Struct, a NamedTuple, a tuple, a
|
|
33
|
+
frozenset, an enum, flag or literal, `complex`, `date`, `time`,
|
|
34
|
+
`datetime`, `timedelta`, `UUID` or `Decimal`) returns the value the
|
|
35
|
+
previous read built until the field is written: 40 ns instead of 540 ns
|
|
36
|
+
for a frozen dataclass of four fields on Windows. A tuple, frozenset or
|
|
37
|
+
record qualifies only when its members are of these kinds or `bool`,
|
|
38
|
+
`int`, `float`, `str` or `bytes`.
|
|
39
|
+
- `SharedBox`: a frozen record's `__post_init__`, attrs converters and
|
|
40
|
+
validators run on the first read after each write instead of on every
|
|
41
|
+
read.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- `SharedBox.attach`: a box whose header gives a field count other than the
|
|
46
|
+
class's raises `SchemaMismatchError` instead of `ValueError`.
|
|
47
|
+
|
|
48
|
+
## [0.4.1] - 07-10-2026
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `SharedBox.update`: takes about 7 to 9 ns less per call on Windows.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- `SharedBox.events`, `SharedBox.watch` and `BoxEvents.follow`: a process
|
|
57
|
+
that exits while watcher threads still run no longer aborts with
|
|
58
|
+
`terminate called without an active exception` on Linux with CPython
|
|
59
|
+
3.11 to 3.13. At exit, sharedbox stops every watcher thread and waits
|
|
60
|
+
up to 2 seconds in all for them to end, including any callback they are
|
|
61
|
+
running.
|
|
62
|
+
|
|
12
63
|
## [0.4.0] - 05-10-2026
|
|
13
64
|
|
|
14
65
|
### Added
|
|
@@ -279,7 +330,9 @@ stage.events.nested.connect(lambda path, new, old: print(path, new))
|
|
|
279
330
|
|
|
280
331
|
- Initial release
|
|
281
332
|
|
|
282
|
-
[Unreleased]: https://github.com/jacopoabramo/sharedbox/compare/v0.
|
|
333
|
+
[Unreleased]: https://github.com/jacopoabramo/sharedbox/compare/v0.5.0...HEAD
|
|
334
|
+
[0.5.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.1...v0.5.0
|
|
335
|
+
[0.4.1]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.0...v0.4.1
|
|
283
336
|
[0.4.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.3.1...v0.4.0
|
|
284
337
|
[0.3.1]: https://github.com/jacopoabramo/sharedbox/compare/v0.3.0...v0.3.1
|
|
285
338
|
[0.3.0]: https://github.com/jacopoabramo/sharedbox/compare/0.2.4...v0.3.0
|
|
@@ -33,15 +33,17 @@ sharedbox/
|
|
|
33
33
|
| |-- py.typed
|
|
34
34
|
| |-- benchmarks/ the benchbox command (extra: benchmarks)
|
|
35
35
|
| | |-- cli.py entry point; exits with an install hint without Typer
|
|
36
|
-
| | |-- _app.py Typer commands: ops, roundtrip, size, plot, all
|
|
36
|
+
| | |-- _app.py Typer commands: ops, roundtrip, contention, size, plot, all
|
|
37
37
|
| | |-- ops.py pyperf timings of single operations, against the stdlib
|
|
38
38
|
| | |-- roundtrip.py cross-process round trip percentiles
|
|
39
|
+
| | |-- contention.py throughput and percentiles with several writer and reader processes
|
|
39
40
|
| | |-- plot.py SVG charts of the ops and roundtrip results (matplotlib)
|
|
40
41
|
| | |-- size.py wheel and extension size (standard library only)
|
|
41
42
|
| | `-- size_diff.py wheel size table against main, for CI (standard library only)
|
|
42
43
|
| `-- _native/
|
|
43
44
|
| |-- module.cpp nanobind module: Segment, the Field descriptor, the BoxMethod type
|
|
44
|
-
| | (native update and snapshot) and the
|
|
45
|
+
| | (native update and snapshot), ValueCache (values kept for reuse) and the
|
|
46
|
+
| | error classes
|
|
45
47
|
| |-- codec.{hpp,cpp} converts field values to and from their stored bytes; encode_all
|
|
46
48
|
| | checks every value of an update before any is written,
|
|
47
49
|
| | with_record reads the whole record at once
|
|
@@ -51,6 +53,7 @@ sharedbox/
|
|
|
51
53
|
|-- tests/ pytest; many tests spawn processes
|
|
52
54
|
| |-- crossproc.py helpers that run a box in another process
|
|
53
55
|
| |-- forged_types.py builds segments with forged description tables
|
|
56
|
+
| |-- test_benchbox_contention.py benchbox contention, a short run
|
|
54
57
|
| |-- test_benchbox_plot.py benchbox plot; skipped without matplotlib and pyperf
|
|
55
58
|
| |-- test_capsule.py __sharedbox_box__, and the C consumer in tests/cpp/consumer/
|
|
56
59
|
| |-- test_doc_examples.py runs each docs/examples/*.py script
|
|
@@ -78,6 +81,8 @@ sharedbox/
|
|
|
78
81
|
|-- .github/workflows/check-docs.yaml builds the site and runs check_xrefs.py
|
|
79
82
|
|-- .github/workflows/publish-docs.yaml deploys the checked site to GitHub Pages
|
|
80
83
|
|-- .github/workflows/codspeed.yml benchmarks on CodSpeed
|
|
84
|
+
|-- .github/workflows/contention.yaml benchbox contention on Linux and Windows, for pull requests
|
|
85
|
+
| that touch the native code, and by hand
|
|
81
86
|
|-- CMakeLists.txt sharedbox::headers, sharedbox::c, extension build
|
|
82
87
|
|-- stubtest-allowlist.txt stubtest exceptions for nanobind types
|
|
83
88
|
|-- .clang-format clang-format style for the C and C++ sources
|
|
@@ -280,11 +285,12 @@ if __name__ == "__main__":
|
|
|
280
285
|
Motor.unlink()
|
|
281
286
|
```
|
|
282
287
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
+
A read decodes the stored bytes; a value that cannot be changed (a
|
|
289
|
+
`datetime`, or a frozen record, tuple or frozenset holding only such values)
|
|
290
|
+
is reused until its field is written. `update(**values)` writes several
|
|
291
|
+
fields at once; `watch(field)` and `events` report changes from any process.
|
|
292
|
+
C++ and C code take a box through `__sharedbox_box__` or open it by name; see
|
|
293
|
+
`docs/how-to/accept-a-box-in-cpp.md`, `docs/how-to/accept-a-box-in-c.md` and
|
|
288
294
|
`docs/how-to/open-a-box-from-a-program.md`.
|
|
289
295
|
|
|
290
296
|
## Docs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sharedbox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Python containers using shared memory.
|
|
5
5
|
Author-Email: Jacopo Abramo <jacopo.abramo@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -34,16 +34,24 @@ Description-Content-Type: text/markdown
|
|
|
34
34
|
> [!WARNING]
|
|
35
35
|
> This project is a work in progress; be patient or feel free to contribute.
|
|
36
36
|
|
|
37
|
-
`sharedbox`
|
|
37
|
+
`sharedbox` lets several Python processes share one record, as if they all
|
|
38
|
+
held the same dataclass. You declare the fields once, and every process that
|
|
39
|
+
opens the record reads and writes the same values in shared memory, so no
|
|
40
|
+
process has to send them to another.
|
|
38
41
|
|
|
39
42
|
## Installation
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
`sharedbox` needs CPython 3.11 or newer on Windows x64 or Linux x86_64. PyPI
|
|
45
|
+
has compiled wheels, so you don't need a compiler:
|
|
42
46
|
|
|
43
47
|
```sh
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
pip install sharedbox
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
or, in a project that [`uv`](https://docs.astral.sh/uv/) manages:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
uv add sharedbox
|
|
47
55
|
```
|
|
48
56
|
|
|
49
57
|
## Quick start
|
|
@@ -76,14 +84,32 @@ if __name__ == "__main__":
|
|
|
76
84
|
Motor.unlink()
|
|
77
85
|
```
|
|
78
86
|
|
|
87
|
+
The child finds the box by its class alone, and the parent prints the change
|
|
88
|
+
as soon as the child makes it.
|
|
89
|
+
|
|
79
90
|
## Documentation
|
|
80
91
|
|
|
81
|
-
The [documentation site](https://jacopoabramo.github.io/sharedbox)
|
|
82
|
-
|
|
83
|
-
reference.
|
|
92
|
+
The [documentation site](https://jacopoabramo.github.io/sharedbox) starts
|
|
93
|
+
with three tutorials, then has how-to guides, explanations of how a
|
|
94
|
+
box works, and the API reference. C and C++ code can use a box too, either
|
|
95
|
+
handed over from Python or opened by name; the
|
|
96
|
+
[C and C++ guides](https://jacopoabramo.github.io/sharedbox/how-to/accept-a-box-in-cpp/)
|
|
97
|
+
show how.
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
To change `sharedbox` itself you need `git`, `uv`, CMake 3.30 or newer and a
|
|
102
|
+
C++20 compiler (MSVC or GCC):
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
git clone https://github.com/jacopoabramo/sharedbox.git
|
|
106
|
+
cd sharedbox
|
|
107
|
+
uv sync --dev
|
|
108
|
+
uv run pytest
|
|
109
|
+
```
|
|
84
110
|
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
[How to set up a development environment](https://jacopoabramo.github.io/sharedbox/how-to/set-up-development/)
|
|
112
|
+
has the details.
|
|
87
113
|
|
|
88
114
|
## License
|
|
89
115
|
|
|
@@ -10,16 +10,24 @@
|
|
|
10
10
|
> [!WARNING]
|
|
11
11
|
> This project is a work in progress; be patient or feel free to contribute.
|
|
12
12
|
|
|
13
|
-
`sharedbox`
|
|
13
|
+
`sharedbox` lets several Python processes share one record, as if they all
|
|
14
|
+
held the same dataclass. You declare the fields once, and every process that
|
|
15
|
+
opens the record reads and writes the same values in shared memory, so no
|
|
16
|
+
process has to send them to another.
|
|
14
17
|
|
|
15
18
|
## Installation
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
`sharedbox` needs CPython 3.11 or newer on Windows x64 or Linux x86_64. PyPI
|
|
21
|
+
has compiled wheels, so you don't need a compiler:
|
|
18
22
|
|
|
19
23
|
```sh
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
pip install sharedbox
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
or, in a project that [`uv`](https://docs.astral.sh/uv/) manages:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
uv add sharedbox
|
|
23
31
|
```
|
|
24
32
|
|
|
25
33
|
## Quick start
|
|
@@ -52,14 +60,32 @@ if __name__ == "__main__":
|
|
|
52
60
|
Motor.unlink()
|
|
53
61
|
```
|
|
54
62
|
|
|
63
|
+
The child finds the box by its class alone, and the parent prints the change
|
|
64
|
+
as soon as the child makes it.
|
|
65
|
+
|
|
55
66
|
## Documentation
|
|
56
67
|
|
|
57
|
-
The [documentation site](https://jacopoabramo.github.io/sharedbox)
|
|
58
|
-
|
|
59
|
-
reference.
|
|
68
|
+
The [documentation site](https://jacopoabramo.github.io/sharedbox) starts
|
|
69
|
+
with three tutorials, then has how-to guides, explanations of how a
|
|
70
|
+
box works, and the API reference. C and C++ code can use a box too, either
|
|
71
|
+
handed over from Python or opened by name; the
|
|
72
|
+
[C and C++ guides](https://jacopoabramo.github.io/sharedbox/how-to/accept-a-box-in-cpp/)
|
|
73
|
+
show how.
|
|
74
|
+
|
|
75
|
+
## Development
|
|
76
|
+
|
|
77
|
+
To change `sharedbox` itself you need `git`, `uv`, CMake 3.30 or newer and a
|
|
78
|
+
C++20 compiler (MSVC or GCC):
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
git clone https://github.com/jacopoabramo/sharedbox.git
|
|
82
|
+
cd sharedbox
|
|
83
|
+
uv sync --dev
|
|
84
|
+
uv run pytest
|
|
85
|
+
```
|
|
60
86
|
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
[How to set up a development environment](https://jacopoabramo.github.io/sharedbox/how-to/set-up-development/)
|
|
88
|
+
has the details.
|
|
63
89
|
|
|
64
90
|
## License
|
|
65
91
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from collections.abc import Iterator
|
|
3
|
+
from dataclasses import dataclass
|
|
3
4
|
from itertools import count
|
|
4
5
|
from typing import Annotated
|
|
5
6
|
|
|
@@ -17,6 +18,22 @@ class Record(SharedBox):
|
|
|
17
18
|
s: Annotated[str, Capacity(32)]
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
class Samples(SharedBox):
|
|
22
|
+
floats: Annotated[list[float], Capacity(16)]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class Quad:
|
|
27
|
+
a: int
|
|
28
|
+
b: float
|
|
29
|
+
c: bool
|
|
30
|
+
d: int
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Quads(SharedBox):
|
|
34
|
+
quad: Quad
|
|
35
|
+
|
|
36
|
+
|
|
20
37
|
@pytest.fixture
|
|
21
38
|
def box() -> Iterator[Record]:
|
|
22
39
|
name = f"bench-codspeed-{os.getpid()}-{next(NAMES)}"
|
|
@@ -55,3 +72,27 @@ def test_native_set_int(benchmark: BenchmarkFixture, box: Record) -> None:
|
|
|
55
72
|
|
|
56
73
|
def test_native_get_int(benchmark: BenchmarkFixture, box: Record) -> None:
|
|
57
74
|
benchmark(box._segment.get, 0)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def samples() -> Iterator[Samples]:
|
|
79
|
+
name = f"bench-codspeed-{os.getpid()}-{next(NAMES)}"
|
|
80
|
+
with Samples.create(name, [0.5] * 16) as box:
|
|
81
|
+
yield box
|
|
82
|
+
Samples.unlink(name)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_read_float_list(benchmark: BenchmarkFixture, samples: Samples) -> None:
|
|
86
|
+
benchmark(getattr, samples, "floats")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.fixture
|
|
90
|
+
def quads() -> Iterator[Quads]:
|
|
91
|
+
name = f"bench-codspeed-{os.getpid()}-{next(NAMES)}"
|
|
92
|
+
with Quads.create(name, Quad(1, 1.5, True, 2)) as box:
|
|
93
|
+
yield box
|
|
94
|
+
Quads.unlink(name)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_read_record(benchmark: BenchmarkFixture, quads: Quads) -> None:
|
|
98
|
+
benchmark(getattr, quads, "quad")
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Shared look of every diagram in the docs. A diagram pulls it in with
|
|
2
|
+
# `...@diagrams/style` on its first line and gives shapes these classes.
|
|
3
|
+
classes: {
|
|
4
|
+
layer: {
|
|
5
|
+
style: {
|
|
6
|
+
border-radius: 10
|
|
7
|
+
font-size: 18
|
|
8
|
+
bold: true
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
step: {
|
|
12
|
+
style.border-radius: 6
|
|
13
|
+
}
|
|
14
|
+
current: {
|
|
15
|
+
style: {
|
|
16
|
+
border-radius: 6
|
|
17
|
+
stroke-width: 4
|
|
18
|
+
bold: true
|
|
19
|
+
shadow: true
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
done: {
|
|
23
|
+
style: {
|
|
24
|
+
border-radius: 6
|
|
25
|
+
opacity: 0.4
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
failed: {
|
|
29
|
+
style: {
|
|
30
|
+
border-radius: 6
|
|
31
|
+
stroke: "#c62828"
|
|
32
|
+
stroke-dash: 4
|
|
33
|
+
font-color: "#c62828"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
process: {
|
|
37
|
+
shape: hexagon
|
|
38
|
+
}
|
|
39
|
+
hardware: {
|
|
40
|
+
shape: cylinder
|
|
41
|
+
}
|
|
42
|
+
file: {
|
|
43
|
+
shape: page
|
|
44
|
+
}
|
|
45
|
+
note: {
|
|
46
|
+
shape: text
|
|
47
|
+
style: {
|
|
48
|
+
italic: true
|
|
49
|
+
font-size: 14
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
gap: {
|
|
53
|
+
label: ""
|
|
54
|
+
style.opacity: 0
|
|
55
|
+
}
|
|
56
|
+
# a shape a later step brings in: declared on the first board so that every
|
|
57
|
+
# board keeps the same layout, and shown by a step that changes its class
|
|
58
|
+
hidden: {
|
|
59
|
+
style.opacity: 0
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -23,6 +23,18 @@ sensor.frame = np.full((4, 6), 7, np.uint8)
|
|
|
23
23
|
print(int(sensor.frame.sum())) # 168
|
|
24
24
|
# --8<-- [end:write]
|
|
25
25
|
|
|
26
|
+
# --8<-- [start:read-into]
|
|
27
|
+
frame = np.empty((4, 6), np.uint8)
|
|
28
|
+
sensor.read_into("frame", frame)
|
|
29
|
+
print(int(frame.sum())) # 168
|
|
30
|
+
# --8<-- [end:read-into]
|
|
31
|
+
|
|
32
|
+
# --8<-- [start:writing]
|
|
33
|
+
with sensor.writing("frame") as frame:
|
|
34
|
+
frame[0, :] = 255
|
|
35
|
+
print(int(sensor.frame[0].sum())) # 1530
|
|
36
|
+
# --8<-- [end:writing]
|
|
37
|
+
|
|
26
38
|
# --8<-- [start:any-library]
|
|
27
39
|
raw = sensor.raw
|
|
28
40
|
print(np.from_dlpack(raw)) # [0. 0. 0.]
|