openrewrite-remote 0.12.0__py3-none-any.whl → 0.13.0__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.
- openrewrite_remote-0.13.0.dist-info/METADATA +12 -0
- openrewrite_remote-0.13.0.dist-info/RECORD +14 -0
- {openrewrite_remote-0.12.0.dist-info → openrewrite_remote-0.13.0.dist-info}/WHEEL +2 -1
- openrewrite_remote-0.13.0.dist-info/entry_points.txt +2 -0
- openrewrite_remote-0.13.0.dist-info/top_level.txt +1 -0
- rewrite_remote/__init__.py +12 -0
- rewrite_remote/client.py +70 -0
- {rewrite/remote → rewrite_remote}/event.py +2 -2
- {rewrite/remote → rewrite_remote}/receiver.py +245 -88
- {rewrite/remote → rewrite_remote}/remote_utils.py +78 -40
- {rewrite/remote → rewrite_remote}/remoting.py +116 -44
- {rewrite/remote → rewrite_remote}/sender.py +222 -90
- {rewrite/remote → rewrite_remote}/server.py +100 -36
- rewrite_remote/type_utils.py +109 -0
- openrewrite_remote-0.12.0.dist-info/METADATA +0 -17
- openrewrite_remote-0.12.0.dist-info/RECORD +0 -12
- rewrite/remote/__init__.py +0 -7
- rewrite/remote/client.py +0 -40
- rewrite/remote/type_utils.py +0 -101
@@ -1,18 +1,30 @@
|
|
1
|
+
# type: ignore
|
1
2
|
import socket
|
2
3
|
import struct
|
3
4
|
from enum import Enum, auto
|
4
5
|
from io import BytesIO
|
5
|
-
from typing import
|
6
|
+
from typing import (
|
7
|
+
Callable,
|
8
|
+
List,
|
9
|
+
Optional,
|
10
|
+
TypeVar,
|
11
|
+
Dict,
|
12
|
+
TYPE_CHECKING,
|
13
|
+
Iterable,
|
14
|
+
cast,
|
15
|
+
Type,
|
16
|
+
Any,
|
17
|
+
)
|
6
18
|
|
7
19
|
from cbor2 import CBORDecoder, CBORDecodeValueError
|
8
20
|
|
9
21
|
from .event import EventType
|
10
22
|
|
11
23
|
if TYPE_CHECKING:
|
12
|
-
from .receiver import ReceiverContext, DetailsReceiver
|
24
|
+
from rewrite_remote.receiver import ReceiverContext, DetailsReceiver
|
13
25
|
|
14
|
-
T = TypeVar(
|
15
|
-
I = TypeVar(
|
26
|
+
T = TypeVar("T")
|
27
|
+
I = TypeVar("I")
|
16
28
|
|
17
29
|
|
18
30
|
class Operation(Enum):
|
@@ -23,9 +35,11 @@ class Operation(Enum):
|
|
23
35
|
Move = auto()
|
24
36
|
|
25
37
|
|
26
|
-
def receive_nodes(
|
27
|
-
|
28
|
-
|
38
|
+
def receive_nodes(
|
39
|
+
before: Optional[List[T]],
|
40
|
+
details: Callable[[Optional[T], Optional[str], "ReceiverContext"], T],
|
41
|
+
ctx: "ReceiverContext",
|
42
|
+
) -> Optional[List[T]]:
|
29
43
|
list_event = ctx.receiver.receive_value(list)
|
30
44
|
if list_event.event_type == EventType.NoChange:
|
31
45
|
return before
|
@@ -33,26 +47,32 @@ def receive_nodes(before: Optional[List[T]],
|
|
33
47
|
return None
|
34
48
|
elif list_event.event_type == EventType.Add:
|
35
49
|
after_size = list_event.msg
|
50
|
+
if after_size is None:
|
51
|
+
after_size = 0
|
36
52
|
after = [None] * after_size # Preallocate list
|
37
53
|
for i in range(after_size):
|
38
54
|
diff_event = ctx.receiver.receive_node()
|
39
55
|
if diff_event.event_type == EventType.Add:
|
40
|
-
after[i] = details
|
56
|
+
after[i] = details(None, diff_event.concrete_type, ctx) # type: ignore
|
41
57
|
elif diff_event.event_type == EventType.NoChange:
|
42
58
|
after[i] = None # Or some default value
|
43
59
|
else:
|
44
|
-
raise NotImplementedError(
|
45
|
-
|
60
|
+
raise NotImplementedError(
|
61
|
+
f"Unexpected operation: {diff_event.event_type}"
|
62
|
+
)
|
63
|
+
return after # type: ignore
|
46
64
|
elif list_event.event_type == EventType.Update:
|
47
|
-
return _receive_updated_nodes(before, list_event.msg, details, ctx)
|
65
|
+
return _receive_updated_nodes(before, list_event.msg, details, ctx) # type: ignore
|
48
66
|
else:
|
49
67
|
raise NotImplementedError(f"Unexpected operation: {list_event.event_type}")
|
50
68
|
|
51
69
|
|
52
|
-
def _receive_updated_nodes(
|
53
|
-
|
54
|
-
|
55
|
-
|
70
|
+
def _receive_updated_nodes(
|
71
|
+
before: List[T],
|
72
|
+
after_size: int,
|
73
|
+
details: "DetailsReceiver[T]",
|
74
|
+
ctx: "ReceiverContext",
|
75
|
+
) -> List[T]:
|
56
76
|
modified = False
|
57
77
|
after_list = before
|
58
78
|
evt = ctx.receiver.receive_node()
|
@@ -77,7 +97,9 @@ def _receive_updated_nodes(before: List[T],
|
|
77
97
|
elif evt.event_type == EventType.Delete:
|
78
98
|
before_idx += 1
|
79
99
|
elif evt.event_type == EventType.Update:
|
80
|
-
after_list.append(
|
100
|
+
after_list.append(
|
101
|
+
details.receive_details(before[before_idx], evt.concrete_type, ctx)
|
102
|
+
)
|
81
103
|
before_idx += 1
|
82
104
|
elif evt.event_type == EventType.Add:
|
83
105
|
after_list.append(details.receive_details(None, evt.concrete_type, ctx))
|
@@ -88,7 +110,9 @@ def _receive_updated_nodes(before: List[T],
|
|
88
110
|
return after_list[:after_size] if len(after_list) > after_size else after_list
|
89
111
|
|
90
112
|
|
91
|
-
def receive_values(
|
113
|
+
def receive_values(
|
114
|
+
before: Optional[List[T]], type: Type[Any], ctx: "ReceiverContext"
|
115
|
+
) -> Optional[List[T]]:
|
92
116
|
list_event = ctx.receiver.receive_value(list)
|
93
117
|
if list_event.event_type == EventType.NoChange:
|
94
118
|
return before
|
@@ -96,6 +120,8 @@ def receive_values(before: Optional[List[T]], type: Type, ctx: 'ReceiverContext'
|
|
96
120
|
return None
|
97
121
|
elif list_event.event_type == EventType.Add:
|
98
122
|
after_size = list_event.msg
|
123
|
+
if after_size is None:
|
124
|
+
after_size = 0
|
99
125
|
after = [None] * after_size # Preallocate list
|
100
126
|
for i in range(after_size):
|
101
127
|
diff_event = ctx.receiver.receive_value(type)
|
@@ -104,15 +130,19 @@ def receive_values(before: Optional[List[T]], type: Type, ctx: 'ReceiverContext'
|
|
104
130
|
elif diff_event.event_type == EventType.NoChange:
|
105
131
|
after[i] = None # Or some default value
|
106
132
|
else:
|
107
|
-
raise NotImplementedError(
|
108
|
-
|
133
|
+
raise NotImplementedError(
|
134
|
+
f"Unexpected operation: {diff_event.event_type}"
|
135
|
+
)
|
136
|
+
return after # type: ignore
|
109
137
|
elif list_event.event_type == EventType.Update:
|
110
|
-
return _receive_updated_values(before, list_event.msg, type, ctx)
|
138
|
+
return _receive_updated_values(before, list_event.msg, type, ctx) # type: ignore
|
111
139
|
else:
|
112
140
|
raise NotImplementedError(f"Unexpected operation: {list_event.event_type}")
|
113
141
|
|
114
142
|
|
115
|
-
def _receive_updated_values(
|
143
|
+
def _receive_updated_values(
|
144
|
+
before: List[T], after_size: int, type: Type[Any], ctx: "ReceiverContext"
|
145
|
+
) -> List[T]:
|
116
146
|
modified = False
|
117
147
|
after_list = before
|
118
148
|
evt = ctx.receiver.receive_node()
|
@@ -137,7 +167,7 @@ def _receive_updated_values(before: List[T], after_size: int, type: Type, ctx: '
|
|
137
167
|
elif evt.event_type == EventType.Delete:
|
138
168
|
before_idx += 1
|
139
169
|
elif evt.event_type in (EventType.Update, EventType.Add):
|
140
|
-
after_list.append(evt.msg)
|
170
|
+
after_list.append(cast(T, evt.msg))
|
141
171
|
if evt.event_type == EventType.Update:
|
142
172
|
before_idx += 1
|
143
173
|
|
@@ -150,17 +180,19 @@ def _receive_updated_values(before: List[T], after_size: int, type: Type, ctx: '
|
|
150
180
|
def _copy_range(before: Iterable[T], j: int) -> List[T]:
|
151
181
|
if isinstance(before, list):
|
152
182
|
return before[:j]
|
153
|
-
elif hasattr(
|
154
|
-
|
183
|
+
elif hasattr(
|
184
|
+
before, "getrange"
|
185
|
+
): # If the object has a 'getrange' method (e.g., an immutable list)
|
186
|
+
return cast(List[T], before.getrange(0, j))
|
155
187
|
else:
|
156
188
|
return list(before)[:j]
|
157
189
|
|
158
190
|
|
159
191
|
def calculate_list_diff(
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
192
|
+
before: List[T],
|
193
|
+
after: List[T],
|
194
|
+
id_function: Callable[[T], I],
|
195
|
+
consumer: Callable[[Operation, int, int, Optional[T], Optional[T]], None],
|
164
196
|
) -> None:
|
165
197
|
before_idx, after_idx = 0, 0
|
166
198
|
before_size, after_size = len(before), len(after)
|
@@ -183,7 +215,7 @@ def calculate_list_diff(
|
|
183
215
|
before_idx,
|
184
216
|
after_idx,
|
185
217
|
before[before_idx],
|
186
|
-
after[after_idx]
|
218
|
+
after[after_idx],
|
187
219
|
)
|
188
220
|
before_idx += 1
|
189
221
|
after_idx += 1
|
@@ -197,7 +229,7 @@ def calculate_list_diff(
|
|
197
229
|
before_idx,
|
198
230
|
after_idx,
|
199
231
|
before[before_idx],
|
200
|
-
after[after_idx]
|
232
|
+
after[after_idx],
|
201
233
|
)
|
202
234
|
before_idx += 1
|
203
235
|
after_idx += 1
|
@@ -215,9 +247,7 @@ def calculate_list_diff(
|
|
215
247
|
|
216
248
|
|
217
249
|
def create_index_map(
|
218
|
-
|
219
|
-
from_index: int,
|
220
|
-
id_function: Callable[[T], I]
|
250
|
+
lst: List[T], from_index: int, id_function: Callable[[T], I]
|
221
251
|
) -> Dict[I, int]:
|
222
252
|
result = {}
|
223
253
|
for i in range(from_index, len(lst)):
|
@@ -225,7 +255,9 @@ def create_index_map(
|
|
225
255
|
return result
|
226
256
|
|
227
257
|
|
228
|
-
def _decode_length(
|
258
|
+
def _decode_length(
|
259
|
+
decoder: CBORDecoder, subtype: int, allow_indefinite: bool = False
|
260
|
+
) -> Optional[int]:
|
229
261
|
if subtype < 24:
|
230
262
|
return subtype
|
231
263
|
elif subtype == 24:
|
@@ -241,7 +273,8 @@ def _decode_length(decoder: CBORDecoder, subtype: int, allow_indefinite: bool =
|
|
241
273
|
else:
|
242
274
|
raise CBORDecodeValueError(f"unknown unsigned integer subtype 0x{subtype:x}")
|
243
275
|
|
244
|
-
|
276
|
+
|
277
|
+
def decode_array_start(decoder: CBORDecoder) -> Optional[int]:
|
245
278
|
initial_byte = decoder.read(1)[0]
|
246
279
|
major_type = initial_byte >> 5
|
247
280
|
assert major_type == 4
|
@@ -253,6 +286,7 @@ COPY_BUFFER_SIZE = 4096
|
|
253
286
|
COPY_BUFFER = bytearray(COPY_BUFFER_SIZE)
|
254
287
|
COMMAND_END = bytes([0x81, 0x17])
|
255
288
|
|
289
|
+
|
256
290
|
def read_to_command_end(sock: socket.socket) -> BytesIO:
|
257
291
|
memory_stream = BytesIO()
|
258
292
|
|
@@ -262,15 +296,19 @@ def read_to_command_end(sock: socket.socket) -> BytesIO:
|
|
262
296
|
if bytes_read == 0:
|
263
297
|
break
|
264
298
|
memory_stream.write(COPY_BUFFER[:bytes_read])
|
265
|
-
if (
|
266
|
-
|
267
|
-
|
299
|
+
if (
|
300
|
+
bytes_read > 1
|
301
|
+
and COPY_BUFFER[bytes_read - 2] == COMMAND_END[0]
|
302
|
+
and COPY_BUFFER[bytes_read - 1] == COMMAND_END[1]
|
303
|
+
):
|
268
304
|
break
|
269
305
|
elif bytes_read == 1:
|
270
306
|
original_position = memory_stream.tell()
|
271
307
|
memory_stream.seek(-2, 1) # Move back by 2 bytes
|
272
|
-
if (
|
273
|
-
|
308
|
+
if (
|
309
|
+
memory_stream.read(1)[0] == COMMAND_END[0]
|
310
|
+
and memory_stream.read(1)[0] == COMMAND_END[1]
|
311
|
+
):
|
274
312
|
memory_stream.seek(original_position)
|
275
313
|
break
|
276
314
|
except socket.error as e:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# type: ignore
|
1
2
|
from __future__ import absolute_import
|
2
3
|
|
3
4
|
import socket
|
@@ -6,19 +7,52 @@ import traceback
|
|
6
7
|
from dataclasses import dataclass
|
7
8
|
from io import BytesIO
|
8
9
|
from threading import Lock
|
9
|
-
from typing import
|
10
|
+
from typing import (
|
11
|
+
Any,
|
12
|
+
Dict,
|
13
|
+
Optional,
|
14
|
+
Type,
|
15
|
+
List,
|
16
|
+
Tuple,
|
17
|
+
Callable,
|
18
|
+
cast,
|
19
|
+
Union,
|
20
|
+
BinaryIO,
|
21
|
+
)
|
10
22
|
|
11
23
|
import cbor2
|
12
24
|
from cbor2 import dumps, loads, load
|
13
|
-
|
25
|
+
|
26
|
+
from rewrite import (
|
27
|
+
Recipe,
|
28
|
+
InMemoryExecutionContext,
|
29
|
+
Cursor,
|
30
|
+
PrinterFactory,
|
31
|
+
TreeVisitor,
|
32
|
+
Tree,
|
33
|
+
)
|
14
34
|
from rewrite.execution import DelegatingExecutionContext
|
15
|
-
from rewrite.remote import ValueSerializer, ValueDeserializer, SenderContext, ReceiverContext, JsonSender, JsonReceiver, \
|
16
|
-
SerializationContext, DeserializationContext, remote_utils
|
17
35
|
from rewrite.tree import PrintOutputCapture, P
|
18
36
|
from rewrite.visitor import T
|
19
37
|
|
38
|
+
from rewrite_remote import (
|
39
|
+
ValueSerializer,
|
40
|
+
ValueDeserializer,
|
41
|
+
SenderContext,
|
42
|
+
ReceiverContext,
|
43
|
+
JsonSender,
|
44
|
+
JsonReceiver,
|
45
|
+
SerializationContext,
|
46
|
+
DeserializationContext,
|
47
|
+
remote_utils,
|
48
|
+
)
|
49
|
+
|
20
50
|
|
21
51
|
class RemotingContext:
|
52
|
+
"""
|
53
|
+
A context for remoting operations.
|
54
|
+
"""
|
55
|
+
|
22
56
|
_remoting_thread_local = threading.local()
|
23
57
|
_recipe_factories: Dict[str, Callable[[str, Dict[str, Any]], Recipe]] = {}
|
24
58
|
_value_serializers: Dict[Type, ValueSerializer] = {}
|
@@ -30,8 +64,8 @@ class RemotingContext:
|
|
30
64
|
self._client = None
|
31
65
|
|
32
66
|
@classmethod
|
33
|
-
def current(cls) ->
|
34
|
-
result = getattr(cls._remoting_thread_local,
|
67
|
+
def current(cls) -> "RemotingContext":
|
68
|
+
result = getattr(cls._remoting_thread_local, "context", None)
|
35
69
|
if result is None:
|
36
70
|
raise ValueError("No RemotingContext has been set")
|
37
71
|
return result
|
@@ -41,10 +75,10 @@ class RemotingContext:
|
|
41
75
|
cls._remoting_thread_local.context = self
|
42
76
|
|
43
77
|
@property
|
44
|
-
def client(self) -> Optional[
|
78
|
+
def client(self) -> Optional["RemotingClient"]:
|
45
79
|
return self._client
|
46
80
|
|
47
|
-
def connect(self, sock: Any) ->
|
81
|
+
def connect(self, sock: Any) -> "RemotingContext":
|
48
82
|
self._client = RemotingClient(self, sock)
|
49
83
|
return self
|
50
84
|
|
@@ -71,30 +105,40 @@ class RemotingContext:
|
|
71
105
|
self._object_to_id_map.clear()
|
72
106
|
self._id_to_object_map.clear()
|
73
107
|
|
74
|
-
def new_sender_context(self, output_stream: Any) ->
|
75
|
-
return SenderContext(
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
108
|
+
def new_sender_context(self, output_stream: Any) -> "SenderContext":
|
109
|
+
return SenderContext(
|
110
|
+
JsonSender(
|
111
|
+
output_stream, SerializationContext(self, self._value_serializers)
|
112
|
+
)
|
113
|
+
)
|
114
|
+
|
115
|
+
def new_receiver_context(self, input_stream: Any) -> "ReceiverContext":
|
116
|
+
return ReceiverContext(
|
117
|
+
JsonReceiver(
|
118
|
+
input_stream, DeserializationContext(self, self._value_deserializers)
|
119
|
+
)
|
120
|
+
)
|
121
|
+
|
122
|
+
def copy(self) -> "RemotingContext":
|
81
123
|
return RemotingContext()
|
82
124
|
|
83
|
-
def new_recipe(self, recipe_id: str, recipe_options: Any) ->
|
125
|
+
def new_recipe(self, recipe_id: str, recipe_options: Any) -> "Recipe":
|
84
126
|
return self._recipe_factories[recipe_id](recipe_options)
|
85
127
|
|
86
128
|
@classmethod
|
87
129
|
def register_value_serializer(cls, serializer: ValueSerializer) -> None:
|
88
|
-
cls._value_serializers[serializer.__annotations__[
|
130
|
+
cls._value_serializers[serializer.__annotations__["value"]] = serializer
|
89
131
|
|
90
132
|
@classmethod
|
91
133
|
def register_value_deserializer(cls, deserializer: ValueDeserializer) -> None:
|
92
134
|
for i in range(len(cls._value_deserializers)):
|
93
135
|
type_ = cls._value_deserializers[i][0]
|
94
|
-
if type_ == deserializer.__annotations__[
|
136
|
+
if type_ == deserializer.__annotations__["data"]:
|
95
137
|
cls._value_deserializers[i] = (type_, deserializer)
|
96
138
|
return
|
97
|
-
cls._value_deserializers.append(
|
139
|
+
cls._value_deserializers.append(
|
140
|
+
(deserializer.__annotations__["data"], deserializer)
|
141
|
+
)
|
98
142
|
|
99
143
|
|
100
144
|
class RemotingExecutionContextView(DelegatingExecutionContext):
|
@@ -110,12 +154,12 @@ class RemotingExecutionContextView(DelegatingExecutionContext):
|
|
110
154
|
|
111
155
|
@property
|
112
156
|
def remoting_context(self) -> RemotingContext:
|
113
|
-
return self._delegate.get_message(
|
157
|
+
return self._delegate.get_message("remoting", RemotingContext.current())
|
114
158
|
|
115
159
|
@remoting_context.setter
|
116
160
|
def remoting_context(self, value: RemotingContext):
|
117
161
|
value.set_current()
|
118
|
-
self._delegate.put_message(
|
162
|
+
self._delegate.put_message("remoting", value)
|
119
163
|
|
120
164
|
|
121
165
|
OK = 0
|
@@ -124,8 +168,13 @@ ERROR = 1
|
|
124
168
|
|
125
169
|
class RemotingMessenger:
|
126
170
|
|
127
|
-
def __init__(
|
128
|
-
|
171
|
+
def __init__(
|
172
|
+
self,
|
173
|
+
context: RemotingContext,
|
174
|
+
additional_handlers: Dict[
|
175
|
+
str, Callable[[BytesIO, socket.socket, RemotingContext], Any]
|
176
|
+
] = None,
|
177
|
+
):
|
129
178
|
self._context = context
|
130
179
|
self._additional_handlers = additional_handlers or {}
|
131
180
|
self._recipes = []
|
@@ -190,7 +239,7 @@ class RemotingMessenger:
|
|
190
239
|
def handle_run_recipe_visitor_command(self, stream: BytesIO, sock: socket.socket):
|
191
240
|
recipe_index = cbor2.load(stream)
|
192
241
|
recipe = self._recipes[recipe_index]
|
193
|
-
received = self.receive_tree(
|
242
|
+
received = self.receive_tree(stream, self._state)
|
194
243
|
|
195
244
|
ctx = InMemoryExecutionContext()
|
196
245
|
RemotingExecutionContextView.view(ctx).remoting_context = self._context
|
@@ -207,7 +256,9 @@ class RemotingMessenger:
|
|
207
256
|
root_cursor = Cursor(None, Cursor.ROOT_VALUE)
|
208
257
|
ctx = InMemoryExecutionContext()
|
209
258
|
RemotingExecutionContextView.view(ctx).remoting_context = self._context
|
210
|
-
print_output = received.print(
|
259
|
+
print_output = received.print(
|
260
|
+
Cursor(root_cursor, received), PrintOutputCapture(0)
|
261
|
+
)
|
211
262
|
|
212
263
|
response_stream = BytesIO()
|
213
264
|
cbor2.dump(RemotingMessageType.Response, response_stream)
|
@@ -232,11 +283,12 @@ class RemotingMessenger:
|
|
232
283
|
|
233
284
|
@staticmethod
|
234
285
|
def send_end_message(sock):
|
235
|
-
sock.sendall(b
|
286
|
+
sock.sendall(b"\x81\x17")
|
236
287
|
|
237
288
|
def send_print_request(self, sock: socket.socket, cursor: Cursor):
|
238
|
-
self.__send_request_stream(
|
239
|
-
|
289
|
+
self.__send_request_stream(
|
290
|
+
sock, "print", lambda s: self.send_tree(s, cast(Tree, cursor.value))
|
291
|
+
)
|
240
292
|
if self.recv_byte(sock) != RemotingMessageType.Response:
|
241
293
|
raise ValueError("Unexpected message type.")
|
242
294
|
if self.recv_byte(sock) != 0:
|
@@ -246,22 +298,35 @@ class RemotingMessenger:
|
|
246
298
|
# end = load(data) # end
|
247
299
|
return print_msg
|
248
300
|
|
249
|
-
def send_tree(
|
301
|
+
def send_tree(
|
302
|
+
self,
|
303
|
+
sock: Union[BinaryIO, socket.socket],
|
304
|
+
after: Tree,
|
305
|
+
before: Optional[Tree] = None,
|
306
|
+
):
|
250
307
|
b = BytesIO()
|
251
308
|
self._context.new_sender_context(b).send_any_tree(after, before)
|
252
309
|
sock.sendall(dumps(b.getvalue()))
|
253
310
|
|
254
|
-
def receive_tree(
|
255
|
-
|
311
|
+
def receive_tree(
|
312
|
+
self, data: Union[BinaryIO, socket.socket], before: Optional[Tree] = None
|
313
|
+
):
|
314
|
+
receiver_context = self._context.new_receiver_context(BytesIO(cbor2.load(data)))
|
256
315
|
return receiver_context.receive_any_tree(before)
|
257
316
|
|
258
|
-
def send_run_recipe_request(
|
259
|
-
self.
|
260
|
-
|
261
|
-
|
262
|
-
sock
|
263
|
-
|
264
|
-
|
317
|
+
def send_run_recipe_request(
|
318
|
+
self, sock: socket.socket, recipe, options: dict, source_files: list
|
319
|
+
):
|
320
|
+
self.__send_request_stream(
|
321
|
+
sock,
|
322
|
+
"run-recipe",
|
323
|
+
lambda s: (
|
324
|
+
sock.sendall(dumps(recipe)),
|
325
|
+
sock.sendall(dumps(options)),
|
326
|
+
sock.sendall(dumps(len(source_files))),
|
327
|
+
*[self.send_tree(sock, sf, None) for sf in source_files],
|
328
|
+
),
|
329
|
+
)
|
265
330
|
while self.recv_byte(sock) == RemotingMessageType.Request:
|
266
331
|
self.process_request(sock)
|
267
332
|
if self.recv_byte(sock) != RemotingMessageType.Response:
|
@@ -285,7 +350,7 @@ class RemotingMessenger:
|
|
285
350
|
return sock.recv(1)[0]
|
286
351
|
|
287
352
|
def recv_all(self, sock, buffer_size=4096):
|
288
|
-
data = b
|
353
|
+
data = b""
|
289
354
|
while True:
|
290
355
|
part = sock.recv(buffer_size)
|
291
356
|
data += part
|
@@ -308,28 +373,35 @@ class RemotingClient:
|
|
308
373
|
def close(self) -> None:
|
309
374
|
self._socket.close()
|
310
375
|
|
311
|
-
def hello(self):
|
376
|
+
def hello(self) -> None:
|
312
377
|
with self._lock:
|
313
378
|
self._messenger.send_request(self._socket, "hello")
|
314
379
|
|
315
|
-
def print(self, cursor):
|
380
|
+
def print(self, cursor: Cursor) -> Any:
|
316
381
|
with self._lock:
|
317
382
|
return self._messenger.send_print_request(self._socket, cursor)
|
318
383
|
|
319
|
-
def reset(self):
|
384
|
+
def reset(self) -> None:
|
320
385
|
with self._lock:
|
321
386
|
self._messenger.send_reset_request(self._socket)
|
322
387
|
|
323
388
|
def run_recipe(self, recipe, options: dict, source_files: list):
|
324
389
|
with self._lock:
|
325
|
-
return self._messenger.send_run_recipe_request(
|
390
|
+
return self._messenger.send_run_recipe_request(
|
391
|
+
self._socket, recipe, options, source_files
|
392
|
+
)
|
326
393
|
|
327
394
|
|
328
395
|
@dataclass
|
329
396
|
class RemotePrinter(TreeVisitor[Any, PrintOutputCapture[P]]):
|
330
397
|
_client: RemotingClient
|
331
398
|
|
332
|
-
def visit(
|
399
|
+
def visit(
|
400
|
+
self,
|
401
|
+
tree: Optional[Tree],
|
402
|
+
p: PrintOutputCapture[P],
|
403
|
+
parent: Optional[Cursor] = None,
|
404
|
+
) -> Optional[T]:
|
333
405
|
self.cursor = Cursor(parent, tree)
|
334
406
|
p.append(self._client.print(self.cursor))
|
335
407
|
self.cursor = self.cursor.parent
|