vortexpy 4.0.23__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.
- vortex/DataWrapTuple.py +27 -0
- vortex/DeferUtil.py +224 -0
- vortex/Jsonable.py +304 -0
- vortex/Payload.py +115 -0
- vortex/PayloadEndpoint.py +216 -0
- vortex/PayloadEndpointTest.py +164 -0
- vortex/PayloadEnvelope.py +166 -0
- vortex/PayloadFilterKeys.py +15 -0
- vortex/PayloadIO.py +152 -0
- vortex/PayloadPriority.py +11 -0
- vortex/PayloadResponse.py +173 -0
- vortex/PayloadResponseTest.py +39 -0
- vortex/PayloadTest.py +136 -0
- vortex/PerformTestActionTuple.py +30 -0
- vortex/SerialiseUtil.py +273 -0
- vortex/TestTuple.py +61 -0
- vortex/Tuple.py +968 -0
- vortex/TupleAction.py +72 -0
- vortex/TupleActionVortex.py +5 -0
- vortex/TupleDataForTest.py +25 -0
- vortex/TuplePerfTest.py +71 -0
- vortex/TuplePolymorphicTupleTypeFieldArgTest.py +74 -0
- vortex/TupleRestfulTest.py +140 -0
- vortex/TupleSelector.py +105 -0
- vortex/TupleTest.py +127 -0
- vortex/VortexABC.py +55 -0
- vortex/VortexClientHttp.py +308 -0
- vortex/VortexClientHttpTest.py +71 -0
- vortex/VortexClientTcp.py +355 -0
- vortex/VortexClientWebsocketFactory.py +383 -0
- vortex/VortexConnectionABC.py +88 -0
- vortex/VortexFactory.py +932 -0
- vortex/VortexPayloadProtocol.py +180 -0
- vortex/VortexServer.py +367 -0
- vortex/VortexServerConnection.py +127 -0
- vortex/VortexServerHttpResource.py +193 -0
- vortex/VortexServerTcp.py +104 -0
- vortex/VortexServerWebsocket.py +287 -0
- vortex/VortexTcpMemoryLeakPayloadTest.py +611 -0
- vortex/VortexTcpMemoryLeakRawTest.py +87 -0
- vortex/VortexTest.py +22 -0
- vortex/VortexUtil.py +314 -0
- vortex/VortexWritePushProducer.py +321 -0
- vortex/__init__.py +10 -0
- vortex/data_loader/TupleDataLiveLockManager.py +383 -0
- vortex/data_loader/TupleDataLoader.py +326 -0
- vortex/data_loader/TupleDataLoaderDelegate.py +90 -0
- vortex/data_loader/TupleDataLoaderTupleABC.py +10 -0
- vortex/data_loader/TupleDataLoaderTuples.py +53 -0
- vortex/data_loader/__init__.py +0 -0
- vortex/event_bus/TupleChangeEventABC.py +15 -0
- vortex/event_bus/TupleChangeEventBus.py +192 -0
- vortex/event_bus/TupleChangeEventBusObserverABC.py +11 -0
- vortex/event_bus/__init__.py +0 -0
- vortex/handler/TupleActionProcessor.py +270 -0
- vortex/handler/TupleActionProcessorProxy.py +218 -0
- vortex/handler/TupleActionProcessorTestHandler.py +27 -0
- vortex/handler/TupleDataActionClient.py +67 -0
- vortex/handler/TupleDataObservableCache.py +201 -0
- vortex/handler/TupleDataObservableHandler.py +371 -0
- vortex/handler/TupleDataObservableProxyHandler.py +340 -0
- vortex/handler/TupleDataObservableTestHandler.py +60 -0
- vortex/handler/TupleDataObserverClient.py +158 -0
- vortex/handler/VortexJSTupleLoaderTestHandler.py +42 -0
- vortex/handler/__init__.py +0 -0
- vortex/restful/GzippedDataHttpClient.py +170 -0
- vortex/restful/GzippedDataHttpClientTest.py +103 -0
- vortex/restful/GzippedPayloadHttpClient.py +181 -0
- vortex/restful/RestfulHttpClient.py +107 -0
- vortex/restful/RestfulHttpClientTest.py +60 -0
- vortex/restful/RestfulResource.py +153 -0
- vortex/restful/RestfulResourceTest.py +100 -0
- vortex/restful/__init__.py +0 -0
- vortex/rpc/RPC.py +446 -0
- vortex/rpc/RPCTest.py +12 -0
- vortex/rpc/__init__.py +0 -0
- vortex/sqla_orm/OrmCrudHandler.py +431 -0
- vortex/sqla_orm/TupleProviderForDb.py +42 -0
- vortex/sqla_orm/VortexTupleJson.py +24 -0
- vortex/sqla_orm/__init__.py +0 -0
- vortex/storage/TupleStorageSqlite.py +359 -0
- vortex/storage/__init__.py +0 -0
- vortexpy-4.0.23.dist-info/LICENSE +21 -0
- vortexpy-4.0.23.dist-info/METADATA +43 -0
- vortexpy-4.0.23.dist-info/RECORD +87 -0
- vortexpy-4.0.23.dist-info/WHEEL +5 -0
- vortexpy-4.0.23.dist-info/top_level.txt +1 -0
vortex/rpc/RPC.py
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
from copy import copy
|
|
4
|
+
from typing import Optional, Set, Union
|
|
5
|
+
|
|
6
|
+
from twisted.internet.defer import (
|
|
7
|
+
succeed,
|
|
8
|
+
fail,
|
|
9
|
+
Deferred,
|
|
10
|
+
TimeoutError,
|
|
11
|
+
inlineCallbacks,
|
|
12
|
+
)
|
|
13
|
+
from twisted.internet.threads import deferToThread
|
|
14
|
+
from twisted.python.failure import Failure
|
|
15
|
+
|
|
16
|
+
from vortex.DeferUtil import yesMainThread
|
|
17
|
+
from vortex.Payload import Payload
|
|
18
|
+
from vortex.PayloadEndpoint import PayloadEndpoint
|
|
19
|
+
from vortex.PayloadEnvelope import PayloadEnvelope
|
|
20
|
+
from vortex.PayloadPriority import RPC_PRIORITY
|
|
21
|
+
from vortex.PayloadResponse import PayloadResponse
|
|
22
|
+
from vortex.Tuple import Tuple, addTupleType, TupleField
|
|
23
|
+
from vortex.VortexFactory import VortexFactory
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@addTupleType
|
|
29
|
+
class _VortexRPCArgTuple(Tuple):
|
|
30
|
+
"""Vortex RPC Arg Tuple
|
|
31
|
+
|
|
32
|
+
This tuple stores the arguments used to call the remote method.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
__tupleType__ = __name__ + "_VortexRPCArgTuple"
|
|
37
|
+
|
|
38
|
+
args = TupleField(defaultValue=[])
|
|
39
|
+
kwargs = TupleField(defaultValue={})
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@addTupleType
|
|
43
|
+
class _VortexRPCResultTuple(Tuple):
|
|
44
|
+
"""Vortex RPC Result Tuple
|
|
45
|
+
|
|
46
|
+
This tuple stores the result from the remote procedure call
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
__tupleType__ = __name__ + "_VortexRPCResultTuple"
|
|
51
|
+
|
|
52
|
+
result = TupleField(defaultValue=None)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class _VortexRPC:
|
|
56
|
+
"""Vortex RPC Wrapper Class
|
|
57
|
+
|
|
58
|
+
This wrapper class handles the mechanics of listening for the RPC calls (handler)
|
|
59
|
+
and sending calls (PayloadResponse)
|
|
60
|
+
|
|
61
|
+
Under the covers, This is what the class.
|
|
62
|
+
|
|
63
|
+
#. The caller will be given a Deferred
|
|
64
|
+
#. The args, kwargs for Tuples and primitive values will be serialised into payload.
|
|
65
|
+
#. The payload will be sent across the vortex
|
|
66
|
+
#. The payload will be deserialized and delivered to a PayloadEndpoint created
|
|
67
|
+
for the decorated method.
|
|
68
|
+
#. The handler will then call the method.
|
|
69
|
+
#. The result from the method will then be serialised and sent back to the calling
|
|
70
|
+
vortex.
|
|
71
|
+
#. The deferred will be called with the result from the remote method.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
__registeredFuncNames: Set[str] = set()
|
|
76
|
+
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
func,
|
|
80
|
+
listeningVortexName: str,
|
|
81
|
+
timeoutSeconds: float,
|
|
82
|
+
acceptOnlyFromVortex: Optional[Union[str, tuple]],
|
|
83
|
+
additionalFilt: dict,
|
|
84
|
+
deferToThread: bool,
|
|
85
|
+
inlineCallbacks: bool,
|
|
86
|
+
) -> None:
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
:param listeningVortexName: If the local vortex name matches this name, then
|
|
90
|
+
a handler will be setup to listen for payloads for this RPC method.
|
|
91
|
+
|
|
92
|
+
:param timeoutSeconds: The seconds to wait for a response before calling the
|
|
93
|
+
deferreds errback with a TimeoutError
|
|
94
|
+
|
|
95
|
+
:param acceptOnlyFromVortex: Accept payloads (calls) only from this vortex.
|
|
96
|
+
The vortex can be str or tuple of str, or None to accept from any.
|
|
97
|
+
|
|
98
|
+
:param additionalFilt: If specified, the items from this dict will be added
|
|
99
|
+
to the filt that this RPCs handler listens on.
|
|
100
|
+
|
|
101
|
+
:param deferToThread: Should the function be called in a thread, or in the
|
|
102
|
+
reactors main loop.
|
|
103
|
+
|
|
104
|
+
:param inlineCallbacks: Should the function be wrapped in the twisted
|
|
105
|
+
@inlinecallbacks decorator before it's called?.
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
self.__func = func
|
|
110
|
+
self.__funcSelf = None
|
|
111
|
+
self.__listeningVortexName = listeningVortexName
|
|
112
|
+
self.__timeoutSeconds = timeoutSeconds
|
|
113
|
+
self.__acceptOnlyFromVortex = acceptOnlyFromVortex
|
|
114
|
+
if isinstance(self.__acceptOnlyFromVortex, str):
|
|
115
|
+
self.__acceptOnlyFromVortex = (self.__acceptOnlyFromVortex,)
|
|
116
|
+
self.__deferToThread = deferToThread
|
|
117
|
+
self.__inlineCallbacks = inlineCallbacks
|
|
118
|
+
|
|
119
|
+
self.__funcName = ""
|
|
120
|
+
if func.__globals__["__spec__"]:
|
|
121
|
+
self.__funcName += func.__globals__["__spec__"].name
|
|
122
|
+
self.__funcName += "." + func.__qualname__
|
|
123
|
+
|
|
124
|
+
if self.__funcName in self.__registeredFuncNames:
|
|
125
|
+
raise Exception(
|
|
126
|
+
"RPC function name %s is already registered" % self.__funcName
|
|
127
|
+
)
|
|
128
|
+
self.__registeredFuncNames.add(self.__funcName)
|
|
129
|
+
|
|
130
|
+
# Define the FILT
|
|
131
|
+
self._filt = {"_internal": "vortexRPC", "key": self.__funcName}
|
|
132
|
+
self._filt.update(additionalFilt)
|
|
133
|
+
|
|
134
|
+
# Define the Endpoint
|
|
135
|
+
|
|
136
|
+
def start(self, funcSelf=None):
|
|
137
|
+
"""Start
|
|
138
|
+
|
|
139
|
+
If this is a class method, then bind the function to the
|
|
140
|
+
object passed in by bindToSelf.
|
|
141
|
+
|
|
142
|
+
:param funcSelf: The object to bind the class instance methods self to.
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
if VortexFactory.isVortexNameLocal(self.__listeningVortexName):
|
|
146
|
+
self.__ep = PayloadEndpoint(self._filt, self._processCall)
|
|
147
|
+
logger.debug("RPC %s listening", self.__funcName)
|
|
148
|
+
|
|
149
|
+
else:
|
|
150
|
+
logger.error(
|
|
151
|
+
"Ignoring request to start listening for RPC %s "
|
|
152
|
+
"as vortex name %s is not local",
|
|
153
|
+
self.__funcName,
|
|
154
|
+
self.__listeningVortexName,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
self.__funcSelf = funcSelf
|
|
158
|
+
|
|
159
|
+
return self
|
|
160
|
+
|
|
161
|
+
def shutdown(self):
|
|
162
|
+
"""Shutdown
|
|
163
|
+
|
|
164
|
+
Shuts down the RPC PayloadEndpoint
|
|
165
|
+
"""
|
|
166
|
+
self.__ep.shutdown()
|
|
167
|
+
self.__func = None
|
|
168
|
+
self.__funcSelf = None
|
|
169
|
+
|
|
170
|
+
@inlineCallbacks
|
|
171
|
+
def _processCall(
|
|
172
|
+
self,
|
|
173
|
+
payloadEnvelope: PayloadEnvelope,
|
|
174
|
+
vortexName,
|
|
175
|
+
sendResponse,
|
|
176
|
+
*args,
|
|
177
|
+
**kwargs
|
|
178
|
+
):
|
|
179
|
+
"""Process
|
|
180
|
+
|
|
181
|
+
Process the incoming RPC call payloads.
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
# If the sending vortex, is local, then ignore it, RPC can not be called locally
|
|
185
|
+
if VortexFactory.isVortexNameLocal(vortexName):
|
|
186
|
+
logger.warning(
|
|
187
|
+
"Received RPC call to %s, from local vortex %s, ignoring it",
|
|
188
|
+
self.__funcName,
|
|
189
|
+
vortexName,
|
|
190
|
+
)
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
# Apply the "allow" logic
|
|
194
|
+
if (
|
|
195
|
+
self.__acceptOnlyFromVortex
|
|
196
|
+
and vortexName not in self.__acceptOnlyFromVortex
|
|
197
|
+
):
|
|
198
|
+
logger.debug(
|
|
199
|
+
"Call from non-accepted vortex %s, allowing only from %s",
|
|
200
|
+
vortexName,
|
|
201
|
+
str(self.__acceptOnlyFromVortex),
|
|
202
|
+
)
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
# Get the args tuple
|
|
206
|
+
payload = yield payloadEnvelope.decodePayloadDefer()
|
|
207
|
+
argsTuple = payload.tuples[0]
|
|
208
|
+
assert isinstance(argsTuple, _VortexRPCArgTuple), (
|
|
209
|
+
"argsTuple is not an instance of %s" % _VortexRPCArgTuple
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
logger.debug("Received RPC call for %s", self.__funcName)
|
|
213
|
+
|
|
214
|
+
# Call the method and setup the callbacks
|
|
215
|
+
result = yield self.callLocally(argsTuple.args, argsTuple.kwargs)
|
|
216
|
+
yield self._processCallCallback(
|
|
217
|
+
result, sendResponse, payloadEnvelope.filt
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
@inlineCallbacks
|
|
221
|
+
def _processCallCallback(self, result, sendResponseCallable, filt):
|
|
222
|
+
|
|
223
|
+
payloadEnvelope = yield (
|
|
224
|
+
Payload(
|
|
225
|
+
filt=filt, tuples=[_VortexRPCResultTuple(result=result)]
|
|
226
|
+
).makePayloadEnvelopeDefer()
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
vortexMsg = yield payloadEnvelope.toVortexMsgDefer()
|
|
230
|
+
|
|
231
|
+
yield sendResponseCallable(vortexMsg, RPC_PRIORITY)
|
|
232
|
+
|
|
233
|
+
@inlineCallbacks
|
|
234
|
+
def callForVortexUuid(self, vortexUuid: str, *args, **kwargs):
|
|
235
|
+
yesMainThread()
|
|
236
|
+
return (
|
|
237
|
+
yield self.__callForVortex(
|
|
238
|
+
(args, kwargs), vortexUuid=vortexUuid, **kwargs
|
|
239
|
+
)
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
@inlineCallbacks
|
|
243
|
+
def __call__(self, *args, **kwargs):
|
|
244
|
+
"""Call"""
|
|
245
|
+
yesMainThread()
|
|
246
|
+
return (
|
|
247
|
+
yield self.__callForVortex(
|
|
248
|
+
(args, kwargs), vortexName=self.__listeningVortexName
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
@inlineCallbacks
|
|
253
|
+
def __callForVortex(
|
|
254
|
+
self,
|
|
255
|
+
argsKwArgs,
|
|
256
|
+
vortexName: Optional[str] = None,
|
|
257
|
+
vortexUuid: Optional[str] = None,
|
|
258
|
+
):
|
|
259
|
+
(args, kwargs) = argsKwArgs
|
|
260
|
+
assert vortexName or vortexUuid
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
# FAKE Exception so we can raise a better stack trace later
|
|
264
|
+
raise Exception()
|
|
265
|
+
except:
|
|
266
|
+
stack = sys.exc_info()[2]
|
|
267
|
+
|
|
268
|
+
logger.debug("Calling RPC for %s", self.__funcName)
|
|
269
|
+
|
|
270
|
+
payloadEnvelope = yield (
|
|
271
|
+
Payload(
|
|
272
|
+
filt=copy(self._filt),
|
|
273
|
+
tuples=[_VortexRPCArgTuple(args=args, kwargs=kwargs)],
|
|
274
|
+
).makePayloadEnvelopeDefer(compressionLevel=4)
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
pr = PayloadResponse(
|
|
278
|
+
payloadEnvelope,
|
|
279
|
+
timeout=self.__timeoutSeconds,
|
|
280
|
+
resultCheck=False,
|
|
281
|
+
logTimeoutError=False,
|
|
282
|
+
destVortexName=vortexName,
|
|
283
|
+
destVortexUuid=vortexUuid,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Delete the payload, we don't need to keep it in memory while we
|
|
287
|
+
# get the result.
|
|
288
|
+
del payloadEnvelope
|
|
289
|
+
|
|
290
|
+
pr.addCallback(self._processResponseCallback, stack)
|
|
291
|
+
pr.addErrback(self._processResponseErrback, stack)
|
|
292
|
+
|
|
293
|
+
val = yield pr
|
|
294
|
+
return val
|
|
295
|
+
|
|
296
|
+
@inlineCallbacks
|
|
297
|
+
def _processResponseCallback(self, payloadEnvelope: PayloadEnvelope, stack):
|
|
298
|
+
"""Process Response Callback
|
|
299
|
+
|
|
300
|
+
Convert the PayloadResponse payload to the result from the remotely called
|
|
301
|
+
method.
|
|
302
|
+
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
if not payloadEnvelope.result in (None, True):
|
|
306
|
+
return Failure(
|
|
307
|
+
Exception(payloadEnvelope.result).with_traceback(stack),
|
|
308
|
+
exc_tb=stack,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Get the Result from the payload
|
|
312
|
+
payload = yield payloadEnvelope.decodePayloadDefer()
|
|
313
|
+
resultTuple = payload.tuples[0]
|
|
314
|
+
assert isinstance(resultTuple, _VortexRPCResultTuple), (
|
|
315
|
+
"resultTuple is not an instance of %s" % _VortexRPCResultTuple
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
logger.debug("Received RPC result for %s", self.__funcName)
|
|
319
|
+
|
|
320
|
+
# Return the remote result
|
|
321
|
+
return resultTuple.result
|
|
322
|
+
|
|
323
|
+
def _processResponseErrback(self, failure, stack):
|
|
324
|
+
"""Process Response Errback
|
|
325
|
+
|
|
326
|
+
Convert the PayloadResponse payload to the result from the remotely called
|
|
327
|
+
method.
|
|
328
|
+
|
|
329
|
+
"""
|
|
330
|
+
|
|
331
|
+
if failure.check(TimeoutError):
|
|
332
|
+
logger.error("Received RPC timeout for %s", self.__funcName)
|
|
333
|
+
|
|
334
|
+
return Failure(
|
|
335
|
+
Exception(
|
|
336
|
+
"RPC call timed out for %s", self.__funcName
|
|
337
|
+
).with_traceback(stack),
|
|
338
|
+
exc_tb=stack,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
return failure
|
|
342
|
+
|
|
343
|
+
def callLocally(self, args, kwargs):
|
|
344
|
+
"""Call Locally
|
|
345
|
+
|
|
346
|
+
This method calls the wrapped function locally, ensuring it returns a
|
|
347
|
+
deferred as it's result.
|
|
348
|
+
|
|
349
|
+
"""
|
|
350
|
+
try:
|
|
351
|
+
if self.__funcSelf:
|
|
352
|
+
args = [self.__funcSelf] + args
|
|
353
|
+
|
|
354
|
+
if self.__inlineCallbacks:
|
|
355
|
+
result = inlineCallbacks(self.__func)(*args, **kwargs)
|
|
356
|
+
|
|
357
|
+
elif self.__deferToThread:
|
|
358
|
+
result = deferToThread(self.__func, *args, **kwargs)
|
|
359
|
+
|
|
360
|
+
else:
|
|
361
|
+
result = self.__func(*args, **kwargs)
|
|
362
|
+
|
|
363
|
+
except Exception as e:
|
|
364
|
+
return fail(Failure(e))
|
|
365
|
+
|
|
366
|
+
if isinstance(result, Deferred):
|
|
367
|
+
return result
|
|
368
|
+
|
|
369
|
+
elif isinstance(result, Failure):
|
|
370
|
+
return fail(result)
|
|
371
|
+
|
|
372
|
+
else:
|
|
373
|
+
return succeed(result)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def vortexRPC(
|
|
377
|
+
listeningVortexName: str,
|
|
378
|
+
timeoutSeconds: float = 30.0,
|
|
379
|
+
acceptOnlyFromVortex: Optional[Union[str, tuple]] = None,
|
|
380
|
+
additionalFilt: Optional[dict] = None,
|
|
381
|
+
deferToThread: bool = False,
|
|
382
|
+
inlineCallbacks: bool = False,
|
|
383
|
+
):
|
|
384
|
+
"""Vortex RPC Decorator
|
|
385
|
+
|
|
386
|
+
:param listeningVortexName: If the local vortex name matches this name, then
|
|
387
|
+
a handler will be setup to listen for payloads for this RPC method.
|
|
388
|
+
|
|
389
|
+
:param timeoutSeconds: The seconds to wait for a response before calling the
|
|
390
|
+
deferreds errback with a TimeoutError
|
|
391
|
+
|
|
392
|
+
:param acceptOnlyFromVortex: Accept payloads (calls) only from this vortex.
|
|
393
|
+
Or None to accept from any.
|
|
394
|
+
|
|
395
|
+
:param additionalFilt: If specified, the items from this dict will be added
|
|
396
|
+
to the filt that this RPCs handler listens on.
|
|
397
|
+
|
|
398
|
+
:param deferToThread: Should the function be called in a thread, or in the
|
|
399
|
+
reactors main loop.
|
|
400
|
+
|
|
401
|
+
:param inlineCallbacks: Should the function be wrapped in the twisted
|
|
402
|
+
@inlinecallbacks decorator before it's called?.
|
|
403
|
+
|
|
404
|
+
:return A wrapped function, that will now work as an RPC call.
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
EXAMPLE:
|
|
408
|
+
|
|
409
|
+
Declare the function and decorate it.
|
|
410
|
+
Because this will be imported on both sides of the vortex, we specify the name
|
|
411
|
+
so that it will only be listening on one side ::
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@vortexRPC("listenVortexName")
|
|
415
|
+
def myRemoteAddMethod(arg1:int, kwarg1:int=0) -> int:
|
|
416
|
+
return arg1 + kwarg1
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
Call the method
|
|
420
|
+
|
|
421
|
+
.. note:: The method will ALWAYS return a deferred, regardless of if the method
|
|
422
|
+
wrapped returns one or not.
|
|
423
|
+
|
|
424
|
+
::
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
deferred = myRemoteAddMethod(5, kwarg1=7)
|
|
428
|
+
print(deferred.addCallback(lambda v:print(v)))
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
"""
|
|
433
|
+
additionalFilt = additionalFilt if additionalFilt else {}
|
|
434
|
+
|
|
435
|
+
def decorator(func):
|
|
436
|
+
return _VortexRPC(
|
|
437
|
+
func,
|
|
438
|
+
listeningVortexName,
|
|
439
|
+
timeoutSeconds,
|
|
440
|
+
acceptOnlyFromVortex,
|
|
441
|
+
additionalFilt,
|
|
442
|
+
deferToThread,
|
|
443
|
+
inlineCallbacks,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
return decorator
|
vortex/rpc/RPCTest.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from vortex.rpc.RPC import vortexRPC
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@vortexRPC("listenVortexName", acceptOnlyFromVortex="sendVortexName")
|
|
5
|
+
def myRemoteExceptionMethod(arg1: int, kwarg1: int = 0) -> int:
|
|
6
|
+
raise ValueError("A is not B")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@vortexRPC("listenVortexName", acceptOnlyFromVortex="sendVortexName")
|
|
10
|
+
def myRemoteAddMethod(arg1: int, kwarg1: int = 0) -> int:
|
|
11
|
+
print(arg1, kwarg1)
|
|
12
|
+
return arg1 + kwarg1
|
vortex/rpc/__init__.py
ADDED
|
File without changes
|