iris-pex-embedded-python 3.5.5b4__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.
- grongier/__init__.py +0 -0
- grongier/cls/Grongier/PEX/BusinessOperation.cls +8 -0
- grongier/cls/Grongier/PEX/BusinessProcess.cls +13 -0
- grongier/cls/Grongier/PEX/BusinessService.cls +8 -0
- grongier/cls/Grongier/PEX/Common.cls +10 -0
- grongier/cls/Grongier/PEX/Director.cls +10 -0
- grongier/cls/Grongier/PEX/Duplex/Operation.cls +4 -0
- grongier/cls/Grongier/PEX/Duplex/Process.cls +13 -0
- grongier/cls/Grongier/PEX/Duplex/Service.cls +4 -0
- grongier/cls/Grongier/PEX/InboundAdapter.cls +8 -0
- grongier/cls/Grongier/PEX/Message.cls +13 -0
- grongier/cls/Grongier/PEX/OutboundAdapter.cls +8 -0
- grongier/cls/Grongier/PEX/PickleMessage.cls +13 -0
- grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +8 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +14 -0
- grongier/cls/Grongier/PEX/Test.cls +10 -0
- grongier/cls/Grongier/PEX/Utils.cls +10 -0
- grongier/cls/Grongier/Service/WSGI.cls +4 -0
- grongier/pex/__init__.py +24 -0
- grongier/pex/__main__.py +4 -0
- grongier/pex/_business_host.py +1 -0
- grongier/pex/_cli.py +4 -0
- grongier/pex/_common.py +1 -0
- grongier/pex/_director.py +1 -0
- grongier/pex/_utils.py +1 -0
- grongier/pex/wsgi/handlers.py +104 -0
- iop/__init__.py +25 -0
- iop/__main__.py +4 -0
- iop/_async_request.py +67 -0
- iop/_business_host.py +256 -0
- iop/_business_operation.py +75 -0
- iop/_business_process.py +224 -0
- iop/_business_service.py +63 -0
- iop/_cli.py +247 -0
- iop/_common.py +334 -0
- iop/_debugpy.py +187 -0
- iop/_decorators.py +49 -0
- iop/_director.py +301 -0
- iop/_dispatch.py +136 -0
- iop/_generator_request.py +30 -0
- iop/_inbound_adapter.py +34 -0
- iop/_iris.py +8 -0
- iop/_log_manager.py +100 -0
- iop/_message.py +40 -0
- iop/_message_validator.py +49 -0
- iop/_outbound_adapter.py +23 -0
- iop/_private_session_duplex.py +103 -0
- iop/_private_session_process.py +41 -0
- iop/_remote.py +91 -0
- iop/_serialization.py +199 -0
- iop/_utils.py +671 -0
- iop/cls/IOP/BusinessOperation.cls +35 -0
- iop/cls/IOP/BusinessProcess.cls +156 -0
- iop/cls/IOP/BusinessService.cls +40 -0
- iop/cls/IOP/Common.cls +569 -0
- iop/cls/IOP/Director.cls +70 -0
- iop/cls/IOP/Duplex/Operation.cls +29 -0
- iop/cls/IOP/Duplex/Process.cls +229 -0
- iop/cls/IOP/Duplex/Service.cls +9 -0
- iop/cls/IOP/Generator/Message/Ack.cls +31 -0
- iop/cls/IOP/Generator/Message/Poll.cls +31 -0
- iop/cls/IOP/Generator/Message/Start.cls +15 -0
- iop/cls/IOP/Generator/Message/StartPickle.cls +15 -0
- iop/cls/IOP/Generator/Message/Stop.cls +32 -0
- iop/cls/IOP/InboundAdapter.cls +22 -0
- iop/cls/IOP/Message/JSONSchema.cls +125 -0
- iop/cls/IOP/Message.cls +754 -0
- iop/cls/IOP/OutboundAdapter.cls +36 -0
- iop/cls/IOP/PickleMessage.cls +58 -0
- iop/cls/IOP/PrivateSession/Duplex.cls +260 -0
- iop/cls/IOP/PrivateSession/Message/Ack.cls +32 -0
- iop/cls/IOP/PrivateSession/Message/Poll.cls +32 -0
- iop/cls/IOP/PrivateSession/Message/Start.cls +31 -0
- iop/cls/IOP/PrivateSession/Message/Stop.cls +48 -0
- iop/cls/IOP/Projection.cls +49 -0
- iop/cls/IOP/Service/Remote/Handler.cls +30 -0
- iop/cls/IOP/Service/Remote/Rest/v1.cls +97 -0
- iop/cls/IOP/Service/WSGI.cls +310 -0
- iop/cls/IOP/Test.cls +85 -0
- iop/cls/IOP/Utils.cls +503 -0
- iop/cls/IOP/Wrapper.cls +58 -0
- iop/wsgi/handlers.py +104 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/METADATA +91 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/RECORD +91 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/WHEEL +5 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/entry_points.txt +2 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/licenses/LICENSE +21 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/top_level.txt +2 -0
iop/_business_host.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
from inspect import getsource
|
|
2
|
+
from typing import Any,List, Optional, Tuple, Union
|
|
3
|
+
|
|
4
|
+
from . import _iris
|
|
5
|
+
from ._common import _Common
|
|
6
|
+
from ._message import _Message as Message
|
|
7
|
+
from ._decorators import input_serializer_param, output_deserializer, input_deserializer, output_serializer
|
|
8
|
+
from ._dispatch import dispatch_serializer, dispatch_deserializer, dispach_message
|
|
9
|
+
from ._async_request import AsyncRequest
|
|
10
|
+
from ._generator_request import _GeneratorRequest
|
|
11
|
+
|
|
12
|
+
class _BusinessHost(_Common):
|
|
13
|
+
"""Base class for business components that defines common methods.
|
|
14
|
+
|
|
15
|
+
This is a superclass for BusinessService, BusinessProcess, and BusinessOperation that
|
|
16
|
+
defines common functionality like message serialization/deserialization and request handling.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
buffer: int = 64000
|
|
20
|
+
DISPATCH: List[Tuple[str, str]] = []
|
|
21
|
+
|
|
22
|
+
@input_serializer_param(1, 'request')
|
|
23
|
+
@output_deserializer
|
|
24
|
+
def send_request_sync(self, target: str, request: Union[Message, Any],
|
|
25
|
+
timeout: int = -1, description: Optional[str] = None) -> Any:
|
|
26
|
+
"""Send message synchronously to target component.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
target: Name of target component
|
|
30
|
+
request: Message to send
|
|
31
|
+
timeout: Timeout in seconds, -1 means wait forever
|
|
32
|
+
description: Optional description for logging
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Response from target component
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
TypeError: If request is invalid type
|
|
39
|
+
"""
|
|
40
|
+
return self.iris_handle.dispatchSendRequestSync(target, request, timeout, description)
|
|
41
|
+
|
|
42
|
+
@input_serializer_param(1, 'request')
|
|
43
|
+
def send_request_async(self, target: str, request: Union[Message, Any],
|
|
44
|
+
description: Optional[str] = None) -> None:
|
|
45
|
+
"""Send message asynchronously to target component.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
target: Name of target component
|
|
49
|
+
request: Message to send
|
|
50
|
+
description: Optional description for logging
|
|
51
|
+
|
|
52
|
+
Raises:
|
|
53
|
+
TypeError: If request is invalid type
|
|
54
|
+
"""
|
|
55
|
+
return self.iris_handle.dispatchSendRequestAsync(target, request, description)
|
|
56
|
+
|
|
57
|
+
async def send_request_async_ng(self, target: str, request: Union[Message, Any],
|
|
58
|
+
timeout: int = -1, description: Optional[str] = None) -> Any:
|
|
59
|
+
"""Send message asynchronously to target component with asyncio.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
target: Name of target component
|
|
63
|
+
request: Message to send
|
|
64
|
+
timeout: Timeout in seconds, -1 means wait forever
|
|
65
|
+
description: Optional description for logging
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Response from target component
|
|
69
|
+
"""
|
|
70
|
+
return await AsyncRequest(target, request, timeout, description, self)
|
|
71
|
+
|
|
72
|
+
def send_generator_request(self, target: str, request: Union[Message, Any],
|
|
73
|
+
timeout: int = -1, description: Optional[str] = None) -> _GeneratorRequest:
|
|
74
|
+
"""Send message as a generator request to target component.
|
|
75
|
+
Args:
|
|
76
|
+
target: Name of target component
|
|
77
|
+
request: Message to send
|
|
78
|
+
timeout: Timeout in seconds, -1 means wait forever
|
|
79
|
+
description: Optional description for logging
|
|
80
|
+
Returns:
|
|
81
|
+
_GeneratorRequest: An instance of _GeneratorRequest to iterate over responses
|
|
82
|
+
Raises:
|
|
83
|
+
TypeError: If request is not of type Message
|
|
84
|
+
"""
|
|
85
|
+
return _GeneratorRequest(self, target, request, timeout, description)
|
|
86
|
+
|
|
87
|
+
def send_multi_request_sync(self, target_request: List[Tuple[str, Union[Message, Any]]],
|
|
88
|
+
timeout: int = -1, description: Optional[str] = None) -> List[Tuple[str, Union[Message, Any], Any, int]]:
|
|
89
|
+
"""Send multiple messages synchronously to target components.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
target_request: List of tuples (target, request) to send
|
|
93
|
+
timeout: Timeout in seconds, -1 means wait forever
|
|
94
|
+
description: Optional description for logging
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
List of tuples (target, request, response, status)
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
TypeError: If target_request is not a list of tuples
|
|
101
|
+
ValueError: If target_request is empty
|
|
102
|
+
"""
|
|
103
|
+
self._validate_target_request(target_request)
|
|
104
|
+
|
|
105
|
+
call_list = [self._create_call_structure(target, request)
|
|
106
|
+
for target, request in target_request]
|
|
107
|
+
|
|
108
|
+
response_list = self.iris_handle.dispatchSendRequestSyncMultiple(call_list, timeout)
|
|
109
|
+
|
|
110
|
+
return [(target_request[i][0],
|
|
111
|
+
target_request[i][1],
|
|
112
|
+
dispatch_deserializer(response_list[i].Response),
|
|
113
|
+
response_list[i].ResponseCode)
|
|
114
|
+
for i in range(len(target_request))]
|
|
115
|
+
|
|
116
|
+
def _validate_target_request(self, target_request: List[Tuple[str, Union[Message, Any]]]) -> None:
|
|
117
|
+
"""Validate the target_request parameter structure."""
|
|
118
|
+
if not isinstance(target_request, list):
|
|
119
|
+
raise TypeError("target_request must be a list")
|
|
120
|
+
if not target_request:
|
|
121
|
+
raise ValueError("target_request must not be empty")
|
|
122
|
+
if not all(isinstance(item, tuple) and len(item) == 2 for item in target_request):
|
|
123
|
+
raise TypeError("target_request must contain tuples of (target, request)")
|
|
124
|
+
|
|
125
|
+
def _create_call_structure(self, target: str, request: Union[Message, Any]) -> Any:
|
|
126
|
+
"""Create an Ens.CallStructure object for the request."""
|
|
127
|
+
iris = _iris.get_iris()
|
|
128
|
+
call = iris.cls("Ens.CallStructure")._New()
|
|
129
|
+
call.TargetDispatchName = target
|
|
130
|
+
call.Request = dispatch_serializer(request)
|
|
131
|
+
return call
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def OnGetConnections() -> Optional[List[str]]:
|
|
135
|
+
"""The OnGetConnections() method returns all of the targets of any SendRequestSync or SendRequestAsync
|
|
136
|
+
calls for the class. Implement this method to allow connections between components to show up in
|
|
137
|
+
the interoperability UI.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
An IRISList containing all targets for this class. Default is None.
|
|
141
|
+
"""
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
def SendRequestSync(self, target: str, request: Union[Message, Any],
|
|
145
|
+
timeout: int = -1, description: Optional[str] = None) -> Any:
|
|
146
|
+
"""DEPRECATED: use send_request_sync.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
target: The target of the request
|
|
150
|
+
request: The request to send
|
|
151
|
+
timeout: The timeout in seconds, -1 means wait forever
|
|
152
|
+
description: A string that describes the request
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
The response from the target component
|
|
156
|
+
"""
|
|
157
|
+
return self.send_request_sync(target, request, timeout, description)
|
|
158
|
+
|
|
159
|
+
def SendRequestAsync(self, target: str, request: Union[Message, Any],
|
|
160
|
+
description: Optional[str] = None) -> None:
|
|
161
|
+
"""DEPRECATED: use send_request_async.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
target: The target of the request
|
|
165
|
+
request: The request to send
|
|
166
|
+
description: A string that describes the request
|
|
167
|
+
"""
|
|
168
|
+
return self.send_request_async(target, request, description)
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def getAdapterType() -> Optional[str]:
|
|
172
|
+
"""DEPRECATED: use get_adapter_type.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Name of the registered Adapter
|
|
176
|
+
"""
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def get_adapter_type() -> Optional[str]:
|
|
181
|
+
"""Returns the name of the registered Adapter.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Name of the registered Adapter
|
|
185
|
+
"""
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
def on_get_connections(self) -> List[str]:
|
|
189
|
+
"""The OnGetConnections() method returns all of the targets of any SendRequestSync or SendRequestAsync
|
|
190
|
+
calls for the class. Implement this method to allow connections between components to show up in
|
|
191
|
+
the interoperability UI.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
A list containing all targets for this class.
|
|
195
|
+
"""
|
|
196
|
+
## Parse the class code to find all invocations of send_request_sync and send_request_async
|
|
197
|
+
## and return the targets
|
|
198
|
+
target_list = []
|
|
199
|
+
# get the source code of the class
|
|
200
|
+
source = getsource(self.__class__)
|
|
201
|
+
# find all invocations of send_request_sync and send_request_async
|
|
202
|
+
for method in ['send_request_sync', 'send_request_async', 'SendRequestSync', 'SendRequestAsync']:
|
|
203
|
+
i = source.find(method)
|
|
204
|
+
while i != -1:
|
|
205
|
+
j = source.find("(", i)
|
|
206
|
+
if j != -1:
|
|
207
|
+
k = source.find(",", j)
|
|
208
|
+
if k != -1:
|
|
209
|
+
target = source[j+1:k]
|
|
210
|
+
if target.find("=") != -1:
|
|
211
|
+
# it's a keyword argument, remove the keyword
|
|
212
|
+
target = target[target.find("=")+1:].strip()
|
|
213
|
+
if target not in target_list:
|
|
214
|
+
target_list.append(target)
|
|
215
|
+
i = source.find(method, i+1)
|
|
216
|
+
|
|
217
|
+
for target in target_list:
|
|
218
|
+
# if target is a string, remove the quotes
|
|
219
|
+
if target[0] == "'" and target[-1] == "'":
|
|
220
|
+
target_list[target_list.index(target)] = target[1:-1]
|
|
221
|
+
elif target[0] == '"' and target[-1] == '"':
|
|
222
|
+
target_list[target_list.index(target)] = target[1:-1]
|
|
223
|
+
# if target is a variable, try to find the value of the variable
|
|
224
|
+
else:
|
|
225
|
+
self.on_init()
|
|
226
|
+
try:
|
|
227
|
+
if target.find("self.") != -1:
|
|
228
|
+
# it's a class variable
|
|
229
|
+
target_list[target_list.index(target)] = getattr(self, target[target.find(".")+1:])
|
|
230
|
+
elif target.find(".") != -1:
|
|
231
|
+
# it's a class variable
|
|
232
|
+
target_list[target_list.index(target)] = getattr(getattr(self, target[:target.find(".")]), target[target.find(".")+1:])
|
|
233
|
+
else:
|
|
234
|
+
target_list[target_list.index(target)] = getattr(self, target)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
return target_list
|
|
239
|
+
|
|
240
|
+
@input_deserializer
|
|
241
|
+
def _dispatch_generator_started(self, request: Any) -> Any:
|
|
242
|
+
"""For internal use only."""
|
|
243
|
+
self._gen = dispach_message(self, request)
|
|
244
|
+
# check if self._gen is a generator
|
|
245
|
+
if not hasattr(self._gen, '__iter__'):
|
|
246
|
+
raise TypeError("Expected a generator or iterable object, got: {}".format(type(self._gen).__name__))
|
|
247
|
+
|
|
248
|
+
return _iris.get_iris().IOP.Generator.Message.Ack._New()
|
|
249
|
+
|
|
250
|
+
@output_serializer
|
|
251
|
+
def _dispatch_generator_poll(self) -> Any:
|
|
252
|
+
"""For internal use only."""
|
|
253
|
+
try:
|
|
254
|
+
return next(self._gen)
|
|
255
|
+
except StopIteration:
|
|
256
|
+
return _iris.get_iris().IOP.Generator.Message.Stop._New()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
from typing import Any, List, Optional, Union, Tuple
|
|
3
|
+
|
|
4
|
+
from ._business_host import _BusinessHost
|
|
5
|
+
from ._decorators import input_deserializer, output_serializer, input_serializer, output_deserializer
|
|
6
|
+
from ._dispatch import create_dispatch, dispach_message
|
|
7
|
+
|
|
8
|
+
class _BusinessOperation(_BusinessHost):
|
|
9
|
+
"""Business operation component that handles outbound communication.
|
|
10
|
+
|
|
11
|
+
Responsible for sending messages to external systems. Can optionally use an
|
|
12
|
+
adapter to handle the outbound messaging protocol.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
DISPATCH: List[Tuple[str, str]] = []
|
|
16
|
+
Adapter: Any = None
|
|
17
|
+
adapter: Any = None
|
|
18
|
+
|
|
19
|
+
def on_message(self, request: Any) -> Any:
|
|
20
|
+
"""Handle incoming messages.
|
|
21
|
+
|
|
22
|
+
Process messages received from other production components and either
|
|
23
|
+
send to external system or forward to another component.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
request: The incoming message
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Response message
|
|
30
|
+
"""
|
|
31
|
+
return self.OnMessage(request)
|
|
32
|
+
|
|
33
|
+
def on_keepalive(self) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Called when the server sends a keepalive message.
|
|
36
|
+
"""
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
def _set_iris_handles(self, handle_current: Any, handle_partner: Any) -> None:
|
|
40
|
+
"""For internal use only."""
|
|
41
|
+
self.iris_handle = handle_current
|
|
42
|
+
if type(handle_partner).__module__.find('iris') == 0:
|
|
43
|
+
if handle_partner._IsA("Grongier.PEX.OutboundAdapter") or handle_partner._IsA("IOP.OutboundAdapter"):
|
|
44
|
+
module = importlib.import_module(handle_partner.GetModule())
|
|
45
|
+
handle_partner = getattr(module, handle_partner.GetClassname())()
|
|
46
|
+
self.Adapter = self.adapter = handle_partner
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
def _dispatch_on_init(self, host_object: Any) -> None:
|
|
50
|
+
"""For internal use only."""
|
|
51
|
+
create_dispatch(self)
|
|
52
|
+
self.on_init()
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
@input_deserializer
|
|
56
|
+
@output_serializer
|
|
57
|
+
def _dispatch_on_message(self, request: Any) -> Any:
|
|
58
|
+
"""For internal use only."""
|
|
59
|
+
return dispach_message(self,request)
|
|
60
|
+
|
|
61
|
+
def OnMessage(self, request: Any) -> Any:
|
|
62
|
+
"""DEPRECATED : use on_message
|
|
63
|
+
Called when the business operation receives a message from another production component.
|
|
64
|
+
Typically, the operation will either send the message to the external system or forward it to a business process or another business operation.
|
|
65
|
+
If the operation has an adapter, it uses the Adapter.invoke() method to call the method on the adapter that sends the message to the external system.
|
|
66
|
+
If the operation is forwarding the message to another production component, it uses the SendRequestAsync() or the SendRequestSync() method
|
|
67
|
+
|
|
68
|
+
Parameters:
|
|
69
|
+
request: An instance of either a subclass of Message or of IRISObject containing the incoming message for the business operation.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
The response object
|
|
73
|
+
"""
|
|
74
|
+
return
|
|
75
|
+
|
iop/_business_process.py
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
from typing import Any, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from ._business_host import _BusinessHost
|
|
4
|
+
from ._decorators import input_deserializer, input_serializer_param, output_serializer, input_serializer, output_deserializer
|
|
5
|
+
from ._dispatch import create_dispatch, dispach_message
|
|
6
|
+
|
|
7
|
+
class _BusinessProcess(_BusinessHost):
|
|
8
|
+
"""Business process component that contains routing and transformation logic.
|
|
9
|
+
|
|
10
|
+
A business process can receive messages from services, other processes, or operations.
|
|
11
|
+
It can modify messages, transform formats, and route based on content.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
DISPATCH: List[tuple] = []
|
|
15
|
+
PERSISTENT_PROPERTY_LIST: Optional[List[str]] = None
|
|
16
|
+
|
|
17
|
+
def on_message(self, request: Any) -> Any:
|
|
18
|
+
"""Handle incoming messages.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
request: The incoming message
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Response message
|
|
25
|
+
"""
|
|
26
|
+
return self.on_request(request)
|
|
27
|
+
|
|
28
|
+
def on_request(self, request: Any) -> Any:
|
|
29
|
+
"""Process initial requests sent to this component.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
request: The incoming request message
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Response message
|
|
36
|
+
"""
|
|
37
|
+
return self.OnRequest(request)
|
|
38
|
+
|
|
39
|
+
def on_response(self, request: Any, response: Any, call_request: Any, call_response: Any, completion_key: str) -> Any:
|
|
40
|
+
"""Handle responses to messages sent by this component.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
request: The initial request message
|
|
44
|
+
response: The response message
|
|
45
|
+
call_request: The request sent to the target
|
|
46
|
+
call_response: The incoming response
|
|
47
|
+
completion_key: The completion key specified in the outgoing SendAsync() method
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Response message
|
|
51
|
+
"""
|
|
52
|
+
return self.OnResponse(request, response, call_request, call_response, completion_key)
|
|
53
|
+
|
|
54
|
+
def on_complete(self, request: Any, response: Any) -> Any:
|
|
55
|
+
"""Called after all responses to requests sent by this component have been handled.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
request: The initial request message
|
|
59
|
+
response: The response message
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Response message
|
|
63
|
+
"""
|
|
64
|
+
return self.OnComplete(request, response)
|
|
65
|
+
|
|
66
|
+
@input_serializer_param(0,'response')
|
|
67
|
+
def reply(self, response: Any) -> None:
|
|
68
|
+
"""Send the specified response to the production component that sent the initial request.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
response: The response message
|
|
72
|
+
"""
|
|
73
|
+
return self.iris_handle.dispatchReply(response)
|
|
74
|
+
|
|
75
|
+
@input_serializer_param(1,'request')
|
|
76
|
+
def send_request_async(self, target: str, request: Any, description: Optional[str]=None, completion_key: Optional[str]=None, response_required: bool=True) -> None:
|
|
77
|
+
"""Send the specified message to the target business process or business operation asynchronously.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
target: The name of the business process or operation to receive the request
|
|
81
|
+
request: The message to send to the target
|
|
82
|
+
description: An optional description property in the message header
|
|
83
|
+
completion_key: A string that will be returned with the response if the maximum time is exceeded
|
|
84
|
+
response_required: Whether a response is required
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
TypeError: If request is not of type Message or IRISObject
|
|
88
|
+
"""
|
|
89
|
+
# Convert boolean to int for Iris API
|
|
90
|
+
if response_required:
|
|
91
|
+
response_required = 1 # type: ignore
|
|
92
|
+
else:
|
|
93
|
+
response_required = 0 # type: ignore
|
|
94
|
+
return self.iris_handle.dispatchSendRequestAsync(target, request, response_required, completion_key, description)
|
|
95
|
+
|
|
96
|
+
def set_timer(self, timeout: Union[int, str], completion_key: Optional[str]=None) -> None:
|
|
97
|
+
"""Specify the maximum time the business process will wait for responses.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
timeout: The maximum time to wait for responses
|
|
101
|
+
completion_key: A string that will be returned with the response if the maximum time is exceeded
|
|
102
|
+
"""
|
|
103
|
+
self.iris_handle.dispatchSetTimer(timeout, completion_key)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
def _set_iris_handles(self, handle_current: Any, handle_partner: Any) -> None:
|
|
107
|
+
"""For internal use only."""
|
|
108
|
+
self.iris_handle = handle_current
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
def _save_persistent_properties(self, host_object: Any) -> None:
|
|
112
|
+
"""For internal use only."""
|
|
113
|
+
if self.PERSISTENT_PROPERTY_LIST is None:
|
|
114
|
+
return
|
|
115
|
+
for prop in self.PERSISTENT_PROPERTY_LIST:
|
|
116
|
+
val = getattr(self, prop, None)
|
|
117
|
+
typ = val.__class__.__name__
|
|
118
|
+
if typ in ["str", "int", "float", "bool", "bytes"]:
|
|
119
|
+
try:
|
|
120
|
+
host_object.setPersistentProperty(prop, val)
|
|
121
|
+
except:
|
|
122
|
+
pass
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
def _restore_persistent_properties(self, host_object: Any) -> None:
|
|
126
|
+
"""For internal use only."""
|
|
127
|
+
if self.PERSISTENT_PROPERTY_LIST is None:
|
|
128
|
+
return
|
|
129
|
+
for prop in self.PERSISTENT_PROPERTY_LIST:
|
|
130
|
+
try:
|
|
131
|
+
val = host_object.getPersistentProperty(prop)
|
|
132
|
+
setattr(self, prop, val)
|
|
133
|
+
except:
|
|
134
|
+
pass
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
def _dispatch_on_connected(self, host_object: Any) -> None:
|
|
138
|
+
"""For internal use only."""
|
|
139
|
+
self.on_connected()
|
|
140
|
+
self._save_persistent_properties(host_object)
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
def _dispatch_on_init(self, host_object: Any) -> None:
|
|
144
|
+
"""For internal use only."""
|
|
145
|
+
self._restore_persistent_properties(host_object)
|
|
146
|
+
create_dispatch(self)
|
|
147
|
+
self.on_init()
|
|
148
|
+
self._save_persistent_properties(host_object)
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
def _dispatch_on_tear_down(self, host_object: Any) -> None:
|
|
152
|
+
"""For internal use only."""
|
|
153
|
+
self._restore_persistent_properties(host_object)
|
|
154
|
+
self.on_tear_down()
|
|
155
|
+
self._save_persistent_properties(host_object)
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
@input_deserializer
|
|
159
|
+
@output_serializer
|
|
160
|
+
def _dispatch_on_request(self, host_object: Any, request: Any) -> Any:
|
|
161
|
+
"""For internal use only."""
|
|
162
|
+
self._restore_persistent_properties(host_object)
|
|
163
|
+
return_object = dispach_message(self,request)
|
|
164
|
+
self._save_persistent_properties(host_object)
|
|
165
|
+
return return_object
|
|
166
|
+
|
|
167
|
+
@input_deserializer
|
|
168
|
+
@output_serializer
|
|
169
|
+
def _dispatch_on_response(self, host_object: Any, request: Any, response: Any, call_request: Any, call_response: Any, completion_key: str) -> Any:
|
|
170
|
+
"""For internal use only."""
|
|
171
|
+
self._restore_persistent_properties(host_object)
|
|
172
|
+
return_object = self.on_response(request, response, call_request, call_response, completion_key)
|
|
173
|
+
self._save_persistent_properties(host_object)
|
|
174
|
+
return return_object
|
|
175
|
+
|
|
176
|
+
@input_deserializer
|
|
177
|
+
@output_serializer
|
|
178
|
+
def _dispatch_on_complete(self, host_object: Any, request: Any, response: Any) -> Any:
|
|
179
|
+
"""For internal use only."""
|
|
180
|
+
self._restore_persistent_properties(host_object)
|
|
181
|
+
return_object = self.on_complete(request, response)
|
|
182
|
+
self._save_persistent_properties(host_object)
|
|
183
|
+
return return_object
|
|
184
|
+
|
|
185
|
+
def OnRequest(self, request: Any) -> Any:
|
|
186
|
+
"""
|
|
187
|
+
DEPRECATED: Use on_request.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
request: The incoming request message
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Response message
|
|
194
|
+
"""
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
def OnResponse(self, request: Any, response: Any, call_request: Any, call_response: Any, completion_key: str) -> Any:
|
|
198
|
+
"""
|
|
199
|
+
DEPRECATED: Use on_response.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
request: The initial request message
|
|
203
|
+
response: The response message
|
|
204
|
+
call_request: The request sent to the target
|
|
205
|
+
call_response: The incoming response
|
|
206
|
+
completion_key: The completion key specified in the outgoing SendAsync() method
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Response message
|
|
210
|
+
"""
|
|
211
|
+
return response
|
|
212
|
+
|
|
213
|
+
def OnComplete(self, request: Any, response: Any) -> Any:
|
|
214
|
+
"""
|
|
215
|
+
DEPRECATED: Use on_complete.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
request: The initial request message
|
|
219
|
+
response: The response message
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Response message
|
|
223
|
+
"""
|
|
224
|
+
return response
|
iop/_business_service.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
|
|
3
|
+
from ._business_host import _BusinessHost
|
|
4
|
+
from ._decorators import input_deserializer, output_serializer, input_serializer, output_deserializer
|
|
5
|
+
|
|
6
|
+
class _BusinessService(_BusinessHost):
|
|
7
|
+
""" This class is responsible for receiving the data from external system and sending it to business processes or business operations in the production.
|
|
8
|
+
The business service can use an adapter to access the external system, which is specified in the InboundAdapter property.
|
|
9
|
+
There are three ways of implementing a business service:
|
|
10
|
+
1) Polling business service with an adapter - The production framework at regular intervals calls the adapter’s OnTask() method,
|
|
11
|
+
which sends the incoming data to the the business service ProcessInput() method, which, in turn calls the OnProcessInput method with your code.
|
|
12
|
+
2) Polling business service that uses the default adapter - In this case, the framework calls the default adapter's OnTask method with no data.
|
|
13
|
+
The OnProcessInput() method then performs the role of the adapter and is responsible for accessing the external system and receiving the data.
|
|
14
|
+
3) Nonpolling business service - The production framework does not initiate the business service. Instead custom code in either a long-running process
|
|
15
|
+
or one that is started at regular intervals initiates the business service by calling the Director.CreateBusinessService() method.
|
|
16
|
+
"""
|
|
17
|
+
Adapter = adapter = None
|
|
18
|
+
_wait_for_next_call_interval = False
|
|
19
|
+
|
|
20
|
+
def _dispatch_on_init(self, host_object) -> None:
|
|
21
|
+
"""For internal use only."""
|
|
22
|
+
self.on_init()
|
|
23
|
+
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
def on_process_input(self, message_input):
|
|
27
|
+
""" Receives the message from the inbond adapter via the PRocessInput method and is responsible for forwarding it to target business processes or operations.
|
|
28
|
+
If the business service does not specify an adapter, then the default adapter calls this method with no message
|
|
29
|
+
and the business service is responsible for receiving the data from the external system and validating it.
|
|
30
|
+
|
|
31
|
+
Parameters:
|
|
32
|
+
message_input: an instance of IRISObject or subclass of Message containing the data that the inbound adapter passes in.
|
|
33
|
+
The message can have any structure agreed upon by the inbound adapter and the business service.
|
|
34
|
+
"""
|
|
35
|
+
return self.OnProcessInput(message_input)
|
|
36
|
+
|
|
37
|
+
def _set_iris_handles(self, handle_current, handle_partner):
|
|
38
|
+
""" For internal use only. """
|
|
39
|
+
self.iris_handle = handle_current
|
|
40
|
+
if type(handle_partner).__module__.find('iris') == 0:
|
|
41
|
+
if handle_partner._IsA("Grongier.PEX.InboundAdapter") or handle_partner._IsA("IOP.InboundAdapter"):
|
|
42
|
+
module = importlib.import_module(handle_partner.GetModule())
|
|
43
|
+
handle_partner = getattr(module, handle_partner.GetClassname())()
|
|
44
|
+
self.Adapter = self.adapter = handle_partner
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
@input_deserializer
|
|
48
|
+
@output_serializer
|
|
49
|
+
def _dispatch_on_process_input(self, request):
|
|
50
|
+
""" For internal use only. """
|
|
51
|
+
return self.on_process_input(request)
|
|
52
|
+
|
|
53
|
+
def OnProcessInput(self, message_input):
|
|
54
|
+
""" DEPRECATED : use on_process_input
|
|
55
|
+
Receives the message from the inbond adapter via the PRocessInput method and is responsible for forwarding it to target business processes or operations.
|
|
56
|
+
If the business service does not specify an adapter, then the default adapter calls this method with no message
|
|
57
|
+
and the business service is responsible for receiving the data from the external system and validating it.
|
|
58
|
+
|
|
59
|
+
Parameters:
|
|
60
|
+
messageInput: an instance of IRISObject or subclass of Message containing the data that the inbound adapter passes in.
|
|
61
|
+
The message can have any structure agreed upon by the inbound adapter and the business service.
|
|
62
|
+
"""
|
|
63
|
+
return
|