meshcall 0.1.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.
- meshcall-0.1.0/.gitignore +14 -0
- meshcall-0.1.0/LICENSE +21 -0
- meshcall-0.1.0/PKG-INFO +53 -0
- meshcall-0.1.0/README.md +26 -0
- meshcall-0.1.0/conformance/fixture.py +166 -0
- meshcall-0.1.0/hatch_build.py +44 -0
- meshcall-0.1.0/pyproject.toml +75 -0
- meshcall-0.1.0/src/meshcall/__init__.py +112 -0
- meshcall-0.1.0/src/meshcall/client.py +906 -0
- meshcall-0.1.0/src/meshcall/context.py +240 -0
- meshcall-0.1.0/src/meshcall/contract.py +801 -0
- meshcall-0.1.0/src/meshcall/contract_io.py +41 -0
- meshcall-0.1.0/src/meshcall/diagnostics.py +232 -0
- meshcall-0.1.0/src/meshcall/driver.py +81 -0
- meshcall-0.1.0/src/meshcall/drivers/__init__.py +11 -0
- meshcall-0.1.0/src/meshcall/drivers/websocket.py +491 -0
- meshcall-0.1.0/src/meshcall/errors.py +250 -0
- meshcall-0.1.0/src/meshcall/export.py +43 -0
- meshcall-0.1.0/src/meshcall/flow.py +33 -0
- meshcall-0.1.0/src/meshcall/ir.py +98 -0
- meshcall-0.1.0/src/meshcall/launcher.py +60 -0
- meshcall-0.1.0/src/meshcall/logging.py +57 -0
- meshcall-0.1.0/src/meshcall/protocol.py +207 -0
- meshcall-0.1.0/src/meshcall/py.typed +0 -0
- meshcall-0.1.0/src/meshcall/router.py +190 -0
- meshcall-0.1.0/src/meshcall/router_auth.py +105 -0
- meshcall-0.1.0/src/meshcall/router_install.py +194 -0
- meshcall-0.1.0/src/meshcall/server.py +1048 -0
- meshcall-0.1.0/src/meshcall/streams.py +68 -0
- meshcall-0.1.0/src/meshcall/transport.py +264 -0
- meshcall-0.1.0/src/meshcall/worker.py +123 -0
- meshcall-0.1.0/tests/conftest.py +45 -0
- meshcall-0.1.0/tests/interop/router_auth_peer.mjs +40 -0
- meshcall-0.1.0/tests/interop/typescript_client.mjs +31 -0
- meshcall-0.1.0/tests/interop/typescript_server.mjs +97 -0
- meshcall-0.1.0/tests/interop_service.py +54 -0
- meshcall-0.1.0/tests/router_fixtures.py +41 -0
- meshcall-0.1.0/tests/test_access_log.py +190 -0
- meshcall-0.1.0/tests/test_contract.py +209 -0
- meshcall-0.1.0/tests/test_contract_roundtrip.py +119 -0
- meshcall-0.1.0/tests/test_diagnostics.py +111 -0
- meshcall-0.1.0/tests/test_direct.py +363 -0
- meshcall-0.1.0/tests/test_errors.py +142 -0
- meshcall-0.1.0/tests/test_interceptors.py +157 -0
- meshcall-0.1.0/tests/test_multilang_codegen.py +230 -0
- meshcall-0.1.0/tests/test_multilang_interop.py +486 -0
- meshcall-0.1.0/tests/test_protocol.py +30 -0
- meshcall-0.1.0/tests/test_router.py +326 -0
- meshcall-0.1.0/tests/test_router_auth.py +178 -0
- meshcall-0.1.0/tests/test_router_process.py +117 -0
- meshcall-0.1.0/tests/test_showcase.py +17 -0
- meshcall-0.1.0/tests/test_targeted.py +133 -0
- meshcall-0.1.0/tests/test_timing.py +515 -0
- meshcall-0.1.0/tests/test_transport.py +64 -0
- meshcall-0.1.0/tests/test_worker.py +94 -0
- meshcall-0.1.0/uv.lock +441 -0
meshcall-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 t4wefan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
meshcall-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: meshcall
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Async typed RPC for Python services: WebSocket direct or through the MeshCall Router
|
|
5
|
+
Project-URL: Homepage, https://github.com/t4wefan/meshcall
|
|
6
|
+
Project-URL: Changelog, https://github.com/t4wefan/meshcall/blob/main/CHANGELOG.md
|
|
7
|
+
Project-URL: Issues, https://github.com/t4wefan/meshcall/issues
|
|
8
|
+
Author: t4wefan
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: asyncio,pydantic,router,rpc,streaming,websocket
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Framework :: Pydantic :: 2
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: System :: Networking
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: loguru>=0.7.3
|
|
24
|
+
Requires-Dist: pydantic>=2.11
|
|
25
|
+
Requires-Dist: websockets>=16.1
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# meshcall-py
|
|
29
|
+
|
|
30
|
+
The Python runtime and code-generation package for the MeshCall monorepo.
|
|
31
|
+
Its import name is `meshcall`.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
go -C ../meshcall-router build -o bin/meshcall-router ./cmd/meshcall-router
|
|
35
|
+
uv sync
|
|
36
|
+
uv run pytest -q
|
|
37
|
+
uv build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The monorepo-level runnable examples are in `../demo`. See the repository root
|
|
41
|
+
README for the complete Python/TypeScript workflow.
|
|
42
|
+
|
|
43
|
+
`WebSocketRouter` launches the standalone Go executable. It supports
|
|
44
|
+
`binary_path`, `auth_file`, readiness timeouts, `pid`, `is_running`,
|
|
45
|
+
`wait_closed()`, and async context management. A prebuilt binary can also be
|
|
46
|
+
selected with `MESHCALL_ROUTER_BINARY`; running it requires no Go compiler.
|
|
47
|
+
|
|
48
|
+
Pass `RouterCredentials(username=..., password=...)` or
|
|
49
|
+
`RouterCredentials(token=...)` as `auth` to a WebSocket client or Router server
|
|
50
|
+
driver. `RouterAuthClient` provides `whoami()`, `issue_token(scopes=..., ...)`,
|
|
51
|
+
and `revoke_token(...)`. Use `RouterScope(service=..., methods=[...])` to limit
|
|
52
|
+
a token, or `register_service=True` for temporary service instances.
|
|
53
|
+
See [Router authentication and management](../docs/router.md).
|
meshcall-0.1.0/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# meshcall-py
|
|
2
|
+
|
|
3
|
+
The Python runtime and code-generation package for the MeshCall monorepo.
|
|
4
|
+
Its import name is `meshcall`.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
go -C ../meshcall-router build -o bin/meshcall-router ./cmd/meshcall-router
|
|
8
|
+
uv sync
|
|
9
|
+
uv run pytest -q
|
|
10
|
+
uv build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The monorepo-level runnable examples are in `../demo`. See the repository root
|
|
14
|
+
README for the complete Python/TypeScript workflow.
|
|
15
|
+
|
|
16
|
+
`WebSocketRouter` launches the standalone Go executable. It supports
|
|
17
|
+
`binary_path`, `auth_file`, readiness timeouts, `pid`, `is_running`,
|
|
18
|
+
`wait_closed()`, and async context management. A prebuilt binary can also be
|
|
19
|
+
selected with `MESHCALL_ROUTER_BINARY`; running it requires no Go compiler.
|
|
20
|
+
|
|
21
|
+
Pass `RouterCredentials(username=..., password=...)` or
|
|
22
|
+
`RouterCredentials(token=...)` as `auth` to a WebSocket client or Router server
|
|
23
|
+
driver. `RouterAuthClient` provides `whoami()`, `issue_token(scopes=..., ...)`,
|
|
24
|
+
and `revoke_token(...)`. Use `RouterScope(service=..., methods=[...])` to limit
|
|
25
|
+
a token, or `register_service=True` for temporary service instances.
|
|
26
|
+
See [Router authentication and management](../docs/router.md).
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Reference Python fixture for the conformance suite (see conformance/FIXTURE.md)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
from collections.abc import AsyncIterator
|
|
9
|
+
from typing import cast
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
|
|
13
|
+
from meshcall import RpcContext, RpcInputStream, RpcServer, method, service
|
|
14
|
+
from meshcall.drivers import WebSocketRouterServerDriver
|
|
15
|
+
from meshcall.errors import MeshCallError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Echo(BaseModel):
|
|
19
|
+
value: int
|
|
20
|
+
text: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Tag(BaseModel):
|
|
24
|
+
tag: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Tags(BaseModel):
|
|
28
|
+
tags: list[str]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Index(BaseModel):
|
|
32
|
+
index: int
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Value(BaseModel):
|
|
36
|
+
value: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Total(BaseModel):
|
|
40
|
+
total: int
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Metadata(BaseModel):
|
|
44
|
+
metadata: dict[str, str]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Ok(BaseModel):
|
|
48
|
+
ok: bool = True
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Instance(BaseModel):
|
|
52
|
+
instance: str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@service("conformance.v1.Targeted", targeted=True)
|
|
56
|
+
class Targeted:
|
|
57
|
+
"""A targeted service: every call must name the instance it is for."""
|
|
58
|
+
|
|
59
|
+
@method(read_only=True)
|
|
60
|
+
async def whoami(self, ctx: RpcContext) -> Instance:
|
|
61
|
+
"""Return the id of the instance that served the call."""
|
|
62
|
+
return Instance(instance=ctx.instance_id)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@service("conformance.v1.Fixture")
|
|
66
|
+
class Fixture:
|
|
67
|
+
"""Deterministic behaviours the conformance suite drives through the Router."""
|
|
68
|
+
|
|
69
|
+
def __init__(self) -> None:
|
|
70
|
+
self.cancelled: list[str] = []
|
|
71
|
+
self.invoked: list[str] = []
|
|
72
|
+
self.server: RpcServer | None = None
|
|
73
|
+
|
|
74
|
+
@method(read_only=True)
|
|
75
|
+
async def echo(self, value: int, text: str) -> Echo:
|
|
76
|
+
"""Return the input unchanged."""
|
|
77
|
+
return Echo(value=value, text=text)
|
|
78
|
+
|
|
79
|
+
@method(idempotent=True)
|
|
80
|
+
async def fail(self, code: str, message: str, retryable: bool = False) -> Ok:
|
|
81
|
+
"""Raise an application error with the given code."""
|
|
82
|
+
raise MeshCallError(code, message, retryable=retryable, details={"from": "fixture"})
|
|
83
|
+
|
|
84
|
+
@method(read_only=True)
|
|
85
|
+
async def bad_response(self) -> Ok:
|
|
86
|
+
"""Return a response that breaks this method's own contract."""
|
|
87
|
+
return cast(Ok, {"ok": "not-a-bool"})
|
|
88
|
+
|
|
89
|
+
@method(idempotent=True)
|
|
90
|
+
async def slow(self, ms: int, tag: str = "") -> Tag:
|
|
91
|
+
"""Sleep ``ms`` milliseconds; record ``tag`` if cancelled meanwhile."""
|
|
92
|
+
self.invoked.append(tag)
|
|
93
|
+
try:
|
|
94
|
+
await asyncio.sleep(ms / 1000)
|
|
95
|
+
except asyncio.CancelledError:
|
|
96
|
+
self.cancelled.append(tag)
|
|
97
|
+
raise
|
|
98
|
+
return Tag(tag=tag)
|
|
99
|
+
|
|
100
|
+
@method(read_only=True)
|
|
101
|
+
async def cancelled_tags(self) -> Tags:
|
|
102
|
+
"""Tags of slow calls that observed cancellation."""
|
|
103
|
+
return Tags(tags=list(self.cancelled))
|
|
104
|
+
|
|
105
|
+
@method(read_only=True)
|
|
106
|
+
async def invoked_tags(self) -> Tags:
|
|
107
|
+
"""Tags of every slow call that started, in order."""
|
|
108
|
+
return Tags(tags=list(self.invoked))
|
|
109
|
+
|
|
110
|
+
@method.server_stream(read_only=True)
|
|
111
|
+
async def count(self, n: int, gap_ms: int = 0) -> AsyncIterator[Index]:
|
|
112
|
+
"""Yield 0..n-1 with ``gap_ms`` between items."""
|
|
113
|
+
for index in range(n):
|
|
114
|
+
if gap_ms:
|
|
115
|
+
await asyncio.sleep(gap_ms / 1000)
|
|
116
|
+
yield Index(index=index)
|
|
117
|
+
|
|
118
|
+
@method.client_stream(idempotent=True)
|
|
119
|
+
async def sum(self, items: RpcInputStream[Value], offset: int = 0) -> Total:
|
|
120
|
+
"""Add every streamed value to ``offset``."""
|
|
121
|
+
total = offset
|
|
122
|
+
async for item in items:
|
|
123
|
+
total += item.value
|
|
124
|
+
return Total(total=total)
|
|
125
|
+
|
|
126
|
+
@method(read_only=True)
|
|
127
|
+
async def metadata_echo(self, ctx: RpcContext) -> Metadata:
|
|
128
|
+
"""Return the call metadata and set trailers describing it."""
|
|
129
|
+
ctx.set_trailer("echoed", "yes")
|
|
130
|
+
ctx.set_trailer("count", str(len(ctx.metadata)))
|
|
131
|
+
return Metadata(metadata=dict(ctx.metadata))
|
|
132
|
+
|
|
133
|
+
@method(destructive=True)
|
|
134
|
+
async def drain_self(self, delay_ms: int = 0) -> Ok:
|
|
135
|
+
"""Drain and stop this instance after ``delay_ms``."""
|
|
136
|
+
|
|
137
|
+
async def later() -> None:
|
|
138
|
+
await asyncio.sleep(delay_ms / 1000)
|
|
139
|
+
assert self.server is not None
|
|
140
|
+
await self.server.stop(drain=True, drain_timeout=30)
|
|
141
|
+
|
|
142
|
+
asyncio.get_running_loop().create_task(later())
|
|
143
|
+
return Ok()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
async def main() -> None:
|
|
147
|
+
fixture = Fixture()
|
|
148
|
+
ping = float(os.environ.get("MESHCALL_PING_INTERVAL_MS", "15000")) / 1000
|
|
149
|
+
server = RpcServer(
|
|
150
|
+
services=[fixture, Targeted],
|
|
151
|
+
driver=WebSocketRouterServerDriver(
|
|
152
|
+
os.environ["MESHCALL_ROUTER_URL"],
|
|
153
|
+
instance_id=os.environ.get("MESHCALL_CONFORMANCE_INSTANCE", "fixture-1"),
|
|
154
|
+
ping_interval=ping,
|
|
155
|
+
ping_timeout=max(1.0, ping * 2),
|
|
156
|
+
),
|
|
157
|
+
access_log=False,
|
|
158
|
+
)
|
|
159
|
+
fixture.server = server
|
|
160
|
+
await server.start()
|
|
161
|
+
print("fixture registered", file=sys.stderr, flush=True)
|
|
162
|
+
await server.wait_closed()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Bundle the Go binaries into platform wheels.
|
|
2
|
+
|
|
3
|
+
Release builds set MESHCALL_BUNDLE_DIR to a directory holding `meshcall-router`
|
|
4
|
+
and `meshcall` (`.exe` on Windows) for one platform and MESHCALL_WHEEL_TAG to
|
|
5
|
+
that platform's wheel tag (e.g. `manylinux_2_17_x86_64.manylinux2014_x86_64`,
|
|
6
|
+
`macosx_11_0_arm64`, `win_amd64`). The binaries land in `meshcall/bin/`, which
|
|
7
|
+
is the first place `meshcall.router_install` looks. Without the variables the
|
|
8
|
+
build is the ordinary pure wheel, and the runtime falls back to downloading
|
|
9
|
+
the release on first use.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class BundleBinaries(BuildHookInterface):
|
|
22
|
+
PLUGIN_NAME = "custom"
|
|
23
|
+
|
|
24
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
25
|
+
if self.target_name != "wheel":
|
|
26
|
+
return
|
|
27
|
+
bundle = os.environ.get("MESHCALL_BUNDLE_DIR")
|
|
28
|
+
tag = os.environ.get("MESHCALL_WHEEL_TAG")
|
|
29
|
+
if not bundle and not tag:
|
|
30
|
+
return
|
|
31
|
+
if not (bundle and tag):
|
|
32
|
+
raise RuntimeError("set both MESHCALL_BUNDLE_DIR and MESHCALL_WHEEL_TAG")
|
|
33
|
+
source = Path(bundle)
|
|
34
|
+
found = 0
|
|
35
|
+
for name in ("meshcall-router", "meshcall", "meshcall-router.exe", "meshcall.exe"):
|
|
36
|
+
binary = source / name
|
|
37
|
+
if binary.is_file():
|
|
38
|
+
build_data["force_include"][str(binary)] = f"meshcall/bin/{name}"
|
|
39
|
+
found += 1
|
|
40
|
+
if found < 2:
|
|
41
|
+
raise RuntimeError(f"{source} must contain meshcall-router and meshcall")
|
|
42
|
+
build_data["pure_python"] = False
|
|
43
|
+
build_data["infer_tag"] = False
|
|
44
|
+
build_data["tag"] = f"py3-none-{tag}"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "meshcall"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Async typed RPC for Python services: WebSocket direct or through the MeshCall Router"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
authors = [{ name = "t4wefan" }]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
keywords = ["rpc", "websocket", "asyncio", "pydantic", "streaming", "router"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Framework :: AsyncIO",
|
|
14
|
+
"Framework :: Pydantic :: 2",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: System :: Networking",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"loguru>=0.7.3",
|
|
25
|
+
"pydantic>=2.11",
|
|
26
|
+
"websockets>=16.1",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/t4wefan/meshcall"
|
|
31
|
+
Changelog = "https://github.com/t4wefan/meshcall/blob/main/CHANGELOG.md"
|
|
32
|
+
Issues = "https://github.com/t4wefan/meshcall/issues"
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
meshcall = "meshcall.launcher:main"
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"pyright>=1.1.411",
|
|
40
|
+
"pytest>=8.3",
|
|
41
|
+
"pytest-asyncio>=0.26",
|
|
42
|
+
"ruff>=0.16.0",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["hatchling"]
|
|
47
|
+
build-backend = "hatchling.build"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel.hooks.custom]
|
|
50
|
+
# Platform wheels carry the Go binaries; see hatch_build.py.
|
|
51
|
+
path = "hatch_build.py"
|
|
52
|
+
|
|
53
|
+
[tool.hatch.build.targets.sdist]
|
|
54
|
+
exclude = ["src/meshcall/bin"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
asyncio_mode = "auto"
|
|
58
|
+
testpaths = ["tests"]
|
|
59
|
+
# Test fixtures are deliberately terse; test_diagnostics asserts the warnings.
|
|
60
|
+
filterwarnings = ["ignore::meshcall.diagnostics.MeshCallWarning"]
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
line-length = 88
|
|
64
|
+
target-version = "py311"
|
|
65
|
+
|
|
66
|
+
[tool.pyright]
|
|
67
|
+
extraPaths = [
|
|
68
|
+
"..",
|
|
69
|
+
"../demo/quickstart/src",
|
|
70
|
+
"../demo/py2ts/src",
|
|
71
|
+
"../demo/showcase/src",
|
|
72
|
+
"../demo/router/src",
|
|
73
|
+
"../demo/ts2py/src",
|
|
74
|
+
"../demo/ts2py/py-client/src",
|
|
75
|
+
]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from meshcall.client import ClientBase
|
|
2
|
+
from meshcall.context import (
|
|
3
|
+
CallOptions,
|
|
4
|
+
ClientCallInfo,
|
|
5
|
+
ClientCallNext,
|
|
6
|
+
ClientInterceptor,
|
|
7
|
+
ReconnectPolicy,
|
|
8
|
+
RetryPolicy,
|
|
9
|
+
RpcContext,
|
|
10
|
+
ServerCallNext,
|
|
11
|
+
ServerInterceptor,
|
|
12
|
+
)
|
|
13
|
+
from meshcall.contract import (
|
|
14
|
+
Balance,
|
|
15
|
+
get_service_contract,
|
|
16
|
+
get_service_method_binding,
|
|
17
|
+
get_service_warnings,
|
|
18
|
+
method,
|
|
19
|
+
service,
|
|
20
|
+
)
|
|
21
|
+
from meshcall.contract_io import load_contract, render_contract, write_contract
|
|
22
|
+
from meshcall.diagnostics import ContractWarning, MeshCallWarning, lint_contract
|
|
23
|
+
from meshcall.errors import (
|
|
24
|
+
CallCancelledError,
|
|
25
|
+
ContractError,
|
|
26
|
+
DeadlineExceededError,
|
|
27
|
+
ErrorCode,
|
|
28
|
+
InternalError,
|
|
29
|
+
InvalidArgumentError,
|
|
30
|
+
MeshCallError,
|
|
31
|
+
MethodNotFoundError,
|
|
32
|
+
PermissionDeniedError,
|
|
33
|
+
ProtocolError,
|
|
34
|
+
ResourceExhaustedError,
|
|
35
|
+
UnauthenticatedError,
|
|
36
|
+
UnavailableError,
|
|
37
|
+
Violation,
|
|
38
|
+
)
|
|
39
|
+
from meshcall.ir import (
|
|
40
|
+
BalanceKind,
|
|
41
|
+
BalancePolicy,
|
|
42
|
+
BindingKind,
|
|
43
|
+
MethodAnnotations,
|
|
44
|
+
StreamKind,
|
|
45
|
+
)
|
|
46
|
+
from meshcall.logging import RpcLogger
|
|
47
|
+
from meshcall.router import WebSocketRouter
|
|
48
|
+
from meshcall.router_auth import (
|
|
49
|
+
IssuedToken,
|
|
50
|
+
RouterAuthClient,
|
|
51
|
+
RouterCredentials,
|
|
52
|
+
RouterIdentity,
|
|
53
|
+
RouterScope,
|
|
54
|
+
)
|
|
55
|
+
from meshcall.server import RpcServer
|
|
56
|
+
from meshcall.streams import RpcDuplex, RpcDuplexClient, RpcInputStream, RpcServerStream
|
|
57
|
+
|
|
58
|
+
__all__ = [
|
|
59
|
+
"Balance",
|
|
60
|
+
"BalanceKind",
|
|
61
|
+
"BalancePolicy",
|
|
62
|
+
"BindingKind",
|
|
63
|
+
"CallCancelledError",
|
|
64
|
+
"CallOptions",
|
|
65
|
+
"ClientBase",
|
|
66
|
+
"ClientCallInfo",
|
|
67
|
+
"ClientCallNext",
|
|
68
|
+
"ClientInterceptor",
|
|
69
|
+
"ContractError",
|
|
70
|
+
"ContractWarning",
|
|
71
|
+
"DeadlineExceededError",
|
|
72
|
+
"ErrorCode",
|
|
73
|
+
"InternalError",
|
|
74
|
+
"InvalidArgumentError",
|
|
75
|
+
"IssuedToken",
|
|
76
|
+
"MeshCallError",
|
|
77
|
+
"MeshCallWarning",
|
|
78
|
+
"MethodAnnotations",
|
|
79
|
+
"MethodNotFoundError",
|
|
80
|
+
"PermissionDeniedError",
|
|
81
|
+
"ProtocolError",
|
|
82
|
+
"ReconnectPolicy",
|
|
83
|
+
"ResourceExhaustedError",
|
|
84
|
+
"RetryPolicy",
|
|
85
|
+
"RouterAuthClient",
|
|
86
|
+
"RouterCredentials",
|
|
87
|
+
"RouterIdentity",
|
|
88
|
+
"RouterScope",
|
|
89
|
+
"RpcContext",
|
|
90
|
+
"RpcDuplex",
|
|
91
|
+
"RpcDuplexClient",
|
|
92
|
+
"RpcInputStream",
|
|
93
|
+
"RpcLogger",
|
|
94
|
+
"RpcServer",
|
|
95
|
+
"RpcServerStream",
|
|
96
|
+
"ServerCallNext",
|
|
97
|
+
"ServerInterceptor",
|
|
98
|
+
"StreamKind",
|
|
99
|
+
"UnauthenticatedError",
|
|
100
|
+
"UnavailableError",
|
|
101
|
+
"Violation",
|
|
102
|
+
"WebSocketRouter",
|
|
103
|
+
"get_service_contract",
|
|
104
|
+
"get_service_method_binding",
|
|
105
|
+
"get_service_warnings",
|
|
106
|
+
"lint_contract",
|
|
107
|
+
"load_contract",
|
|
108
|
+
"method",
|
|
109
|
+
"render_contract",
|
|
110
|
+
"service",
|
|
111
|
+
"write_contract",
|
|
112
|
+
]
|