band-sdk-core 0.2.1.dev2__tar.gz → 0.2.1.dev4__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 (34) hide show
  1. band_sdk_core-0.2.1.dev4/PKG-INFO +51 -0
  2. band_sdk_core-0.2.1.dev4/README.md +42 -0
  3. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/Cargo.toml +2 -1
  4. band_sdk_core-0.2.1.dev4/bindings/python/README.md +42 -0
  5. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/src/lib.rs +1 -1
  6. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_claim_registry.py +14 -14
  7. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_panic_boundary.py +4 -4
  8. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_participant_tracker.py +16 -16
  9. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_retry_tracker.py +6 -6
  10. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_smoke.py +2 -2
  11. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_stub_surface.py +8 -8
  12. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_tracing_propagation.py +10 -10
  13. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/pyproject.toml +3 -2
  14. band_sdk_core-0.2.1.dev2/PKG-INFO +0 -6
  15. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/Cargo.lock +0 -0
  16. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/Cargo.toml +0 -0
  17. /band_sdk_core-0.2.1.dev2/bindings/python/_band_sdk_core.pyi → /band_sdk_core-0.2.1.dev4/bindings/python/band_sdk_core.pyi +0 -0
  18. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/src/claim_registry.rs +0 -0
  19. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/src/participant_tracker.rs +0 -0
  20. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/src/retry_tracker.rs +0 -0
  21. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/src/tracing_init.rs +0 -0
  22. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/bindings/python/tests/test_wheel_ships_typing.py +0 -0
  23. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/Cargo.toml +0 -0
  24. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/src/claims.rs +0 -0
  25. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/src/lib.rs +0 -0
  26. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/src/participant_tracker.rs +0 -0
  27. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/src/retry_tracker.rs +0 -0
  28. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/.gitkeep +0 -0
  29. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/claims.rs +0 -0
  30. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/common/mod.rs +0 -0
  31. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/observability.rs +0 -0
  32. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/participant_tracker.rs +0 -0
  33. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/retry_tracker.proptest-regressions +0 -0
  34. {band_sdk_core-0.2.1.dev2 → band_sdk_core-0.2.1.dev4}/crates/core-runtime/tests/retry_tracker.rs +0 -0
@@ -0,0 +1,51 @@
1
+ Metadata-Version: 2.4
2
+ Name: band-sdk-core
3
+ Version: 0.2.1.dev4
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Summary: Shared Rust core for the Band SDK stack: claims registry, retry tracking, and participant tracking, with Python bindings via PyO3.
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+
9
+ # band-sdk-core
10
+
11
+ Shared Rust core for the Band SDK stack, exposed to Python via PyO3: a message claims
12
+ registry, a retry tracker, and a participant tracker, plus an optional tracing bridge.
13
+ See the [repo README](https://github.com/band-ai/band-sdk-core) for the full workspace
14
+ layout and how this binding fits alongside the Rust crates and the Node binding.
15
+
16
+ ```bash
17
+ pip install --pre band-sdk-core # currently pre-release only, see Versioning below
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```python
23
+ import band_sdk_core as core
24
+
25
+ registry = core.MessageClaimRegistry(max_completed=500)
26
+ with registry.claim("room-1", "msg-1") as acquired:
27
+ if acquired:
28
+ ... # handle the message; released automatically on exit, even on exception
29
+
30
+ retry = core.MessageRetryTracker(max_retries=3)
31
+ attempt, exceeded = retry.record_attempt("msg-1")
32
+
33
+ participants = core.ParticipantTracker("room-1")
34
+ participants.add(core.TrackedParticipant(id="user-1", name="Alice"))
35
+ ```
36
+
37
+ Optional tracing bridge (`RUST_LOG`-filtered, defaults to `info`):
38
+
39
+ ```python
40
+ with core.Tracing():
41
+ ...
42
+ ```
43
+
44
+ ## Versioning
45
+
46
+ This package is currently shipping as an ongoing pre-release stream
47
+ (`X.Y.Z.devN`) — install with `pip install --pre band-sdk-core` or pin an exact
48
+ version. A stable release will follow once the API settles.
49
+
50
+ Ships `py.typed` and a `.pyi` stub for full type-checker support.
51
+
@@ -0,0 +1,42 @@
1
+ # band-sdk-core
2
+
3
+ Shared Rust core for the Band SDK stack, exposed to Python via PyO3: a message claims
4
+ registry, a retry tracker, and a participant tracker, plus an optional tracing bridge.
5
+ See the [repo README](https://github.com/band-ai/band-sdk-core) for the full workspace
6
+ layout and how this binding fits alongside the Rust crates and the Node binding.
7
+
8
+ ```bash
9
+ pip install --pre band-sdk-core # currently pre-release only, see Versioning below
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```python
15
+ import band_sdk_core as core
16
+
17
+ registry = core.MessageClaimRegistry(max_completed=500)
18
+ with registry.claim("room-1", "msg-1") as acquired:
19
+ if acquired:
20
+ ... # handle the message; released automatically on exit, even on exception
21
+
22
+ retry = core.MessageRetryTracker(max_retries=3)
23
+ attempt, exceeded = retry.record_attempt("msg-1")
24
+
25
+ participants = core.ParticipantTracker("room-1")
26
+ participants.add(core.TrackedParticipant(id="user-1", name="Alice"))
27
+ ```
28
+
29
+ Optional tracing bridge (`RUST_LOG`-filtered, defaults to `info`):
30
+
31
+ ```python
32
+ with core.Tracing():
33
+ ...
34
+ ```
35
+
36
+ ## Versioning
37
+
38
+ This package is currently shipping as an ongoing pre-release stream
39
+ (`X.Y.Z.devN`) — install with `pip install --pre band-sdk-core` or pin an exact
40
+ version. A stable release will follow once the API settles.
41
+
42
+ Ships `py.typed` and a `.pyi` stub for full type-checker support.
@@ -5,6 +5,7 @@ edition.workspace = true
5
5
  rust-version.workspace = true
6
6
  license.workspace = true
7
7
  repository.workspace = true
8
+ readme = "README.md"
8
9
 
9
10
  [lints]
10
11
  workspace = true
@@ -16,7 +17,7 @@ workspace = true
16
17
  panic-test = []
17
18
 
18
19
  [lib]
19
- name = "_band_sdk_core"
20
+ name = "band_sdk_core"
20
21
  crate-type = ["cdylib"]
21
22
 
22
23
  [dependencies]
@@ -0,0 +1,42 @@
1
+ # band-sdk-core
2
+
3
+ Shared Rust core for the Band SDK stack, exposed to Python via PyO3: a message claims
4
+ registry, a retry tracker, and a participant tracker, plus an optional tracing bridge.
5
+ See the [repo README](https://github.com/band-ai/band-sdk-core) for the full workspace
6
+ layout and how this binding fits alongside the Rust crates and the Node binding.
7
+
8
+ ```bash
9
+ pip install --pre band-sdk-core # currently pre-release only, see Versioning below
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```python
15
+ import band_sdk_core as core
16
+
17
+ registry = core.MessageClaimRegistry(max_completed=500)
18
+ with registry.claim("room-1", "msg-1") as acquired:
19
+ if acquired:
20
+ ... # handle the message; released automatically on exit, even on exception
21
+
22
+ retry = core.MessageRetryTracker(max_retries=3)
23
+ attempt, exceeded = retry.record_attempt("msg-1")
24
+
25
+ participants = core.ParticipantTracker("room-1")
26
+ participants.add(core.TrackedParticipant(id="user-1", name="Alice"))
27
+ ```
28
+
29
+ Optional tracing bridge (`RUST_LOG`-filtered, defaults to `info`):
30
+
31
+ ```python
32
+ with core.Tracing():
33
+ ...
34
+ ```
35
+
36
+ ## Versioning
37
+
38
+ This package is currently shipping as an ongoing pre-release stream
39
+ (`X.Y.Z.devN`) — install with `pip install --pre band-sdk-core` or pin an exact
40
+ version. A stable release will follow once the API settles.
41
+
42
+ Ships `py.typed` and a `.pyi` stub for full type-checker support.
@@ -18,7 +18,7 @@ fn debug_panic() {
18
18
  }
19
19
 
20
20
  #[pymodule]
21
- fn _band_sdk_core(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
21
+ fn band_sdk_core(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
22
22
  m.add_class::<claim_registry::MessageClaimRegistry>()?;
23
23
  m.add_class::<claim_registry::ClaimGuard>()?;
24
24
  m.add_class::<retry_tracker::MessageRetryTracker>()?;
@@ -1,10 +1,10 @@
1
1
  import pytest
2
2
 
3
- import _band_sdk_core
3
+ import band_sdk_core
4
4
 
5
5
 
6
6
  def test_try_claim_blocks_a_second_owner_until_released():
7
- registry = _band_sdk_core.MessageClaimRegistry(10)
7
+ registry = band_sdk_core.MessageClaimRegistry(10)
8
8
 
9
9
  assert registry._try_claim("room-1", "msg-1") is True
10
10
  assert registry._try_claim("room-1", "msg-1") is False
@@ -14,14 +14,14 @@ def test_try_claim_blocks_a_second_owner_until_released():
14
14
 
15
15
 
16
16
  def test_try_claim_accepts_an_optional_correlation_id_without_error():
17
- registry = _band_sdk_core.MessageClaimRegistry(10)
17
+ registry = band_sdk_core.MessageClaimRegistry(10)
18
18
 
19
19
  assert registry._try_claim("room-1", "msg-1", correlation_id="corr-abc") is True
20
20
  registry._release("room-1", "msg-1", correlation_id="corr-abc")
21
21
 
22
22
 
23
23
  def test_max_completed_defaults_without_an_explicit_argument():
24
- registry = _band_sdk_core.MessageClaimRegistry()
24
+ registry = band_sdk_core.MessageClaimRegistry()
25
25
 
26
26
  for i in range(501):
27
27
  registry.remember_completed("room-1", f"msg-{i}")
@@ -31,7 +31,7 @@ def test_max_completed_defaults_without_an_explicit_argument():
31
31
 
32
32
 
33
33
  def test_completed_cache_is_scoped_per_room_and_respects_its_cap():
34
- registry = _band_sdk_core.MessageClaimRegistry(1)
34
+ registry = band_sdk_core.MessageClaimRegistry(1)
35
35
 
36
36
  registry.remember_completed("room-1", "msg-1")
37
37
  registry.remember_completed("room-1", "msg-2") # evicts msg-1, cap is 1
@@ -41,7 +41,7 @@ def test_completed_cache_is_scoped_per_room_and_respects_its_cap():
41
41
 
42
42
 
43
43
  def test_ack_pending_lifecycle():
44
- registry = _band_sdk_core.MessageClaimRegistry(10)
44
+ registry = band_sdk_core.MessageClaimRegistry(10)
45
45
 
46
46
  assert registry.is_ack_pending("room-1", "msg-1") is False
47
47
  registry.remember_ack_pending("room-1", "msg-1")
@@ -56,7 +56,7 @@ def test_ack_pending_lifecycle():
56
56
 
57
57
 
58
58
  def test_discard_ack_pending_gives_up_and_resets_the_retry_count():
59
- registry = _band_sdk_core.MessageClaimRegistry(10)
59
+ registry = band_sdk_core.MessageClaimRegistry(10)
60
60
  registry.remember_ack_pending("room-1", "msg-1")
61
61
  registry.record_ack_retry("room-1", "msg-1")
62
62
 
@@ -67,7 +67,7 @@ def test_discard_ack_pending_gives_up_and_resets_the_retry_count():
67
67
 
68
68
 
69
69
  def test_discard_room_forgets_claims_acks_and_the_completed_cache():
70
- registry = _band_sdk_core.MessageClaimRegistry(10)
70
+ registry = band_sdk_core.MessageClaimRegistry(10)
71
71
  registry.remember_completed("room-1", "done")
72
72
  registry._try_claim("room-1", "stranded")
73
73
  registry.remember_ack_pending("room-1", "owed")
@@ -80,7 +80,7 @@ def test_discard_room_forgets_claims_acks_and_the_completed_cache():
80
80
 
81
81
 
82
82
  def test_claim_guard_releases_on_normal_exit():
83
- registry = _band_sdk_core.MessageClaimRegistry(10)
83
+ registry = band_sdk_core.MessageClaimRegistry(10)
84
84
 
85
85
  with registry.claim("room-1", "msg-1") as acquired:
86
86
  assert acquired is True
@@ -89,7 +89,7 @@ def test_claim_guard_releases_on_normal_exit():
89
89
 
90
90
 
91
91
  def test_claim_guard_releases_even_when_the_body_raises():
92
- registry = _band_sdk_core.MessageClaimRegistry(10)
92
+ registry = band_sdk_core.MessageClaimRegistry(10)
93
93
 
94
94
  try:
95
95
  with registry.claim("room-1", "msg-1") as acquired:
@@ -102,7 +102,7 @@ def test_claim_guard_releases_even_when_the_body_raises():
102
102
 
103
103
 
104
104
  def test_claim_guard_reports_contention_and_does_not_release_the_owner():
105
- registry = _band_sdk_core.MessageClaimRegistry(10)
105
+ registry = band_sdk_core.MessageClaimRegistry(10)
106
106
  assert registry._try_claim("room-1", "msg-1") is True
107
107
 
108
108
  with registry.claim("room-1", "msg-1") as acquired:
@@ -113,7 +113,7 @@ def test_claim_guard_reports_contention_and_does_not_release_the_owner():
113
113
 
114
114
 
115
115
  def test_claim_guard_rejects_a_second_enter_instead_of_losing_track_of_the_first():
116
- registry = _band_sdk_core.MessageClaimRegistry(10)
116
+ registry = band_sdk_core.MessageClaimRegistry(10)
117
117
  guard = registry.claim("room-1", "msg-1")
118
118
 
119
119
  guard.__enter__()
@@ -128,7 +128,7 @@ def test_claim_guard_rejects_a_second_enter_instead_of_losing_track_of_the_first
128
128
 
129
129
 
130
130
  def test_claim_guard_exit_is_a_no_op_after_the_first_release():
131
- registry = _band_sdk_core.MessageClaimRegistry(10)
131
+ registry = band_sdk_core.MessageClaimRegistry(10)
132
132
  guard = registry.claim("room-1", "msg-1")
133
133
  guard.__enter__()
134
134
  guard.__exit__(None, None, None)
@@ -142,7 +142,7 @@ def test_claim_guard_exit_is_a_no_op_after_the_first_release():
142
142
 
143
143
 
144
144
  def test_claim_guard_accepts_an_optional_correlation_id_without_error():
145
- registry = _band_sdk_core.MessageClaimRegistry(10)
145
+ registry = band_sdk_core.MessageClaimRegistry(10)
146
146
 
147
147
  with registry.claim("room-1", "msg-1", correlation_id="corr-abc") as acquired:
148
148
  assert acquired is True
@@ -8,17 +8,17 @@ skip rather than fail.
8
8
 
9
9
  import pytest
10
10
 
11
- import _band_sdk_core
11
+ import band_sdk_core
12
12
 
13
13
  pytestmark = pytest.mark.skipif(
14
- not hasattr(_band_sdk_core, "debug_panic"),
14
+ not hasattr(band_sdk_core, "debug_panic"),
15
15
  reason="built without --features panic-test",
16
16
  )
17
17
 
18
18
 
19
19
  def test_rust_panic_surfaces_as_catchable_panic_exception():
20
20
  with pytest.raises(BaseException, match="deliberate panic") as excinfo:
21
- _band_sdk_core.debug_panic()
21
+ band_sdk_core.debug_panic()
22
22
 
23
23
  assert type(excinfo.value).__name__ == "PanicException"
24
24
 
@@ -29,6 +29,6 @@ def test_panic_exception_is_a_base_exception_not_an_exception():
29
29
  # swallow it. Pinned on purpose: handler code relying on `except
30
30
  # Exception` must know a Rust panic flies past it.
31
31
  with pytest.raises(BaseException) as excinfo:
32
- _band_sdk_core.debug_panic()
32
+ band_sdk_core.debug_panic()
33
33
 
34
34
  assert not isinstance(excinfo.value, Exception)
@@ -1,46 +1,46 @@
1
- import _band_sdk_core
1
+ import band_sdk_core
2
2
 
3
3
 
4
4
  def test_room_id_returns_the_configured_room():
5
- tracker = _band_sdk_core.ParticipantTracker("room-1")
5
+ tracker = band_sdk_core.ParticipantTracker("room-1")
6
6
  assert tracker.room_id() == "room-1"
7
7
 
8
8
 
9
9
  def test_add_returns_true_and_stores_the_participant():
10
- tracker = _band_sdk_core.ParticipantTracker("room-1")
11
- participant = _band_sdk_core.TrackedParticipant(id="p1", name="Ada")
10
+ tracker = band_sdk_core.ParticipantTracker("room-1")
11
+ participant = band_sdk_core.TrackedParticipant(id="p1", name="Ada")
12
12
 
13
13
  assert tracker.add(participant) is True
14
14
  assert [p.id for p in tracker.participants()] == ["p1"]
15
15
 
16
16
 
17
17
  def test_tracked_participant_equality_compares_fields_not_identity():
18
- a = _band_sdk_core.TrackedParticipant(id="p1", name="Ada")
19
- b = _band_sdk_core.TrackedParticipant(id="p1", name="Ada")
18
+ a = band_sdk_core.TrackedParticipant(id="p1", name="Ada")
19
+ b = band_sdk_core.TrackedParticipant(id="p1", name="Ada")
20
20
 
21
21
  assert a == b
22
- assert a != _band_sdk_core.TrackedParticipant(id="p2", name="Ada")
22
+ assert a != band_sdk_core.TrackedParticipant(id="p2", name="Ada")
23
23
 
24
24
 
25
25
  def test_add_rejects_a_duplicate_id_without_storing_it_twice():
26
- tracker = _band_sdk_core.ParticipantTracker("room-1")
27
- tracker.add(_band_sdk_core.TrackedParticipant(id="p1"))
26
+ tracker = band_sdk_core.ParticipantTracker("room-1")
27
+ tracker.add(band_sdk_core.TrackedParticipant(id="p1"))
28
28
 
29
- assert tracker.add(_band_sdk_core.TrackedParticipant(id="p1")) is False
29
+ assert tracker.add(band_sdk_core.TrackedParticipant(id="p1")) is False
30
30
  assert len(tracker.participants()) == 1
31
31
 
32
32
 
33
33
  def test_remove_reports_whether_a_participant_was_actually_present():
34
- tracker = _band_sdk_core.ParticipantTracker("room-1")
35
- tracker.add(_band_sdk_core.TrackedParticipant(id="p1"))
34
+ tracker = band_sdk_core.ParticipantTracker("room-1")
35
+ tracker.add(band_sdk_core.TrackedParticipant(id="p1"))
36
36
 
37
37
  assert tracker.remove("p1") is True
38
38
  assert tracker.remove("p1") is False
39
39
 
40
40
 
41
41
  def test_changed_is_true_until_the_current_roster_is_marked_sent():
42
- tracker = _band_sdk_core.ParticipantTracker("room-1")
43
- tracker.add(_band_sdk_core.TrackedParticipant(id="p1"))
42
+ tracker = band_sdk_core.ParticipantTracker("room-1")
43
+ tracker.add(band_sdk_core.TrackedParticipant(id="p1"))
44
44
 
45
45
  assert tracker.changed() is True
46
46
  tracker.mark_sent()
@@ -48,10 +48,10 @@ def test_changed_is_true_until_the_current_roster_is_marked_sent():
48
48
 
49
49
 
50
50
  def test_set_loaded_replaces_the_roster_and_flips_the_loaded_flag():
51
- tracker = _band_sdk_core.ParticipantTracker("room-1")
51
+ tracker = band_sdk_core.ParticipantTracker("room-1")
52
52
  assert tracker.is_loaded() is False
53
53
 
54
- tracker.set_loaded([_band_sdk_core.TrackedParticipant(id="p1")])
54
+ tracker.set_loaded([band_sdk_core.TrackedParticipant(id="p1")])
55
55
 
56
56
  assert tracker.is_loaded() is True
57
57
  assert [p.id for p in tracker.participants()] == ["p1"]
@@ -1,13 +1,13 @@
1
- import _band_sdk_core
1
+ import band_sdk_core
2
2
 
3
3
 
4
4
  def test_default_tracks_a_budget_of_one_retry():
5
- tracker = _band_sdk_core.MessageRetryTracker()
5
+ tracker = band_sdk_core.MessageRetryTracker()
6
6
  assert tracker.max_retries() == 1
7
7
 
8
8
 
9
9
  def test_tracks_attempts_and_exceeds_budget():
10
- tracker = _band_sdk_core.MessageRetryTracker(2, 100)
10
+ tracker = band_sdk_core.MessageRetryTracker(2, 100)
11
11
 
12
12
  assert tracker.record_attempt("msg-1") == (1, False)
13
13
  assert tracker.record_attempt("msg-1") == (2, False)
@@ -18,7 +18,7 @@ def test_tracks_attempts_and_exceeds_budget():
18
18
 
19
19
 
20
20
  def test_mark_success_resets_the_attempt_count():
21
- tracker = _band_sdk_core.MessageRetryTracker(3, 100)
21
+ tracker = band_sdk_core.MessageRetryTracker(3, 100)
22
22
  tracker.record_attempt("msg-1")
23
23
  tracker.record_attempt("msg-1")
24
24
 
@@ -28,7 +28,7 @@ def test_mark_success_resets_the_attempt_count():
28
28
 
29
29
 
30
30
  def test_discard_attempt_decrements_rather_than_clears():
31
- tracker = _band_sdk_core.MessageRetryTracker(5, 100)
31
+ tracker = band_sdk_core.MessageRetryTracker(5, 100)
32
32
  tracker.record_attempt("msg-1")
33
33
  tracker.record_attempt("msg-1")
34
34
  tracker.record_attempt("msg-1")
@@ -39,6 +39,6 @@ def test_discard_attempt_decrements_rather_than_clears():
39
39
 
40
40
 
41
41
  def test_mark_permanently_failed_bypasses_the_retry_budget_entirely():
42
- tracker = _band_sdk_core.MessageRetryTracker(100, 100)
42
+ tracker = band_sdk_core.MessageRetryTracker(100, 100)
43
43
  tracker.mark_permanently_failed("msg-1")
44
44
  assert tracker.is_permanently_failed("msg-1") is True
@@ -1,7 +1,7 @@
1
1
  """Smoke test against the built extension only — not band-sdk-python's suite."""
2
2
 
3
- import _band_sdk_core
3
+ import band_sdk_core
4
4
 
5
5
 
6
6
  def test_module_imports():
7
- assert _band_sdk_core is not None
7
+ assert band_sdk_core is not None
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
 
14
14
  import pytest
15
15
 
16
- import _band_sdk_core
16
+ import band_sdk_core
17
17
 
18
18
  # Feature-gated test hooks (built only with `--features panic-test`) are
19
19
  # deliberately absent from the stub: they never ship in a release artifact.
@@ -21,12 +21,12 @@ FEATURE_GATED = {"debug_panic"}
21
21
 
22
22
 
23
23
  def _load_stub():
24
- module_file = getattr(_band_sdk_core, "__file__", None)
24
+ module_file = getattr(band_sdk_core, "__file__", None)
25
25
  candidates = []
26
26
  if module_file:
27
27
  candidates.extend(Path(module_file).parent.glob("*.pyi"))
28
28
  # maturin-develop / repo checkout fallback.
29
- candidates.append(Path(__file__).parent.parent / "_band_sdk_core.pyi")
29
+ candidates.append(Path(__file__).parent.parent / "band_sdk_core.pyi")
30
30
  for candidate in candidates:
31
31
  if candidate.exists():
32
32
  return ast.parse(candidate.read_text())
@@ -42,10 +42,10 @@ STUB_FUNCTIONS = {
42
42
 
43
43
  def _module_surface():
44
44
  classes, functions = set(), set()
45
- for name in dir(_band_sdk_core):
45
+ for name in dir(band_sdk_core):
46
46
  if name.startswith("__") or name in FEATURE_GATED:
47
47
  continue
48
- obj = getattr(_band_sdk_core, name)
48
+ obj = getattr(band_sdk_core, name)
49
49
  if inspect.ismodule(obj):
50
50
  continue # the extension exposes a self-reference attribute
51
51
  (classes if inspect.isclass(obj) else functions).add(name)
@@ -76,7 +76,7 @@ def _stub_attributes(cls_node):
76
76
 
77
77
  @pytest.mark.parametrize("class_name", sorted(STUB_CLASSES))
78
78
  def test_every_stub_declared_member_exists(class_name):
79
- cls = getattr(_band_sdk_core, class_name)
79
+ cls = getattr(band_sdk_core, class_name)
80
80
  node = STUB_CLASSES[class_name]
81
81
 
82
82
  for method_name in _stub_methods(node):
@@ -87,7 +87,7 @@ def test_every_stub_declared_member_exists(class_name):
87
87
 
88
88
  @pytest.mark.parametrize("class_name", sorted(STUB_CLASSES))
89
89
  def test_every_runtime_public_member_is_declared_in_the_stub(class_name):
90
- cls = getattr(_band_sdk_core, class_name)
90
+ cls = getattr(band_sdk_core, class_name)
91
91
  node = STUB_CLASSES[class_name]
92
92
  declared = set(_stub_methods(node)) | _stub_attributes(node)
93
93
 
@@ -150,7 +150,7 @@ def _assert_signatures_match(qualname, stub_params, runtime_params):
150
150
 
151
151
  @pytest.mark.parametrize("class_name", sorted(STUB_CLASSES))
152
152
  def test_method_signatures_match_the_stub(class_name):
153
- cls = getattr(_band_sdk_core, class_name)
153
+ cls = getattr(band_sdk_core, class_name)
154
154
  node = STUB_CLASSES[class_name]
155
155
 
156
156
  compared = 0
@@ -12,13 +12,13 @@ import os
12
12
  import subprocess
13
13
  import sys
14
14
 
15
- import _band_sdk_core
15
+ import band_sdk_core
16
16
 
17
17
  SCRIPT = """
18
- import _band_sdk_core
18
+ import band_sdk_core
19
19
 
20
- with _band_sdk_core.Tracing():
21
- registry = _band_sdk_core.MessageClaimRegistry(10)
20
+ with band_sdk_core.Tracing():
21
+ registry = band_sdk_core.MessageClaimRegistry(10)
22
22
  registry._try_claim("room-e2e", "message-e2e", correlation_id="corr-e2e")
23
23
  """
24
24
 
@@ -52,11 +52,11 @@ def test_default_filter_is_info_when_rust_log_is_unset():
52
52
  # default too), while the debug-level lifecycle chatter stays off. An
53
53
  # error-only default would make a host conclude the telemetry is broken.
54
54
  script = """
55
- import _band_sdk_core
55
+ import band_sdk_core
56
56
 
57
- with _band_sdk_core.Tracing():
58
- _band_sdk_core.MessageClaimRegistry(10)._try_claim("room-default", "message-default")
59
- _band_sdk_core.MessageRetryTracker().mark_permanently_failed("message-default")
57
+ with band_sdk_core.Tracing():
58
+ band_sdk_core.MessageClaimRegistry(10)._try_claim("room-default", "message-default")
59
+ band_sdk_core.MessageRetryTracker().mark_permanently_failed("message-default")
60
60
  """
61
61
  env = {key: value for key, value in os.environ.items() if key != "RUST_LOG"}
62
62
  result = subprocess.run(
@@ -90,7 +90,7 @@ def test_rust_log_filter_silences_claim_telemetry():
90
90
  def test_tracing_can_be_entered_more_than_once_in_one_process():
91
91
  # The subscriber is global and installed once per process, so a second
92
92
  # entry has nothing left to install — it must no-op rather than raise.
93
- with _band_sdk_core.Tracing():
93
+ with band_sdk_core.Tracing():
94
94
  pass
95
- with _band_sdk_core.Tracing():
95
+ with band_sdk_core.Tracing():
96
96
  pass
@@ -5,10 +5,11 @@ build-backend = "maturin"
5
5
  [project]
6
6
  name = "band-sdk-core"
7
7
  description = "Shared Rust core for the Band SDK stack: claims registry, retry tracking, and participant tracking, with Python bindings via PyO3."
8
- version = "0.2.1.dev2"
8
+ readme = { file = "README.md", content-type = "text/markdown" }
9
+ version = "0.2.1.dev4"
9
10
  requires-python = ">=3.11"
10
11
  classifiers = ["Development Status :: 3 - Alpha"]
11
12
 
12
13
  [tool.maturin]
13
- module-name = "_band_sdk_core"
14
+ module-name = "band_sdk_core"
14
15
  manifest-path = "bindings/python/Cargo.toml"
@@ -1,6 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: band-sdk-core
3
- Version: 0.2.1.dev2
4
- Classifier: Development Status :: 3 - Alpha
5
- Summary: Shared Rust core for the Band SDK stack: claims registry, retry tracking, and participant tracking, with Python bindings via PyO3.
6
- Requires-Python: >=3.11