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
grongier/pex/_common.py CHANGED
@@ -1,347 +1 @@
1
- import traceback
2
- import dataclasses
3
- import inspect
4
- import iris
5
- import abc
6
-
7
- class _Common(metaclass=abc.ABCMeta):
8
- """ This is a common superclass for all component types that defines common methods."""
9
-
10
- INFO_URL: str
11
- ICON_URL: str
12
- iris_handle = None
13
-
14
- def on_init(self):
15
- """ The on_init() method is called when the component is started.
16
- Use the on_init() method to initialize any structures needed by the component."""
17
- return self.OnInit()
18
-
19
- def on_tear_down(self):
20
- """ Called before the component is terminated. Use it to free any structures."""
21
- return self.OnTearDown()
22
-
23
- def on_connected(self):
24
- """ The on_connected() method is called when the component is connected or reconnected after being disconnected.
25
- Use the on_connected() method to initialize any structures needed by the component."""
26
- return self.OnConnected()
27
-
28
- def _dispatch_on_connected(self, host_object):
29
- """ For internal use only. """
30
- self.on_connected()
31
- return
32
-
33
- def _dispatch_on_init(self, host_object):
34
- """ For internal use only. """
35
- self.on_init()
36
- return
37
-
38
- def _dispatch_on_tear_down(self, host_object):
39
- """ For internal use only. """
40
- self.on_tear_down()
41
- return
42
-
43
- def _set_iris_handles(self, handle_current, handle_partner):
44
- pass
45
-
46
- @classmethod
47
- def _is_message_instance(cls, obj):
48
- if cls._is_message_class(type(obj)):
49
- if not dataclasses.is_dataclass(obj):
50
- raise TypeError(type(obj).__module__ + '.' + type(obj).__qualname__+" must be a dataclass")
51
- return True
52
- return False
53
-
54
- @classmethod
55
- def _is_pickle_message_instance(cls, obj):
56
- if cls._is_pickel_message_class(type(obj)):
57
- return True
58
- return False
59
-
60
- @classmethod
61
- def _is_iris_object_instance(cls, obj):
62
- if (obj is not None and type(obj).__module__.find('iris') == 0) and obj._IsA("%Persistent"):
63
- return True
64
- return False
65
-
66
- @classmethod
67
- def _is_message_class(cls, klass):
68
- name = klass.__module__ + '.' + klass.__qualname__
69
- if name == "grongier.pex.Message":
70
- return True
71
- for c in klass.__bases__:
72
- if cls._is_message_class(c):
73
- return True
74
- return False
75
-
76
- @classmethod
77
- def _is_pickel_message_class(cls, klass):
78
- name = klass.__module__ + '.' + klass.__qualname__
79
- if name == "grongier.pex.PickleMessage":
80
- return True
81
- for c in klass.__bases__:
82
- if cls._is_pickel_message_class(c):
83
- return True
84
- return False
85
-
86
- @classmethod
87
- def _get_info(cls):
88
- """ Get class information to display in the Informational Settings expando for Production config items of this Business Host or Adapter.
89
- This method returns a list of Superclass, Description, InfoURL, and IconURL, and possibly Adapter (if class is a Business Service or Business Operation)
90
- IconURL is not yet displayed anywhere
91
- """
92
- ret = []
93
- desc = ""
94
- info_url = ""
95
- icon_url = ""
96
- super_class = ""
97
- adapter = ""
98
- try:
99
- # Get tuple of the class's base classes and loop through them until we find one of the PEX component classes
100
- classes = inspect.getmro(cls)
101
- for cl in classes:
102
- classname = str(cl)[7:-1]
103
- if classname in ["'grongier.pex.BusinessService'","'grongier.pex.BusinessOperation'","'grongier.pex.DuplexOperation'","'grongier.pex.DuplexService'"] :
104
- # Remove the apostrophes and set as super_class, then find if it uses an adapter
105
- super_class = classname[1:-1]
106
- adapter = cls.get_adapter_type()
107
- if adapter is None:
108
- adapter = cls.getAdapterType()
109
- break
110
- elif classname in ["'grongier.pex.BusinessProcess'","'grongier.pex.DuplexProcess'","'grongier.pex.InboundAdapter'","'grongier.pex.OutboundAdapter'"] :
111
- # Remove the apostrophes and set as super_class
112
- super_class = classname[1:-1]
113
- break
114
-
115
- if ""==super_class:
116
- return ""
117
- ret.append(super_class)
118
-
119
- # Get the class documentation, if any
120
- class_desc = inspect.getdoc(cls)
121
- super_desc = inspect.getdoc(classes[1])
122
- if class_desc!=super_desc:
123
- desc = class_desc
124
- ret.append(str(desc))
125
-
126
- info_url = inspect.getattr_static(cls,"INFO_URL","")
127
- icon_url = inspect.getattr_static(cls,"ICON_URL","")
128
-
129
- ret.append(info_url)
130
- ret.append(icon_url)
131
-
132
- if ""!=adapter:
133
- ret.append(adapter)
134
- except Exception as e:
135
- raise e
136
- return ret
137
-
138
- @classmethod
139
- def _get_properties(cls):
140
- """ Get a list of the Attributes and Properties of this Python class.
141
- Return value is a list of lists of form $lb(propName,data_type,defaultVal,required,category,description).
142
- which can be used by the Production Configuration to display them as settings.
143
- This list will only include class attributes (no instance attributes) and properties which are not marked to be private by use of the _ prefix.
144
- For class attributes, we will use the value that it is defined with as the defaultVal and its type as the data_type, or "" and String if set to None.
145
- Add a function attrName_info() for a attribute or property 'attrName' in order to add more information about that attribute by using the function annotation for the return value.
146
- The annotation should be a dictionary including any of 'IsRequired', 'Category', 'Description', 'DataType', or 'ExcludeFromSettings' as keys.
147
- 'ExcludeFromSettings' should be a boolean, and if true will exclude an attribute from being returned in the list, and so prevent it from being displayed as a setting in the Production Configuration Page
148
- 'DataType' does not need to be specified if it is the same as the type of the attribute definition. Otherwise, it can be either a Python type or a string.
149
- If 'IsRequired' is not specified, this will default to false.
150
- If 'Category' is not specified, the attribute will be added to the Additional category.
151
- """
152
- ret = []
153
- try:
154
- # getmembers() returns all the members of an obj
155
- for member in inspect.getmembers(cls):
156
- # remove private and protected functions
157
- if not member[0].startswith('_'):
158
- # remove other methods and functions
159
- if not inspect.ismethod(member[1]) and not inspect.isfunction(member[1]) and not inspect.isclass(member[1]):
160
- if member[0] not in ('INFO_URL','ICON_URL','PERSISTENT_PROPERTY_LIST') :
161
- name = member[0]
162
- req = 0
163
- cat = "Additional"
164
- desc = ""
165
- # get value, set to "" if None or a @property
166
- val = member[1]
167
- if isinstance(val,property) or (val is None):
168
- val = ""
169
- dt = str(type(val))[8:-2]
170
- # get datatype from attribute definition, default to String
171
- data_type = {'int':'Integer','float':'Numeric','complex':'Numeric','bool':'Boolean'}.get(dt,'String')
172
- # if the user has created a attr_info function, then check the annotation on the return from that for more information about this attribute
173
- if hasattr(cls,name + '_info') :
174
- func = getattr(cls,name+'_info')
175
- if callable(func) :
176
- annotations = func.__annotations__['return']
177
- if annotations is not None:
178
- if bool(annotations.get("ExcludeFromSettings")) :
179
- # don't add this attribute to the settings list
180
- continue
181
- req = bool(annotations.get("IsRequired"))
182
- cat = annotations.get("Category","Additional")
183
- desc = annotations.get("Description")
184
- dt = annotations.get("DataType")
185
- # only override DataType found
186
- if (dt is not None) and ("" != dt):
187
- data_type = {int:'Integer',float:'Number',complex:'Number',bool:'Boolean',str:'String'}.get(dt,str(dt))
188
- default = func()
189
- if default is not None:
190
- val = default
191
- # create list of information for this specific property
192
- info = []
193
- info.append(name) # Name
194
- info.append(data_type) # DataType
195
- info.append(val) # Default Value
196
- info.append(req) # Required
197
- info.append(cat) # Category
198
- info.append(desc) # Description
199
- # add this property to the list
200
- ret.append(info)
201
- except:
202
- pass
203
- return ret
204
-
205
- def log_info(self, message):
206
- """ Write a log entry of type "info". Log entries can be viewed in the management portal.
207
-
208
- Parameters:
209
- message: a string that is written to the log.
210
- """
211
-
212
- current_class = self.__class__.__name__
213
- current_method = None
214
- try:
215
- frame = traceback.extract_stack()[-2]
216
- current_method = frame.name
217
- except:
218
- pass
219
- iris.cls("Ens.Util.Log").LogInfo(current_class, current_method, message)
220
- return
221
-
222
- def log_alert(self, message):
223
- """ Write a log entry of type "alert". Log entries can be viewed in the management portal.
224
-
225
- Parameters:
226
- message: a string that is written to the log.
227
- """
228
- current_class = self.__class__.__name__
229
- current_method = None
230
- try:
231
- frame = traceback.extract_stack()[-2]
232
- current_method = frame.name
233
- except:
234
- pass
235
- iris.cls("Ens.Util.Log").LogAlert(current_class, current_method, message)
236
- return
237
-
238
- def log_warning(self, message):
239
- """ Write a log entry of type "warning". Log entries can be viewed in the management portal.
240
-
241
- Parameters:
242
- message: a string that is written to the log.
243
- """
244
- current_class = self.__class__.__name__
245
- current_method = None
246
- try:
247
- frame = traceback.extract_stack()[-2]
248
- current_method = frame.name
249
- except:
250
- pass
251
- iris.cls("Ens.Util.Log").LogWarning(current_class, current_method, message)
252
- return
253
-
254
- def log_error(self, message):
255
- """ Write a log entry of type "error". Log entries can be viewed in the management portal.
256
-
257
- Parameters:
258
- message: a string that is written to the log.
259
- """
260
- current_class = self.__class__.__name__
261
- current_method = None
262
- try:
263
- frame = traceback.extract_stack()[-2]
264
- current_method = frame.name
265
- except:
266
- pass
267
- iris.cls("Ens.Util.Log").LogError(current_class, current_method, message)
268
- return
269
-
270
- def log_assert(self, message):
271
- """ Write a log entry of type "assert". Log entries can be viewed in the management portal.
272
-
273
- Parameters:
274
- message: a string that is written to the log.
275
- """
276
- current_class = self.__class__.__name__
277
- current_method = None
278
- try:
279
- frame = traceback.extract_stack()[-2]
280
- current_method = frame.name
281
- except:
282
- pass
283
- iris.cls("Ens.Util.Log").LogAssert(current_class, current_method, message)
284
- return
285
-
286
- def LOGINFO(self, message):
287
- """ DECAPRETED : use log_info
288
- Write a log entry of type "info". Log entries can be viewed in the management portal.
289
-
290
- Parameters:
291
- message: a string that is written to the log.
292
- """
293
- return self.log_info(message=message)
294
-
295
- def LOGALERT(self, message):
296
- """ DECAPRETED : use log_alert
297
- Write a log entry of type "alert". Log entries can be viewed in the management portal.
298
-
299
- Parameters:
300
- message: a string that is written to the log.
301
- """
302
- return self.log_alert(message)
303
-
304
- def LOGWARNING(self, message):
305
- """ DECAPRETED : use log_warning
306
- Write a log entry of type "warning". Log entries can be viewed in the management portal.
307
-
308
- Parameters:
309
- message: a string that is written to the log.
310
- """
311
- return self.log_warning(message)
312
-
313
- def LOGERROR(self, message):
314
- """ DECAPRETED : use log_error
315
- Write a log entry of type "error". Log entries can be viewed in the management portal.
316
-
317
- Parameters:
318
- message: a string that is written to the log.
319
- """
320
- return self.log_error(message)
321
-
322
- def LOGASSERT(self, message):
323
- """ DECAPRETED : use log_assert
324
- Write a log entry of type "assert". Log entries can be viewed in the management portal.
325
-
326
- Parameters:
327
- message: a string that is written to the log.
328
- """
329
- return self.log_assert(message)
330
-
331
- def OnInit(self):
332
- """ DEPRECATED : use on_init
333
- The on_init() method is called when the component is started.
334
- Use the on_init() method to initialize any structures needed by the component."""
335
- return
336
-
337
- def OnTearDown(self):
338
- """ DEPRECATED : use on_tear_down
339
- Called before the component is terminated. Use it to freee any structures.
340
- """
341
- return
342
-
343
- def OnConnected(self):
344
- """ DEPRECATED : use on_connected
345
- The on_connected() method is called when the component is connected or reconnected after being disconnected.
346
- Use the on_connected() method to initialize any structures needed by the component."""
347
- return
1
+ from iop._common import _Common
grongier/pex/_director.py CHANGED
@@ -1,286 +1 @@
1
- import iris
2
- import datetime
3
- import intersystems_iris.dbapi._DBAPI as irisdbapi
4
- import signal
5
- import functools
6
- import asyncio
7
- from dataclasses import dataclass
8
-
9
- from grongier.pex._business_host import _BusinessHost
10
- from grongier.pex._utils import _Utils
11
-
12
- class _Director():
13
- """ The Directorclass is used for nonpolling business services, that is, business services which are not automatically
14
- called by the production framework (through the inbound adapter) at the call interval.
15
- Instead these business services are created by a custom application by calling the Director.CreateBusinessService() method.
16
- """
17
-
18
- @staticmethod
19
- def CreateBusinessService(target):
20
- """ DEPRECATED : use create_business_service
21
- The CreateBusinessService() method initiates the specifiied business service.
22
-
23
- Parameters:
24
- connection: an IRISConnection object that specifies the connection to an IRIS instance for Java.
25
- target: a string that specifies the name of the business service in the production definition.
26
-
27
- Returns:
28
- an object that contains an instance of IRISBusinessService
29
- """
30
- return _Director.create_business_service(target)
31
-
32
- @staticmethod
33
- def create_business_service(target):
34
- """ The create_business_service() method initiates the specified business service.
35
-
36
- Parameters:
37
- connection: an IRISConnection object that specifies the connection to an IRIS instance for Java.
38
- target: a string that specifies the name of the business service in the production definition.
39
-
40
- Returns:
41
- an object that contains an instance of IRISBusinessService
42
- """
43
- iris_object = iris.cls("Grongier.PEX.Director").dispatchCreateBusinessService(target)
44
- return iris_object
45
-
46
- @staticmethod
47
- def create_python_business_service(target):
48
- """ The create_business_service() method initiates the specified business service.
49
-
50
- Parameters:
51
- connection: an IRISConnection object that specifies the connection to an IRIS instance for Java.
52
- target: a string that specifies the name of the business service in the production definition.
53
-
54
- Returns:
55
- an object that contains an instance of IRISBusinessService
56
- """
57
- iris_object = iris.cls("Grongier.PEX.Director").dispatchCreateBusinessService(target)
58
- return iris_object.GetClass()
59
-
60
- ### List of function to manage the production
61
- ### start production
62
- @staticmethod
63
- def start_production_with_log(production_name=None):
64
- if production_name is None or production_name == '':
65
- production_name = _Director.get_default_production()
66
- # create two async task
67
- loop = asyncio.get_event_loop()
68
- # add signal handler
69
- handler = SigintHandler()
70
- loop.add_signal_handler(signal.SIGINT, functools.partial(handler.signal_handler, signal.SIGINT, loop))
71
- loop.run_until_complete(asyncio.gather(
72
- _Director._start_production_async(production_name, handler),
73
- _Director._log_production_async(handler)
74
- ))
75
- loop.close()
76
-
77
- @staticmethod
78
- async def _start_production_async(production_name=None, handler=None):
79
- _Director.start_production(production_name)
80
- while True:
81
- if handler.sigint:
82
- _Director.stop_production()
83
- break
84
- await asyncio.sleep(1)
85
-
86
- @staticmethod
87
- def start_production(production_name=None):
88
- if production_name is None or production_name == '':
89
- production_name = _Director.get_default_production()
90
- iris.cls('Ens.Director').StartProduction(production_name)
91
-
92
- ### stop production
93
- @staticmethod
94
- def stop_production():
95
- iris.cls('Ens.Director').StopProduction()
96
-
97
- ### restart production
98
- @staticmethod
99
- def restart_production():
100
- iris.cls('Ens.Director').RestartProduction()
101
-
102
- ### shutdown production
103
- @staticmethod
104
- def shutdown_production():
105
- iris.cls('Ens.Director').StopProduction(10,1)
106
-
107
- ### update production
108
- @staticmethod
109
- def update_production():
110
- iris.cls('Ens.Director').UpdateProduction()
111
-
112
- ### list production
113
- @staticmethod
114
- def list_productions():
115
- return iris.cls('Grongier.PEX.Director').dispatchListProductions()
116
-
117
- ### status production
118
- @staticmethod
119
- def status_production():
120
- dikt = iris.cls('Grongier.PEX.Director').StatusProduction()
121
- if dikt['Production'] is None or dikt['Production'] == '':
122
- dikt['Production'] = _Director.get_default_production()
123
- return dikt
124
-
125
- ### set default production
126
- @staticmethod
127
- def set_default_production(production_name=''):
128
- #set ^Ens.Configuration("SuperUser","LastProduction")
129
- glb = iris.gref("^Ens.Configuration")
130
- glb['csp', "LastProduction"] = production_name
131
-
132
- ### get default production
133
- @staticmethod
134
- def get_default_production():
135
- glb = iris.gref("^Ens.Configuration")
136
- default_production_name = glb['csp', "LastProduction"]
137
- if default_production_name is None or default_production_name == '':
138
- default_production_name = 'Not defined'
139
- return default_production_name
140
-
141
- @staticmethod
142
- def format_log(row: list) -> str:
143
- # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
144
- # ID, ConfigName, Job, MessageId, SessionId, SourceClass, SourceMethod, Stack, Text, TimeLogged, TraceCat, Type
145
- # yield all except stack aand tracecat
146
- # in first position, the timelogged
147
- # cast the result to string
148
- # convert Type to its string value
149
- # Assert,Error,Warning,Info,Trace,Alert
150
- typ = row[11]
151
- if typ == 1:
152
- typ = 'Assert'
153
- elif typ == 2:
154
- typ = 'Error'
155
- elif typ == 3:
156
- typ = 'Warning'
157
- elif typ == 4:
158
- typ = 'Info'
159
- elif typ == 5:
160
- typ = 'Trace'
161
- elif typ == 6:
162
- typ = 'Alert'
163
- return str(row[9]) + ' ' + typ + ' ' + str(row[1]) + ' ' + str(row[2]) + ' ' + str(row[3]) + ' ' + str(row[4]) + ' ' + str(row[5]) + ' ' + str(row[6]) + ' ' + str(row[8])
164
-
165
- @staticmethod
166
- def read_top_log(cursor,top) -> list:
167
- sql = """
168
- SELECT top ?
169
- ID, ConfigName, Job, MessageId, SessionId, SourceClass, SourceMethod, Stack, Text, TimeLogged, TraceCat, Type
170
- FROM Ens_Util.Log
171
- order by id desc
172
- """
173
- result = []
174
- cursor.execute(sql, top)
175
- for row in cursor:
176
- result.append(_Director.format_log(row))
177
- return result
178
-
179
- @staticmethod
180
- def read_log(cursor) -> list:
181
- sql = """
182
- SELECT
183
- ID, ConfigName, Job, MessageId, SessionId, SourceClass, SourceMethod, Stack, Text, TimeLogged, TraceCat, Type
184
- FROM Ens_Util.Log
185
- where TimeLogged >= ?
186
- order by id desc
187
- """
188
- result = []
189
- cursor.execute(sql, (datetime.datetime.now() - datetime.timedelta(seconds=1),))
190
- for row in cursor:
191
- result.append(_Director.format_log(row))
192
- return result
193
-
194
- @staticmethod
195
- async def _log_production_async(handler):
196
- """ Log production
197
- if ctrl+c is pressed, the log is stopped
198
- """
199
- with irisdbapi.connect(embedded=True) as conn:
200
- with conn.cursor() as cursor:
201
- while True:
202
- for row in reversed(_Director.read_log(cursor)):
203
- print(row)
204
- if handler.sigint_log:
205
- break
206
- await asyncio.sleep(1)
207
-
208
- @staticmethod
209
- def log_production_top(top):
210
- """
211
- Log the top N logs of the production
212
- Parameters:
213
- top: the number of log to display
214
- """
215
- with irisdbapi.connect(embedded=True) as conn:
216
- with conn.cursor() as cursor:
217
- for row in reversed(_Director.read_top_log(cursor, top)):
218
- print(row)
219
-
220
- @staticmethod
221
- def log_production():
222
- """ Log production
223
- if ctrl+c is pressed, the log is stopped
224
- """
225
- loop = asyncio.get_event_loop()
226
- handler = SigintHandler(log_only=True)
227
- loop.add_signal_handler(signal.SIGINT, functools.partial(handler.signal_handler, signal.SIGINT, loop))
228
- with irisdbapi.connect(embedded=True) as conn:
229
- with conn.cursor() as cursor:
230
- for row in reversed(_Director.read_top_log(cursor, 10)):
231
- print(row)
232
- loop.run_until_complete(_Director._log_production_async(handler))
233
- loop.close()
234
-
235
- @staticmethod
236
- def test_component(target,message=None,classname=None,body=None):
237
- """
238
- Test a component
239
- Parameters:
240
- target: the name of the component
241
- classname: the name of the class to test
242
- body: the body of the message
243
- """
244
- if not message:
245
- message = iris.cls('Ens.Request')._New()
246
- if classname:
247
- # if classname start with 'iris.' then create an iris object
248
- if classname.startswith('iris.'):
249
- # strip the iris. prefix
250
- classname = classname[5:]
251
- if body:
252
- message = iris.cls(classname)._New(body)
253
- else:
254
- message = iris.cls(classname)._New()
255
- # else create a python object
256
- else:
257
- # python message are casted to Grongier.PEX.Message
258
- message = iris.cls("Grongier.PEX.Message")._New()
259
- message.classname = classname
260
- if body:
261
- message.jstr = _Utils.string_to_stream(body)
262
- else:
263
- message.jstr = _Utils.string_to_stream("{}")
264
- # serialize the message
265
- business_host = _BusinessHost()
266
- serial_message = business_host._dispatch_serializer(message)
267
- response = iris.cls('Grongier.PEX.Utils').dispatchTestComponent(target,serial_message)
268
- try:
269
- deserialized_response = business_host._dispatch_deserializer(response)
270
- except ImportError as e:
271
- # can't import the class, return the string
272
- deserialized_response = f'{response.classname} : {_Utils.stream_to_string(response.jstr)}'
273
- return deserialized_response
274
-
275
-
276
- @dataclass
277
- class SigintHandler():
278
-
279
- sigint: bool = False
280
- sigint_log: bool = False
281
- log_only: bool = False
282
-
283
- def signal_handler(self, signal, frame):
284
- if self.sigint or self.log_only:
285
- self.sigint_log = True
286
- self.sigint = True
1
+ from iop._director import _Director