iris-pex-embedded-python 2.3.28b2__py3-none-any.whl → 3.0.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.
- grongier/cls/Grongier/PEX/BusinessOperation.cls +1 -28
- grongier/cls/Grongier/PEX/BusinessProcess.cls +1 -112
- grongier/cls/Grongier/PEX/BusinessService.cls +1 -28
- grongier/cls/Grongier/PEX/Common.cls +1 -194
- grongier/cls/Grongier/PEX/Director.cls +1 -48
- grongier/cls/Grongier/PEX/Duplex/Operation.cls +1 -26
- grongier/cls/Grongier/PEX/Duplex/Process.cls +1 -217
- grongier/cls/Grongier/PEX/Duplex/Service.cls +1 -6
- grongier/cls/Grongier/PEX/InboundAdapter.cls +1 -15
- grongier/cls/Grongier/PEX/Message.cls +1 -116
- grongier/cls/Grongier/PEX/OutboundAdapter.cls +1 -29
- grongier/cls/Grongier/PEX/PickleMessage.cls +1 -46
- grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +1 -253
- grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +1 -19
- grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +1 -19
- grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +1 -19
- grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +1 -35
- grongier/cls/Grongier/PEX/Test.cls +1 -53
- grongier/cls/Grongier/PEX/Utils.cls +1 -365
- grongier/cls/Grongier/Service/WSGI.cls +1 -307
- grongier/pex/__init__.py +11 -11
- grongier/pex/__main__.py +1 -1
- grongier/pex/_business_host.py +1 -511
- grongier/pex/_cli.py +1 -152
- grongier/pex/_common.py +1 -347
- grongier/pex/_director.py +1 -286
- grongier/pex/_utils.py +1 -369
- iop/__init__.py +24 -0
- iop/__main__.py +4 -0
- iop/_business_host.py +511 -0
- {grongier/pex → iop}/_business_operation.py +1 -1
- {grongier/pex → iop}/_business_process.py +1 -1
- {grongier/pex → iop}/_business_service.py +1 -1
- iop/_cli.py +152 -0
- iop/_common.py +349 -0
- iop/_director.py +286 -0
- {grongier/pex → iop}/_inbound_adapter.py +1 -1
- {grongier/pex → iop}/_outbound_adapter.py +1 -1
- {grongier/pex → iop}/_private_session_duplex.py +1 -1
- {grongier/pex → iop}/_private_session_process.py +2 -2
- iop/_utils.py +374 -0
- iop/cls/IOP/BusinessOperation.cls +35 -0
- iop/cls/IOP/BusinessProcess.cls +124 -0
- iop/cls/IOP/BusinessService.cls +35 -0
- iop/cls/IOP/Common.cls +203 -0
- iop/cls/IOP/Director.cls +57 -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/InboundAdapter.cls +22 -0
- iop/cls/IOP/Message.cls +128 -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 +32 -0
- iop/cls/IOP/PrivateSession/Message/Stop.cls +48 -0
- iop/cls/IOP/Service/WSGI.cls +310 -0
- iop/cls/IOP/Test.cls +62 -0
- iop/cls/IOP/Utils.cls +374 -0
- iop/wsgi/handlers.py +104 -0
- {iris_pex_embedded_python-2.3.28b2.dist-info → iris_pex_embedded_python-3.0.0.dist-info}/METADATA +28 -28
- {iris_pex_embedded_python-2.3.28b2.dist-info → iris_pex_embedded_python-3.0.0.dist-info}/RECORD +70 -42
- {iris_pex_embedded_python-2.3.28b2.dist-info → iris_pex_embedded_python-3.0.0.dist-info}/WHEEL +1 -1
- iris_pex_embedded_python-3.0.0.dist-info/entry_points.txt +2 -0
- {iris_pex_embedded_python-2.3.28b2.dist-info → iris_pex_embedded_python-3.0.0.dist-info}/top_level.txt +1 -0
- iris_pex_embedded_python-2.3.28b2.dist-info/entry_points.txt +0 -2
- {grongier/pex → iop}/_message.py +0 -0
- {grongier/pex → iop}/_pickle_message.py +0 -0
- {iris_pex_embedded_python-2.3.28b2.dist-info → iris_pex_embedded_python-3.0.0.dist-info}/LICENSE +0 -0
iop/_utils.py
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import ast
|
|
3
|
+
import iris
|
|
4
|
+
import inspect
|
|
5
|
+
import xmltodict
|
|
6
|
+
import pkg_resources
|
|
7
|
+
|
|
8
|
+
class _Utils():
|
|
9
|
+
@staticmethod
|
|
10
|
+
def raise_on_error(sc):
|
|
11
|
+
"""
|
|
12
|
+
If the status code is an error, raise an exception
|
|
13
|
+
|
|
14
|
+
:param sc: The status code returned by the Iris API
|
|
15
|
+
"""
|
|
16
|
+
if iris.system.Status.IsError(sc):
|
|
17
|
+
raise RuntimeError(iris.system.Status.GetOneStatusText(sc))
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def setup(path:str = None):
|
|
21
|
+
|
|
22
|
+
if path is None:
|
|
23
|
+
# get the path of the data folder with pkg_resources
|
|
24
|
+
path = pkg_resources.resource_filename('iop', 'cls')
|
|
25
|
+
|
|
26
|
+
_Utils.raise_on_error(iris.cls('%SYSTEM.OBJ').LoadDir(path,'cubk',"*.cls",1))
|
|
27
|
+
|
|
28
|
+
# for retrocompatibility load grongier.pex
|
|
29
|
+
path = pkg_resources.resource_filename('grongier', 'cls')
|
|
30
|
+
|
|
31
|
+
_Utils.raise_on_error(iris.cls('%SYSTEM.OBJ').LoadDir(path,'cubk',"*.cls",1))
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def register_component(module:str,classname:str,path:str,overwrite:int=1,iris_classname:str='Python'):
|
|
35
|
+
"""
|
|
36
|
+
It registers a component in the Iris database.
|
|
37
|
+
|
|
38
|
+
:param module: The name of the module that contains the class
|
|
39
|
+
:type module: str
|
|
40
|
+
:param classname: The name of the class you want to register
|
|
41
|
+
:type classname: str
|
|
42
|
+
:param path: The path to the component
|
|
43
|
+
:type path: str
|
|
44
|
+
:param overwrite: 0 = no, 1 = yes
|
|
45
|
+
:type overwrite: int
|
|
46
|
+
:param iris_classname: The name of the class in the Iris class hierarchy
|
|
47
|
+
:type iris_classname: str
|
|
48
|
+
:return: The return value is a string.
|
|
49
|
+
"""
|
|
50
|
+
path = os.path.normpath(path)
|
|
51
|
+
# get the absolute path of the folder
|
|
52
|
+
path = os.path.abspath(path)
|
|
53
|
+
return iris.cls('Grongier.PEX.Utils').dispatchRegisterComponent(module,classname,path,overwrite,iris_classname)
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def register_folder(path:str,overwrite:int=1,iris_package_name:str='Python'):
|
|
57
|
+
"""
|
|
58
|
+
> This function takes a path to a folder, and registers all the Python files in that folder as IRIS
|
|
59
|
+
classes
|
|
60
|
+
|
|
61
|
+
:param path: the path to the folder containing the files you want to register
|
|
62
|
+
:type path: str
|
|
63
|
+
:param overwrite:
|
|
64
|
+
:type overwrite: int
|
|
65
|
+
:param iris_package_name: The name of the iris package you want to register the file to
|
|
66
|
+
:type iris_package_name: str
|
|
67
|
+
"""
|
|
68
|
+
path = os.path.normpath(path)
|
|
69
|
+
# get the absolute path of the folder
|
|
70
|
+
path = os.path.abspath(path)
|
|
71
|
+
for filename in os.listdir(path):
|
|
72
|
+
if filename.endswith(".py"):
|
|
73
|
+
_Utils._register_file(filename, path, overwrite, iris_package_name)
|
|
74
|
+
else:
|
|
75
|
+
continue
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def register_file(file:str,overwrite:int=1,iris_package_name:str='Python'):
|
|
79
|
+
"""
|
|
80
|
+
It takes a file name, a boolean to overwrite existing components, and the name of the Iris
|
|
81
|
+
package that the file is in. It then opens the file, parses it, and looks for classes that extend
|
|
82
|
+
BusinessOperation, BusinessProcess, or BusinessService. If it finds one, it calls register_component
|
|
83
|
+
with the module name, class name, path, overwrite boolean, and the full Iris package name
|
|
84
|
+
|
|
85
|
+
:param file: the name of the file containing the component
|
|
86
|
+
:type file: str
|
|
87
|
+
:param overwrite: if the component already exists, overwrite it
|
|
88
|
+
:type overwrite: int
|
|
89
|
+
:param iris_package_name: the name of the iris package that you want to register the components to
|
|
90
|
+
:type iris_package_name: str
|
|
91
|
+
"""
|
|
92
|
+
head_tail = os.path.split(file)
|
|
93
|
+
return _Utils._register_file(head_tail[1],head_tail[0],overwrite,iris_package_name)
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def _register_file(filename:str,path:str,overwrite:int=1,iris_package_name:str='Python'):
|
|
97
|
+
"""
|
|
98
|
+
It takes a file name, a path, a boolean to overwrite existing components, and the name of the Iris
|
|
99
|
+
package that the file is in. It then opens the file, parses it, and looks for classes that extend
|
|
100
|
+
BusinessOperation, BusinessProcess, or BusinessService. If it finds one, it calls register_component
|
|
101
|
+
with the module name, class name, path, overwrite boolean, and the full Iris package name
|
|
102
|
+
|
|
103
|
+
:param filename: the name of the file containing the component
|
|
104
|
+
:type filename: str
|
|
105
|
+
:param path: the path to the directory containing the files to be registered
|
|
106
|
+
:type path: str
|
|
107
|
+
:param overwrite: if the component already exists, overwrite it
|
|
108
|
+
:type overwrite: int
|
|
109
|
+
:param iris_package_name: the name of the iris package that you want to register the components to
|
|
110
|
+
:type iris_package_name: str
|
|
111
|
+
"""
|
|
112
|
+
#pour chaque classe dans le module, appeler register_component
|
|
113
|
+
f = os.path.join(path,filename)
|
|
114
|
+
with open(f) as file:
|
|
115
|
+
node = ast.parse(file.read())
|
|
116
|
+
#list of class in the file
|
|
117
|
+
classes = [n for n in node.body if isinstance(n, ast.ClassDef)]
|
|
118
|
+
for klass in classes:
|
|
119
|
+
extend = ''
|
|
120
|
+
if len(klass.bases) == 1:
|
|
121
|
+
if hasattr(klass.bases[0],'id'):
|
|
122
|
+
extend = klass.bases[0].id
|
|
123
|
+
else:
|
|
124
|
+
extend = klass.bases[0].attr
|
|
125
|
+
if extend in ('BusinessOperation','BusinessProcess','BusinessService','DuplexService','DuplexProcess','DuplexOperation','InboundAdapter','OutboundAdapter'):
|
|
126
|
+
module = _Utils.filename_to_module(filename)
|
|
127
|
+
iris_class_name = f"{iris_package_name}.{module}.{klass.name}"
|
|
128
|
+
# strip "_" for iris class name
|
|
129
|
+
iris_class_name = iris_class_name.replace('_','')
|
|
130
|
+
_Utils.register_component(module, klass.name, path, overwrite, iris_class_name)
|
|
131
|
+
@staticmethod
|
|
132
|
+
def register_package(package:str,path:str,overwrite:int=1,iris_package_name:str='Python'):
|
|
133
|
+
"""
|
|
134
|
+
It takes a package name, a path to the package, a flag to overwrite existing files, and the name of
|
|
135
|
+
the iris package to register the files to. It then loops through all the files in the package and
|
|
136
|
+
registers them to the iris package
|
|
137
|
+
|
|
138
|
+
:param package: the name of the package you want to register
|
|
139
|
+
:type package: str
|
|
140
|
+
:param path: the path to the directory containing the package
|
|
141
|
+
:type path: str
|
|
142
|
+
:param overwrite: 0 = don't overwrite, 1 = overwrite
|
|
143
|
+
:type overwrite: int
|
|
144
|
+
:param iris_package_name: The name of the package in the Iris package manager
|
|
145
|
+
:type iris_package_name: str
|
|
146
|
+
"""
|
|
147
|
+
for filename in os.listdir(os.path.join(path,package)):
|
|
148
|
+
if filename.endswith(".py"):
|
|
149
|
+
_Utils._register_file(filename, os.path.join(path,package), overwrite, iris_package_name)
|
|
150
|
+
else:
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def filename_to_module(filename) -> str:
|
|
155
|
+
"""
|
|
156
|
+
It takes a filename and returns the module name
|
|
157
|
+
|
|
158
|
+
:param filename: The name of the file to be imported
|
|
159
|
+
:return: The module name
|
|
160
|
+
"""
|
|
161
|
+
module = ''
|
|
162
|
+
|
|
163
|
+
path,file = os.path.split(filename)
|
|
164
|
+
mod = file.split('.')[0]
|
|
165
|
+
packages = path.replace(os.sep, ('.'))
|
|
166
|
+
if len(packages) >1:
|
|
167
|
+
module = packages+'.'+mod
|
|
168
|
+
else:
|
|
169
|
+
module = mod
|
|
170
|
+
|
|
171
|
+
return module
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def migrate(filename=None,root_path=None):
|
|
175
|
+
"""
|
|
176
|
+
Read the settings.py file and register all the components
|
|
177
|
+
settings.py file has two dictionaries:
|
|
178
|
+
* CLASSES
|
|
179
|
+
* key: the name of the class
|
|
180
|
+
* value: an instance of the class
|
|
181
|
+
* PRODUCTIONS
|
|
182
|
+
list of dictionaries:
|
|
183
|
+
* key: the name of the production
|
|
184
|
+
* value: a dictionary containing the settings for the production
|
|
185
|
+
"""
|
|
186
|
+
# try to load the settings file
|
|
187
|
+
if filename:
|
|
188
|
+
import sys
|
|
189
|
+
path = None
|
|
190
|
+
# check if the filename is absolute or relative
|
|
191
|
+
if os.path.isabs(filename):
|
|
192
|
+
path = os.path.dirname(filename)
|
|
193
|
+
else:
|
|
194
|
+
raise ValueError("The filename must be absolute")
|
|
195
|
+
# add the path to the system path
|
|
196
|
+
sys.path.append(path)
|
|
197
|
+
import settings
|
|
198
|
+
# get the path of the settings file
|
|
199
|
+
path = os.path.dirname(inspect.getfile(settings))
|
|
200
|
+
try:
|
|
201
|
+
# set the classes settings
|
|
202
|
+
_Utils.set_classes_settings(settings.CLASSES,path)
|
|
203
|
+
except AttributeError:
|
|
204
|
+
print("No classes to register")
|
|
205
|
+
try:
|
|
206
|
+
# set the productions settings
|
|
207
|
+
_Utils.set_productions_settings(settings.PRODUCTIONS,path)
|
|
208
|
+
except AttributeError:
|
|
209
|
+
print("No productions to register")
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@staticmethod
|
|
214
|
+
def set_classes_settings(class_items,root_path=None):
|
|
215
|
+
"""
|
|
216
|
+
It takes a dictionary of classes and returns a dictionary of settings for each class
|
|
217
|
+
|
|
218
|
+
:param class_items: a dictionary of classes
|
|
219
|
+
:return: a dictionary of settings for each class
|
|
220
|
+
"""
|
|
221
|
+
for key, value in class_items.items():
|
|
222
|
+
if inspect.isclass(value):
|
|
223
|
+
path = None
|
|
224
|
+
if root_path:
|
|
225
|
+
path = root_path
|
|
226
|
+
else:
|
|
227
|
+
path = os.path.dirname(inspect.getfile(value))
|
|
228
|
+
_Utils.register_component(value.__module__,value.__name__,path,1,key)
|
|
229
|
+
elif inspect.ismodule(value):
|
|
230
|
+
path = None
|
|
231
|
+
if root_path:
|
|
232
|
+
path = root_path
|
|
233
|
+
else:
|
|
234
|
+
path = os.path.dirname(inspect.getfile(value))
|
|
235
|
+
_Utils._register_file(value.__name__+'.py',path,1,key)
|
|
236
|
+
# if the value is a dict
|
|
237
|
+
elif isinstance(value,dict):
|
|
238
|
+
# if the dict has a key 'path' and a key 'module' and a key 'class'
|
|
239
|
+
if 'path' in value and 'module' in value and 'class' in value:
|
|
240
|
+
# register the component
|
|
241
|
+
_Utils.register_component(value['module'],value['class'],value['path'],1,key)
|
|
242
|
+
# if the dict has a key 'path' and a key 'package'
|
|
243
|
+
elif 'path' in value and 'package' in value:
|
|
244
|
+
# register the package
|
|
245
|
+
_Utils.register_package(value['package'],value['path'],1,key)
|
|
246
|
+
# if the dict has a key 'path' and a key 'file'
|
|
247
|
+
elif 'path' in value and 'file' in value:
|
|
248
|
+
# register the file
|
|
249
|
+
_Utils._register_file(value['file'],value['path'],1,key)
|
|
250
|
+
# if the dict has a key 'path'
|
|
251
|
+
elif 'path' in value:
|
|
252
|
+
# register folder
|
|
253
|
+
_Utils.register_folder(value['path'],1,key)
|
|
254
|
+
else:
|
|
255
|
+
raise ValueError(f"Invalid value for {key}.")
|
|
256
|
+
|
|
257
|
+
@staticmethod
|
|
258
|
+
def set_productions_settings(production_list,root_path=None):
|
|
259
|
+
"""
|
|
260
|
+
It takes a list of dictionaries and registers the productions
|
|
261
|
+
"""
|
|
262
|
+
# for each production in the list
|
|
263
|
+
for production in production_list:
|
|
264
|
+
# get the production name (first key in the dictionary)
|
|
265
|
+
production_name = list(production.keys())[0]
|
|
266
|
+
# set the first key to 'production'
|
|
267
|
+
production['Production'] = production.pop(production_name)
|
|
268
|
+
# handle Items
|
|
269
|
+
production = _Utils.handle_items(production,root_path)
|
|
270
|
+
# transform the json as an xml
|
|
271
|
+
xml = _Utils.dict_to_xml(production)
|
|
272
|
+
# register the production
|
|
273
|
+
_Utils.register_production(production_name,xml)
|
|
274
|
+
|
|
275
|
+
@staticmethod
|
|
276
|
+
def handle_items(production,root_path=None):
|
|
277
|
+
# if an item is a class, register it and replace it with the name of the class
|
|
278
|
+
if 'Item' in production['Production']:
|
|
279
|
+
# for each item in the list
|
|
280
|
+
for i,item in enumerate(production['Production']['Item']):
|
|
281
|
+
# if the attribute "@ClassName" is a class, register it and replace it with the name of the class
|
|
282
|
+
if '@ClassName' in item:
|
|
283
|
+
if inspect.isclass(item['@ClassName']):
|
|
284
|
+
path = None
|
|
285
|
+
if root_path:
|
|
286
|
+
path = root_path
|
|
287
|
+
else:
|
|
288
|
+
path = os.path.dirname(inspect.getfile(item['@ClassName']))
|
|
289
|
+
_Utils.register_component(item['@ClassName'].__module__,item['@ClassName'].__name__,path,1,item['@Name'])
|
|
290
|
+
# replace the class with the name of the class
|
|
291
|
+
production['Production']['Item'][i]['@ClassName'] = item['@Name']
|
|
292
|
+
# if the attribute "@ClassName" is a dict
|
|
293
|
+
elif isinstance(item['@ClassName'],dict):
|
|
294
|
+
# create a new dict where the key is the name of the class and the value is the dict
|
|
295
|
+
class_dict = {item['@Name']:item['@ClassName']}
|
|
296
|
+
# pass the new dict to set_classes_settings
|
|
297
|
+
_Utils.set_classes_settings(class_dict)
|
|
298
|
+
# replace the class with the name of the class
|
|
299
|
+
production['Production']['Item'][i]['@ClassName'] = item['@Name']
|
|
300
|
+
else:
|
|
301
|
+
raise ValueError(f"Invalid value for {item['@Name']}.")
|
|
302
|
+
|
|
303
|
+
return production
|
|
304
|
+
|
|
305
|
+
@staticmethod
|
|
306
|
+
def dict_to_xml(json):
|
|
307
|
+
"""
|
|
308
|
+
It takes a json and returns an xml
|
|
309
|
+
|
|
310
|
+
:param json: a json
|
|
311
|
+
:return: an xml
|
|
312
|
+
"""
|
|
313
|
+
xml = xmltodict.unparse(json,pretty=True)
|
|
314
|
+
# remove the xml version tag
|
|
315
|
+
xml = xml.replace('<?xml version="1.0" encoding="utf-8"?>','')
|
|
316
|
+
# remove the new line at the beginning of the xml
|
|
317
|
+
xml = xml[1:]
|
|
318
|
+
return xml
|
|
319
|
+
|
|
320
|
+
@staticmethod
|
|
321
|
+
def register_production(production_name,xml):
|
|
322
|
+
"""
|
|
323
|
+
It takes a production name and an xml and registers the production
|
|
324
|
+
|
|
325
|
+
:param production_name: the name of the production
|
|
326
|
+
:type production_name: str
|
|
327
|
+
:param xml: the xml of the production
|
|
328
|
+
:type xml: str
|
|
329
|
+
"""
|
|
330
|
+
# split the production name in the package name and the production name
|
|
331
|
+
# the production name is the last part of the string
|
|
332
|
+
package = '.'.join(production_name.split('.')[:-1])
|
|
333
|
+
production_name = production_name.split('.')[-1]
|
|
334
|
+
stream = _Utils.string_to_stream(xml)
|
|
335
|
+
# register the production
|
|
336
|
+
_Utils.raise_on_error(iris.cls('Grongier.PEX.Utils').CreateProduction(package,production_name,stream))
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def export_production(production_name):
|
|
340
|
+
"""
|
|
341
|
+
It takes a production name and exports the production
|
|
342
|
+
|
|
343
|
+
:param production_name: the name of the production
|
|
344
|
+
:type production_name: str
|
|
345
|
+
"""
|
|
346
|
+
def postprocessor(path, key, value):
|
|
347
|
+
if value is None:
|
|
348
|
+
return key, ''
|
|
349
|
+
return key, value
|
|
350
|
+
# export the production
|
|
351
|
+
xdata = iris.cls('Grongier.PEX.Utils').ExportProduction(production_name)
|
|
352
|
+
# for each chunk of 1024 characters
|
|
353
|
+
string = _Utils.stream_to_string(xdata)
|
|
354
|
+
# convert the xml to a dictionary
|
|
355
|
+
data = xmltodict.parse(string,postprocessor=postprocessor)
|
|
356
|
+
# return the dictionary
|
|
357
|
+
return data
|
|
358
|
+
|
|
359
|
+
@staticmethod
|
|
360
|
+
def stream_to_string(stream)-> str:
|
|
361
|
+
string = ""
|
|
362
|
+
stream.Rewind()
|
|
363
|
+
while not stream.AtEnd:
|
|
364
|
+
string += stream.Read(4092)
|
|
365
|
+
return string
|
|
366
|
+
|
|
367
|
+
@staticmethod
|
|
368
|
+
def string_to_stream(string:str):
|
|
369
|
+
stream = iris.cls('%Stream.GlobalCharacter')._New()
|
|
370
|
+
n = 4092
|
|
371
|
+
chunks = [string[i:i+n] for i in range(0, len(string), n)]
|
|
372
|
+
for chunk in chunks:
|
|
373
|
+
stream.Write(chunk)
|
|
374
|
+
return stream
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Copyright (c) 2021 by InterSystems Corporation.
|
|
2
|
+
Cambridge, Massachusetts, U.S.A. All rights reserved.
|
|
3
|
+
Confidential property of InterSystems Corporation. */
|
|
4
|
+
|
|
5
|
+
Class IOP.BusinessOperation Extends (Ens.BusinessOperation, IOP.Common) [ Inheritance = right, ProcedureBlock, System = 4 ]
|
|
6
|
+
{
|
|
7
|
+
|
|
8
|
+
Parameter SETTINGS = "%classname:Python BusinessOperation,%module:Python BusinessOperation,%settings:Python BusinessOperation,%classpaths:Python BusinessOperation";
|
|
9
|
+
|
|
10
|
+
Method OnMessage(
|
|
11
|
+
request As %Library.Persistent,
|
|
12
|
+
Output response As %Library.Persistent) As %Status
|
|
13
|
+
{
|
|
14
|
+
set tSC = $$$OK
|
|
15
|
+
try {
|
|
16
|
+
set response = ..%class."_dispatch_on_message"(request)
|
|
17
|
+
} catch ex {
|
|
18
|
+
set tSC = ex.AsStatus()
|
|
19
|
+
}
|
|
20
|
+
quit tSC
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Method OnKeepalive(pStatus As %Status = {$$$OK}) As %Status
|
|
24
|
+
{
|
|
25
|
+
set tSC = $$$OK
|
|
26
|
+
try {
|
|
27
|
+
$$$ThrowOnError(##super(pStatus))
|
|
28
|
+
do ..%class."on_keepalive"()
|
|
29
|
+
} catch ex {
|
|
30
|
+
set tSC = ex.AsStatus()
|
|
31
|
+
}
|
|
32
|
+
quit tSC
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* Copyright (c) 2021 by InterSystems Corporation.
|
|
2
|
+
Cambridge, Massachusetts, U.S.A. All rights reserved.
|
|
3
|
+
Confidential property of InterSystems Corporation. */
|
|
4
|
+
|
|
5
|
+
Class IOP.BusinessProcess Extends (Ens.BusinessProcess, IOP.Common) [ Inheritance = right, ProcedureBlock, System = 4 ]
|
|
6
|
+
{
|
|
7
|
+
|
|
8
|
+
Parameter SETTINGS = "%classname:Python BusinessProcess,%module:Python BusinessProcess,%settings:Python BusinessProcess,%classpaths:Python BusinessProcess";
|
|
9
|
+
|
|
10
|
+
Property persistentProperties As array Of %String(MAXLEN = "");
|
|
11
|
+
|
|
12
|
+
Method dispatchReply(response)
|
|
13
|
+
{
|
|
14
|
+
set tSC = ..Reply(response)
|
|
15
|
+
if $$$ISERR(tSC) throw ##class(%Exception.StatusException).CreateFromStatus(tSC)
|
|
16
|
+
quit
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Method dispatchSetTimer(
|
|
20
|
+
timeout,
|
|
21
|
+
completionKey)
|
|
22
|
+
{
|
|
23
|
+
set tSC = ..SetTimer(timeout,$g(completionKey))
|
|
24
|
+
if $$$ISERR(tSC) throw ##class(%Exception.StatusException).CreateFromStatus(tSC)
|
|
25
|
+
quit
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Method dispatchSendRequestAsync(
|
|
29
|
+
target,
|
|
30
|
+
request,
|
|
31
|
+
responseRequired,
|
|
32
|
+
completionKey,
|
|
33
|
+
description)
|
|
34
|
+
{
|
|
35
|
+
set tSC = ..SendRequestAsync(target,request,responseRequired,completionKey,description)
|
|
36
|
+
if $$$ISERR(tSC) throw ##class(%Exception.StatusException).CreateFromStatus(tSC)
|
|
37
|
+
quit
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Method OnRequest(
|
|
41
|
+
request As %Persistent,
|
|
42
|
+
Output response As %Persistent) As %Status
|
|
43
|
+
{
|
|
44
|
+
set tSC = $$$OK
|
|
45
|
+
try {
|
|
46
|
+
set response = ..%class."_dispatch_on_request"($this,request)
|
|
47
|
+
} catch ex {
|
|
48
|
+
set tSC = ex.AsStatus()
|
|
49
|
+
}
|
|
50
|
+
quit tSC
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Handle a 'Response'
|
|
54
|
+
Method OnResponse(
|
|
55
|
+
request As %Persistent,
|
|
56
|
+
Output response As %Persistent,
|
|
57
|
+
callRequest As %Persistent,
|
|
58
|
+
callResponse As %Persistent,
|
|
59
|
+
pCompletionKey As %String) As %Status
|
|
60
|
+
{
|
|
61
|
+
set tSC = $$$OK
|
|
62
|
+
try {
|
|
63
|
+
set response = ..%class."_dispatch_on_response"($this,request,response,callRequest,callResponse,pCompletionKey)
|
|
64
|
+
} catch ex {
|
|
65
|
+
set tSC = ex.AsStatus()
|
|
66
|
+
}
|
|
67
|
+
quit tSC
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Method OnComplete(
|
|
71
|
+
request As %Library.Persistent,
|
|
72
|
+
ByRef response As %Library.Persistent) As %Status
|
|
73
|
+
{
|
|
74
|
+
set tSC = $$$OK
|
|
75
|
+
try {
|
|
76
|
+
set response = ..%class."_dispatch_on_complete"($this,request,response)
|
|
77
|
+
} catch ex {
|
|
78
|
+
set tSC = ex.AsStatus()
|
|
79
|
+
}
|
|
80
|
+
quit tSC
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Method getPersistentProperty(name)
|
|
84
|
+
{
|
|
85
|
+
quit ..persistentProperties.GetAt(name)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Method setPersistentProperty(
|
|
89
|
+
name,
|
|
90
|
+
value)
|
|
91
|
+
{
|
|
92
|
+
quit ..persistentProperties.SetAt(value,name)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Storage Default
|
|
96
|
+
{
|
|
97
|
+
<Data name="BusinessProcessDefaultData1">
|
|
98
|
+
<Subscript>"BusinessProcess"</Subscript>
|
|
99
|
+
<Value name="1">
|
|
100
|
+
<Value>%classpaths</Value>
|
|
101
|
+
</Value>
|
|
102
|
+
<Value name="2">
|
|
103
|
+
<Value>%classname</Value>
|
|
104
|
+
</Value>
|
|
105
|
+
<Value name="3">
|
|
106
|
+
<Value>%module</Value>
|
|
107
|
+
</Value>
|
|
108
|
+
<Value name="4">
|
|
109
|
+
<Value>%settings</Value>
|
|
110
|
+
</Value>
|
|
111
|
+
<Value name="5">
|
|
112
|
+
<Value>%class</Value>
|
|
113
|
+
</Value>
|
|
114
|
+
</Data>
|
|
115
|
+
<Data name="persistentProperties">
|
|
116
|
+
<Attribute>persistentProperties</Attribute>
|
|
117
|
+
<Structure>subnode</Structure>
|
|
118
|
+
<Subscript>"IOP.BusinessProcess.persistentProperties"</Subscript>
|
|
119
|
+
</Data>
|
|
120
|
+
<DefaultData>BusinessProcessDefaultData1</DefaultData>
|
|
121
|
+
<Type>%Storage.Persistent</Type>
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Copyright (c) 2021 by InterSystems Corporation.
|
|
2
|
+
Cambridge, Massachusetts, U.S.A. All rights reserved.
|
|
3
|
+
Confidential property of InterSystems Corporation. */
|
|
4
|
+
|
|
5
|
+
Class IOP.BusinessService Extends (Ens.BusinessService, IOP.Common) [ Inheritance = right, ProcedureBlock, System = 4 ]
|
|
6
|
+
{
|
|
7
|
+
|
|
8
|
+
Parameter SETTINGS = "%classname:Python BusinessService,%module:Python BusinessService,%settings:Python BusinessService,%classpaths:Python BusinessService";
|
|
9
|
+
|
|
10
|
+
Method dispatchProcessInput(pInput As %RegisteredObject) As %RegisteredObject
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
quit ..%class."on_process_input"(pInput)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Method OnProcessInput(
|
|
17
|
+
request As %RegisteredObject,
|
|
18
|
+
Output response As %RegisteredObject) As %Status
|
|
19
|
+
{
|
|
20
|
+
set tSC = $$$OK
|
|
21
|
+
try {
|
|
22
|
+
try {
|
|
23
|
+
set ..%class."_wait_for_next_call_interval" = ..%WaitForNextCallInterval
|
|
24
|
+
} catch {}
|
|
25
|
+
set response = ..%class."_dispatch_on_process_input"(request)
|
|
26
|
+
try {
|
|
27
|
+
set ..%WaitForNextCallInterval = ..%class."_wait_for_next_call_interval"
|
|
28
|
+
} catch {}
|
|
29
|
+
} catch ex {
|
|
30
|
+
set tSC = ex.AsStatus()
|
|
31
|
+
}
|
|
32
|
+
quit tSC
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|