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.
Files changed (56) hide show
  1. meshcall-0.1.0/.gitignore +14 -0
  2. meshcall-0.1.0/LICENSE +21 -0
  3. meshcall-0.1.0/PKG-INFO +53 -0
  4. meshcall-0.1.0/README.md +26 -0
  5. meshcall-0.1.0/conformance/fixture.py +166 -0
  6. meshcall-0.1.0/hatch_build.py +44 -0
  7. meshcall-0.1.0/pyproject.toml +75 -0
  8. meshcall-0.1.0/src/meshcall/__init__.py +112 -0
  9. meshcall-0.1.0/src/meshcall/client.py +906 -0
  10. meshcall-0.1.0/src/meshcall/context.py +240 -0
  11. meshcall-0.1.0/src/meshcall/contract.py +801 -0
  12. meshcall-0.1.0/src/meshcall/contract_io.py +41 -0
  13. meshcall-0.1.0/src/meshcall/diagnostics.py +232 -0
  14. meshcall-0.1.0/src/meshcall/driver.py +81 -0
  15. meshcall-0.1.0/src/meshcall/drivers/__init__.py +11 -0
  16. meshcall-0.1.0/src/meshcall/drivers/websocket.py +491 -0
  17. meshcall-0.1.0/src/meshcall/errors.py +250 -0
  18. meshcall-0.1.0/src/meshcall/export.py +43 -0
  19. meshcall-0.1.0/src/meshcall/flow.py +33 -0
  20. meshcall-0.1.0/src/meshcall/ir.py +98 -0
  21. meshcall-0.1.0/src/meshcall/launcher.py +60 -0
  22. meshcall-0.1.0/src/meshcall/logging.py +57 -0
  23. meshcall-0.1.0/src/meshcall/protocol.py +207 -0
  24. meshcall-0.1.0/src/meshcall/py.typed +0 -0
  25. meshcall-0.1.0/src/meshcall/router.py +190 -0
  26. meshcall-0.1.0/src/meshcall/router_auth.py +105 -0
  27. meshcall-0.1.0/src/meshcall/router_install.py +194 -0
  28. meshcall-0.1.0/src/meshcall/server.py +1048 -0
  29. meshcall-0.1.0/src/meshcall/streams.py +68 -0
  30. meshcall-0.1.0/src/meshcall/transport.py +264 -0
  31. meshcall-0.1.0/src/meshcall/worker.py +123 -0
  32. meshcall-0.1.0/tests/conftest.py +45 -0
  33. meshcall-0.1.0/tests/interop/router_auth_peer.mjs +40 -0
  34. meshcall-0.1.0/tests/interop/typescript_client.mjs +31 -0
  35. meshcall-0.1.0/tests/interop/typescript_server.mjs +97 -0
  36. meshcall-0.1.0/tests/interop_service.py +54 -0
  37. meshcall-0.1.0/tests/router_fixtures.py +41 -0
  38. meshcall-0.1.0/tests/test_access_log.py +190 -0
  39. meshcall-0.1.0/tests/test_contract.py +209 -0
  40. meshcall-0.1.0/tests/test_contract_roundtrip.py +119 -0
  41. meshcall-0.1.0/tests/test_diagnostics.py +111 -0
  42. meshcall-0.1.0/tests/test_direct.py +363 -0
  43. meshcall-0.1.0/tests/test_errors.py +142 -0
  44. meshcall-0.1.0/tests/test_interceptors.py +157 -0
  45. meshcall-0.1.0/tests/test_multilang_codegen.py +230 -0
  46. meshcall-0.1.0/tests/test_multilang_interop.py +486 -0
  47. meshcall-0.1.0/tests/test_protocol.py +30 -0
  48. meshcall-0.1.0/tests/test_router.py +326 -0
  49. meshcall-0.1.0/tests/test_router_auth.py +178 -0
  50. meshcall-0.1.0/tests/test_router_process.py +117 -0
  51. meshcall-0.1.0/tests/test_showcase.py +17 -0
  52. meshcall-0.1.0/tests/test_targeted.py +133 -0
  53. meshcall-0.1.0/tests/test_timing.py +515 -0
  54. meshcall-0.1.0/tests/test_transport.py +64 -0
  55. meshcall-0.1.0/tests/test_worker.py +94 -0
  56. meshcall-0.1.0/uv.lock +441 -0
@@ -0,0 +1,14 @@
1
+ .DS_Store
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ .venv/
5
+ __pycache__/
6
+ *.py[cod]
7
+ build/
8
+ dist/
9
+ node_modules/
10
+ .yarn/
11
+ generated/
12
+ meshcall-router/bin/
13
+ .conformance-*.log
14
+ dist-npm/
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.
@@ -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).
@@ -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
+ ]