iris-pex-embedded-python 3.2.1b2__py3-none-any.whl → 3.3.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.
Potentially problematic release.
This version of iris-pex-embedded-python might be problematic. Click here for more details.
- iop/_async_request.py +62 -0
- iop/_business_host.py +36 -489
- iop/_business_operation.py +6 -4
- iop/_business_process.py +12 -10
- iop/_business_service.py +3 -2
- iop/_cli.py +161 -104
- iop/_common.py +15 -80
- iop/_decorators.py +48 -0
- iop/_director.py +4 -3
- iop/_dispatch.py +219 -0
- iop/_log_manager.py +20 -12
- iop/_message_validator.py +41 -0
- iop/_private_session_duplex.py +11 -10
- iop/_private_session_process.py +7 -7
- iop/_serialization.py +196 -0
- iop/_utils.py +27 -19
- iop/cls/IOP/Common.cls +6 -1
- iop/cls/IOP/Message.cls +1 -0
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/METADATA +1 -1
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/RECORD +24 -19
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/LICENSE +0 -0
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/WHEEL +0 -0
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/entry_points.txt +0 -0
- {iris_pex_embedded_python-3.2.1b2.dist-info → iris_pex_embedded_python-3.3.0.dist-info}/top_level.txt +0 -0
iop/_business_process.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Any, List, Optional, Union
|
|
2
2
|
from iop._business_host import _BusinessHost
|
|
3
|
+
from iop._decorators import input_deserializer, input_serializer_param, output_serializer, input_serializer, output_deserializer
|
|
4
|
+
from iop._dispatch import create_dispatch, dispach_message
|
|
3
5
|
|
|
4
6
|
class _BusinessProcess(_BusinessHost):
|
|
5
7
|
"""Business process component that contains routing and transformation logic.
|
|
@@ -60,7 +62,7 @@ class _BusinessProcess(_BusinessHost):
|
|
|
60
62
|
"""
|
|
61
63
|
return self.OnComplete(request, response)
|
|
62
64
|
|
|
63
|
-
@
|
|
65
|
+
@input_serializer_param(0,'response')
|
|
64
66
|
def reply(self, response: Any) -> None:
|
|
65
67
|
"""Send the specified response to the production component that sent the initial request.
|
|
66
68
|
|
|
@@ -69,7 +71,7 @@ class _BusinessProcess(_BusinessHost):
|
|
|
69
71
|
"""
|
|
70
72
|
return self.iris_handle.dispatchReply(response)
|
|
71
73
|
|
|
72
|
-
@
|
|
74
|
+
@input_serializer_param(1,'request')
|
|
73
75
|
def send_request_async(self, target: str, request: Any, response_required: bool=True, completion_key: Optional[str]=None, description: Optional[str]=None) -> None:
|
|
74
76
|
"""Send the specified message to the target business process or business operation asynchronously.
|
|
75
77
|
|
|
@@ -139,7 +141,7 @@ class _BusinessProcess(_BusinessHost):
|
|
|
139
141
|
def _dispatch_on_init(self, host_object: Any) -> None:
|
|
140
142
|
"""For internal use only."""
|
|
141
143
|
self._restore_persistent_properties(host_object)
|
|
142
|
-
self
|
|
144
|
+
create_dispatch(self)
|
|
143
145
|
self.on_init()
|
|
144
146
|
self._save_persistent_properties(host_object)
|
|
145
147
|
return
|
|
@@ -151,17 +153,17 @@ class _BusinessProcess(_BusinessHost):
|
|
|
151
153
|
self._save_persistent_properties(host_object)
|
|
152
154
|
return
|
|
153
155
|
|
|
154
|
-
@
|
|
155
|
-
@
|
|
156
|
+
@input_deserializer
|
|
157
|
+
@output_serializer
|
|
156
158
|
def _dispatch_on_request(self, host_object: Any, request: Any) -> Any:
|
|
157
159
|
"""For internal use only."""
|
|
158
160
|
self._restore_persistent_properties(host_object)
|
|
159
|
-
return_object = self
|
|
161
|
+
return_object = dispach_message(self,request)
|
|
160
162
|
self._save_persistent_properties(host_object)
|
|
161
163
|
return return_object
|
|
162
164
|
|
|
163
|
-
@
|
|
164
|
-
@
|
|
165
|
+
@input_deserializer
|
|
166
|
+
@output_serializer
|
|
165
167
|
def _dispatch_on_response(self, host_object: Any, request: Any, response: Any, call_request: Any, call_response: Any, completion_key: str) -> Any:
|
|
166
168
|
"""For internal use only."""
|
|
167
169
|
self._restore_persistent_properties(host_object)
|
|
@@ -169,8 +171,8 @@ class _BusinessProcess(_BusinessHost):
|
|
|
169
171
|
self._save_persistent_properties(host_object)
|
|
170
172
|
return return_object
|
|
171
173
|
|
|
172
|
-
@
|
|
173
|
-
@
|
|
174
|
+
@input_deserializer
|
|
175
|
+
@output_serializer
|
|
174
176
|
def _dispatch_on_complete(self, host_object: Any, request: Any, response: Any) -> Any:
|
|
175
177
|
"""For internal use only."""
|
|
176
178
|
self._restore_persistent_properties(host_object)
|
iop/_business_service.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
from iop._business_host import _BusinessHost
|
|
3
|
+
from iop._decorators import input_deserializer, output_serializer, input_serializer, output_deserializer
|
|
3
4
|
|
|
4
5
|
class _BusinessService(_BusinessHost):
|
|
5
6
|
""" This class is responsible for receiving the data from external system and sending it to business processes or business operations in the production.
|
|
@@ -36,8 +37,8 @@ class _BusinessService(_BusinessHost):
|
|
|
36
37
|
self.Adapter = self.adapter = handle_partner
|
|
37
38
|
return
|
|
38
39
|
|
|
39
|
-
@
|
|
40
|
-
@
|
|
40
|
+
@input_deserializer
|
|
41
|
+
@output_serializer
|
|
41
42
|
def _dispatch_on_process_input(self, request):
|
|
42
43
|
""" For internal use only. """
|
|
43
44
|
return self.on_process_input(request)
|
iop/_cli.py
CHANGED
|
@@ -1,141 +1,198 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import argparse
|
|
2
3
|
import json
|
|
3
4
|
import os
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum, auto
|
|
7
|
+
import sys
|
|
8
|
+
from typing import Optional, Callable
|
|
4
9
|
from importlib.metadata import version
|
|
5
10
|
|
|
6
11
|
from iop._director import _Director
|
|
7
12
|
from iop._utils import _Utils
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
14
|
+
class CommandType(Enum):
|
|
15
|
+
DEFAULT = auto()
|
|
16
|
+
LIST = auto()
|
|
17
|
+
START = auto()
|
|
18
|
+
STOP = auto()
|
|
19
|
+
KILL = auto()
|
|
20
|
+
RESTART = auto()
|
|
21
|
+
STATUS = auto()
|
|
22
|
+
TEST = auto()
|
|
23
|
+
VERSION = auto()
|
|
24
|
+
EXPORT = auto()
|
|
25
|
+
MIGRATE = auto()
|
|
26
|
+
LOG = auto()
|
|
27
|
+
INIT = auto()
|
|
28
|
+
HELP = auto()
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class CommandArgs:
|
|
32
|
+
"""Container for parsed command arguments"""
|
|
33
|
+
default: Optional[str] = None
|
|
34
|
+
list: bool = False
|
|
35
|
+
start: Optional[str] = None
|
|
36
|
+
detach: bool = False
|
|
37
|
+
stop: bool = False
|
|
38
|
+
kill: bool = False
|
|
39
|
+
restart: bool = False
|
|
40
|
+
status: bool = False
|
|
41
|
+
migrate: Optional[str] = None
|
|
42
|
+
export: Optional[str] = None
|
|
43
|
+
version: bool = False
|
|
44
|
+
log: Optional[str] = None
|
|
45
|
+
init: Optional[str] = None
|
|
46
|
+
test: Optional[str] = None
|
|
47
|
+
classname: Optional[str] = None
|
|
48
|
+
body: Optional[str] = None
|
|
49
|
+
|
|
50
|
+
class Command:
|
|
51
|
+
def __init__(self, args: CommandArgs):
|
|
52
|
+
self.args = args
|
|
53
|
+
|
|
54
|
+
def execute(self) -> None:
|
|
55
|
+
command_type = self._determine_command_type()
|
|
56
|
+
command_handlers = {
|
|
57
|
+
CommandType.DEFAULT: self._handle_default,
|
|
58
|
+
CommandType.LIST: self._handle_list,
|
|
59
|
+
CommandType.START: self._handle_start,
|
|
60
|
+
CommandType.STOP: self._handle_stop,
|
|
61
|
+
CommandType.KILL: self._handle_kill,
|
|
62
|
+
CommandType.RESTART: self._handle_restart,
|
|
63
|
+
CommandType.STATUS: self._handle_status,
|
|
64
|
+
CommandType.TEST: self._handle_test,
|
|
65
|
+
CommandType.VERSION: self._handle_version,
|
|
66
|
+
CommandType.EXPORT: self._handle_export,
|
|
67
|
+
CommandType.MIGRATE: self._handle_migrate,
|
|
68
|
+
CommandType.LOG: self._handle_log,
|
|
69
|
+
CommandType.INIT: self._handle_init,
|
|
70
|
+
CommandType.HELP: self._handle_help
|
|
71
|
+
}
|
|
72
|
+
handler = command_handlers.get(command_type)
|
|
73
|
+
if handler:
|
|
74
|
+
handler()
|
|
75
|
+
|
|
76
|
+
def _determine_command_type(self) -> CommandType:
|
|
77
|
+
if self.args.default: return CommandType.DEFAULT
|
|
78
|
+
if self.args.list: return CommandType.LIST
|
|
79
|
+
if self.args.start: return CommandType.START
|
|
80
|
+
if self.args.stop: return CommandType.STOP
|
|
81
|
+
if self.args.kill: return CommandType.KILL
|
|
82
|
+
if self.args.restart: return CommandType.RESTART
|
|
83
|
+
if self.args.status: return CommandType.STATUS
|
|
84
|
+
if self.args.test: return CommandType.TEST
|
|
85
|
+
if self.args.version: return CommandType.VERSION
|
|
86
|
+
if self.args.export: return CommandType.EXPORT
|
|
87
|
+
if self.args.migrate: return CommandType.MIGRATE
|
|
88
|
+
if self.args.log: return CommandType.LOG
|
|
89
|
+
if self.args.init: return CommandType.INIT
|
|
90
|
+
return CommandType.HELP
|
|
91
|
+
|
|
92
|
+
def _handle_default(self) -> None:
|
|
93
|
+
if self.args.default == 'not_set':
|
|
44
94
|
print(_Director.get_default_production())
|
|
45
95
|
else:
|
|
46
|
-
_Director.set_default_production(args.default)
|
|
96
|
+
_Director.set_default_production(self.args.default)
|
|
47
97
|
|
|
48
|
-
|
|
49
|
-
# display list of productions
|
|
98
|
+
def _handle_list(self) -> None:
|
|
50
99
|
dikt = _Director.list_productions()
|
|
51
100
|
print(json.dumps(dikt, indent=4))
|
|
52
101
|
|
|
53
|
-
|
|
54
|
-
production_name =
|
|
55
|
-
if args.
|
|
56
|
-
# start default production
|
|
57
|
-
production_name = _Director.get_default_production()
|
|
58
|
-
else:
|
|
59
|
-
# start production with name
|
|
60
|
-
production_name = args.start
|
|
61
|
-
if args.detach:
|
|
62
|
-
# start production in detach mode
|
|
102
|
+
def _handle_start(self) -> None:
|
|
103
|
+
production_name = self.args.start if self.args.start != 'not_set' else _Director.get_default_production()
|
|
104
|
+
if self.args.detach:
|
|
63
105
|
_Director.start_production(production_name)
|
|
64
106
|
print(f"Production {production_name} started")
|
|
65
107
|
else:
|
|
66
108
|
_Director.start_production_with_log(production_name)
|
|
67
109
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
args.init = None
|
|
72
|
-
_Utils.setup(args.start)
|
|
110
|
+
def _handle_stop(self) -> None:
|
|
111
|
+
_Director.stop_production()
|
|
112
|
+
print(f"Production {_Director.get_default_production()} stopped")
|
|
73
113
|
|
|
74
|
-
|
|
75
|
-
# kill a production
|
|
114
|
+
def _handle_kill(self) -> None:
|
|
76
115
|
_Director.shutdown_production()
|
|
77
116
|
|
|
78
|
-
|
|
79
|
-
# restart a production
|
|
117
|
+
def _handle_restart(self) -> None:
|
|
80
118
|
_Director.restart_production()
|
|
81
119
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
120
|
+
def _handle_status(self) -> None:
|
|
121
|
+
print(json.dumps(_Director.status_production(), indent=4))
|
|
122
|
+
|
|
123
|
+
def _handle_test(self) -> None:
|
|
124
|
+
test_name = None if self.args.test == 'not_set' else self.args.test
|
|
125
|
+
response = _Director.test_component(
|
|
126
|
+
test_name,
|
|
127
|
+
classname=self.args.classname if self.args.classname != 'not_set' else None,
|
|
128
|
+
body=self.args.body if self.args.body != 'not_set' else None
|
|
129
|
+
)
|
|
130
|
+
print(response)
|
|
90
131
|
|
|
91
|
-
|
|
92
|
-
# display version
|
|
132
|
+
def _handle_version(self) -> None:
|
|
93
133
|
print(version('iris-pex-embedded-python'))
|
|
94
134
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# display default production log
|
|
99
|
-
_Director.log_production()
|
|
100
|
-
else:
|
|
101
|
-
_Director.log_production_top(args.log)
|
|
135
|
+
def _handle_export(self) -> None:
|
|
136
|
+
export_name = _Director.get_default_production() if self.args.export == 'not_set' else self.args.export
|
|
137
|
+
print(json.dumps(_Utils.export_production(export_name), indent=4))
|
|
102
138
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
139
|
+
def _handle_migrate(self) -> None:
|
|
140
|
+
migrate_path = self.args.migrate
|
|
141
|
+
if not os.path.isabs(migrate_path):
|
|
142
|
+
migrate_path = os.path.join(os.getcwd(), migrate_path)
|
|
143
|
+
_Utils.migrate(migrate_path)
|
|
107
144
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
145
|
+
def _handle_log(self) -> None:
|
|
146
|
+
if self.args.log == 'not_set':
|
|
147
|
+
print(_Director.log_production())
|
|
148
|
+
else:
|
|
149
|
+
print(_Director.log_production_top(self.args.log))
|
|
111
150
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
body = None
|
|
115
|
-
if args.test == 'not_set':
|
|
116
|
-
# set arg to None
|
|
117
|
-
args.test = None
|
|
118
|
-
if args.classname:
|
|
119
|
-
classname = args.classname
|
|
120
|
-
if args.body:
|
|
121
|
-
body = args.body
|
|
122
|
-
response = _Director.test_component(args.test, classname=classname, body=body)
|
|
123
|
-
print(response)
|
|
151
|
+
def _handle_init(self) -> None:
|
|
152
|
+
_Utils.setup(None)
|
|
124
153
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
args.export=_Director.get_default_production()
|
|
154
|
+
def _handle_help(self) -> None:
|
|
155
|
+
create_parser().print_help()
|
|
156
|
+
print(f"\nDefault production: {_Director.get_default_production()}")
|
|
129
157
|
|
|
130
|
-
|
|
131
|
-
|
|
158
|
+
def create_parser() -> argparse.ArgumentParser:
|
|
159
|
+
"""Create and configure argument parser"""
|
|
160
|
+
main_parser = argparse.ArgumentParser()
|
|
161
|
+
parser = main_parser.add_mutually_exclusive_group()
|
|
162
|
+
|
|
163
|
+
# Main commands
|
|
164
|
+
parser.add_argument('-d', '--default', help='set the default production', nargs='?', const='not_set')
|
|
165
|
+
parser.add_argument('-l', '--list', help='list productions', action='store_true')
|
|
166
|
+
parser.add_argument('-s', '--start', help='start a production', nargs='?', const='not_set')
|
|
167
|
+
parser.add_argument('-S', '--stop', help='stop a production', action='store_true')
|
|
168
|
+
parser.add_argument('-k', '--kill', help='kill a production', action='store_true')
|
|
169
|
+
parser.add_argument('-r', '--restart', help='restart a production', action='store_true')
|
|
170
|
+
parser.add_argument('-x', '--status', help='status a production', action='store_true')
|
|
171
|
+
parser.add_argument('-m', '-M', '--migrate', help='migrate production and classes with settings file')
|
|
172
|
+
parser.add_argument('-e', '--export', help='export a production', nargs='?', const='not_set')
|
|
173
|
+
parser.add_argument('-v', '--version', help='display version', action='store_true')
|
|
174
|
+
parser.add_argument('-L', '--log', help='display log', nargs='?', const='not_set')
|
|
175
|
+
parser.add_argument('-i', '--init', help='init the pex module in iris', nargs='?', const='not_set')
|
|
176
|
+
parser.add_argument('-t', '--test', help='test the pex module in iris', nargs='?', const='not_set')
|
|
132
177
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
178
|
+
# Command groups
|
|
179
|
+
start = main_parser.add_argument_group('start arguments')
|
|
180
|
+
start.add_argument('-D', '--detach', help='start a production in detach mode', action='store_true')
|
|
181
|
+
|
|
182
|
+
test = main_parser.add_argument_group('test arguments')
|
|
183
|
+
test.add_argument('-C', '--classname', help='test classname', nargs='?', const='not_set')
|
|
184
|
+
test.add_argument('-B', '--body', help='test body', nargs='?', const='not_set')
|
|
185
|
+
|
|
186
|
+
return main_parser
|
|
138
187
|
|
|
188
|
+
def main(argv=None) -> None:
|
|
189
|
+
parser = create_parser()
|
|
190
|
+
args = parser.parse_args(argv)
|
|
191
|
+
cmd_args = CommandArgs(**vars(args))
|
|
192
|
+
|
|
193
|
+
command = Command(cmd_args)
|
|
194
|
+
command.execute()
|
|
195
|
+
sys.exit(0)
|
|
139
196
|
|
|
140
197
|
if __name__ == '__main__':
|
|
141
198
|
main()
|
iop/_common.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
import dataclasses
|
|
3
2
|
import inspect
|
|
4
|
-
import iris
|
|
5
3
|
import traceback
|
|
6
|
-
from typing import Any, ClassVar,
|
|
7
|
-
|
|
8
|
-
import
|
|
4
|
+
from typing import Any, ClassVar, List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
import iris
|
|
7
|
+
|
|
8
|
+
from iop._log_manager import LogManager, logging
|
|
9
9
|
|
|
10
10
|
class _Common(metaclass=abc.ABCMeta):
|
|
11
11
|
"""Base class that defines common methods for all component types.
|
|
@@ -19,100 +19,34 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
19
19
|
iris_handle: Any = None
|
|
20
20
|
log_to_console: bool = False
|
|
21
21
|
|
|
22
|
+
# Lifecycle methods
|
|
22
23
|
def on_init(self) -> None:
|
|
23
|
-
"""Initialize component when started.
|
|
24
|
-
|
|
25
|
-
Called when component starts. Use to initialize required structures.
|
|
26
|
-
"""
|
|
27
|
-
return self.OnInit()
|
|
24
|
+
"""Initialize component when started."""
|
|
25
|
+
pass
|
|
28
26
|
|
|
29
27
|
def on_tear_down(self) -> None:
|
|
30
|
-
"""Clean up component before termination.
|
|
31
|
-
|
|
32
|
-
Called before component terminates. Use to free resources.
|
|
33
|
-
"""
|
|
34
|
-
return self.OnTearDown()
|
|
28
|
+
"""Clean up component before termination."""
|
|
29
|
+
pass
|
|
35
30
|
|
|
36
31
|
def on_connected(self) -> None:
|
|
37
|
-
"""Handle component connection/reconnection.
|
|
38
|
-
|
|
39
|
-
Called when component connects or reconnects after disconnection.
|
|
40
|
-
Use to initialize connection-dependent structures.
|
|
41
|
-
"""
|
|
42
|
-
return self.OnConnected()
|
|
32
|
+
"""Handle component connection/reconnection."""
|
|
33
|
+
pass
|
|
43
34
|
|
|
35
|
+
# Internal dispatch methods
|
|
44
36
|
def _dispatch_on_connected(self, host_object: Any) -> None:
|
|
45
|
-
"""Internal dispatch for connection handling."""
|
|
46
37
|
self.on_connected()
|
|
47
|
-
return
|
|
48
38
|
|
|
49
39
|
def _dispatch_on_init(self, host_object: Any) -> None:
|
|
50
|
-
"""Internal dispatch for initialization."""
|
|
51
40
|
self.on_init()
|
|
52
|
-
return
|
|
53
41
|
|
|
54
42
|
def _dispatch_on_tear_down(self, host_object: Any) -> None:
|
|
55
|
-
"""Internal dispatch for teardown."""
|
|
56
43
|
self.on_tear_down()
|
|
57
|
-
return
|
|
58
44
|
|
|
59
45
|
def _set_iris_handles(self, handle_current: Any, handle_partner: Any) -> None:
|
|
60
46
|
"""Internal method to set IRIS handles."""
|
|
61
47
|
pass
|
|
62
48
|
|
|
63
|
-
|
|
64
|
-
def _is_message_instance(cls, obj: Any) -> bool:
|
|
65
|
-
"""Check if object is a valid Message instance.
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
obj: Object to check
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
True if object is a Message instance
|
|
72
|
-
|
|
73
|
-
Raises:
|
|
74
|
-
TypeError: If object is Message class but not a dataclass
|
|
75
|
-
"""
|
|
76
|
-
if cls._is_message_class(type(obj)):
|
|
77
|
-
if not dataclasses.is_dataclass(obj):
|
|
78
|
-
raise TypeError(f"{type(obj).__module__}.{type(obj).__qualname__} must be a dataclass")
|
|
79
|
-
return True
|
|
80
|
-
return False
|
|
81
|
-
|
|
82
|
-
@classmethod
|
|
83
|
-
def _is_pickle_message_instance(cls, obj: Any) -> bool:
|
|
84
|
-
"""Check if object is a PickleMessage instance."""
|
|
85
|
-
if cls._is_pickel_message_class(type(obj)):
|
|
86
|
-
return True
|
|
87
|
-
return False
|
|
88
|
-
|
|
89
|
-
@classmethod
|
|
90
|
-
def _is_iris_object_instance(cls, obj: Any) -> bool:
|
|
91
|
-
"""Check if object is an IRIS persistent object."""
|
|
92
|
-
if (obj is not None and type(obj).__module__.find('iris') == 0) and obj._IsA("%Persistent"):
|
|
93
|
-
return True
|
|
94
|
-
return False
|
|
95
|
-
|
|
96
|
-
@classmethod
|
|
97
|
-
def _is_message_class(cls, klass: Type) -> bool:
|
|
98
|
-
name = klass.__module__ + '.' + klass.__qualname__
|
|
99
|
-
if name == "iop.Message" or name == "grongier.pex.Message":
|
|
100
|
-
return True
|
|
101
|
-
for c in klass.__bases__:
|
|
102
|
-
if cls._is_message_class(c):
|
|
103
|
-
return True
|
|
104
|
-
return False
|
|
105
|
-
|
|
106
|
-
@classmethod
|
|
107
|
-
def _is_pickel_message_class(cls, klass: Type) -> bool:
|
|
108
|
-
name = klass.__module__ + '.' + klass.__qualname__
|
|
109
|
-
if name == "iop.PickleMessage" or name == "grongier.pex.PickleMessage":
|
|
110
|
-
return True
|
|
111
|
-
for c in klass.__bases__:
|
|
112
|
-
if cls._is_pickel_message_class(c):
|
|
113
|
-
return True
|
|
114
|
-
return False
|
|
115
|
-
|
|
49
|
+
# Component information methods
|
|
116
50
|
@classmethod
|
|
117
51
|
def _get_info(cls) -> List[str]:
|
|
118
52
|
"""Get component configuration information.
|
|
@@ -239,6 +173,7 @@ class _Common(metaclass=abc.ABCMeta):
|
|
|
239
173
|
pass
|
|
240
174
|
return ret
|
|
241
175
|
|
|
176
|
+
# Logging methods
|
|
242
177
|
def _log(self) -> Tuple[str, Optional[str]]:
|
|
243
178
|
"""Get class and method name for logging.
|
|
244
179
|
|
iop/_decorators.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Any, Callable
|
|
3
|
+
from iop._dispatch import dispatch_deserializer, dispatch_serializer
|
|
4
|
+
|
|
5
|
+
def input_serializer(fonction: Callable) -> Callable:
|
|
6
|
+
"""Decorator that serializes all input arguments."""
|
|
7
|
+
def _dispatch_serializer(self, *params: Any, **param2: Any) -> Any:
|
|
8
|
+
serialized = [dispatch_serializer(param) for param in params]
|
|
9
|
+
param2 = {key: dispatch_serializer(value) for key, value in param2.items()}
|
|
10
|
+
return fonction(self, *serialized, **param2)
|
|
11
|
+
return _dispatch_serializer
|
|
12
|
+
|
|
13
|
+
def input_serializer_param(position: int, name: str) -> Callable:
|
|
14
|
+
"""Decorator that serializes specific parameter by position or name."""
|
|
15
|
+
def _input_serializer_param(fonction: Callable) -> Callable:
|
|
16
|
+
@wraps(fonction)
|
|
17
|
+
def _dispatch_serializer(self, *params: Any, **param2: Any) -> Any:
|
|
18
|
+
serialized = [
|
|
19
|
+
dispatch_serializer(param) if i == position else param
|
|
20
|
+
for i, param in enumerate(params)
|
|
21
|
+
]
|
|
22
|
+
param2 = {
|
|
23
|
+
key: dispatch_serializer(value) if key == name else value
|
|
24
|
+
for key, value in param2.items()
|
|
25
|
+
}
|
|
26
|
+
return fonction(self, *serialized, **param2)
|
|
27
|
+
return _dispatch_serializer
|
|
28
|
+
return _input_serializer_param
|
|
29
|
+
|
|
30
|
+
def output_deserializer(fonction: Callable) -> Callable:
|
|
31
|
+
"""Decorator that deserializes function output."""
|
|
32
|
+
def _dispatch_deserializer(self, *params: Any, **param2: Any) -> Any:
|
|
33
|
+
return dispatch_deserializer(fonction(self, *params, **param2))
|
|
34
|
+
return _dispatch_deserializer
|
|
35
|
+
|
|
36
|
+
def input_deserializer(fonction: Callable) -> Callable:
|
|
37
|
+
"""Decorator that deserializes all input arguments."""
|
|
38
|
+
def _dispatch_deserializer(self, *params: Any, **param2: Any) -> Any:
|
|
39
|
+
serialized = [dispatch_deserializer(param) for param in params]
|
|
40
|
+
param2 = {key: dispatch_deserializer(value) for key, value in param2.items()}
|
|
41
|
+
return fonction(self, *serialized, **param2)
|
|
42
|
+
return _dispatch_deserializer
|
|
43
|
+
|
|
44
|
+
def output_serializer(fonction: Callable) -> Callable:
|
|
45
|
+
"""Decorator that serializes function output."""
|
|
46
|
+
def _dispatch_serializer(self, *params: Any, **param2: Any) -> Any:
|
|
47
|
+
return dispatch_serializer(fonction(self, *params, **param2))
|
|
48
|
+
return _dispatch_serializer
|
iop/_director.py
CHANGED
|
@@ -7,6 +7,7 @@ import signal
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
9
|
from iop._business_host import _BusinessHost
|
|
10
|
+
from iop._dispatch import dispatch_deserializer, dispatch_serializer
|
|
10
11
|
from iop._utils import _Utils
|
|
11
12
|
|
|
12
13
|
class _Director():
|
|
@@ -221,7 +222,7 @@ class _Director():
|
|
|
221
222
|
await asyncio.sleep(1)
|
|
222
223
|
|
|
223
224
|
@staticmethod
|
|
224
|
-
def log_production_top(top):
|
|
225
|
+
def log_production_top(top=10):
|
|
225
226
|
"""
|
|
226
227
|
Log the top N logs of the production
|
|
227
228
|
Parameters:
|
|
@@ -278,10 +279,10 @@ class _Director():
|
|
|
278
279
|
message.json = _Utils.string_to_stream("{}")
|
|
279
280
|
# serialize the message
|
|
280
281
|
business_host = _BusinessHost()
|
|
281
|
-
serial_message =
|
|
282
|
+
serial_message = dispatch_serializer(message)
|
|
282
283
|
response = iris.cls('IOP.Utils').dispatchTestComponent(target,serial_message)
|
|
283
284
|
try:
|
|
284
|
-
deserialized_response =
|
|
285
|
+
deserialized_response = dispatch_deserializer(response)
|
|
285
286
|
except ImportError as e:
|
|
286
287
|
# can't import the class, return the string
|
|
287
288
|
deserialized_response = f'{response.classname} : {_Utils.stream_to_string(response.jstr)}'
|