rocket-welder-sdk 1.1.43__py3-none-any.whl → 1.1.45__py3-none-any.whl
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.
- rocket_welder_sdk/__init__.py +44 -22
- rocket_welder_sdk/binary_frame_reader.py +222 -0
- rocket_welder_sdk/binary_frame_writer.py +213 -0
- rocket_welder_sdk/confidence.py +206 -0
- rocket_welder_sdk/delta_frame.py +150 -0
- rocket_welder_sdk/graphics/__init__.py +42 -0
- rocket_welder_sdk/graphics/layer_canvas.py +157 -0
- rocket_welder_sdk/graphics/protocol.py +72 -0
- rocket_welder_sdk/graphics/rgb_color.py +109 -0
- rocket_welder_sdk/graphics/stage.py +494 -0
- rocket_welder_sdk/graphics/vector_graphics_encoder.py +575 -0
- rocket_welder_sdk/high_level/__init__.py +8 -1
- rocket_welder_sdk/high_level/client.py +114 -3
- rocket_welder_sdk/high_level/connection_strings.py +88 -15
- rocket_welder_sdk/high_level/frame_sink_factory.py +2 -15
- rocket_welder_sdk/high_level/transport_protocol.py +4 -130
- rocket_welder_sdk/keypoints_protocol.py +520 -55
- rocket_welder_sdk/rocket_welder_client.py +210 -89
- rocket_welder_sdk/segmentation_result.py +387 -2
- rocket_welder_sdk/session_id.py +7 -182
- rocket_welder_sdk/transport/__init__.py +10 -3
- rocket_welder_sdk/transport/frame_sink.py +3 -3
- rocket_welder_sdk/transport/frame_source.py +2 -2
- rocket_welder_sdk/transport/websocket_transport.py +316 -0
- rocket_welder_sdk/varint.py +213 -0
- {rocket_welder_sdk-1.1.43.dist-info → rocket_welder_sdk-1.1.45.dist-info}/METADATA +1 -4
- rocket_welder_sdk-1.1.45.dist-info/RECORD +51 -0
- {rocket_welder_sdk-1.1.43.dist-info → rocket_welder_sdk-1.1.45.dist-info}/WHEEL +1 -1
- rocket_welder_sdk/transport/nng_transport.py +0 -197
- rocket_welder_sdk-1.1.43.dist-info/RECORD +0 -40
- {rocket_welder_sdk-1.1.43.dist-info → rocket_welder_sdk-1.1.45.dist-info}/top_level.txt +0 -0
|
@@ -2,18 +2,24 @@
|
|
|
2
2
|
RocketWelderClient - High-level API matching C# RocketWelder.SDK.
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
|
-
with
|
|
5
|
+
with RocketWelderClientFactory.from_environment() as client:
|
|
6
6
|
# Define schema
|
|
7
7
|
nose = client.keypoints.define_point("nose")
|
|
8
8
|
person = client.segmentation.define_class(1, "person")
|
|
9
9
|
|
|
10
10
|
# Start processing
|
|
11
11
|
client.start(process_frame)
|
|
12
|
+
|
|
13
|
+
Alternatively:
|
|
14
|
+
# Using class methods directly
|
|
15
|
+
with RocketWelderClient.from_environment() as client:
|
|
16
|
+
...
|
|
12
17
|
"""
|
|
13
18
|
|
|
14
19
|
from __future__ import annotations
|
|
15
20
|
|
|
16
21
|
import logging
|
|
22
|
+
from abc import ABC, abstractmethod
|
|
17
23
|
from dataclasses import dataclass, field
|
|
18
24
|
from typing import TYPE_CHECKING, Any, Callable, Optional
|
|
19
25
|
|
|
@@ -50,6 +56,73 @@ Mat: TypeAlias = npt.NDArray[np.uint8]
|
|
|
50
56
|
logger = logging.getLogger(__name__)
|
|
51
57
|
|
|
52
58
|
|
|
59
|
+
class IRocketWelderClient(ABC):
|
|
60
|
+
"""
|
|
61
|
+
Main entry point for RocketWelder SDK high-level API.
|
|
62
|
+
|
|
63
|
+
Provides schema definitions and frame processing loop.
|
|
64
|
+
Matches C# IRocketWelderClient interface.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def keypoints(self) -> IKeyPointsSchema:
|
|
70
|
+
"""Schema for defining keypoints."""
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def segmentation(self) -> ISegmentationSchema:
|
|
76
|
+
"""Schema for defining segmentation classes."""
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def start(
|
|
81
|
+
self,
|
|
82
|
+
process_frame: Callable[[Mat, ISegmentationDataContext, IKeyPointsDataContext, Mat], None],
|
|
83
|
+
) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Start the processing loop with full context (keypoints + segmentation).
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
process_frame: Callback for each frame with:
|
|
89
|
+
- input_frame: Source video frame (Mat)
|
|
90
|
+
- segmentation: Segmentation data context
|
|
91
|
+
- keypoints: KeyPoints data context
|
|
92
|
+
- output_frame: Output frame for visualization (Mat)
|
|
93
|
+
"""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@abstractmethod
|
|
97
|
+
def start_keypoints(
|
|
98
|
+
self,
|
|
99
|
+
process_frame: Callable[[Mat, IKeyPointsDataContext, Mat], None],
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Start the processing loop (keypoints only)."""
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def start_segmentation(
|
|
106
|
+
self,
|
|
107
|
+
process_frame: Callable[[Mat, ISegmentationDataContext, Mat], None],
|
|
108
|
+
) -> None:
|
|
109
|
+
"""Start the processing loop (segmentation only)."""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def close(self) -> None:
|
|
114
|
+
"""Release resources."""
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
def __enter__(self) -> IRocketWelderClient:
|
|
118
|
+
"""Context manager entry."""
|
|
119
|
+
return self
|
|
120
|
+
|
|
121
|
+
def __exit__(self, *args: object) -> None:
|
|
122
|
+
"""Context manager exit."""
|
|
123
|
+
self.close()
|
|
124
|
+
|
|
125
|
+
|
|
53
126
|
@dataclass
|
|
54
127
|
class RocketWelderClientOptions:
|
|
55
128
|
"""Configuration options for RocketWelderClient."""
|
|
@@ -72,11 +145,12 @@ class RocketWelderClientOptions:
|
|
|
72
145
|
)
|
|
73
146
|
|
|
74
147
|
|
|
75
|
-
class RocketWelderClient:
|
|
148
|
+
class RocketWelderClient(IRocketWelderClient):
|
|
76
149
|
"""
|
|
77
150
|
High-level client for RocketWelder SDK.
|
|
78
151
|
|
|
79
|
-
|
|
152
|
+
Implements IRocketWelderClient interface.
|
|
153
|
+
Mirrors C# RocketWelder.SDK.RocketWelderClientImpl.
|
|
80
154
|
"""
|
|
81
155
|
|
|
82
156
|
def __init__(self, options: RocketWelderClientOptions) -> None:
|
|
@@ -233,3 +307,40 @@ class RocketWelderClient:
|
|
|
233
307
|
|
|
234
308
|
def __exit__(self, *args: object) -> None:
|
|
235
309
|
self.close()
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class RocketWelderClientFactory:
|
|
313
|
+
"""
|
|
314
|
+
Factory for creating RocketWelderClient instances.
|
|
315
|
+
|
|
316
|
+
Matches C# RocketWelderClientFactory static class.
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
@staticmethod
|
|
320
|
+
def from_environment() -> IRocketWelderClient:
|
|
321
|
+
"""
|
|
322
|
+
Creates a client configured from environment variables.
|
|
323
|
+
|
|
324
|
+
Environment variables:
|
|
325
|
+
- VIDEO_SOURCE or CONNECTION_STRING: Video input
|
|
326
|
+
- KEYPOINTS_CONNECTION_STRING: KeyPoints output
|
|
327
|
+
- SEGMENTATION_CONNECTION_STRING: Segmentation output
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
IRocketWelderClient configured from environment.
|
|
331
|
+
"""
|
|
332
|
+
options = RocketWelderClientOptions.from_environment()
|
|
333
|
+
return RocketWelderClient(options)
|
|
334
|
+
|
|
335
|
+
@staticmethod
|
|
336
|
+
def create(options: Optional[RocketWelderClientOptions] = None) -> IRocketWelderClient:
|
|
337
|
+
"""
|
|
338
|
+
Creates a client with explicit configuration.
|
|
339
|
+
|
|
340
|
+
Args:
|
|
341
|
+
options: Configuration options. If None, uses defaults.
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
IRocketWelderClient with the specified configuration.
|
|
345
|
+
"""
|
|
346
|
+
return RocketWelderClient(options or RocketWelderClientOptions())
|
|
@@ -4,10 +4,8 @@ Strongly-typed connection strings with parsing support.
|
|
|
4
4
|
Connection string format: protocol://path?param1=value1¶m2=value2
|
|
5
5
|
|
|
6
6
|
Examples:
|
|
7
|
-
nng+push+ipc://tmp/keypoints?masterFrameInterval=300
|
|
8
|
-
nng+pub+tcp://localhost:5555
|
|
9
7
|
file:///path/to/output.bin
|
|
10
|
-
socket:///tmp/my.sock
|
|
8
|
+
socket:///tmp/my.sock?masterFrameInterval=300
|
|
11
9
|
"""
|
|
12
10
|
|
|
13
11
|
from __future__ import annotations
|
|
@@ -148,8 +146,6 @@ class KeyPointsConnectionString:
|
|
|
148
146
|
Supported protocols:
|
|
149
147
|
- file:///path/to/file.bin - File output (absolute path)
|
|
150
148
|
- socket:///tmp/socket.sock - Unix domain socket
|
|
151
|
-
- nng+push+ipc://tmp/keypoints - NNG Push over IPC
|
|
152
|
-
- nng+push+tcp://host:port - NNG Push over TCP
|
|
153
149
|
|
|
154
150
|
Supported parameters:
|
|
155
151
|
- masterFrameInterval: Interval between master frames (default: 300)
|
|
@@ -164,7 +160,7 @@ class KeyPointsConnectionString:
|
|
|
164
160
|
@classmethod
|
|
165
161
|
def default(cls) -> KeyPointsConnectionString:
|
|
166
162
|
"""Default connection string for KeyPoints."""
|
|
167
|
-
return cls.parse("
|
|
163
|
+
return cls.parse("socket:///tmp/rocket-welder-keypoints.sock?masterFrameInterval=300")
|
|
168
164
|
|
|
169
165
|
@classmethod
|
|
170
166
|
def from_environment(
|
|
@@ -217,9 +213,6 @@ class KeyPointsConnectionString:
|
|
|
217
213
|
elif protocol.is_socket:
|
|
218
214
|
# socket:///tmp/sock -> /tmp/sock
|
|
219
215
|
address = path_part if path_part.startswith("/") else "/" + path_part
|
|
220
|
-
elif protocol.is_nng:
|
|
221
|
-
# NNG protocols need proper address format
|
|
222
|
-
address = protocol.create_nng_address(path_part)
|
|
223
216
|
else:
|
|
224
217
|
return None
|
|
225
218
|
|
|
@@ -249,8 +242,6 @@ class SegmentationConnectionString:
|
|
|
249
242
|
Supported protocols:
|
|
250
243
|
- file:///path/to/file.bin - File output (absolute path)
|
|
251
244
|
- socket:///tmp/socket.sock - Unix domain socket
|
|
252
|
-
- nng+push+ipc://tmp/segmentation - NNG Push over IPC
|
|
253
|
-
- nng+push+tcp://host:port - NNG Push over TCP
|
|
254
245
|
"""
|
|
255
246
|
|
|
256
247
|
value: str
|
|
@@ -261,7 +252,7 @@ class SegmentationConnectionString:
|
|
|
261
252
|
@classmethod
|
|
262
253
|
def default(cls) -> SegmentationConnectionString:
|
|
263
254
|
"""Default connection string for Segmentation."""
|
|
264
|
-
return cls.parse("
|
|
255
|
+
return cls.parse("socket:///tmp/rocket-welder-segmentation.sock")
|
|
265
256
|
|
|
266
257
|
@classmethod
|
|
267
258
|
def from_environment(
|
|
@@ -314,9 +305,91 @@ class SegmentationConnectionString:
|
|
|
314
305
|
elif protocol.is_socket:
|
|
315
306
|
# socket:///tmp/sock -> /tmp/sock
|
|
316
307
|
address = path_part if path_part.startswith("/") else "/" + path_part
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
308
|
+
else:
|
|
309
|
+
return None
|
|
310
|
+
|
|
311
|
+
return cls(
|
|
312
|
+
value=s,
|
|
313
|
+
protocol=protocol,
|
|
314
|
+
address=address,
|
|
315
|
+
parameters=parameters,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
def __str__(self) -> str:
|
|
319
|
+
return self.value
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@dataclass(frozen=True)
|
|
323
|
+
class GraphicsConnectionString:
|
|
324
|
+
"""
|
|
325
|
+
Strongly-typed connection string for Stage (graphics) output.
|
|
326
|
+
|
|
327
|
+
Supported protocols:
|
|
328
|
+
- file:///path/to/file.bin - File output (absolute path)
|
|
329
|
+
- socket:///tmp/socket.sock - Unix domain socket
|
|
330
|
+
"""
|
|
331
|
+
|
|
332
|
+
value: str
|
|
333
|
+
protocol: TransportProtocol
|
|
334
|
+
address: str
|
|
335
|
+
parameters: Dict[str, str] = field(default_factory=dict)
|
|
336
|
+
|
|
337
|
+
@classmethod
|
|
338
|
+
def default(cls) -> GraphicsConnectionString:
|
|
339
|
+
"""Default connection string for Stage."""
|
|
340
|
+
return cls.parse("socket:///tmp/rocket-welder-stage.sock")
|
|
341
|
+
|
|
342
|
+
@classmethod
|
|
343
|
+
def from_environment(
|
|
344
|
+
cls, variable_name: str = "STAGE_CONNECTION_STRING"
|
|
345
|
+
) -> GraphicsConnectionString:
|
|
346
|
+
"""Create from environment variable or use default."""
|
|
347
|
+
value = os.environ.get(variable_name)
|
|
348
|
+
return cls.parse(value) if value else cls.default()
|
|
349
|
+
|
|
350
|
+
@classmethod
|
|
351
|
+
def parse(cls, s: str) -> GraphicsConnectionString:
|
|
352
|
+
"""Parse a connection string."""
|
|
353
|
+
result = cls.try_parse(s)
|
|
354
|
+
if result is None:
|
|
355
|
+
raise ValueError(f"Invalid Graphics connection string: {s}")
|
|
356
|
+
return result
|
|
357
|
+
|
|
358
|
+
@classmethod
|
|
359
|
+
def try_parse(cls, s: str) -> Optional[GraphicsConnectionString]:
|
|
360
|
+
"""Try to parse a connection string."""
|
|
361
|
+
if not s or not s.strip():
|
|
362
|
+
return None
|
|
363
|
+
|
|
364
|
+
s = s.strip()
|
|
365
|
+
parameters: Dict[str, str] = {}
|
|
366
|
+
|
|
367
|
+
# Extract query parameters
|
|
368
|
+
endpoint_part = s
|
|
369
|
+
if "?" in s:
|
|
370
|
+
endpoint_part, query = s.split("?", 1)
|
|
371
|
+
for key, values in parse_qs(query).items():
|
|
372
|
+
parameters[key.lower()] = values[0] if values else ""
|
|
373
|
+
|
|
374
|
+
# Parse protocol and address
|
|
375
|
+
scheme_end = endpoint_part.find("://")
|
|
376
|
+
if scheme_end <= 0:
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
schema_str = endpoint_part[:scheme_end]
|
|
380
|
+
path_part = endpoint_part[scheme_end + 3 :] # skip "://"
|
|
381
|
+
|
|
382
|
+
protocol = TransportProtocol.try_parse(schema_str)
|
|
383
|
+
if protocol is None:
|
|
384
|
+
return None
|
|
385
|
+
|
|
386
|
+
# Build address based on protocol type
|
|
387
|
+
if protocol.is_file:
|
|
388
|
+
# file:///absolute/path -> /absolute/path
|
|
389
|
+
address = path_part if path_part.startswith("/") else "/" + path_part
|
|
390
|
+
elif protocol.is_socket:
|
|
391
|
+
# socket:///tmp/sock -> /tmp/sock
|
|
392
|
+
address = path_part if path_part.startswith("/") else "/" + path_part
|
|
320
393
|
else:
|
|
321
394
|
return None
|
|
322
395
|
|
|
@@ -51,7 +51,7 @@ class FrameSinkFactory:
|
|
|
51
51
|
|
|
52
52
|
Args:
|
|
53
53
|
protocol: The transport protocol (from ConnectionString.protocol), or None
|
|
54
|
-
address: The address (file path
|
|
54
|
+
address: The address (file path or socket path)
|
|
55
55
|
logger_instance: Optional logger for diagnostics
|
|
56
56
|
|
|
57
57
|
Returns:
|
|
@@ -64,7 +64,7 @@ class FrameSinkFactory:
|
|
|
64
64
|
cs = SegmentationConnectionString.parse("socket:///tmp/seg.sock")
|
|
65
65
|
sink = FrameSinkFactory.create(cs.protocol, cs.address)
|
|
66
66
|
"""
|
|
67
|
-
from rocket_welder_sdk.transport import
|
|
67
|
+
from rocket_welder_sdk.transport import NullFrameSink
|
|
68
68
|
from rocket_welder_sdk.transport.stream_transport import StreamFrameSink
|
|
69
69
|
from rocket_welder_sdk.transport.unix_socket_transport import UnixSocketFrameSink
|
|
70
70
|
|
|
@@ -87,19 +87,6 @@ class FrameSinkFactory:
|
|
|
87
87
|
log.info("Creating Unix socket frame sink (server/bind) at: %s", address)
|
|
88
88
|
return UnixSocketFrameSink.bind(address)
|
|
89
89
|
|
|
90
|
-
if protocol.is_nng:
|
|
91
|
-
log.info("Creating NNG frame sink (%s) at: %s", protocol.schema, address)
|
|
92
|
-
|
|
93
|
-
if protocol.is_pub:
|
|
94
|
-
return NngFrameSink.create_publisher(address)
|
|
95
|
-
if protocol.is_push:
|
|
96
|
-
return NngFrameSink.create_pusher(address)
|
|
97
|
-
|
|
98
|
-
raise ValueError(
|
|
99
|
-
f"NNG protocol '{protocol.schema}' is not supported for sinks "
|
|
100
|
-
"(only pub and push are supported)"
|
|
101
|
-
)
|
|
102
|
-
|
|
103
90
|
raise ValueError(f"Transport protocol '{protocol.schema}' is not supported for frame sinks")
|
|
104
91
|
|
|
105
92
|
@staticmethod
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Unified transport protocol as a value type.
|
|
3
3
|
|
|
4
|
-
Supports: file://, socket
|
|
4
|
+
Supports: file://, socket://
|
|
5
5
|
|
|
6
6
|
Examples:
|
|
7
7
|
file:///home/user/output.bin - absolute file path
|
|
8
8
|
socket:///tmp/my.sock - Unix domain socket
|
|
9
|
-
nng+push+ipc://tmp/keypoints - NNG Push over IPC
|
|
10
|
-
nng+push+tcp://host:5555 - NNG Push over TCP
|
|
11
9
|
"""
|
|
12
10
|
|
|
13
11
|
from __future__ import annotations
|
|
@@ -25,61 +23,21 @@ class TransportKind(Enum):
|
|
|
25
23
|
SOCKET = auto()
|
|
26
24
|
"""Unix domain socket (direct, no messaging library)."""
|
|
27
25
|
|
|
28
|
-
NNG_PUSH_IPC = auto()
|
|
29
|
-
"""NNG Push over IPC."""
|
|
30
|
-
|
|
31
|
-
NNG_PUSH_TCP = auto()
|
|
32
|
-
"""NNG Push over TCP."""
|
|
33
|
-
|
|
34
|
-
NNG_PULL_IPC = auto()
|
|
35
|
-
"""NNG Pull over IPC."""
|
|
36
|
-
|
|
37
|
-
NNG_PULL_TCP = auto()
|
|
38
|
-
"""NNG Pull over TCP."""
|
|
39
|
-
|
|
40
|
-
NNG_PUB_IPC = auto()
|
|
41
|
-
"""NNG Pub over IPC."""
|
|
42
|
-
|
|
43
|
-
NNG_PUB_TCP = auto()
|
|
44
|
-
"""NNG Pub over TCP."""
|
|
45
|
-
|
|
46
|
-
NNG_SUB_IPC = auto()
|
|
47
|
-
"""NNG Sub over IPC."""
|
|
48
|
-
|
|
49
|
-
NNG_SUB_TCP = auto()
|
|
50
|
-
"""NNG Sub over TCP."""
|
|
51
|
-
|
|
52
26
|
|
|
53
27
|
class TransportProtocol:
|
|
54
28
|
"""
|
|
55
29
|
Unified transport protocol specification as a value type.
|
|
56
30
|
|
|
57
|
-
Supports: file://, socket
|
|
31
|
+
Supports: file://, socket://
|
|
58
32
|
"""
|
|
59
33
|
|
|
60
34
|
# Predefined protocols
|
|
61
35
|
File: TransportProtocol
|
|
62
36
|
Socket: TransportProtocol
|
|
63
|
-
NngPushIpc: TransportProtocol
|
|
64
|
-
NngPushTcp: TransportProtocol
|
|
65
|
-
NngPullIpc: TransportProtocol
|
|
66
|
-
NngPullTcp: TransportProtocol
|
|
67
|
-
NngPubIpc: TransportProtocol
|
|
68
|
-
NngPubTcp: TransportProtocol
|
|
69
|
-
NngSubIpc: TransportProtocol
|
|
70
|
-
NngSubTcp: TransportProtocol
|
|
71
37
|
|
|
72
38
|
_SCHEMA_MAP: ClassVar[Dict[str, TransportKind]] = {
|
|
73
39
|
"file": TransportKind.FILE,
|
|
74
40
|
"socket": TransportKind.SOCKET,
|
|
75
|
-
"nng+push+ipc": TransportKind.NNG_PUSH_IPC,
|
|
76
|
-
"nng+push+tcp": TransportKind.NNG_PUSH_TCP,
|
|
77
|
-
"nng+pull+ipc": TransportKind.NNG_PULL_IPC,
|
|
78
|
-
"nng+pull+tcp": TransportKind.NNG_PULL_TCP,
|
|
79
|
-
"nng+pub+ipc": TransportKind.NNG_PUB_IPC,
|
|
80
|
-
"nng+pub+tcp": TransportKind.NNG_PUB_TCP,
|
|
81
|
-
"nng+sub+ipc": TransportKind.NNG_SUB_IPC,
|
|
82
|
-
"nng+sub+tcp": TransportKind.NNG_SUB_TCP,
|
|
83
41
|
}
|
|
84
42
|
|
|
85
43
|
_KIND_TO_SCHEMA: ClassVar[Dict[TransportKind, str]] = {}
|
|
@@ -95,7 +53,7 @@ class TransportProtocol:
|
|
|
95
53
|
|
|
96
54
|
@property
|
|
97
55
|
def schema(self) -> str:
|
|
98
|
-
"""The schema string (e.g., 'file', 'socket'
|
|
56
|
+
"""The schema string (e.g., 'file', 'socket')."""
|
|
99
57
|
return self._schema
|
|
100
58
|
|
|
101
59
|
# Classification properties
|
|
@@ -110,82 +68,6 @@ class TransportProtocol:
|
|
|
110
68
|
"""True if this is a Unix socket transport."""
|
|
111
69
|
return self._kind == TransportKind.SOCKET
|
|
112
70
|
|
|
113
|
-
@property
|
|
114
|
-
def is_nng(self) -> bool:
|
|
115
|
-
"""True if this is any NNG-based transport."""
|
|
116
|
-
return self._kind in {
|
|
117
|
-
TransportKind.NNG_PUSH_IPC,
|
|
118
|
-
TransportKind.NNG_PUSH_TCP,
|
|
119
|
-
TransportKind.NNG_PULL_IPC,
|
|
120
|
-
TransportKind.NNG_PULL_TCP,
|
|
121
|
-
TransportKind.NNG_PUB_IPC,
|
|
122
|
-
TransportKind.NNG_PUB_TCP,
|
|
123
|
-
TransportKind.NNG_SUB_IPC,
|
|
124
|
-
TransportKind.NNG_SUB_TCP,
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
@property
|
|
128
|
-
def is_push(self) -> bool:
|
|
129
|
-
"""True if this is a Push pattern."""
|
|
130
|
-
return self._kind in {TransportKind.NNG_PUSH_IPC, TransportKind.NNG_PUSH_TCP}
|
|
131
|
-
|
|
132
|
-
@property
|
|
133
|
-
def is_pull(self) -> bool:
|
|
134
|
-
"""True if this is a Pull pattern."""
|
|
135
|
-
return self._kind in {TransportKind.NNG_PULL_IPC, TransportKind.NNG_PULL_TCP}
|
|
136
|
-
|
|
137
|
-
@property
|
|
138
|
-
def is_pub(self) -> bool:
|
|
139
|
-
"""True if this is a Pub pattern."""
|
|
140
|
-
return self._kind in {TransportKind.NNG_PUB_IPC, TransportKind.NNG_PUB_TCP}
|
|
141
|
-
|
|
142
|
-
@property
|
|
143
|
-
def is_sub(self) -> bool:
|
|
144
|
-
"""True if this is a Sub pattern."""
|
|
145
|
-
return self._kind in {TransportKind.NNG_SUB_IPC, TransportKind.NNG_SUB_TCP}
|
|
146
|
-
|
|
147
|
-
@property
|
|
148
|
-
def is_ipc(self) -> bool:
|
|
149
|
-
"""True if this uses IPC layer."""
|
|
150
|
-
return self._kind in {
|
|
151
|
-
TransportKind.NNG_PUSH_IPC,
|
|
152
|
-
TransportKind.NNG_PULL_IPC,
|
|
153
|
-
TransportKind.NNG_PUB_IPC,
|
|
154
|
-
TransportKind.NNG_SUB_IPC,
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
@property
|
|
158
|
-
def is_tcp(self) -> bool:
|
|
159
|
-
"""True if this uses TCP layer."""
|
|
160
|
-
return self._kind in {
|
|
161
|
-
TransportKind.NNG_PUSH_TCP,
|
|
162
|
-
TransportKind.NNG_PULL_TCP,
|
|
163
|
-
TransportKind.NNG_PUB_TCP,
|
|
164
|
-
TransportKind.NNG_SUB_TCP,
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
def create_nng_address(self, path_or_host: str) -> str:
|
|
168
|
-
"""
|
|
169
|
-
Create the NNG address from a path/host.
|
|
170
|
-
|
|
171
|
-
For IPC: ipc:///path
|
|
172
|
-
For TCP: tcp://host:port
|
|
173
|
-
|
|
174
|
-
Raises:
|
|
175
|
-
ValueError: If this is not an NNG protocol.
|
|
176
|
-
"""
|
|
177
|
-
if not self.is_nng:
|
|
178
|
-
raise ValueError(f"Cannot create NNG address for {self._kind} transport")
|
|
179
|
-
|
|
180
|
-
if self.is_ipc:
|
|
181
|
-
# IPC paths need leading "/" for absolute paths
|
|
182
|
-
if not path_or_host.startswith("/"):
|
|
183
|
-
return f"ipc:///{path_or_host}"
|
|
184
|
-
return f"ipc://{path_or_host}"
|
|
185
|
-
|
|
186
|
-
# TCP
|
|
187
|
-
return f"tcp://{path_or_host}"
|
|
188
|
-
|
|
189
71
|
def __str__(self) -> str:
|
|
190
72
|
return self._schema
|
|
191
73
|
|
|
@@ -202,7 +84,7 @@ class TransportProtocol:
|
|
|
202
84
|
|
|
203
85
|
@classmethod
|
|
204
86
|
def parse(cls, s: str) -> TransportProtocol:
|
|
205
|
-
"""Parse a protocol string (e.g., '
|
|
87
|
+
"""Parse a protocol string (e.g., 'file', 'socket')."""
|
|
206
88
|
result = cls.try_parse(s)
|
|
207
89
|
if result is None:
|
|
208
90
|
raise ValueError(f"Invalid transport protocol: {s}")
|
|
@@ -225,14 +107,6 @@ class TransportProtocol:
|
|
|
225
107
|
# Initialize predefined protocols
|
|
226
108
|
TransportProtocol.File = TransportProtocol(TransportKind.FILE, "file")
|
|
227
109
|
TransportProtocol.Socket = TransportProtocol(TransportKind.SOCKET, "socket")
|
|
228
|
-
TransportProtocol.NngPushIpc = TransportProtocol(TransportKind.NNG_PUSH_IPC, "nng+push+ipc")
|
|
229
|
-
TransportProtocol.NngPushTcp = TransportProtocol(TransportKind.NNG_PUSH_TCP, "nng+push+tcp")
|
|
230
|
-
TransportProtocol.NngPullIpc = TransportProtocol(TransportKind.NNG_PULL_IPC, "nng+pull+ipc")
|
|
231
|
-
TransportProtocol.NngPullTcp = TransportProtocol(TransportKind.NNG_PULL_TCP, "nng+pull+tcp")
|
|
232
|
-
TransportProtocol.NngPubIpc = TransportProtocol(TransportKind.NNG_PUB_IPC, "nng+pub+ipc")
|
|
233
|
-
TransportProtocol.NngPubTcp = TransportProtocol(TransportKind.NNG_PUB_TCP, "nng+pub+tcp")
|
|
234
|
-
TransportProtocol.NngSubIpc = TransportProtocol(TransportKind.NNG_SUB_IPC, "nng+sub+ipc")
|
|
235
|
-
TransportProtocol.NngSubTcp = TransportProtocol(TransportKind.NNG_SUB_TCP, "nng+sub+tcp")
|
|
236
110
|
|
|
237
111
|
# Initialize reverse lookup map
|
|
238
112
|
TransportProtocol._KIND_TO_SCHEMA = {v: k for k, v in TransportProtocol._SCHEMA_MAP.items()}
|