sharedbox 0.4.0__tar.gz → 0.4.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.
- sharedbox-0.4.1/.github/dependabot.yml +23 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.github/workflows/check-docs.yaml +2 -2
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.github/workflows/ci.yaml +15 -15
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.github/workflows/codspeed.yml +1 -1
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.github/workflows/publish-docs.yaml +2 -2
- {sharedbox-0.4.0 → sharedbox-0.4.1}/CHANGELOG.md +13 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/PKG-INFO +1 -1
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_events.py +45 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/codec.cpp +8 -4
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_version.py +3 -3
- sharedbox-0.4.1/tests/test_exit.py +53 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.clang-format +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.claude/settings.json +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/.gitignore +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/CLAUDE.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/CMakeLists.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/LICENSE +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/README.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/benchmarks/test_bench_box.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/cmake/sharedbox-config.cmake +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/cmake/sharedbox-require-cxx.cmake +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/assets/benchmarks/ops-dark.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/assets/benchmarks/ops-light.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/assets/benchmarks/roundtrip-dark.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/assets/benchmarks/roundtrip-light.svg +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/change_several_fields_at_once.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/clean_up_segments.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/follow_a_whole_reference_graph.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/name_a_box.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/send_a_box_to_another_process.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/set_defaults_and_check_values.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/store_arrays.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/store_collections.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/store_records.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/examples/store_text_and_bytes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/checking-a-process-is-alive.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/closing-and-lifetime.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/field-types.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/glossary.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/how-a-box-is-stored.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/how-the-module-is-built.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/limits.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/performance.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/reading-and-writing.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/references.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/waiting-for-changes.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/explanation/when-to-use-sharedbox.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/accept-a-box-in-c.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/accept-a-box-in-cpp.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/ai-contribution-policy.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/build-docs.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/change-several-fields-at-once.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/clean-up-segments.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/commits-and-prs.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/contribute.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/follow-a-whole-reference-graph.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/install-sharedbox.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/make-a-release.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/name-a-box.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/open-a-box-from-a-program.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/run-benchmarks.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/run-commit-checks.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/run-tests.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/send-a-box-to-another-process.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/set-defaults-and-check-values.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/set-up-development.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/store-arrays.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/store-collections.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/store-records.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/store-text-and-bytes.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/how-to/write-docs.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/arrays.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/box.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/errors.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/events.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/library-authors.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/api/references.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/changelog.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/cpp-and-c-api.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/reference/segment-layout.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/tutorials/index.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/tutorials/motor.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/tutorials/react-to-changes.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/tutorials/refer-to-another-box.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/docs/tutorials/share-a-record.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/include/sharedbox/sharedbox.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/include/sharedbox/sharedbox_c.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/include/sharedbox/sharedbox_c.h +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/includes/abbreviations.md +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/prek.toml +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/pyproject.toml +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/scripts/check_xrefs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/scripts/vscode_setup.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/__init__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_arrays.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_box.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_layout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/codec.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/module.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/scalars.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/scalars.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/segment.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/segment.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/types.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native/types.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_native.pyi +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_refs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/__init__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/__main__.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/_app.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/cli.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/ops.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/plot.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/roundtrip.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/size.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/benchmarks/size_diff.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/src/sharedbox/py.typed +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/stubtest-allowlist.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/conftest.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/CMakeLists.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/compile_fail.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/consumer/CMakeLists.txt +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/consumer/consumer.c +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/table_builder.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_atomics.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_c_smoke.c +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_c_smoke_box.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_fork.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_layout2.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_lock.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_mapping.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_result.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_slots.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_small_shm.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_types.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_values.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_wait.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/test_windows_h.cpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/cpp/unique.hpp +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/crossproc.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/forged_open.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/forged_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/refs_future.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/stress_helpers.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_contention.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_crashes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_lock_timeout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_memory.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_waiters.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/stress/test_stress_watchers.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_benchbox_plot.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_box.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_capsule.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_doc_examples.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_doc_tutorials.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_events_async.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_events_bytes.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_events_signals.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_events_sync.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_fields.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_follow.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_fork.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_layout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_layout_v1.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_codec.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_liveness.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_segment.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_wait.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_native_waiters.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_properties_codec.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_properties_forged.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_properties_layout.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_properties_stateful.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_properties_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_refs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_refs_lazy.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_arrays.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_arrays_bfloat16.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_arrays_torch.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_choices.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_collections.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_records.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_records_attrs.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_records_msgspec.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_scalars.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/test_types_unions.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/type_checks/box_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/tests/type_checks/events_types.py +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/uv.lock +0 -0
- {sharedbox-0.4.0 → sharedbox-0.4.1}/zensical.toml +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-*
|
|
@@ -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,19 @@ Dates are marked as `DD-MM-YYYY`
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- `SharedBox.update`: takes about 7 to 9 ns less per call on Windows.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- `SharedBox.events`, `SharedBox.watch` and `BoxEvents.follow`: a process
|
|
19
|
+
that exits while watcher threads still run no longer aborts with
|
|
20
|
+
`terminate called without an active exception` on Linux with CPython
|
|
21
|
+
3.11 to 3.13. At exit, sharedbox stops every watcher thread and waits
|
|
22
|
+
up to 2 seconds in all for them to end, including any callback they are
|
|
23
|
+
running.
|
|
24
|
+
|
|
12
25
|
## [0.4.0] - 05-10-2026
|
|
13
26
|
|
|
14
27
|
### Added
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import atexit
|
|
4
5
|
import contextlib
|
|
5
6
|
import logging
|
|
6
7
|
import threading
|
|
8
|
+
import time
|
|
7
9
|
from collections.abc import AsyncIterator, Callable, Generator, Iterator
|
|
8
10
|
from concurrent.futures import CancelledError
|
|
9
11
|
from typing import (
|
|
@@ -32,11 +34,14 @@ if TYPE_CHECKING:
|
|
|
32
34
|
T = TypeVar("T")
|
|
33
35
|
PENDING, DONE, CANCELLED = "pending", "done", "cancelled"
|
|
34
36
|
STEP: Final = 1.0
|
|
37
|
+
# Seconds the exit handler waits for stopped watcher threads, together.
|
|
38
|
+
EXIT_WAIT: Final = 2.0
|
|
35
39
|
logger = logging.getLogger("sharedbox")
|
|
36
40
|
# Receives each change of a field as native values: the field, the new value, the old one.
|
|
37
41
|
Sink: TypeAlias = "Callable[[FieldSpec, Any, Any], None]"
|
|
38
42
|
# Marks watcher threads: one must not join another, since that one may be joining it.
|
|
39
43
|
WATCHER_THREAD = threading.local()
|
|
44
|
+
RUNNING: set[Watcher] = set()
|
|
40
45
|
|
|
41
46
|
|
|
42
47
|
def on_watcher_thread() -> bool:
|
|
@@ -44,6 +49,43 @@ def on_watcher_thread() -> bool:
|
|
|
44
49
|
return getattr(WATCHER_THREAD, "active", False)
|
|
45
50
|
|
|
46
51
|
|
|
52
|
+
def stop_watchers() -> None:
|
|
53
|
+
"""Stop every watcher thread and wait for them to end, before the interpreter finalizes.
|
|
54
|
+
|
|
55
|
+
The wait lasts at most `EXIT_WAIT` seconds in all; a thread still running
|
|
56
|
+
a callback after that is logged and left running. On CPython before 3.14, a daemon thread that takes the GIL back during
|
|
57
|
+
finalization is ended with `pthread_exit` on Linux. The unwinding that
|
|
58
|
+
starts there aborts the process when it reaches the native call that
|
|
59
|
+
released the GIL, such as a watcher's wait or a box's `close`.
|
|
60
|
+
"""
|
|
61
|
+
# A copy, because watcher threads remove themselves from the set while this runs.
|
|
62
|
+
watchers = RUNNING.copy()
|
|
63
|
+
threads = [watcher._thread for watcher in watchers]
|
|
64
|
+
for watcher in watchers:
|
|
65
|
+
watcher.stop(wait=False)
|
|
66
|
+
# Bounded, so a callback that never returns cannot keep the process from exiting.
|
|
67
|
+
deadline = time.monotonic() + EXIT_WAIT
|
|
68
|
+
for thread in threads:
|
|
69
|
+
if thread is not None and thread is not threading.current_thread():
|
|
70
|
+
thread.join(max(0.0, deadline - time.monotonic()))
|
|
71
|
+
late = [
|
|
72
|
+
thread.name
|
|
73
|
+
for thread in threads
|
|
74
|
+
if thread is not None
|
|
75
|
+
and thread.is_alive()
|
|
76
|
+
and thread is not threading.current_thread()
|
|
77
|
+
]
|
|
78
|
+
if late:
|
|
79
|
+
logger.warning(
|
|
80
|
+
"watcher threads still running at exit after %s s: %s",
|
|
81
|
+
EXIT_WAIT,
|
|
82
|
+
", ".join(late),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
atexit.register(stop_watchers)
|
|
87
|
+
|
|
88
|
+
|
|
47
89
|
class FieldFuture(Generic[T]):
|
|
48
90
|
"""The next value written to one field of a box.
|
|
49
91
|
|
|
@@ -402,6 +444,7 @@ class Watcher:
|
|
|
402
444
|
self._thread = None
|
|
403
445
|
self._pending = []
|
|
404
446
|
self._slot = None
|
|
447
|
+
RUNNING.discard(self)
|
|
405
448
|
|
|
406
449
|
def _start_locked(self) -> None:
|
|
407
450
|
if self._thread is None and not self._stop.is_set():
|
|
@@ -410,6 +453,7 @@ class Watcher:
|
|
|
410
453
|
name=f"sharedbox-watch-{self._segment.name}",
|
|
411
454
|
daemon=True,
|
|
412
455
|
)
|
|
456
|
+
RUNNING.add(self)
|
|
413
457
|
self._thread.start()
|
|
414
458
|
|
|
415
459
|
def _claim(self) -> int | None:
|
|
@@ -456,6 +500,7 @@ class Watcher:
|
|
|
456
500
|
# The step bounds how long a freed slot or a missed wake-up goes unnoticed.
|
|
457
501
|
generation = self._segment.wait(generation, STEP, slot)
|
|
458
502
|
finally:
|
|
503
|
+
RUNNING.discard(self)
|
|
459
504
|
if self._slot is not None:
|
|
460
505
|
self._segment.release_waiter(self._slot)
|
|
461
506
|
|
|
@@ -206,10 +206,14 @@ void encode_all(const Segment &s, const Types *types, std::span<const Pending> v
|
|
|
206
206
|
// Checked before the narrowing cast, which would otherwise turn index 65536 into field 0.
|
|
207
207
|
check_index(index, fields.size());
|
|
208
208
|
const FieldDesc &field = fields[index];
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
// The members are written separately because MSVC copies a value built in one step through
|
|
210
|
+
// a stack temporary and reloads it, which stalls for about 10 ns per update.
|
|
211
|
+
const std::span<const std::byte> bytes =
|
|
212
|
+
static_cast<std::uint8_t>(field.kind) <= kind_ref
|
|
213
|
+
? encode(field, names[index], values[i].value, buffers[i])
|
|
214
|
+
: need(types, index).encode(index, values[i].value, buffers[i]);
|
|
215
|
+
out[i].field = static_cast<std::uint16_t>(index);
|
|
216
|
+
out[i].bytes = bytes;
|
|
213
217
|
}
|
|
214
218
|
}
|
|
215
219
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.4.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 4,
|
|
21
|
+
__version__ = version = '0.4.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 4, 1)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gcd153a59e'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import multiprocessing as mp
|
|
2
|
+
import threading
|
|
3
|
+
import time
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from sharedbox import DType, Shape, SharedBox
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Blob(SharedBox):
|
|
12
|
+
tick: int = 0
|
|
13
|
+
big: Annotated[np.ndarray, Shape(512, 512), DType("float64")] = np.zeros((512, 512))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def exit_during_a_callback(name: str) -> None:
|
|
17
|
+
"""Return from the child while a callback is reading and closing fresh handles."""
|
|
18
|
+
box = Blob.attach(name)
|
|
19
|
+
started = threading.Event()
|
|
20
|
+
|
|
21
|
+
def churn(new: int, old: int) -> None:
|
|
22
|
+
started.set()
|
|
23
|
+
end = time.monotonic() + 1
|
|
24
|
+
while time.monotonic() < end:
|
|
25
|
+
with Blob.attach(name) as fresh:
|
|
26
|
+
_ = fresh.big
|
|
27
|
+
|
|
28
|
+
box.events.tick.connect(churn)
|
|
29
|
+
with Blob.attach(name) as writer:
|
|
30
|
+
while not started.wait(0.05):
|
|
31
|
+
writer.tick += 1
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_a_process_exits_cleanly_while_a_callback_makes_native_calls(
|
|
35
|
+
unique_name: str,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Check that spawned processes exit with code 0 when a callback is inside native calls at exit."""
|
|
38
|
+
context = mp.get_context("spawn")
|
|
39
|
+
with Blob.create(unique_name):
|
|
40
|
+
children = [
|
|
41
|
+
context.Process(target=exit_during_a_callback, args=(unique_name,))
|
|
42
|
+
for _ in range(5)
|
|
43
|
+
]
|
|
44
|
+
for child in children:
|
|
45
|
+
child.start()
|
|
46
|
+
for child in children:
|
|
47
|
+
child.join(60)
|
|
48
|
+
if child.is_alive():
|
|
49
|
+
child.kill()
|
|
50
|
+
child.join(10)
|
|
51
|
+
Blob.unlink(unique_name)
|
|
52
|
+
exitcodes = [child.exitcode for child in children]
|
|
53
|
+
assert exitcodes == [0] * len(children), f"exit codes: {exitcodes}"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|