Skip to content

fix(websocket): make @websocket usable from the package name - #116

Merged
andrevanzuydam merged 4 commits into
tina4stack:v3from
MichaelC8E:fix/websocket-decorator-shadowed
Aug 20, 2026
Merged

fix(websocket): make @websocket usable from the package name#116
andrevanzuydam merged 4 commits into
tina4stack:v3from
MichaelC8E:fix/websocket-decorator-shadowed

Conversation

@MichaelC8E

@MichaelC8E MichaelC8E commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Issue: from tina4_python import websocket imported the RFC 6455 module, not the route decorator. @websocket("/ws") then raised TypeError: 'module' object is not callable. Auto-discovery logged one error and dropped every route from that line onward. The landing page and the WebSocket spec both teach this import.

Fix: make tina4_python.websocket a callable module that forwards to core.router.websocket. from tina4_python.websocket import WebSocketServer still works. A re-export was not used: it would make import tina4_python.websocket as ws return the function and break ws.WebSocketServer.

mypy/pyright still flag Module not callable on the package spelling; import from core.router if that matters.

Migael and others added 4 commits August 19, 2026 14:53
`tina4_python.websocket` is two things at once: the RFC 6455 subpackage,
and — to every reader of the docs — the route decorator that sits beside
@get/@post in core.router. Python binds a submodule onto its parent
package the moment the submodule is imported, so the name resolved to
the module and the documented usage died at import time:

    from tina4_python import websocket

    @websocket("/ws")        # TypeError: 'module' object is not callable
    async def chat(connection, event, data): ...

taking the whole route file down with it. Reproduced on 3.13.105:
type(tina4_python.websocket).__name__ == "module", callable() False.

Note what does NOT work: re-exporting the decorator from
tina4_python/__init__.py, alongside get/post/put/cached/template and the
rest of the core surface, which is where a reader would expect the fix.
Importing the subpackage rebinds the attribute over that re-export
afterwards, so the failure would come and go with import order — worse
than a consistent one. Making the module itself callable is the only
change that keeps both public surfaces: `from tina4_python.websocket
import WebSocketServer` still resolves, and `@websocket("/ws")` now
reaches core.router.websocket. The router import is deferred to call
time so the subpackage keeps no import-time dependency on core.router.

tests/test_websocket_decorator_name.py covers both halves; its four
decorator tests fail against the unfixed source, and the three
module-surface tests guard the exports the change could have cost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A re-export after first load is stable; it still turns
`import tina4_python.websocket as ws` into a function.
Guard sys.modules, forward *args/**kwargs, pin backplane.

Co-Authored-By: Tina4 <82961293+tina4stack@users.noreply.github.com>
Co-Authored-By: Tina4 <82961293+tina4stack@users.noreply.github.com>
Co-Authored-By: Tina4 <82961293+tina4stack@users.noreply.github.com>
@andrevanzuydam
andrevanzuydam merged commit 6920743 into tina4stack:v3 Aug 20, 2026
1 check passed
andrevanzuydam added a commit that referenced this pull request Aug 20, 2026
Bumps version + moves the @websocket changelog entry into its own 3.13.106
section (it had been filed under the already-released 3.13.105).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants