iris-pex-embedded-python 2.3.27b2__py3-none-any.whl → 3.2.1b2__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.

Files changed (85) hide show
  1. grongier/cls/Grongier/PEX/BusinessOperation.cls +1 -28
  2. grongier/cls/Grongier/PEX/BusinessProcess.cls +1 -100
  3. grongier/cls/Grongier/PEX/BusinessService.cls +1 -28
  4. grongier/cls/Grongier/PEX/Common.cls +1 -194
  5. grongier/cls/Grongier/PEX/Director.cls +1 -48
  6. grongier/cls/Grongier/PEX/Duplex/Operation.cls +1 -26
  7. grongier/cls/Grongier/PEX/Duplex/Process.cls +1 -217
  8. grongier/cls/Grongier/PEX/Duplex/Service.cls +1 -6
  9. grongier/cls/Grongier/PEX/InboundAdapter.cls +1 -15
  10. grongier/cls/Grongier/PEX/Message.cls +1 -116
  11. grongier/cls/Grongier/PEX/OutboundAdapter.cls +1 -29
  12. grongier/cls/Grongier/PEX/PickleMessage.cls +1 -46
  13. grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +1 -253
  14. grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +1 -19
  15. grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +1 -19
  16. grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +1 -19
  17. grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +1 -35
  18. grongier/cls/Grongier/PEX/Test.cls +1 -53
  19. grongier/cls/Grongier/PEX/Utils.cls +1 -365
  20. grongier/cls/Grongier/Service/WSGI.cls +1 -307
  21. grongier/pex/__init__.py +11 -11
  22. grongier/pex/__main__.py +1 -1
  23. grongier/pex/_business_host.py +1 -511
  24. grongier/pex/_cli.py +2 -150
  25. grongier/pex/_common.py +1 -347
  26. grongier/pex/_director.py +1 -286
  27. grongier/pex/_utils.py +1 -369
  28. intersystems_iris/_ConnectionInformation.py +22 -20
  29. intersystems_iris/dbapi/_DBAPI.py +6 -1
  30. intersystems_iris/dbapi/_ResultSetRow.py +26 -15
  31. intersystems_iris/dbapi/preparser/_PreParser.py +4 -1
  32. iop/__init__.py +24 -0
  33. iop/__main__.py +4 -0
  34. iop/_business_host.py +675 -0
  35. iop/_business_operation.py +71 -0
  36. iop/_business_process.py +220 -0
  37. {grongier/pex → iop}/_business_service.py +2 -2
  38. iop/_cli.py +141 -0
  39. iop/_common.py +352 -0
  40. iop/_director.py +301 -0
  41. {grongier/pex → iop}/_inbound_adapter.py +1 -1
  42. iop/_log_manager.py +81 -0
  43. {grongier/pex → iop}/_message.py +1 -1
  44. {grongier/pex → iop}/_outbound_adapter.py +1 -1
  45. {grongier/pex → iop}/_private_session_duplex.py +3 -2
  46. {grongier/pex → iop}/_private_session_process.py +2 -2
  47. iop/_utils.py +458 -0
  48. iop/cls/IOP/BusinessOperation.cls +35 -0
  49. iop/cls/IOP/BusinessProcess.cls +124 -0
  50. iop/cls/IOP/BusinessService.cls +35 -0
  51. iop/cls/IOP/Common.cls +344 -0
  52. iop/cls/IOP/Director.cls +62 -0
  53. iop/cls/IOP/Duplex/Operation.cls +29 -0
  54. iop/cls/IOP/Duplex/Process.cls +229 -0
  55. iop/cls/IOP/Duplex/Service.cls +9 -0
  56. iop/cls/IOP/InboundAdapter.cls +22 -0
  57. iop/cls/IOP/Message/JSONSchema.cls +125 -0
  58. iop/cls/IOP/Message.cls +729 -0
  59. iop/cls/IOP/OutboundAdapter.cls +36 -0
  60. iop/cls/IOP/PickleMessage.cls +58 -0
  61. iop/cls/IOP/PrivateSession/Duplex.cls +260 -0
  62. iop/cls/IOP/PrivateSession/Message/Ack.cls +32 -0
  63. iop/cls/IOP/PrivateSession/Message/Poll.cls +32 -0
  64. iop/cls/IOP/PrivateSession/Message/Start.cls +32 -0
  65. iop/cls/IOP/PrivateSession/Message/Stop.cls +48 -0
  66. iop/cls/IOP/Service/WSGI.cls +310 -0
  67. iop/cls/IOP/Test.cls +85 -0
  68. iop/cls/IOP/Utils.cls +378 -0
  69. iop/wsgi/handlers.py +104 -0
  70. iris_pex_embedded_python-3.2.1b2.dist-info/METADATA +90 -0
  71. iris_pex_embedded_python-3.2.1b2.dist-info/RECORD +139 -0
  72. {iris_pex_embedded_python-2.3.27b2.dist-info → iris_pex_embedded_python-3.2.1b2.dist-info}/WHEEL +1 -1
  73. iris_pex_embedded_python-3.2.1b2.dist-info/entry_points.txt +2 -0
  74. {iris_pex_embedded_python-2.3.27b2.dist-info → iris_pex_embedded_python-3.2.1b2.dist-info}/top_level.txt +1 -1
  75. grongier/pex/_business_operation.py +0 -70
  76. grongier/pex/_business_process.py +0 -215
  77. iris/__init__.py +0 -60
  78. iris/__init__.pyi +0 -236
  79. iris/iris_ipm.py +0 -40
  80. iris/iris_ipm.pyi +0 -17
  81. iris_pex_embedded_python-2.3.27b2.dist-info/METADATA +0 -1384
  82. iris_pex_embedded_python-2.3.27b2.dist-info/RECORD +0 -113
  83. iris_pex_embedded_python-2.3.27b2.dist-info/entry_points.txt +0 -2
  84. {grongier/pex → iop}/_pickle_message.py +0 -0
  85. {iris_pex_embedded_python-2.3.27b2.dist-info → iris_pex_embedded_python-3.2.1b2.dist-info}/LICENSE +0 -0
@@ -1,511 +1 @@
1
- import datetime
2
- import pickle
3
- import codecs
4
- import uuid
5
- import decimal
6
- import base64
7
- import json
8
- import importlib
9
- import iris
10
-
11
- from functools import wraps
12
-
13
- from inspect import signature, getsource
14
-
15
- from dacite import from_dict, Config
16
-
17
- from grongier.pex._common import _Common
18
- from grongier.pex._utils import _Utils
19
-
20
- class _BusinessHost(_Common):
21
- """ This is a superclass for BusinessService, BusinesProcess, and BusinessOperation that
22
- defines common methods. It is a subclass of Common.
23
- """
24
-
25
- buffer:int = 64000
26
- DISPATCH = []
27
-
28
- def input_serialzer(fonction):
29
- """
30
- It takes a function as an argument, and returns a function that takes the same arguments as the
31
- original function, but serializes the arguments before passing them to the original function
32
-
33
- :param fonction: the function that will be decorated
34
- :return: The function dispatch_serializer is being returned.
35
- """
36
- def dispatch_serializer(self,*params, **param2):
37
- # Handle positional arguments
38
- serialized=[]
39
- for param in params:
40
- serialized.append(self._dispatch_serializer(param))
41
- # Handle keyword arguments
42
- for key, value in param2.items():
43
- param2[key] = self._dispatch_serializer(value)
44
- return fonction(self,*serialized, **param2)
45
- return dispatch_serializer
46
-
47
- def input_serialzer_param(position:int,name:str):
48
- """
49
- It takes a function as an argument, and returns a function that takes the same arguments as the
50
- original function, but serializes the arguments before passing them to the original function
51
-
52
- :param fonction: the function that will be decorated
53
- :return: The function dispatch_serializer is being returned.
54
- """
55
- def input_serialzer_param(fonction):
56
- @wraps(fonction)
57
- def dispatch_serializer(self,*params, **param2):
58
- # Handle positional arguments
59
- serialized=[]
60
- for i,param in enumerate(params):
61
- if i == position:
62
- serialized.append(self._dispatch_serializer(param))
63
- else:
64
- serialized.append(param)
65
- # Handle keyword arguments
66
- for key, value in param2.items():
67
- if key == name:
68
- param2[key] = self._dispatch_serializer(value)
69
- return fonction(self,*serialized, **param2)
70
- return dispatch_serializer
71
- return input_serialzer_param
72
-
73
- def output_deserialzer(fonction):
74
- """
75
- It takes a function as an argument, and returns a function that takes the same arguments as the
76
- original function, but returns the result of the original function passed to the
77
- `_dispatch_deserializer` function
78
-
79
- :param fonction: the function that will be decorated
80
- :return: The function dispatch_deserializer is being returned.
81
- """
82
- def dispatch_deserializer(self,*params, **param2):
83
- return self._dispatch_deserializer(fonction(self,*params, **param2))
84
-
85
- return dispatch_deserializer
86
-
87
- def input_deserialzer(fonction):
88
- """
89
- It takes a function as input, and returns a function that takes the same arguments as the input
90
- function, but deserializes the arguments before passing them to the input function
91
-
92
- :param fonction: the function that will be decorated
93
- :return: The function dispatch_deserializer is being returned.
94
- """
95
- def dispatch_deserializer(self,*params, **param2):
96
- # Handle positional arguments
97
- serialized=[]
98
- for param in params:
99
- serialized.append(self._dispatch_deserializer(param))
100
- # Handle keyword arguments
101
- for key, value in param2.items():
102
- param2[key] = self._dispatch_deserializer(value)
103
- return fonction(self,*serialized, **param2)
104
- return dispatch_deserializer
105
-
106
- def output_serialzer(fonction):
107
- """
108
- It takes a function as an argument, and returns a function that takes the same arguments as the
109
- original function, and returns the result of the original function, after passing it through the
110
- _dispatch_serializer function
111
-
112
- :param fonction: The function that is being decorated
113
- :return: The function dispatch_serializer is being returned.
114
- """
115
- def dispatch_serializer(self,*params, **param2):
116
- return self._dispatch_serializer(fonction(self,*params, **param2))
117
- return dispatch_serializer
118
-
119
- @input_serialzer_param(1,'request')
120
- @output_deserialzer
121
- def send_request_sync(self, target, request, timeout=-1, description=None):
122
- """ Send the specified message to the target business process or business operation synchronously.
123
-
124
- Parameters:
125
- target: a string that specifies the name of the business process or operation to receive the request.
126
- The target is the name of the component as specified in the Item Name property in the production definition, not the class name of the component.
127
- request: specifies the message to send to the target. The request is either an instance of a class that is a subclass of Message class or of IRISObject class.
128
- If the target is a build-in ObjectScript component, you should use the IRISObject class. The IRISObject class enables the PEX framework to convert the message to a class supported by the target.
129
- timeout: an optional integer that specifies the number of seconds to wait before treating the send request as a failure. The default value is -1, which means wait forever.
130
- description: an optional string parameter that sets a description property in the message header. The default is None.
131
- Returns:
132
- the response object from target.
133
- Raises:
134
- TypeError: if request is not of type Message or IRISObject.
135
- """
136
-
137
- return self.iris_handle.dispatchSendRequestSync(target,request,timeout,description)
138
-
139
- @input_serialzer_param(1,'request')
140
- def send_request_async(self, target, request, description=None):
141
- """ Send the specified message to the target business process or business operation asynchronously.
142
- Parameters:
143
- target: a string that specifies the name of the business process or operation to receive the request.
144
- The target is the name of the component as specified in the Item Name property in the production definition, not the class name of the component.
145
- request: specifies the message to send to the target. The request is an instance of IRISObject or of a subclass of Message.
146
- If the target is a built-in ObjectScript component, you should use the IRISObject class. The IRISObject class enables the PEX framework to convert the message to a class supported by the target.
147
- description: an optional string parameter that sets a description property in the message header. The default is None.
148
-
149
- Raises:
150
- TypeError: if request is not of type Message or IRISObject.
151
- """
152
-
153
- return self.iris_handle.dispatchSendRequestAsync(target,request,description)
154
-
155
- def _serialize_pickle_message(self,message):
156
- """ Converts a python dataclass message into an iris grongier.pex.message.
157
-
158
- Parameters:
159
- message: The message to serialize, an instance of a class that is a subclass of Message.
160
-
161
- Returns:
162
- string: The message in json format.
163
- """
164
-
165
- pickle_string = codecs.encode(pickle.dumps(message), "base64").decode()
166
- module = message.__class__.__module__
167
- classname = message.__class__.__name__
168
-
169
- msg = iris.cls('Grongier.PEX.PickleMessage')._New()
170
- msg.classname = module + "." + classname
171
-
172
- stream = _Utils.string_to_stream(pickle_string)
173
- msg.jstr = stream
174
-
175
- return msg
176
-
177
-
178
- def _dispatch_serializer(self,message):
179
- """
180
- If the message is a message instance, serialize it as a message, otherwise, if it's a pickle message
181
- instance, serialize it as a pickle message, otherwise, return the message
182
-
183
- :param message: The message to be serialized
184
- :return: The serialized message
185
- """
186
- if (message is not None and self._is_message_instance(message)):
187
- return self._serialize_message(message)
188
- elif (message is not None and self._is_pickle_message_instance(message)):
189
- return self._serialize_pickle_message(message)
190
- elif (message is not None and self._is_iris_object_instance(message)):
191
- return message
192
- elif (message is None or message == ""):
193
- return message
194
- else:
195
- # todo : decorator takes care of all the parameters, so this should never happen
196
- # return message
197
- raise TypeError("The message must be an instance of a class that is a subclass of Message or IRISObject %Persistent class.")
198
-
199
- def _serialize_message(self,message):
200
- """ Converts a python dataclass message into an iris grongier.pex.message.
201
-
202
- Parameters:
203
- message: The message to serialize, an instance of a class that is a subclass of Message.
204
-
205
- Returns:
206
- string: The message in json format.
207
- """
208
- json_string = json.dumps(message, cls=IrisJSONEncoder, ensure_ascii=False)
209
- module = message.__class__.__module__
210
- classname = message.__class__.__name__
211
-
212
- msg = iris.cls('Grongier.PEX.Message')._New()
213
- msg.classname = module + "." + classname
214
-
215
- stream = _Utils.string_to_stream(json_string)
216
- msg.jstr = stream
217
-
218
- return msg
219
-
220
- def _deserialize_pickle_message(self,serial):
221
- """
222
- Converts an iris grongier.pex.message into an python dataclass message.
223
-
224
- """
225
- string = _Utils.stream_to_string(serial.jstr)
226
-
227
- msg = pickle.loads(codecs.decode(string.encode(), "base64"))
228
- return msg
229
-
230
- def _dispatch_deserializer(self,serial):
231
- """
232
- If the serialized object is a Message, deserialize it as a Message, otherwise deserialize it as a
233
- PickleMessage
234
-
235
- :param serial: The serialized object
236
- :return: The return value is a tuple of the form (serial, serial_type)
237
- """
238
- if (serial is not None and type(serial).__module__.find('iris') == 0) and serial._IsA("Grongier.PEX.Message"):
239
- return self._deserialize_message(serial)
240
- elif (serial is not None and type(serial).__module__.find('iris') == 0) and serial._IsA("Grongier.PEX.PickleMessage"):
241
- return self._deserialize_pickle_message(serial)
242
- else:
243
- return serial
244
-
245
- def _deserialize_message(self,serial):
246
- """
247
- Converts an iris grongier.pex.message into an python dataclass message.
248
- """
249
-
250
- if (serial.classname is None):
251
- raise ValueError("JSON message malformed, must include classname")
252
- classname = serial.classname
253
-
254
- j = classname.rindex(".")
255
- if (j <=0):
256
- raise ValueError("Classname must include a module: " + classname)
257
- try:
258
- module = importlib.import_module(classname[:j])
259
- msg = getattr(module, classname[j+1:])
260
- except Exception:
261
- raise ImportError("Class not found: " + classname)
262
-
263
- string = _Utils.stream_to_string(serial.jstr)
264
-
265
- jdict = json.loads(string, cls=IrisJSONDecoder)
266
- msg = self._dataclass_from_dict(msg,jdict)
267
- return msg
268
-
269
- def _dataclass_from_dict(self,klass, dikt):
270
- """
271
- > If the field is not in the dataclass, then add it as an attribute
272
-
273
- :param klass: The dataclass to convert to
274
- :param dikt: the dictionary to convert to a dataclass
275
- :return: A dataclass object with the fields of the dataclass and the fields of the dictionary.
276
- """
277
- ret = from_dict(klass, dikt, Config(check_types=False))
278
-
279
- try:
280
- fieldtypes = klass.__annotations__
281
- except Exception as e:
282
- fieldtypes = []
283
-
284
- for key,val in dikt.items():
285
- if key not in fieldtypes:
286
- setattr(ret, key, val)
287
- return ret
288
-
289
- def _dispach_message(self, request):
290
- """
291
- It takes a request object, and returns a response object
292
-
293
- :param request: The request object
294
- :return: The return value is the result of the method call.
295
- """
296
-
297
- call = 'on_message'
298
-
299
- module = request.__class__.__module__
300
- classname = request.__class__.__name__
301
-
302
- for msg,method in self.DISPATCH:
303
- if msg == module+"."+classname:
304
- call = method
305
-
306
- return getattr(self,call)(request)
307
-
308
-
309
- def _create_dispatch(self):
310
- """
311
- It creates a list of tuples, where each tuple contains the name of a class and the name of a method
312
- that takes an instance of that class as its only argument
313
- :return: A list of tuples.
314
- """
315
- if len(self.DISPATCH) == 0:
316
- #get all function in current BO
317
- method_list = [func for func in dir(self) if callable(getattr(self, func)) and not func.startswith("_")]
318
- for method in method_list:
319
- #get signature of current function
320
- try:
321
- param = signature(getattr(self, method)).parameters
322
- # Handle staticmethod
323
- except ValueError as e:
324
- param=''
325
- #one parameter
326
- if (len(param)==1):
327
- #get parameter type
328
- annotation = str(param[list(param)[0]].annotation)
329
- #trim annotation format <class 'toto'>
330
- i = annotation.find("'")
331
- j = annotation.rfind("'")
332
- #if end is not found
333
- if j == -1:
334
- j = None
335
- classname = annotation[i+1:j]
336
- self.DISPATCH.append((classname,method))
337
- return
338
-
339
- @staticmethod
340
- def OnGetConnections():
341
- """ The OnGetConnections() method returns all of the targets of any SendRequestSync or SendRequestAsync
342
- calls for the class. Implement this method to allow connections between components to show up in
343
- the interoperability UI.
344
-
345
- Returns:
346
- An IRISList containing all targets for this class. Default is None.
347
- """
348
- return None
349
-
350
- def SendRequestSync(self, target, request, timeout=-1, description=None):
351
- """ DEPRECATED : use send_request_sync
352
- `SendRequestSync` is a function that sends a request to a target and waits for a response
353
-
354
- :param target: The target of the request
355
- :param request: The request to send
356
- :param timeout: The timeout in seconds. If the timeout is negative, the default timeout will be used
357
- :param description: A string that describes the request. This is used for logging purposes
358
- :return: The return value is a tuple of (response, status).
359
- """
360
- return self.send_request_sync(target,request,timeout,description)
361
-
362
- def SendRequestAsync(self, target, request, description=None):
363
- """ DEPRECATED : use send_request_async
364
- It takes a target, a request, and a description, and returns a send_request_async function
365
-
366
- :param target: The target of the request. This is the name of the function you want to call
367
- :param request: The request to send
368
- :param description: A string that describes the request
369
- :return: The return value is a Future object.
370
- """
371
- return self.send_request_async(target,request,description)
372
-
373
- @staticmethod
374
- def getAdapterType():
375
- """ DEPRECATED : use get_adapter_type
376
- Name of the registred Adapter
377
- """
378
- return
379
-
380
- @staticmethod
381
- def get_adapter_type():
382
- """
383
- Name of the registred Adapter
384
- """
385
- return
386
-
387
- def on_get_connections(self) -> list:
388
- """
389
- The OnGetConnections() method returns all of the targets of any SendRequestSync or SendRequestAsync
390
- calls for the class. Implement this method to allow connections between components to show up in
391
- the interoperability UI.
392
-
393
- Returns:
394
- An IRISList containing all targets for this class. Default is None.
395
- """
396
- ## Parse the class code to find all invocations of send_request_sync and send_request_async
397
- ## and return the targets
398
- targer_list = []
399
- # get the source code of the class
400
- source = getsource(self.__class__)
401
- # find all invocations of send_request_sync and send_request_async
402
- for method in ['send_request_sync','send_request_async','SendRequestSync','SendRequestAsync']:
403
- i = source.find(method)
404
- while i != -1:
405
- j = source.find("(",i)
406
- if j != -1:
407
- k = source.find(",",j)
408
- if k != -1:
409
- target = source[j+1:k]
410
- if target.find("=") != -1:
411
- # it's a keyword argument, remove the keyword
412
- target = target[target.find("=")+1:].strip()
413
- if target not in targer_list:
414
- targer_list.append(target)
415
- i = source.find(method,i+1)
416
-
417
- for target in targer_list:
418
- # if target is a string, remove the quotes
419
- if target[0] == "'" and target[-1] == "'":
420
- targer_list[targer_list.index(target)] = target[1:-1]
421
- elif target[0] == '"' and target[-1] == '"':
422
- targer_list[targer_list.index(target)] = target[1:-1]
423
- # if target is a variable, try to find the value of the variable
424
- else:
425
- self.on_init()
426
- try:
427
- if target.find("self.") != -1:
428
- # it's a class variable
429
- targer_list[targer_list.index(target)] = getattr(self,target[target.find(".")+1:])
430
- elif target.find(".") != -1:
431
- # it's a class variable
432
- targer_list[targer_list.index(target)] = getattr(getattr(self,target[:target.find(".")]),target[target.find(".")+1:])
433
- else:
434
- targer_list[targer_list.index(target)] = getattr(self,target)
435
- except Exception as e:
436
- pass
437
-
438
- return targer_list
439
-
440
- # It's a subclass of the standard JSONEncoder class that knows how to encode date/time, decimal types,
441
- # and UUIDs.
442
- class IrisJSONEncoder(json.JSONEncoder):
443
- """
444
- JSONEncoder subclass that knows how to encode date/time, decimal types, and
445
- UUIDs.
446
- """
447
-
448
- def default(self, o):
449
- if o.__class__.__name__ == 'DataFrame':
450
- return 'dataframe:'+o.to_json(orient="table")
451
- elif isinstance(o, datetime.datetime):
452
- r = o.isoformat()
453
- if o.microsecond:
454
- r = r[:23] + r[26:]
455
- if r.endswith("+00:00"):
456
- r = r[:-6] + "Z"
457
- return 'datetime:'+r
458
- elif isinstance(o, datetime.date):
459
- return 'date:'+o.isoformat()
460
- elif isinstance(o, datetime.time):
461
- r = o.isoformat()
462
- if o.microsecond:
463
- r = r[:12]
464
- return 'time:'+r
465
- elif isinstance(o, decimal.Decimal):
466
- return 'decimal:'+str(o)
467
- elif isinstance(o, uuid.UUID):
468
- return 'uuid:'+str(o)
469
- elif isinstance(o, bytes):
470
- return 'bytes:'+base64.b64encode(o).decode("UTF-8")
471
- elif hasattr(o, '__dict__'):
472
- return o.__dict__
473
- else:
474
- return super().default(o)
475
-
476
- # It's a JSON decoder that looks for a colon in the value of a key/value pair. If it finds one, it
477
- # assumes the value is a string that represents a type and a value. It then converts the value to the
478
- # appropriate type
479
- class IrisJSONDecoder(json.JSONDecoder):
480
- def __init__(self, *args, **kwargs):
481
- json.JSONDecoder.__init__(
482
- self, object_hook=self.object_hook, *args, **kwargs)
483
-
484
- def object_hook(self, obj):
485
- ret = {}
486
- for key, value in obj.items():
487
- i = 0
488
- if isinstance(value, str):
489
- i = value.find(":")
490
- if (i>0):
491
- typ = value[:i]
492
- if typ == 'datetime':
493
- ret[key] = datetime.datetime.fromisoformat(value[i+1:])
494
- elif typ == 'date':
495
- ret[key] = datetime.date.fromisoformat(value[i+1:])
496
- elif typ == 'time':
497
- ret[key] = datetime.time.fromisoformat(value[i+1:])
498
- elif typ == 'dataframe':
499
- module = importlib.import_module('pandas')
500
- ret[key] = module.read_json(value[i+1:],orient="table")
501
- elif typ == 'decimal':
502
- ret[key] = decimal.Decimal(value[i+1:])
503
- elif typ == 'uuid':
504
- ret[key] = uuid.UUID(value[i+1:])
505
- elif typ == 'bytes':
506
- ret[key] = base64.b64decode((value[i+1:].encode("UTF-8")))
507
- else:
508
- ret[key] = value
509
- else:
510
- ret[key] = value
511
- return ret
1
+ from iop._business_host import _BusinessHost
grongier/pex/_cli.py CHANGED
@@ -1,152 +1,4 @@
1
- # _manager.py is the main entry point of the pex package
2
- # it's a command line interface to manage productions
3
- # eg :
4
- # python3 -m grongier.pex -h : display help and the default production name
5
- # python3 -m grongier.pex -l : list productions
6
- # python3 -m grongier.pex -d <production_name> : set the default production to <production_name>
7
- # python3 -m grongier.pex -s <production_name> : start a production named <production_name> if <production_name> is not set, the default production is started
8
- # python3 -m grongier.pex -k <production_name> : stop a production named <production_name> if <production_name> is not set, the default production is killed
9
- # python3 -m grongier.pex -r <production_name> : restart a production named <production_name> if <production_name> is not set, the default production is restarted
10
- # python3 -m grongier.pex -m <settings_file> : migrate a production and classes with the settings file <settings_file>
11
- # python3 -m grongier.pex -x <production_name> : export a production named <production_name> if <production_name> is not set, the default production is exported
12
- from grongier.pex._director import _Director
13
- from grongier.pex._utils import _Utils
14
-
15
- import argparse
16
- import json
17
- import os
18
- from importlib.metadata import version
19
-
20
- def parse_args():
21
- # parse arguments
22
- main_parser = argparse.ArgumentParser()
23
- parser = main_parser.add_mutually_exclusive_group()
24
- parser.add_argument('-d', '--default', help='set the default production', nargs='?', const='not_set')
25
- parser.add_argument('-l', '--list', help='list productions', action='store_true')
26
- parser.add_argument('-s', '--start', help='start a production', nargs='?', const='not_set')
27
- start = main_parser.add_argument_group('start arguments')
28
- start.add_argument('-D', '--detach', help='start a production in detach mode', action='store_true')
29
- parser.add_argument('-S', '--stop', help='stop a production', action='store_true')
30
- parser.add_argument('-k', '--kill', help='kill a production', action='store_true')
31
- parser.add_argument('-r', '--restart', help='restart a production', action='store_true')
32
- parser.add_argument('-x', '--status', help='status a production', action='store_true')
33
- parser.add_argument('-m', '-M', '--migrate', help='migrate production and classes with settings file')
34
- parser.add_argument('-e', '--export', help='export a production', nargs='?', const='not_set')
35
- parser.add_argument('-v', '--version', help='display version', action='store_true')
36
- parser.add_argument('-L', '--log', help='display log', nargs='?', const='not_set')
37
- parser.add_argument('-i', '--init', help='init the pex module in iris', nargs='?', const='not_set')
38
- parser.add_argument('-t', '--test', help='test the pex module in iris', nargs='?', const='not_set')
39
- test = main_parser.add_argument_group('test arguments')
40
- # add classname argument
41
- test.add_argument('-C', '--classname', help='test classname', nargs='?', const='not_set')
42
- # body argument
43
- test.add_argument('-B', '--body', help='test body', nargs='?', const='not_set')
44
- return main_parser
45
-
46
- def main(argv=None):
47
- # build arguments
48
- parser = parse_args()
49
- args = parser.parse_args(argv)
50
-
51
- if args.default:
52
- # set default production
53
- if args.default == 'not_set':
54
- # display default production name
55
- print(_Director.get_default_production())
56
- else:
57
- _Director.set_default_production(args.default)
58
-
59
- elif args.list:
60
- # display list of productions
61
- dikt = _Director.list_productions()
62
- print(json.dumps(dikt, indent=4))
63
-
64
- elif args.start:
65
- production_name = None
66
- if args.start == 'not_set':
67
- # start default production
68
- production_name = _Director.get_default_production()
69
- else:
70
- # start production with name
71
- production_name = args.start
72
- if args.detach:
73
- # start production in detach mode
74
- _Director.start_production(production_name)
75
- print(f"Production {production_name} started")
76
- else:
77
- _Director.start_production_with_log(production_name)
78
-
79
- elif args.init:
80
- if args.init == 'not_set':
81
- # set arg to None
82
- args.init = None
83
- _Utils.setup(args.start)
84
-
85
- elif args.kill:
86
- # kill a production
87
- _Director.shutdown_production()
88
-
89
- elif args.restart:
90
- # restart a production
91
- _Director.restart_production()
92
-
93
- elif args.migrate:
94
- # check if migrate is absolute path
95
- if os.path.isabs(args.migrate):
96
- # migrate a production with absolute path
97
- _Utils.migrate(args.migrate)
98
- else:
99
- # migrate a production with relative path
100
- _Utils.migrate(os.path.join(os.getcwd(), args.migrate))
101
-
102
- elif args.version:
103
- # display version
104
- print(version('iris-pex-embedded-python'))
105
-
106
- elif args.log:
107
- # display log
108
- if args.log == 'not_set':
109
- # display default production log
110
- _Director.log_production()
111
- else:
112
- _Director.log_production_top(args.log)
113
-
114
- elif args.stop:
115
- # stop a production
116
- _Director.stop_production()
117
- print(f"Production {_Director.get_default_production()} stopped")
118
-
119
- elif args.status:
120
- dikt=_Director.status_production()
121
- print(json.dumps(dikt, indent=4))
122
-
123
- elif args.test:
124
- classname = None
125
- body = None
126
- if args.test == 'not_set':
127
- # set arg to None
128
- args.test = None
129
- if args.classname:
130
- classname = args.classname
131
- if args.body:
132
- body = args.body
133
- response = _Director.test_component(args.test, classname=classname, body=body)
134
- print(response)
135
-
136
- elif args.export:
137
- if args.export == 'not_set':
138
- # export default production
139
- args.export=_Director.get_default_production()
140
-
141
- dikt = _Utils.export_production(args.export)
142
- print(json.dumps(dikt, indent=4))
143
-
144
- else:
145
- # display help
146
- parser.print_help()
147
- print()
148
- print("Default production : " + _Director.get_default_production())
149
-
1
+ from iop._cli import main
150
2
 
151
3
  if __name__ == '__main__':
152
- main()
4
+ main()