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
iop/cls/IOP/Utils.cls ADDED
@@ -0,0 +1,378 @@
1
+ /* Copyright (c) 2021 by InterSystems Corporation.
2
+ Cambridge, Massachusetts, U.S.A. All rights reserved.
3
+ Confidential property of InterSystems Corporation. */
4
+
5
+ Include Ensemble
6
+
7
+ Class IOP.Utils Extends %RegisteredObject
8
+ {
9
+
10
+ ClassMethod dispatchRegisterComponent(
11
+ pModule As %String,
12
+ pRemoteClassname As %String,
13
+ pCLASSPATHS As %String = "",
14
+ pFullpath As %String = "",
15
+ pOverwrite As %Boolean = 0,
16
+ pProxyClassname As %String = "") As %Status
17
+ {
18
+ set tSc = $$$OK
19
+ $$$ThrowOnError(##class(IOP.Utils).RegisterComponent(pModule, pRemoteClassname, pCLASSPATHS, pFullpath, pOverwrite , pProxyClassname))
20
+ return tSc
21
+ }
22
+
23
+ /// "bo","Duplex","/irisdev/app/src/python/demo/duplex/",1,"Duplex.Duplex"
24
+ ClassMethod RegisterComponent(
25
+ pModule As %String,
26
+ pRemoteClassname As %String,
27
+ pCLASSPATHS As %String = "",
28
+ pFullpath As %String = "",
29
+ pOverwrite As %Boolean = 0,
30
+ pProxyClassname As %String = "") As %Status
31
+ {
32
+ #dim tSC As %Status = $$$OK
33
+ #dim ex As %Exception.AbstractException
34
+ #dim tLanguage,tExtraClasspaths,tDelimiter,tOnePath As %String = ""
35
+ #dim tClassDetails,tRemoteSettings As %String = ""
36
+ #dim tClasspaths As %ListOfDataTypes
37
+
38
+ Quit:(""=pRemoteClassname) $$$ERROR($$$EnsErrGeneral,"Remote Classname must be specified in order to register a Production EXtensions component")
39
+ Quit:(""=pModule) $$$ERROR($$$EnsErrGeneral,"Must specify the module of the remote code.")
40
+
41
+ Try {
42
+
43
+ $$$ThrowOnError(..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,pFullpath,.tClassDetails,.tRemoteSettings))
44
+
45
+ Set tConnectionSettings("Classpaths") = pCLASSPATHS
46
+ Set tConnectionSettings("Module") = pModule
47
+ Set tConnectionSettings("Classname") = pRemoteClassname
48
+ Set:(""=pProxyClassname) pProxyClassname = "User."_pRemoteClassname
49
+
50
+ $$$ThrowOnError(..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite))
51
+
52
+ } Catch ex {
53
+ set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
54
+ set tSC = $$$ERROR($$$EnsErrGeneral,msg)
55
+ }
56
+
57
+ Quit tSC
58
+ }
59
+
60
+ ClassMethod DeleteComponentProxy(pClassname As %String = "") As %Status
61
+ {
62
+ #dim tSC As %Status = $$$OK
63
+ #dim ex As %Exception.AbstractException
64
+ #dim tIsPEX As %Boolean = 0
65
+ #dim tClass As %Dictionary.CompiledClass
66
+
67
+ Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Remote class name must be specified.")
68
+
69
+ Try {
70
+
71
+ If '##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
72
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("No proxy class defined for remote class '%1'.",pClassname))
73
+ Quit
74
+ }
75
+ If $classmethod(pClassname,"%Extends","IOP.Common") {
76
+ Set tClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname,,.tSC)
77
+ Quit:$$$ISERR(tSC)
78
+ If '$IsObject(tClass) {
79
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class for remote class '%1' could not be opened.",pClassname))
80
+ Quit
81
+ }
82
+ Set tIsPEX = ("IOP.Utils" = tClass.GeneratedBy)
83
+ }
84
+ If tIsPEX {
85
+ Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
86
+ If $$$ISERR(tSC) {
87
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete proxy class for remote class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
88
+ Quit
89
+ }
90
+ } Else {
91
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot delete class '%1' because it is not a PEX proxy class.",pClassname))
92
+ Quit
93
+ }
94
+
95
+ } Catch ex {
96
+ Set tSC = ex.AsStatus()
97
+ }
98
+
99
+ Quit tSC
100
+ }
101
+
102
+ // ..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,.tClassDetails,.tRemoteSettings)
103
+
104
+ ClassMethod GetRemoteClassInfo(
105
+ pRemoteClassname As %String,
106
+ pModule As %String,
107
+ pClasspaths As %String,
108
+ pFullpath As %String = "",
109
+ ByRef pClassDetails,
110
+ ByRef pRemoteSettings) As %Status [ Internal ]
111
+ {
112
+ #dim tSC As %Status = $$$OK
113
+ #dim ex As %Exception.AbstractException
114
+
115
+ Try {
116
+ if pClasspaths '="" {
117
+ set sys = ##class(%SYS.Python).Import("sys")
118
+ set delimiter = $s($system.Version.GetOS()="Windows":";",1:":")
119
+ set extraClasspaths = $tr(pClasspaths,delimiter,"|")
120
+ for i=1:1:$l(extraClasspaths,"|") {
121
+ set onePath = $p(extraClasspaths,"|",i)
122
+ set onePath = ##class(%File).NormalizeDirectory(onePath)
123
+ if onePath?1"$$IRISHOME"1P.E set onePath = $e($system.Util.InstallDirectory(),1,*-1)_$e(onePath,11,*)
124
+ if onePath'="" do ##class(IOP.Common).SetPythonPath(onePath)
125
+ }
126
+ }
127
+
128
+ set importlib = ##class(%SYS.Python).Import("importlib")
129
+ set builtins = ##class(%SYS.Python).Import("builtins")
130
+ // Load the module form a specific path
131
+ Try {
132
+ set spec = importlib.util."spec_from_file_location"(pModule, pFullpath)
133
+ set module = importlib.util."module_from_spec"(spec)
134
+ do sys.modules."__setitem__"(pModule, module)
135
+ do spec.loader."exec_module"(module)
136
+ }
137
+ Catch ex {
138
+ // If the module is not found, try to import the frist one found
139
+ set module = importlib."import_module"(pModule)
140
+ }
141
+
142
+ // Get the class
143
+ set class = builtins.getattr(module, pRemoteClassname)
144
+ set tClass = class."__new__"(class)
145
+
146
+ If $IsObject(tClass) {
147
+ #; List of information about the class as a whole - $lb(SuperClass, Description, InfoURL, IconURL, Adapter)
148
+ Set pClassDetails = tClass."_get_info"()
149
+ #; List of information about the various properties of the class
150
+ #; List of lists of form $lb(propName,dataType,defaultVal,required,category,description)
151
+ Set pRemoteSettings = tClass."_get_properties"()
152
+ } Else {
153
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Error opening gateway proxy for class '%1'"),pRemoteClassname)
154
+ }
155
+ } Catch ex {
156
+ set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
157
+ set tSC = $$$ERROR($$$EnsErrGeneral,msg)
158
+ }
159
+
160
+ Quit tSC
161
+ }
162
+
163
+ ClassMethod GenerateProxyClass(
164
+ pClassname As %String,
165
+ ByRef pConnectionSettings,
166
+ pClassDetails As %String = "",
167
+ pRemoteSettings As %String = "",
168
+ pOverwrite As %Boolean = 0) As %Status [ Internal, Private ]
169
+ {
170
+ #dim tSC As %Status = $$$OK
171
+ #dim ex As %Exception.AbstractException
172
+
173
+ Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Class name must be specified in order to generate a proxy class for this Production EXtensions component")
174
+
175
+ Try {
176
+
177
+ If ##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
178
+ If 'pOverwrite {
179
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class '%1' already exists.",pClassname))
180
+ Quit
181
+ } Else {
182
+ #dim tIsPEX As %Boolean = 0
183
+ If $classmethod(pClassname,"%Extends","IOP.Common") {
184
+ #dim tClass As %Dictionary.CompiledClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname)
185
+ If '$IsObject(tClass) {
186
+ Set tSC = $$$ERROR($$$EnsErrGeneral,"Class not found")
187
+ Quit
188
+ }
189
+ Set tIsPEX = ("IOP.Utils" = tClass.GeneratedBy)
190
+ }
191
+ If tIsPEX {
192
+ Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
193
+ If $$$ISERR(tSC) {
194
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete existing proxy class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
195
+ Quit
196
+ }
197
+ } Else {
198
+ Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot overwrite class '%1' because it is not a PEX proxy class.",pClassname))
199
+ Quit
200
+ }
201
+ }
202
+ }
203
+
204
+ #; create subclass of the ObjectScript Business Host
205
+ #dim tCOSClass As %Dictionary.ClassDefinition
206
+ Set tCOSClass = ##class(%Dictionary.ClassDefinition).%New()
207
+ Set tCOSClass.Name = pClassname
208
+
209
+ #dim tSuperClass As %String = pClassDetails."__getitem__"(0)
210
+ If (""=tSuperClass) {
211
+ Set tSC = $$$ERROR($$$EnsErrGeneral,"No PEX superclass found.")
212
+ Quit
213
+ }
214
+ If '$Case($P(tSuperClass,".",*),"DuplexProcess":1,"DuplexService":1,"DuplexOperation":1,"InboundAdapter":1,"OutboundAdapter":1,"BusinessService":1,"BusinessProcess":1,"BusinessOperation":1,:0) {
215
+ Set tSC = $$$ERROR($$$EnsErrGeneral,"Invalid superclass")
216
+ Quit
217
+ }
218
+ Set tSuperClass = "IOP."_$P(tSuperClass,".",*)
219
+
220
+ Set tCOSClass.Super = tSuperClass
221
+ Set tCOSClass.GeneratedBy = $CLASSNAME()
222
+ Set tCOSClass.ClassVersion = $$$CLASSDEFINITIONVERSION
223
+ #dim tDescription As %String = pClassDetails."__getitem__"(1)
224
+ If (""'=tDescription) {
225
+ Set tCOSClass.Description = $Replace(tDescription,$C(10),$C(13,10))
226
+ }
227
+
228
+ #; Do not display any of the connection settings
229
+ #dim tSETTINGSParamValue As %String = "%classname:Python $type,%module:Python $type,%settings:Python $type,%classpaths:Python $type"
230
+
231
+ #dim tPropClassname As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
232
+ Set tPropClassname.Name = "%classname"
233
+ Set tPropClassname.Type = "%String"
234
+ Set tPropClassname.InitialExpression = $$$quote(pConnectionSettings("Classname"))
235
+ Set tPropClassname.Internal = 1
236
+ Set tSC = tCOSClass.Properties.Insert(tPropClassname)
237
+ Quit:$$$ISERR(tSC)
238
+
239
+
240
+ #dim tPropClasspaths As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
241
+ Set tPropClasspaths.Name = "%classpaths"
242
+ Set tPropClasspaths.Type = "%String"
243
+ Set tSC = tPropClasspaths.Parameters.SetAt("","MAXLEN")
244
+ Quit:$$$ISERR(tSC)
245
+ Set tPropClasspaths.InitialExpression = $$$quote(pConnectionSettings("Classpaths"))
246
+ Set tPropClasspaths.Description = "One or more Classpaths (separated by '|' character) needed in addition to the ones configured in the Remote Gateway"
247
+ Set tSC = tCOSClass.Properties.Insert(tPropClasspaths)
248
+ Quit:$$$ISERR(tSC)
249
+
250
+
251
+ #dim tPropLanguage As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
252
+ Set tPropLanguage.Name = "%module"
253
+ Set tPropLanguage.Type = "%String"
254
+ Set tPropLanguage.Internal = 1
255
+ Set tPropLanguage.InitialExpression = $$$quote(pConnectionSettings("Module"))
256
+ Set tSC = tCOSClass.Properties.Insert(tPropLanguage)
257
+ Quit:$$$ISERR(tSC)
258
+
259
+ If $Case(tSuperClass,"IOP.BusinessService":1,"IOP.BusinessOperation":1,"IOP.DuplexService":1,"IOP.DuplexOperation":1,:0) {
260
+ set builtins = ##class(%SYS.Python).Import("builtins")
261
+ If (builtins.len(pClassDetails)>4) { //Adaptor
262
+
263
+ #dim tAdapterClass = pClassDetails."__getitem__"(4)
264
+ #; May want to issue a warning in the UI if the Adapter class does not exist
265
+ #; but we don't check here because it does compile and may just be that the user is registering the Service/Operation before the Adapter
266
+ #dim tADAPTERParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
267
+ Set tADAPTERParam.Name = "ADAPTER"
268
+ Set tADAPTERParam.Default = tAdapterClass
269
+ Set tSC = tCOSClass.Parameters.Insert(tADAPTERParam)
270
+ Quit:$$$ISERR(tSC)
271
+ }
272
+ }
273
+
274
+ set type = ""
275
+ set:($Case(tSuperClass,"IOP.InboundAdapter":1,"IOP.OutboundAdapter":1,:0)) type = "Adapter"
276
+ set tSETTINGSParamValue = $REPLACE(tSETTINGSParamValue,"$type",type)
277
+
278
+ #dim tSETTINGSParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
279
+ Set tSETTINGSParam.Name = "SETTINGS"
280
+ Set tSETTINGSParam.Default = tSETTINGSParamValue
281
+ Set tSC = tCOSClass.Parameters.Insert(tSETTINGSParam)
282
+ Quit:$$$ISERR(tSC)
283
+
284
+ Set tSC = tCOSClass.%Save()
285
+ Quit:$$$ISERR(tSC)
286
+
287
+ Set tSC = $System.OBJ.Compile(pClassname,"-d")
288
+
289
+ } Catch ex {
290
+ Set tSC = ex.AsStatus()
291
+ }
292
+
293
+ Quit tSC
294
+ }
295
+
296
+ ClassMethod CreateProduction(
297
+ package As %String = "test",
298
+ name As %String = "AutoCreatedProduction",
299
+ xdata As %CharacterStream) As %Status
300
+ {
301
+ #Dim produtionClassName As %String = package _ "." _ name
302
+ If ('$ZName(produtionClassName, 4))
303
+ {
304
+ Return $System.Status.Error(5001, "Invalid Production package or name.")
305
+ }
306
+ #Dim productionDefinition As %Dictionary.ClassDefinition
307
+ // Check if the production already exists
308
+ If (##class(%Dictionary.ClassDefinition).%ExistsId(produtionClassName))
309
+ {
310
+ // Open the production
311
+ set productionDefinition = ##class(%Dictionary.ClassDefinition).%OpenId(produtionClassName)
312
+ }
313
+ Else
314
+ {
315
+ // Create the production definition
316
+ set productionDefinition = ##Class(%Dictionary.ClassDefinition).%New()
317
+ }
318
+ //
319
+ Set productionDefinition.Name = produtionClassName
320
+ Set productionDefinition.Super = "Ens.Production"
321
+ Set productionDefinition.ClassVersion = 25
322
+ //
323
+ // Check if the XData Definition already exists
324
+ If (##Class(%Dictionary.XDataDefinition).%ExistsId(produtionClassName_"||ProductionDefinition"))
325
+ {
326
+ // delete the XData Definition
327
+ $$$ThrowOnError(##Class(%Dictionary.XDataDefinition).%DeleteId(produtionClassName_"||ProductionDefinition"))
328
+ }
329
+ #Dim xdataDefinition As %Dictionary.XDataDefinition = ##Class(%Dictionary.XDataDefinition).%New()
330
+ //
331
+ Set xdataDefinition.Name = "ProductionDefinition"
332
+ //
333
+ Do xdataDefinition.Data.CopyFrom(xdata)
334
+ //
335
+ // Insert XData Definition into Production Definition
336
+ Do productionDefinition.XDatas.Insert(xdataDefinition)
337
+ //
338
+ #Dim statusCode As %Status = productionDefinition.%Save()
339
+ //
340
+ If ($System.Status.IsError(statusCode))
341
+ {
342
+ Return statusCode
343
+ }
344
+ // Compile the production class
345
+ return $System.OBJ.Compile(produtionClassName,"k-d")
346
+ }
347
+
348
+ /// Export a production to an XML string
349
+ ClassMethod ExportProduction(pProductionName As %String) As %String
350
+ {
351
+ Set sc = $$$OK
352
+ set xdata = ""
353
+ // Check if the XData Definition exists
354
+ If (##Class(%Dictionary.XDataDefinition).%ExistsId(pProductionName_"||ProductionDefinition"))
355
+ {
356
+ // Open the XData Definition
357
+ Set xdataDefinition = ##Class(%Dictionary.XDataDefinition).%OpenId(pProductionName_"||ProductionDefinition")
358
+ Set xdata = xdataDefinition.Data
359
+ }
360
+ Else
361
+ {
362
+ $$$ThrowOnError($System.Status.Error(5001, "Production does not exist."))
363
+ }
364
+ Return xdata
365
+ }
366
+
367
+ ClassMethod dispatchTestComponent(
368
+ pTargetName As %String,
369
+ pInput As Ens.Request) As Ens.Response
370
+ {
371
+ #dim tService as EnsLib.Testing.Service
372
+ set tOutput = ""
373
+ $$$ThrowOnError(##class(Ens.Director).CreateBusinessService("EnsLib.Testing.Service", .tService))
374
+ $$$ThrowOnError(tService.SendTestRequest(pTargetName, pInput, .tOutput, .sessionID , 1))
375
+ Quit tOutput
376
+ }
377
+
378
+ }
iop/wsgi/handlers.py ADDED
@@ -0,0 +1,104 @@
1
+ import os, sys, importlib, urllib.parse
2
+ from io import BytesIO
3
+
4
+ __ospath = os.getcwd()
5
+
6
+ import iris
7
+
8
+ os.chdir(__ospath)
9
+
10
+ enc, esc = sys.getfilesystemencoding(), 'surrogateescape'
11
+
12
+ rest_service = iris.cls('%REST.Impl')
13
+
14
+ def get_from_module(app_path, app_module, app_name):
15
+
16
+ # Add the path to the application
17
+ if (app_path not in sys.path) :
18
+ sys.path.append(app_path)
19
+
20
+ # retrieve the application
21
+ return getattr(importlib.import_module(app_module), app_name)
22
+
23
+ # Changes the current working directory to the manager directory of the instance.
24
+ def goto_manager_dir():
25
+ iris.system.Process.CurrentDirectory(iris.system.Util.ManagerDirectory())
26
+
27
+ def unicode_to_wsgi(u):
28
+ # Convert an environment variable to a WSGI "bytes-as-unicode" string
29
+ return u.encode(enc, esc).decode('iso-8859-1')
30
+
31
+ def wsgi_to_bytes(s):
32
+ return s.encode('iso-8859-1')
33
+
34
+ def write(chunk):
35
+ rest_service._WriteResponse(chunk)
36
+
37
+ def start_response(status, response_headers, exc_info=None):
38
+ '''WSGI start_response callable'''
39
+ if exc_info:
40
+ try:
41
+ raise exc_info[1].with_traceback(exc_info[2])
42
+ finally:
43
+ exc_info = None
44
+
45
+ rest_service._SetStatusCode(status)
46
+ for tuple in response_headers:
47
+ rest_service._SetHeader(tuple[0], tuple[1])
48
+ return write
49
+
50
+
51
+ # Make request to application
52
+ def make_request(environ, stream, application, path):
53
+
54
+ # Change the working directory for logging purposes
55
+ goto_manager_dir()
56
+
57
+ error_log_file = open('WSGI.log', 'a+')
58
+
59
+ # We want the working directory to be the app's directory
60
+ if (not path.endswith(os.path.sep)):
61
+ path = path + os.path.sep
62
+
63
+ #iris.system.Process.CurrentDirectory(path)
64
+
65
+ # Set up the body of the request
66
+ if stream != '':
67
+ bytestream = stream
68
+ elif (environ['CONTENT_TYPE'] == 'application/x-www-form-urlencoded'):
69
+ bytestream = BytesIO()
70
+ part = urllib.parse.urlencode(environ['formdata'])
71
+ bytestream.write(part.encode('utf-8'))
72
+ bytestream.seek(0)
73
+ else:
74
+ bytestream = BytesIO(b'')
75
+
76
+ #for k,v in os.environ.items():
77
+ #environ[k] = unicode_to_wsgi(v)
78
+ environ['wsgi.input'] = bytestream
79
+ environ['wsgi.errors'] = error_log_file
80
+ environ['wsgi.version'] = (1, 0)
81
+ environ['wsgi.multithread'] = False
82
+ environ['wsgi.multiprocess'] = True
83
+ environ['wsgi.run_once'] = True
84
+
85
+
86
+ if environ.get('HTTPS', 'off') in ('on', '1'):
87
+ environ['wsgi.url_scheme'] = 'https'
88
+ else:
89
+ environ['wsgi.url_scheme'] = 'http'
90
+
91
+ # Calling WSGI application
92
+ response = application(environ, start_response)
93
+
94
+ error_log_file.close()
95
+
96
+ try:
97
+ for data in response:
98
+ if data:
99
+ # (REST.Impl).Write() needs a utf-8 string
100
+ write(data.decode('utf-8'))
101
+ write(b'')
102
+ finally:
103
+ if hasattr(response, 'close'):
104
+ response.close()
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.2
2
+ Name: iris_pex_embedded_python
3
+ Version: 3.2.1b2
4
+ Summary: Iris Interoperability based on Embedded Python
5
+ Author-email: grongier <guillaume.rongier@intersystems.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2019 InterSystems Developer Community
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: homepage, https://github.com/grongierisc/interoperability-embedded-python
29
+ Project-URL: documentation, https://github.com/grongierisc/interoperability-embedded-python/blob/master/README.md
30
+ Project-URL: repository, https://github.com/grongierisc/interoperability-embedded-python
31
+ Project-URL: issues, https://github.com/grongierisc/interoperability-embedded-python/issues
32
+ Keywords: iris,intersystems,python,embedded
33
+ Classifier: Development Status :: 5 - Production/Stable
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3.6
38
+ Classifier: Programming Language :: Python :: 3.7
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Topic :: Utilities
45
+ Description-Content-Type: text/markdown
46
+ License-File: LICENSE
47
+ Requires-Dist: dacite>=1.6.0
48
+ Requires-Dist: xmltodict>=0.12.0
49
+ Requires-Dist: iris-embedded-python-wrapper>=0.0.6
50
+ Requires-Dist: setuptools>=40.8.0
51
+ Requires-Dist: dc-schema>=0.0.8
52
+ Requires-Dist: jsonpath-ng>=1.7.0
53
+
54
+ # IoP (Interoperability On Python)
55
+
56
+ [![PyPI - Status](https://img.shields.io/pypi/status/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
57
+ [![PyPI](https://img.shields.io/pypi/v/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
58
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
59
+ [![PyPI - License](https://img.shields.io/pypi/l/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
60
+ ![GitHub last commit](https://img.shields.io/github/last-commit/grongierisc/interoperability-embedded-python)
61
+
62
+ Welcome to the **Interoperability On Python (IoP)** proof of concept! This project demonstrates how the **IRIS Interoperability Framework** can be utilized with a **Python-first approach**.
63
+
64
+ Documentation can be found [here](https://grongierisc.github.io/interoperability-embedded-python/).
65
+
66
+ ## Example
67
+
68
+ Here's a simple example of how a Business Operation can be implemented in Python:
69
+
70
+ ```python
71
+ from iop import BusinessOperation
72
+
73
+ class MyBo(BusinessOperation):
74
+ def on_message(self, request):
75
+ self.log_info("Hello World")
76
+ ```
77
+
78
+ ## Installation
79
+
80
+ To start using this proof of concept, install it using pip:
81
+
82
+ ```bash
83
+ pip install iris-pex-embedded-python
84
+ ```
85
+
86
+ ## Getting Started
87
+
88
+ If you're new to this project, begin by reading the [installation guide](https://grongierisc.github.io/interoperability-embedded-python/getting-started/installation). Then, follow the [first steps](https://grongierisc.github.io/interoperability-embedded-python/getting-started/first-steps) to create your first Business Operation.
89
+
90
+ Happy coding!