sillo-wire 0.1.0.dev1__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/.github/workflows/ci.yml +17 -8
  2. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/.github/workflows/release.yml +4 -3
  3. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/CHANGELOG.md +34 -0
  4. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/PKG-INFO +12 -38
  5. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/README.md +9 -35
  6. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/pyproject.toml +4 -23
  7. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/__init__.py +1 -1
  8. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/uv.lock +211 -210
  9. sillo_wire-0.1.0.dev1/_sillo_wire_bootstrap.py +0 -104
  10. sillo_wire-0.1.0.dev1/sillo-stubs/py.typed +0 -1
  11. sillo_wire-0.1.0.dev1/sillo-stubs/wire.pyi +0 -48
  12. sillo_wire-0.1.0.dev1/sillo_wire.pth +0 -1
  13. sillo_wire-0.1.0.dev1/tests/test_alias.py +0 -115
  14. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/.gitignore +0 -0
  15. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/LICENSE +0 -0
  16. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/backlog.py +0 -0
  17. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/consumer.py +0 -0
  18. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/envelope.py +0 -0
  19. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/errors.py +0 -0
  20. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/hub.py +0 -0
  21. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/peer.py +0 -0
  22. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/policy.py +0 -0
  23. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/py.typed +0 -0
  24. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/sillo_wire/testing.py +0 -0
  25. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_backlog.py +0 -0
  26. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_consumer.py +0 -0
  27. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_envelope.py +0 -0
  28. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_hub.py +0 -0
  29. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_peer.py +0 -0
  30. {sillo_wire-0.1.0.dev1 → sillo_wire-1.0.0}/tests/test_testing_helpers.py +0 -0
@@ -27,7 +27,7 @@ jobs:
27
27
  pip install pytest pytest-asyncio pytest-cov ruff mypy
28
28
 
29
29
  - name: Lint
30
- run: ruff check sillo_wire tests _sillo_wire_bootstrap.py
30
+ run: ruff check sillo_wire tests
31
31
 
32
32
  - name: Types
33
33
  run: mypy sillo_wire
@@ -35,19 +35,28 @@ jobs:
35
35
  - name: Install the package
36
36
  run: pip install -e .
37
37
 
38
- # The `.pth` only fires for a real install, so the alias is checked
39
- # against a built wheel rather than the editable checkout.
40
- - name: Check the sillo.wire alias against a real install
38
+ # Checked against a built wheel rather than the editable checkout: an
39
+ # editable install can import a package the wheel does not actually ship.
40
+ - name: Check a built wheel installs and imports
41
41
  run: |
42
42
  pip install build && python -m build --wheel -o /tmp/w .
43
43
  python -m venv /tmp/v && /tmp/v/bin/pip install -q sillo-framework /tmp/w/*.whl mypy
44
44
  /tmp/v/bin/python -c "
45
- import sillo, sillo.wire, sillo_wire, os
46
- assert sillo.wire is sillo_wire
45
+ import os, sillo, sillo_wire
46
+ from sillo_wire import Hub
47
+ # The package is top-level and adds nothing to the framework's own
48
+ # directory; it used to ship a .pth that aliased sillo.wire onto it.
47
49
  assert 'wire' not in os.listdir(os.path.dirname(sillo.__file__)), 'wrote into sillo/'
48
- print('alias ok, sillo/ untouched')
50
+ try:
51
+ import sillo.wire
52
+ except ImportError:
53
+ pass
54
+ else:
55
+ raise AssertionError('sillo.wire still resolves; the alias was removed')
56
+ print('sillo_wire imports, sillo/ untouched, no alias')
49
57
  "
50
- printf 'from sillo.wire import Hub\nh: Hub = Hub()\n' > /tmp/tc.py
58
+ # Types come from the package's own inline annotations now, not stubs.
59
+ printf 'from sillo_wire import Hub\nh: Hub = Hub()\n' > /tmp/tc.py
51
60
  /tmp/v/bin/python -m mypy /tmp/tc.py
52
61
 
53
62
  - name: Test
@@ -77,9 +77,10 @@ jobs:
77
77
  - name: Build the package
78
78
  run: uv build
79
79
 
80
- # The whole point of this package's layout: the wheel adds a top-level
81
- # `sillo_wire` plus the `.pth`/bootstrap at the site-packages root, and
82
- # it must never write into the framework's own `sillo/` directory.
80
+ # The wheel adds a top-level `sillo_wire` and nothing else; it must never
81
+ # write into the framework's own `sillo/` directory. Two distributions
82
+ # sharing one package directory goes wrong in both directions, which is
83
+ # why this is asserted rather than assumed.
83
84
  - name: The wheel must stay out of sillo/
84
85
  run: |
85
86
  python - <<'PY'
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## [1.0.0] - 2026-09-26
6
+
7
+ Stable Sillo 1.0 WebSocket and realtime transport release.
8
+
9
+ ## [1.0.0a1] - 2026-09-13
10
+
11
+ First alpha, released alongside `sillo-framework` 1.0.0a1. Install with
12
+ `pip install --pre sillo-wire==1.0.0a1`.
13
+
14
+ An alpha: this is what 1.0 is expected to look like, but the API is not frozen
15
+ yet and may still change before `1.0.0`.
16
+
17
+ ### Removed
18
+
19
+ - **The `sillo.wire` import alias.** `sillo_wire` is now the only import path:
20
+
21
+ ```python
22
+ from sillo_wire import Hub, Peer # was: from sillo.wire import ...
23
+ ```
24
+
25
+ The alias was a meta-path finder registered by a `.pth` at interpreter
26
+ startup, plus PEP 561 stubs under `sillo-stubs/` to serve type checkers,
27
+ which never run import hooks. It read as part of the framework, but it cost a
28
+ `.pth` executing on every interpreter start in every environment the package
29
+ was installed in, a second set of stubs to keep in step with the real
30
+ package, and a name that static analysis only resolved because a second set
31
+ of files said so. A plain top-level package needs none of that.
32
+
33
+ `_sillo_wire_bootstrap.py`, `sillo_wire.pth` and `sillo-stubs/` are gone, and
34
+ so are the `force-include` blocks that shipped them. Inline types in
35
+ `sillo_wire` are now the single source of truth for type checkers.
36
+
3
37
  ## 0.1.0.dev1
4
38
 
5
39
  Development pre-release for testing. Install with
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sillo-wire
3
- Version: 0.1.0.dev1
3
+ Version: 1.0.0
4
4
  Summary: Rooms, presence and fan-out for Sillo WebSockets — bounded queues, replayable backlog, no global state.
5
5
  Project-URL: Homepage, https://sillo.build
6
6
  Project-URL: Documentation, https://docs.sillo.build/packages/wire/
@@ -9,7 +9,7 @@ Author-email: Chidebele Dunamis <techwithdunamix@gmail.com>
9
9
  License-Expression: BSD-3-Clause
10
10
  License-File: LICENSE
11
11
  Keywords: asgi,broadcast,presence,pubsub,realtime,sillo,websocket
12
- Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Framework :: AsyncIO
14
14
  Classifier: Intended Audience :: Developers
15
15
  Classifier: License :: OSI Approved :: BSD License
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.14
21
21
  Classifier: Topic :: Internet :: WWW/HTTP
22
22
  Classifier: Typing :: Typed
23
23
  Requires-Python: >=3.10
24
- Requires-Dist: sillo-framework>=0.3
24
+ Requires-Dist: sillo-framework>=1.0.0
25
25
  Provides-Extra: dev
26
26
  Requires-Dist: mypy>=1.11; extra == 'dev'
27
27
  Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
@@ -38,11 +38,11 @@ Rooms, presence and fan-out for [Sillo](https://sillo.build) WebSockets.
38
38
  pip install sillo-wire
39
39
  ```
40
40
 
41
- Installs as `sillo-wire`, imports as `sillo.wire`.
41
+ Installs as `sillo-wire`, imports as `sillo_wire`.
42
42
 
43
43
  ```python
44
44
  from sillo import SilloApp
45
- from sillo.wire import Hub, Peer
45
+ from sillo_wire import Hub, Peer
46
46
 
47
47
  app = SilloApp()
48
48
  hub = Hub()
@@ -98,7 +98,7 @@ await hub.replay(peer, "lobby", since=last_seq_the_client_saw)
98
98
  When a peer's queue fills, what happens is a choice, not a default:
99
99
 
100
100
  ```python
101
- from sillo.wire import Overflow, Peer
101
+ from sillo_wire import Overflow, Peer
102
102
 
103
103
  Peer(socket, overflow=Overflow.DROP_OLDEST) # keep current — prices, cursors
104
104
  Peer(socket, overflow=Overflow.DROP_NEWEST) # keep order — reconcile later
@@ -130,7 +130,7 @@ joins the rooms, pumps messages, and guarantees the peer is removed from every
130
130
  room when the connection ends — including when a hook raises.
131
131
 
132
132
  ```python
133
- from sillo.wire import Hub, RoomConsumer
133
+ from sillo_wire import Hub, RoomConsumer
134
134
 
135
135
  hub = Hub()
136
136
 
@@ -154,7 +154,7 @@ app.add_ws_route(path="/ws/{room}", handler=Chat.as_handler())
154
154
  Retention is per room and capped by payload bytes, evicting oldest first:
155
155
 
156
156
  ```python
157
- from sillo.wire import Hub, MemoryBacklog, NullBacklog
157
+ from sillo_wire import Hub, MemoryBacklog, NullBacklog
158
158
 
159
159
  Hub(backlog=MemoryBacklog(capacity_bytes=4 * 1024 * 1024))
160
160
  Hub(backlog=NullBacklog()) # keep nothing — typing indicators, telemetry
@@ -165,10 +165,10 @@ importing anything from here.
165
165
 
166
166
  ## Testing
167
167
 
168
- `sillo.wire.testing` ships the piece unit tests are missing — a socket:
168
+ `sillo_wire.testing` ships the piece unit tests are missing — a socket:
169
169
 
170
170
  ```python
171
- from sillo.wire import Hub, Peer
171
+ from sillo_wire import Hub, Peer
172
172
  from sillo_wire.testing import FakeSocket, drain
173
173
 
174
174
  async def test_a_broadcast_reaches_the_room():
@@ -197,32 +197,6 @@ to reproduce against a real server and the two most worth testing.
197
197
  | `Backlog` | `MemoryBacklog` `NullBacklog`, or your own |
198
198
  | `Overflow` | `DROP_OLDEST` `DROP_NEWEST` `CLOSE` |
199
199
 
200
- ## The two import paths
201
-
202
- `sillo.wire` and `sillo_wire` name the same objects. The code lives in the
203
- top-level `sillo_wire` package; `sillo.wire` is an alias, so it reads as part
204
- of the framework:
205
-
206
- ```python
207
- from sillo.wire import Hub # both of these
208
- from sillo_wire import Hub # bind the same class
209
- ```
210
-
211
- The alias is a meta-path finder registered by a `.pth` at interpreter startup —
212
- the only hook that runs before an `import sillo.wire` could fail. Type checkers
213
- never run import hooks, so they are served separately by the partial stubs in
214
- `sillo-stubs/` (PEP 561), which are additive: mypy resolves `sillo.wire` and
215
- still uses the framework's own inline types for the rest of `sillo`.
216
-
217
- Nothing is written into the framework's package directory. Shipping
218
- `sillo/wire/` in there would be simpler, and it is what this did first — but
219
- two distributions sharing one directory goes wrong in both directions.
220
- Installing the framework from a checkout moves where `sillo` resolves and
221
- orphans the copy in site-packages; removing or replacing the framework leaves
222
- that directory standing with no `__init__.py`, which is an override rather than
223
- an addition. Uninstalling either package here leaves the other exactly as it
224
- was.
225
-
226
200
  ## Working on it
227
201
 
228
202
  The alias works under an editable install too — the `.pth` is shipped by the
@@ -231,13 +205,13 @@ editable build target as well as the wheel.
231
205
  ```bash
232
206
  pip install -e ".[dev]"
233
207
  pytest --cov # 100% required, bootstrap included
234
- ruff check sillo_wire tests _sillo_wire_bootstrap.py
208
+ ruff check sillo_wire tests
235
209
  mypy sillo_wire
236
210
  ```
237
211
 
238
212
  ## Requirements
239
213
 
240
- Python 3.10+, `sillo-framework` 0.3 or newer. No other dependencies.
214
+ Python 3.10+, `sillo-framework` 1.0 or newer. No other dependencies.
241
215
 
242
216
  ## Licence
243
217
 
@@ -6,11 +6,11 @@ Rooms, presence and fan-out for [Sillo](https://sillo.build) WebSockets.
6
6
  pip install sillo-wire
7
7
  ```
8
8
 
9
- Installs as `sillo-wire`, imports as `sillo.wire`.
9
+ Installs as `sillo-wire`, imports as `sillo_wire`.
10
10
 
11
11
  ```python
12
12
  from sillo import SilloApp
13
- from sillo.wire import Hub, Peer
13
+ from sillo_wire import Hub, Peer
14
14
 
15
15
  app = SilloApp()
16
16
  hub = Hub()
@@ -66,7 +66,7 @@ await hub.replay(peer, "lobby", since=last_seq_the_client_saw)
66
66
  When a peer's queue fills, what happens is a choice, not a default:
67
67
 
68
68
  ```python
69
- from sillo.wire import Overflow, Peer
69
+ from sillo_wire import Overflow, Peer
70
70
 
71
71
  Peer(socket, overflow=Overflow.DROP_OLDEST) # keep current — prices, cursors
72
72
  Peer(socket, overflow=Overflow.DROP_NEWEST) # keep order — reconcile later
@@ -98,7 +98,7 @@ joins the rooms, pumps messages, and guarantees the peer is removed from every
98
98
  room when the connection ends — including when a hook raises.
99
99
 
100
100
  ```python
101
- from sillo.wire import Hub, RoomConsumer
101
+ from sillo_wire import Hub, RoomConsumer
102
102
 
103
103
  hub = Hub()
104
104
 
@@ -122,7 +122,7 @@ app.add_ws_route(path="/ws/{room}", handler=Chat.as_handler())
122
122
  Retention is per room and capped by payload bytes, evicting oldest first:
123
123
 
124
124
  ```python
125
- from sillo.wire import Hub, MemoryBacklog, NullBacklog
125
+ from sillo_wire import Hub, MemoryBacklog, NullBacklog
126
126
 
127
127
  Hub(backlog=MemoryBacklog(capacity_bytes=4 * 1024 * 1024))
128
128
  Hub(backlog=NullBacklog()) # keep nothing — typing indicators, telemetry
@@ -133,10 +133,10 @@ importing anything from here.
133
133
 
134
134
  ## Testing
135
135
 
136
- `sillo.wire.testing` ships the piece unit tests are missing — a socket:
136
+ `sillo_wire.testing` ships the piece unit tests are missing — a socket:
137
137
 
138
138
  ```python
139
- from sillo.wire import Hub, Peer
139
+ from sillo_wire import Hub, Peer
140
140
  from sillo_wire.testing import FakeSocket, drain
141
141
 
142
142
  async def test_a_broadcast_reaches_the_room():
@@ -165,32 +165,6 @@ to reproduce against a real server and the two most worth testing.
165
165
  | `Backlog` | `MemoryBacklog` `NullBacklog`, or your own |
166
166
  | `Overflow` | `DROP_OLDEST` `DROP_NEWEST` `CLOSE` |
167
167
 
168
- ## The two import paths
169
-
170
- `sillo.wire` and `sillo_wire` name the same objects. The code lives in the
171
- top-level `sillo_wire` package; `sillo.wire` is an alias, so it reads as part
172
- of the framework:
173
-
174
- ```python
175
- from sillo.wire import Hub # both of these
176
- from sillo_wire import Hub # bind the same class
177
- ```
178
-
179
- The alias is a meta-path finder registered by a `.pth` at interpreter startup —
180
- the only hook that runs before an `import sillo.wire` could fail. Type checkers
181
- never run import hooks, so they are served separately by the partial stubs in
182
- `sillo-stubs/` (PEP 561), which are additive: mypy resolves `sillo.wire` and
183
- still uses the framework's own inline types for the rest of `sillo`.
184
-
185
- Nothing is written into the framework's package directory. Shipping
186
- `sillo/wire/` in there would be simpler, and it is what this did first — but
187
- two distributions sharing one directory goes wrong in both directions.
188
- Installing the framework from a checkout moves where `sillo` resolves and
189
- orphans the copy in site-packages; removing or replacing the framework leaves
190
- that directory standing with no `__init__.py`, which is an override rather than
191
- an addition. Uninstalling either package here leaves the other exactly as it
192
- was.
193
-
194
168
  ## Working on it
195
169
 
196
170
  The alias works under an editable install too — the `.pth` is shipped by the
@@ -199,13 +173,13 @@ editable build target as well as the wheel.
199
173
  ```bash
200
174
  pip install -e ".[dev]"
201
175
  pytest --cov # 100% required, bootstrap included
202
- ruff check sillo_wire tests _sillo_wire_bootstrap.py
176
+ ruff check sillo_wire tests
203
177
  mypy sillo_wire
204
178
  ```
205
179
 
206
180
  ## Requirements
207
181
 
208
- Python 3.10+, `sillo-framework` 0.3 or newer. No other dependencies.
182
+ Python 3.10+, `sillo-framework` 1.0 or newer. No other dependencies.
209
183
 
210
184
  ## Licence
211
185
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sillo-wire"
7
- version = "0.1.0.dev1"
7
+ version = "1.0.0"
8
8
  description = "Rooms, presence and fan-out for Sillo WebSockets — bounded queues, replayable backlog, no global state."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -14,7 +14,7 @@ authors = [
14
14
  ]
15
15
  keywords = ["sillo", "websocket", "realtime", "pubsub", "presence", "broadcast", "asgi"]
16
16
  classifiers = [
17
- "Development Status :: 3 - Alpha",
17
+ "Development Status :: 5 - Production/Stable",
18
18
  "Framework :: AsyncIO",
19
19
  "Intended Audience :: Developers",
20
20
  "License :: OSI Approved :: BSD License",
@@ -28,7 +28,7 @@ classifiers = [
28
28
  ]
29
29
  # Only the socket surface is used — WebSocketContext and the logger. No ORM,
30
30
  # no cache, no extras.
31
- dependencies = ["sillo-framework>=0.3"]
31
+ dependencies = ["sillo-framework>=1.0.0"]
32
32
 
33
33
  [project.urls]
34
34
  Homepage = "https://sillo.build"
@@ -39,21 +39,7 @@ Source = "https://github.com/sillohq/wire"
39
39
  dev = ["pytest>=8.0", "pytest-asyncio>=0.24", "pytest-cov>=5.0", "ruff>=0.6", "mypy>=1.11"]
40
40
 
41
41
  [tool.hatch.build.targets.wheel]
42
- # `sillo-stubs` serves type checkers, which never run the import hook below.
43
- packages = ["sillo_wire", "sillo-stubs"]
44
-
45
- # The bootstrap and its .pth land at the site-packages root. The .pth is what
46
- # runs at interpreter startup and registers the `sillo.wire` alias; see
47
- # _sillo_wire_bootstrap.py for why the package is not shipped into `sillo/`.
48
- [tool.hatch.build.targets.wheel.force-include]
49
- "_sillo_wire_bootstrap.py" = "_sillo_wire_bootstrap.py"
50
- "sillo_wire.pth" = "sillo_wire.pth"
51
-
52
- # The same two files for `pip install -e .`, so the `sillo.wire` alias works in
53
- # a development checkout and not only from a built wheel.
54
- [tool.hatch.build.targets.editable.force-include]
55
- "_sillo_wire_bootstrap.py" = "_sillo_wire_bootstrap.py"
56
- "sillo_wire.pth" = "sillo_wire.pth"
42
+ packages = ["sillo_wire"]
57
43
 
58
44
  [tool.pytest.ini_options]
59
45
  asyncio_mode = "auto"
@@ -61,11 +47,6 @@ asyncio_default_fixture_loop_scope = "function"
61
47
  testpaths = ["tests"]
62
48
 
63
49
  [tool.coverage.run]
64
- # `_sillo_wire_bootstrap` is deliberately not measured. Its `.pth` imports it
65
- # at interpreter startup, before coverage exists, so its `def` and `class`
66
- # statements never run under the tracer and it reads as 65% however thoroughly
67
- # it is tested. tests/test_alias.py covers it; the number would be an artefact
68
- # of import timing rather than of testing.
69
50
  source = ["sillo_wire"]
70
51
  branch = true
71
52
 
@@ -38,7 +38,7 @@ from sillo_wire.hub import Hub
38
38
  from sillo_wire.peer import Peer
39
39
  from sillo_wire.policy import Overflow
40
40
 
41
- __version__ = "0.1.0.dev1"
41
+ __version__ = "1.0.0"
42
42
 
43
43
  __all__ = [
44
44
  "Backlog",