iris-pex-embedded-python 3.5.5b4__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.
- grongier/__init__.py +0 -0
- grongier/cls/Grongier/PEX/BusinessOperation.cls +8 -0
- grongier/cls/Grongier/PEX/BusinessProcess.cls +13 -0
- grongier/cls/Grongier/PEX/BusinessService.cls +8 -0
- grongier/cls/Grongier/PEX/Common.cls +10 -0
- grongier/cls/Grongier/PEX/Director.cls +10 -0
- grongier/cls/Grongier/PEX/Duplex/Operation.cls +4 -0
- grongier/cls/Grongier/PEX/Duplex/Process.cls +13 -0
- grongier/cls/Grongier/PEX/Duplex/Service.cls +4 -0
- grongier/cls/Grongier/PEX/InboundAdapter.cls +8 -0
- grongier/cls/Grongier/PEX/Message.cls +13 -0
- grongier/cls/Grongier/PEX/OutboundAdapter.cls +8 -0
- grongier/cls/Grongier/PEX/PickleMessage.cls +13 -0
- grongier/cls/Grongier/PEX/PrivateSession/Duplex.cls +8 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Ack.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Poll.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Start.cls +14 -0
- grongier/cls/Grongier/PEX/PrivateSession/Message/Stop.cls +14 -0
- grongier/cls/Grongier/PEX/Test.cls +10 -0
- grongier/cls/Grongier/PEX/Utils.cls +10 -0
- grongier/cls/Grongier/Service/WSGI.cls +4 -0
- grongier/pex/__init__.py +24 -0
- grongier/pex/__main__.py +4 -0
- grongier/pex/_business_host.py +1 -0
- grongier/pex/_cli.py +4 -0
- grongier/pex/_common.py +1 -0
- grongier/pex/_director.py +1 -0
- grongier/pex/_utils.py +1 -0
- grongier/pex/wsgi/handlers.py +104 -0
- iop/__init__.py +25 -0
- iop/__main__.py +4 -0
- iop/_async_request.py +67 -0
- iop/_business_host.py +256 -0
- iop/_business_operation.py +75 -0
- iop/_business_process.py +224 -0
- iop/_business_service.py +63 -0
- iop/_cli.py +247 -0
- iop/_common.py +334 -0
- iop/_debugpy.py +187 -0
- iop/_decorators.py +49 -0
- iop/_director.py +301 -0
- iop/_dispatch.py +136 -0
- iop/_generator_request.py +30 -0
- iop/_inbound_adapter.py +34 -0
- iop/_iris.py +8 -0
- iop/_log_manager.py +100 -0
- iop/_message.py +40 -0
- iop/_message_validator.py +49 -0
- iop/_outbound_adapter.py +23 -0
- iop/_private_session_duplex.py +103 -0
- iop/_private_session_process.py +41 -0
- iop/_remote.py +91 -0
- iop/_serialization.py +199 -0
- iop/_utils.py +671 -0
- iop/cls/IOP/BusinessOperation.cls +35 -0
- iop/cls/IOP/BusinessProcess.cls +156 -0
- iop/cls/IOP/BusinessService.cls +40 -0
- iop/cls/IOP/Common.cls +569 -0
- iop/cls/IOP/Director.cls +70 -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/Generator/Message/Ack.cls +31 -0
- iop/cls/IOP/Generator/Message/Poll.cls +31 -0
- iop/cls/IOP/Generator/Message/Start.cls +15 -0
- iop/cls/IOP/Generator/Message/StartPickle.cls +15 -0
- iop/cls/IOP/Generator/Message/Stop.cls +32 -0
- iop/cls/IOP/InboundAdapter.cls +22 -0
- iop/cls/IOP/Message/JSONSchema.cls +125 -0
- iop/cls/IOP/Message.cls +754 -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 +31 -0
- iop/cls/IOP/PrivateSession/Message/Stop.cls +48 -0
- iop/cls/IOP/Projection.cls +49 -0
- iop/cls/IOP/Service/Remote/Handler.cls +30 -0
- iop/cls/IOP/Service/Remote/Rest/v1.cls +97 -0
- iop/cls/IOP/Service/WSGI.cls +310 -0
- iop/cls/IOP/Test.cls +85 -0
- iop/cls/IOP/Utils.cls +503 -0
- iop/cls/IOP/Wrapper.cls +58 -0
- iop/wsgi/handlers.py +104 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/METADATA +91 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/RECORD +91 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/WHEEL +5 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/entry_points.txt +2 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/licenses/LICENSE +21 -0
- iris_pex_embedded_python-3.5.5b4.dist-info/top_level.txt +2 -0
iop/cls/IOP/Utils.cls
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
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 = "",
|
|
17
|
+
pPythonLib,
|
|
18
|
+
pPythonPath,
|
|
19
|
+
pPythonVersion) As %Status
|
|
20
|
+
{
|
|
21
|
+
set tSc = $$$OK
|
|
22
|
+
$$$ThrowOnError(##class(IOP.Utils).RegisterComponent(pModule, pRemoteClassname, pCLASSPATHS, pFullpath, pOverwrite , pProxyClassname,pPythonLib, pPythonPath, pPythonVersion))
|
|
23
|
+
return tSc
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// "bo","Duplex","/irisdev/app/src/python/demo/duplex/",1,"Duplex.Duplex"
|
|
27
|
+
ClassMethod RegisterComponent(
|
|
28
|
+
pModule As %String,
|
|
29
|
+
pRemoteClassname As %String,
|
|
30
|
+
pCLASSPATHS As %String = "",
|
|
31
|
+
pFullpath As %String = "",
|
|
32
|
+
pOverwrite As %Boolean = 0,
|
|
33
|
+
pProxyClassname As %String = "",
|
|
34
|
+
pPythonLib,
|
|
35
|
+
pPythonPath,
|
|
36
|
+
pPythonVersion) As %Status
|
|
37
|
+
{
|
|
38
|
+
#dim tSC As %Status = $$$OK
|
|
39
|
+
#dim ex As %Exception.AbstractException
|
|
40
|
+
#dim tLanguage,tExtraClasspaths,tDelimiter,tOnePath As %String = ""
|
|
41
|
+
#dim tClassDetails,tRemoteSettings As %String = ""
|
|
42
|
+
#dim tClasspaths As %ListOfDataTypes
|
|
43
|
+
|
|
44
|
+
Quit:(""=pRemoteClassname) $$$ERROR($$$EnsErrGeneral,"Remote Classname must be specified in order to register a Production EXtensions component")
|
|
45
|
+
Quit:(""=pModule) $$$ERROR($$$EnsErrGeneral,"Must specify the module of the remote code.")
|
|
46
|
+
|
|
47
|
+
Try {
|
|
48
|
+
LOCK +^PythonSettings:10
|
|
49
|
+
// Set the Python settings
|
|
50
|
+
do ..SetPythonSettings(pPythonLib, pPythonPath, pPythonVersion)
|
|
51
|
+
|
|
52
|
+
$$$ThrowOnError(..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,pFullpath,.tClassDetails,.tRemoteSettings))
|
|
53
|
+
|
|
54
|
+
Set tConnectionSettings("Classpaths") = pCLASSPATHS
|
|
55
|
+
Set tConnectionSettings("Module") = pModule
|
|
56
|
+
Set tConnectionSettings("Classname") = pRemoteClassname
|
|
57
|
+
Set:(""=pProxyClassname) pProxyClassname = "User."_pRemoteClassname
|
|
58
|
+
|
|
59
|
+
$$$ThrowOnError(..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite, pPythonLib, pPythonPath, pPythonVersion))
|
|
60
|
+
|
|
61
|
+
} Catch ex {
|
|
62
|
+
set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
|
|
63
|
+
set tSC = $$$ERROR($$$EnsErrGeneral,msg)
|
|
64
|
+
}
|
|
65
|
+
LOCK -PythonSettings
|
|
66
|
+
Quit tSC
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
ClassMethod DeleteComponentProxy(pClassname As %String = "") As %Status
|
|
70
|
+
{
|
|
71
|
+
#dim tSC As %Status = $$$OK
|
|
72
|
+
#dim ex As %Exception.AbstractException
|
|
73
|
+
#dim tIsIOP As %Boolean = 0
|
|
74
|
+
#dim tClass As %Dictionary.CompiledClass
|
|
75
|
+
|
|
76
|
+
Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Remote class name must be specified.")
|
|
77
|
+
|
|
78
|
+
Try {
|
|
79
|
+
|
|
80
|
+
If '##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
|
|
81
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("No proxy class defined for remote class '%1'.",pClassname))
|
|
82
|
+
Quit
|
|
83
|
+
}
|
|
84
|
+
If $classmethod(pClassname,"%Extends","IOP.Common") {
|
|
85
|
+
Set tClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname,,.tSC)
|
|
86
|
+
Quit:$$$ISERR(tSC)
|
|
87
|
+
If '$IsObject(tClass) {
|
|
88
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class for remote class '%1' could not be opened.",pClassname))
|
|
89
|
+
Quit
|
|
90
|
+
}
|
|
91
|
+
Set tIsIOP = ("IOP.Utils" = tClass.GeneratedBy)
|
|
92
|
+
}
|
|
93
|
+
If tIsIOP {
|
|
94
|
+
Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
|
|
95
|
+
If $$$ISERR(tSC) {
|
|
96
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete proxy class for remote class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
|
|
97
|
+
Quit
|
|
98
|
+
}
|
|
99
|
+
} Else {
|
|
100
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot delete class '%1' because it is not a IOP proxy class.",pClassname))
|
|
101
|
+
Quit
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
} Catch ex {
|
|
105
|
+
Set tSC = ex.AsStatus()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Quit tSC
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,.tClassDetails,.tRemoteSettings)
|
|
112
|
+
|
|
113
|
+
ClassMethod GetRemoteClassInfo(
|
|
114
|
+
pRemoteClassname As %String,
|
|
115
|
+
pModule As %String,
|
|
116
|
+
pClasspaths As %String,
|
|
117
|
+
pFullpath As %String = "",
|
|
118
|
+
ByRef pClassDetails,
|
|
119
|
+
ByRef pRemoteSettings) As %Status [ Internal ]
|
|
120
|
+
{
|
|
121
|
+
#dim tSC As %Status = $$$OK
|
|
122
|
+
#dim ex As %Exception.AbstractException
|
|
123
|
+
|
|
124
|
+
Try {
|
|
125
|
+
if pClasspaths '="" {
|
|
126
|
+
set sys = ##class(%SYS.Python).Import("sys")
|
|
127
|
+
set delimiter = $s($system.Version.GetOS()="Windows":";",1:":")
|
|
128
|
+
set extraClasspaths = $tr(pClasspaths,delimiter,"|")
|
|
129
|
+
for i=1:1:$l(extraClasspaths,"|") {
|
|
130
|
+
set onePath = $p(extraClasspaths,"|",i)
|
|
131
|
+
set onePath = ##class(%File).NormalizeDirectory(onePath)
|
|
132
|
+
if onePath?1"$$IRISHOME"1P.E set onePath = $e($system.Util.InstallDirectory(),1,*-1)_$e(onePath,11,*)
|
|
133
|
+
if onePath'="" do ##class(IOP.Common).SetPythonPath(onePath)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
set importlib = ##class(%SYS.Python).Import("importlib")
|
|
138
|
+
set builtins = ##class(%SYS.Python).Import("builtins")
|
|
139
|
+
// Load the module form a specific path
|
|
140
|
+
Try {
|
|
141
|
+
set spec = importlib.util."spec_from_file_location"(pModule, pFullpath)
|
|
142
|
+
set module = importlib.util."module_from_spec"(spec)
|
|
143
|
+
do sys.modules."__setitem__"(pModule, module)
|
|
144
|
+
do spec.loader."exec_module"(module)
|
|
145
|
+
}
|
|
146
|
+
Catch ex {
|
|
147
|
+
// If the module is not found, try to import the frist one found
|
|
148
|
+
set module = importlib."import_module"(pModule)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Get the class
|
|
152
|
+
set class = builtins.getattr(module, pRemoteClassname)
|
|
153
|
+
set tClass = class."__new__"(class)
|
|
154
|
+
|
|
155
|
+
If $IsObject(tClass) {
|
|
156
|
+
#; List of information about the class as a whole - $lb(SuperClass, Description, InfoURL, IconURL, Adapter)
|
|
157
|
+
Set pClassDetails = tClass."_get_info"()
|
|
158
|
+
#; List of information about the various properties of the class
|
|
159
|
+
#; List of lists of form $lb(propName,dataType,defaultVal,required,category,description)
|
|
160
|
+
Set pRemoteSettings = tClass."_get_properties"()
|
|
161
|
+
} Else {
|
|
162
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Error opening gateway proxy for class '%1'"),pRemoteClassname)
|
|
163
|
+
}
|
|
164
|
+
} Catch ex {
|
|
165
|
+
set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
|
|
166
|
+
set tSC = $$$ERROR($$$EnsErrGeneral,msg)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
Quit tSC
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
ClassMethod GenerateProxyClass(
|
|
173
|
+
pClassname As %String,
|
|
174
|
+
ByRef pConnectionSettings,
|
|
175
|
+
pClassDetails As %String = "",
|
|
176
|
+
pRemoteSettings As %String = "",
|
|
177
|
+
pOverwrite As %Boolean = 0,
|
|
178
|
+
pPythonLib,
|
|
179
|
+
pPythonPath,
|
|
180
|
+
pPythonVersion) As %Status [ Internal, Private ]
|
|
181
|
+
{
|
|
182
|
+
#dim tSC As %Status = $$$OK
|
|
183
|
+
#dim ex As %Exception.AbstractException
|
|
184
|
+
|
|
185
|
+
Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Class name must be specified in order to generate a proxy class for this Production EXtensions component")
|
|
186
|
+
|
|
187
|
+
Try {
|
|
188
|
+
|
|
189
|
+
If ##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
|
|
190
|
+
If 'pOverwrite {
|
|
191
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class '%1' already exists.",pClassname))
|
|
192
|
+
Quit
|
|
193
|
+
} Else {
|
|
194
|
+
#dim tIsIOP As %Boolean = 0
|
|
195
|
+
If $classmethod(pClassname,"%Extends","IOP.Common") {
|
|
196
|
+
#dim tClass As %Dictionary.CompiledClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname)
|
|
197
|
+
If '$IsObject(tClass) {
|
|
198
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,"Class not found")
|
|
199
|
+
Quit
|
|
200
|
+
}
|
|
201
|
+
Set tIsIOP = ("IOP.Utils" = tClass.GeneratedBy)
|
|
202
|
+
}
|
|
203
|
+
If tIsIOP {
|
|
204
|
+
Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
|
|
205
|
+
If $$$ISERR(tSC) {
|
|
206
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete existing proxy class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
|
|
207
|
+
Quit
|
|
208
|
+
}
|
|
209
|
+
} Else {
|
|
210
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot overwrite class '%1' because it is not a IOP proxy class.",pClassname))
|
|
211
|
+
Quit
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
#; create subclass of the ObjectScript Business Host
|
|
217
|
+
#dim tCOSClass As %Dictionary.ClassDefinition
|
|
218
|
+
Set tCOSClass = ##class(%Dictionary.ClassDefinition).%New()
|
|
219
|
+
Set tCOSClass.Name = pClassname
|
|
220
|
+
|
|
221
|
+
#dim tSuperClass As %String = pClassDetails."__getitem__"(0)
|
|
222
|
+
If (""=tSuperClass) {
|
|
223
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,"No IOP superclass found.")
|
|
224
|
+
Quit
|
|
225
|
+
}
|
|
226
|
+
If '$Case($P(tSuperClass,".",*),"DuplexProcess":1,"DuplexService":1,"DuplexOperation":1,"InboundAdapter":1,"OutboundAdapter":1,"BusinessService":1,"BusinessProcess":1,"BusinessOperation":1,:0) {
|
|
227
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,"Invalid superclass")
|
|
228
|
+
Quit
|
|
229
|
+
}
|
|
230
|
+
Set tSuperClass = "IOP."_$P(tSuperClass,".",*)
|
|
231
|
+
|
|
232
|
+
Set tCOSClass.Super = tSuperClass
|
|
233
|
+
Set tCOSClass.GeneratedBy = $CLASSNAME()
|
|
234
|
+
Set tCOSClass.ClassVersion = $$$CLASSDEFINITIONVERSION
|
|
235
|
+
#dim tDescription As %String = pClassDetails."__getitem__"(1)
|
|
236
|
+
If (""'=tDescription) {
|
|
237
|
+
Set tCOSClass.Description = $Replace(tDescription,$C(10),$C(13,10))
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#; Do not display any of the connection settings
|
|
241
|
+
#dim tSETTINGSParamValue As %String = "%classname:Python $type,%module:Python $type,%settings:Python $type,%classpaths:Python $type:directorySelector"
|
|
242
|
+
set tSETTINGSParamValue = tSETTINGSParamValue_","_"%enable:Python Debug $type,%timeout:Python Debug $type,%port:Python Debug $type,%PythonInterpreterPath:Python Debug $type,%traceback:Python Debug $type"
|
|
243
|
+
set tSETTINGSParamValue = tSETTINGSParamValue_","_"%PythonPath:Python Settings $type,%PythonRuntimeLibrary:Python Settings $type,%PythonRuntimeLibraryVersion:Python Settings $type,%Venv:Python Settings $type"
|
|
244
|
+
|
|
245
|
+
#dim tPropClassname As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
246
|
+
Set tPropClassname.Name = "%classname"
|
|
247
|
+
Set tPropClassname.Type = "%String"
|
|
248
|
+
Set tPropClassname.InitialExpression = $$$quote(pConnectionSettings("Classname"))
|
|
249
|
+
Set tPropClassname.Internal = 1
|
|
250
|
+
Set tSC = tCOSClass.Properties.Insert(tPropClassname)
|
|
251
|
+
Quit:$$$ISERR(tSC)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
#dim tPropClasspaths As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
255
|
+
Set tPropClasspaths.Name = "%classpaths"
|
|
256
|
+
Set tPropClasspaths.Type = "%String"
|
|
257
|
+
Set tSC = tPropClasspaths.Parameters.SetAt("","MAXLEN")
|
|
258
|
+
Quit:$$$ISERR(tSC)
|
|
259
|
+
Set tPropClasspaths.InitialExpression = $$$quote(pConnectionSettings("Classpaths"))
|
|
260
|
+
Set tPropClasspaths.Description = "One or more Classpaths (separated by '|' character) needed in addition to the ones configured in the Remote Gateway"
|
|
261
|
+
Set tSC = tCOSClass.Properties.Insert(tPropClasspaths)
|
|
262
|
+
Quit:$$$ISERR(tSC)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
#dim tPropLanguage As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
266
|
+
Set tPropLanguage.Name = "%module"
|
|
267
|
+
Set tPropLanguage.Type = "%String"
|
|
268
|
+
Set tPropLanguage.Internal = 1
|
|
269
|
+
Set tPropLanguage.InitialExpression = $$$quote(pConnectionSettings("Module"))
|
|
270
|
+
Set tSC = tCOSClass.Properties.Insert(tPropLanguage)
|
|
271
|
+
Quit:$$$ISERR(tSC)
|
|
272
|
+
|
|
273
|
+
if pPythonLib'="" {
|
|
274
|
+
#dim tPropPythonLib As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
275
|
+
Set tPropPythonLib.Name = "%PythonRuntimeLibrary"
|
|
276
|
+
Set tPropPythonLib.Type = "%String"
|
|
277
|
+
Set tPropPythonLib.Internal = 1
|
|
278
|
+
Set tSC = tPropPythonLib.Parameters.SetAt("","MAXLEN")
|
|
279
|
+
Quit:$$$ISERR(tSC)
|
|
280
|
+
Set tPropPythonLib.InitialExpression = $$$quote(pPythonLib)
|
|
281
|
+
Set tSC = tCOSClass.Properties.Insert(tPropPythonLib)
|
|
282
|
+
Quit:$$$ISERR(tSC)
|
|
283
|
+
}
|
|
284
|
+
if pPythonPath'="" {
|
|
285
|
+
#dim tPropPythonPath As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
286
|
+
Set tPropPythonPath.Name = "%PythonPath"
|
|
287
|
+
Set tPropPythonPath.Type = "%String"
|
|
288
|
+
Set tSC = tPropPythonPath.Parameters.SetAt("","MAXLEN")
|
|
289
|
+
Quit:$$$ISERR(tSC)
|
|
290
|
+
Set tPropPythonPath.Internal = 1
|
|
291
|
+
Set tPropPythonPath.InitialExpression = $$$quote(pPythonPath)
|
|
292
|
+
Set tSC = tCOSClass.Properties.Insert(tPropPythonPath)
|
|
293
|
+
Quit:$$$ISERR(tSC)
|
|
294
|
+
}
|
|
295
|
+
if pPythonVersion'="" {
|
|
296
|
+
#dim tPropPythonVersion As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
|
|
297
|
+
Set tPropPythonVersion.Name = "%PythonRuntimeLibraryVersion"
|
|
298
|
+
Set tPropPythonVersion.Type = "%String"
|
|
299
|
+
Set tPropPythonVersion.Internal = 1
|
|
300
|
+
Set tPropPythonVersion.InitialExpression = $$$quote(pPythonVersion)
|
|
301
|
+
Set tSC = tCOSClass.Properties.Insert(tPropPythonVersion)
|
|
302
|
+
Quit:$$$ISERR(tSC)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
If $Case(tSuperClass,"IOP.BusinessService":1,"IOP.BusinessOperation":1,"IOP.DuplexService":1,"IOP.DuplexOperation":1,:0) {
|
|
306
|
+
set builtins = ##class(%SYS.Python).Import("builtins")
|
|
307
|
+
If (builtins.len(pClassDetails)>4) { //Adaptor
|
|
308
|
+
|
|
309
|
+
#dim tAdapterClass = pClassDetails."__getitem__"(4)
|
|
310
|
+
#; May want to issue a warning in the UI if the Adapter class does not exist
|
|
311
|
+
#; 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
|
|
312
|
+
#dim tADAPTERParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
|
|
313
|
+
Set tADAPTERParam.Name = "ADAPTER"
|
|
314
|
+
Set tADAPTERParam.Default = tAdapterClass
|
|
315
|
+
Set tSC = tCOSClass.Parameters.Insert(tADAPTERParam)
|
|
316
|
+
Quit:$$$ISERR(tSC)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
#dim tCustomProp As %Dictionary.PropertyDefinition
|
|
321
|
+
#dim tPropInfo,tPropName,tDataType,tDefault,tDesc,tPropCat,tContext As %String
|
|
322
|
+
|
|
323
|
+
set builtins = ##class(%SYS.Python).Import("builtins")
|
|
324
|
+
#; each remote setting is of form $lb(propName,dataType,defaultVal,required,category,description,editorContext)
|
|
325
|
+
For i=0:1:builtins.len(pRemoteSettings)-1 {
|
|
326
|
+
Set tPropInfo = pRemoteSettings."__getitem__"(i)
|
|
327
|
+
Continue:""=tPropInfo ; this shouldn't happen, but just in case
|
|
328
|
+
Set tPropName = tPropInfo."__getitem__"(0)
|
|
329
|
+
Set tDataType = tPropInfo."__getitem__"(1)
|
|
330
|
+
If (""=tPropName) || (""=tDataType) {
|
|
331
|
+
Set tSC = $$$ERROR($$$EnsErrGeneral,"All properties must have a name and datatype defined")
|
|
332
|
+
Quit
|
|
333
|
+
}
|
|
334
|
+
Set tCustomProp = ##class(%Dictionary.PropertyDefinition).%New()
|
|
335
|
+
Set tCustomProp.Name = tPropName
|
|
336
|
+
If $Case(tDataType,"String":1,"Integer":1,"Boolean":1,"Numeric":1,:0) {
|
|
337
|
+
Set tDataType = "%"_tDataType
|
|
338
|
+
} ElseIf '##class(%Dictionary.ClassDefinition).%ExistsId(tDataType) {
|
|
339
|
+
Set tDataType = "%String"
|
|
340
|
+
}
|
|
341
|
+
Set tCustomProp.Type = tDataType
|
|
342
|
+
If tDataType["%String" {
|
|
343
|
+
Set tSC = tCustomProp.Parameters.SetAt("255","MAXLEN")
|
|
344
|
+
Quit:$$$ISERR(tSC)
|
|
345
|
+
}
|
|
346
|
+
Set tDefault = tPropInfo."__getitem__"(2)
|
|
347
|
+
If ""'=tDefault {
|
|
348
|
+
Set tCustomProp.InitialExpression = $$$quote(tDefault)
|
|
349
|
+
if $LENGTH(tDefault)>255 {
|
|
350
|
+
Set tSC = tCustomProp.Parameters.SetAt("","MAXLEN")
|
|
351
|
+
Quit:$$$ISERR(tSC)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
Set tCustomProp.Required = tPropInfo."__getitem__"(3)
|
|
355
|
+
|
|
356
|
+
Set tSC = tCOSClass.Properties.Insert(tCustomProp)
|
|
357
|
+
Quit:$$$ISERR(tSC)
|
|
358
|
+
|
|
359
|
+
Set tPropCat = "Python Attributes $type"
|
|
360
|
+
Set tSETTINGSParamValue = tSETTINGSParamValue_","_tPropName_":"_tPropCat
|
|
361
|
+
}
|
|
362
|
+
Quit:$$$ISERR(tSC)
|
|
363
|
+
|
|
364
|
+
set type = ""
|
|
365
|
+
set:($Case(tSuperClass,"IOP.InboundAdapter":1,"IOP.OutboundAdapter":1,:0)) type = "Adapter"
|
|
366
|
+
set tSETTINGSParamValue = $REPLACE(tSETTINGSParamValue,"$type",type)
|
|
367
|
+
|
|
368
|
+
#dim tSETTINGSParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
|
|
369
|
+
Set tSETTINGSParam.Name = "SETTINGS"
|
|
370
|
+
Set tSETTINGSParam.Default = tSETTINGSParamValue
|
|
371
|
+
Set tSC = tCOSClass.Parameters.Insert(tSETTINGSParam)
|
|
372
|
+
Quit:$$$ISERR(tSC)
|
|
373
|
+
|
|
374
|
+
Set tSC = tCOSClass.%Save()
|
|
375
|
+
Quit:$$$ISERR(tSC)
|
|
376
|
+
|
|
377
|
+
Set tSC = $System.OBJ.Compile(pClassname,"-d")
|
|
378
|
+
|
|
379
|
+
} Catch ex {
|
|
380
|
+
Set tSC = ex.AsStatus()
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
Quit tSC
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
ClassMethod CreateProduction(
|
|
387
|
+
package As %String = "test",
|
|
388
|
+
name As %String = "AutoCreatedProduction",
|
|
389
|
+
xdata As %CharacterStream) As %Status
|
|
390
|
+
{
|
|
391
|
+
#Dim produtionClassName As %String = package _ "." _ name
|
|
392
|
+
If ('$ZName(produtionClassName, 4))
|
|
393
|
+
{
|
|
394
|
+
Return $System.Status.Error(5001, "Invalid Production package or name.")
|
|
395
|
+
}
|
|
396
|
+
#Dim productionDefinition As %Dictionary.ClassDefinition
|
|
397
|
+
// Check if the production already exists
|
|
398
|
+
If (##class(%Dictionary.ClassDefinition).%ExistsId(produtionClassName))
|
|
399
|
+
{
|
|
400
|
+
// Open the production
|
|
401
|
+
set productionDefinition = ##class(%Dictionary.ClassDefinition).%OpenId(produtionClassName)
|
|
402
|
+
}
|
|
403
|
+
Else
|
|
404
|
+
{
|
|
405
|
+
// Create the production definition
|
|
406
|
+
set productionDefinition = ##Class(%Dictionary.ClassDefinition).%New()
|
|
407
|
+
}
|
|
408
|
+
//
|
|
409
|
+
Set productionDefinition.Name = produtionClassName
|
|
410
|
+
Set productionDefinition.Super = "Ens.Production"
|
|
411
|
+
Set productionDefinition.ClassVersion = 25
|
|
412
|
+
//
|
|
413
|
+
// Check if the XData Definition already exists
|
|
414
|
+
If (##Class(%Dictionary.XDataDefinition).%ExistsId(produtionClassName_"||ProductionDefinition"))
|
|
415
|
+
{
|
|
416
|
+
// delete the XData Definition
|
|
417
|
+
$$$ThrowOnError(##Class(%Dictionary.XDataDefinition).%DeleteId(produtionClassName_"||ProductionDefinition"))
|
|
418
|
+
}
|
|
419
|
+
#Dim xdataDefinition As %Dictionary.XDataDefinition = ##Class(%Dictionary.XDataDefinition).%New()
|
|
420
|
+
//
|
|
421
|
+
Set xdataDefinition.Name = "ProductionDefinition"
|
|
422
|
+
//
|
|
423
|
+
Do xdataDefinition.Data.CopyFrom(xdata)
|
|
424
|
+
//
|
|
425
|
+
// Insert XData Definition into Production Definition
|
|
426
|
+
Do productionDefinition.XDatas.Insert(xdataDefinition)
|
|
427
|
+
//
|
|
428
|
+
#Dim statusCode As %Status = productionDefinition.%Save()
|
|
429
|
+
//
|
|
430
|
+
If ($System.Status.IsError(statusCode))
|
|
431
|
+
{
|
|
432
|
+
Return statusCode
|
|
433
|
+
}
|
|
434
|
+
// Compile the production class
|
|
435
|
+
return $System.OBJ.Compile(produtionClassName,"k-d")
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/// Export a production to an XML string
|
|
439
|
+
ClassMethod ExportProduction(pProductionName As %String) As %String
|
|
440
|
+
{
|
|
441
|
+
Set sc = $$$OK
|
|
442
|
+
set xdata = ""
|
|
443
|
+
// Check if the XData Definition exists
|
|
444
|
+
If (##Class(%Dictionary.XDataDefinition).%ExistsId(pProductionName_"||ProductionDefinition"))
|
|
445
|
+
{
|
|
446
|
+
// Open the XData Definition
|
|
447
|
+
Set xdataDefinition = ##Class(%Dictionary.XDataDefinition).%OpenId(pProductionName_"||ProductionDefinition")
|
|
448
|
+
Set xdata = xdataDefinition.Data
|
|
449
|
+
}
|
|
450
|
+
Else
|
|
451
|
+
{
|
|
452
|
+
$$$ThrowOnError($System.Status.Error(5001, "Production does not exist."))
|
|
453
|
+
}
|
|
454
|
+
Return xdata
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
ClassMethod dispatchTestComponent(
|
|
458
|
+
pTargetName As %String,
|
|
459
|
+
pInput As Ens.Request) As Ens.Response
|
|
460
|
+
{
|
|
461
|
+
#dim tService as EnsLib.Testing.Service
|
|
462
|
+
set tOutput = ""
|
|
463
|
+
$$$ThrowOnError(##class(Ens.Director).CreateBusinessService("EnsLib.Testing.Service", .tService))
|
|
464
|
+
$$$ThrowOnError(tService.SendTestRequest(pTargetName, pInput, .tOutput, .sessionID , 1))
|
|
465
|
+
Quit tOutput
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
ClassMethod SetPythonSettings(
|
|
469
|
+
pPythonLib,
|
|
470
|
+
pPythonPath,
|
|
471
|
+
pPythonVersion) As %Status
|
|
472
|
+
{
|
|
473
|
+
set currentNS = $namespace
|
|
474
|
+
set $NAMESPACE = "%SYS"
|
|
475
|
+
set tSC = $$$OK
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
// Get Config
|
|
479
|
+
$$$ThrowOnError(##Class(Config.config).Get(.Properties))
|
|
480
|
+
// Set the Python interpreter path
|
|
481
|
+
if pPythonPath'="" {
|
|
482
|
+
set Properties("PythonPath") = pPythonPath
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Set the Python runtime library
|
|
486
|
+
if pPythonLib'="" {
|
|
487
|
+
set Properties("PythonRuntimeLibrary") = pPythonLib
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Set the Python runtime library version
|
|
491
|
+
if pPythonVersion'="" {
|
|
492
|
+
set Properties("PythonRuntimeLibraryVersion") = pPythonVersion
|
|
493
|
+
}
|
|
494
|
+
$$$ThrowOnError(##Class(Config.config).Modify(.Properties))
|
|
495
|
+
} catch ex {
|
|
496
|
+
set tSC = ex.AsStatus()
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
set $NAMESPACE = currentNS
|
|
500
|
+
Quit tSC
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
}
|
iop/cls/IOP/Wrapper.cls
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Class IOP.Wrapper Extends %RegisteredObject
|
|
2
|
+
{
|
|
3
|
+
|
|
4
|
+
ClassMethod Import(
|
|
5
|
+
moduleName As %String,
|
|
6
|
+
path As %String = "",
|
|
7
|
+
debugPort As %Integer = 0) As %Status
|
|
8
|
+
{
|
|
9
|
+
set tSC = $$$OK
|
|
10
|
+
Try {
|
|
11
|
+
do ##class(IOP.Common).SetPythonPath(path)
|
|
12
|
+
// For traceback debugging
|
|
13
|
+
do $system.Python.Debugging(1)
|
|
14
|
+
if debugPort > 0 {
|
|
15
|
+
|
|
16
|
+
set debugpy = ##class(%SYS.Python).Import("iop._debugpy")
|
|
17
|
+
do debugpy."debugpy_in_iris"($zu(12),debugPort)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Import the module
|
|
21
|
+
set tModule = ##class(%SYS.Python).Import(moduleName)
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
Catch ex {
|
|
25
|
+
Set tSC= ##class(IOP.Wrapper).DisplayTraceback(ex)
|
|
26
|
+
throw ex
|
|
27
|
+
}
|
|
28
|
+
return tModule
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
ClassMethod DisplayTraceback(ex) As %Status
|
|
32
|
+
{
|
|
33
|
+
set tSC = ex.AsStatus()
|
|
34
|
+
|
|
35
|
+
// Import Modules
|
|
36
|
+
set sys = ##class(%SYS.Python).Import("sys")
|
|
37
|
+
set tracebackModule = ##class(%SYS.Python).Import("traceback")
|
|
38
|
+
set builtins = ##class(%SYS.Python).Import("builtins")
|
|
39
|
+
// Get the last traceback
|
|
40
|
+
set traceback = sys."last_traceback"
|
|
41
|
+
set exType = sys."last_type"."__name__"
|
|
42
|
+
set exValue = sys."last_value"."__str__"()
|
|
43
|
+
// Check if traceback is an object
|
|
44
|
+
if $isObject(traceback) {
|
|
45
|
+
// Format the traceback
|
|
46
|
+
set tb = tracebackModule."format_exception"(sys."last_type", sys."last_value", traceback)
|
|
47
|
+
set tbString = ""
|
|
48
|
+
for i=0:1:(tb."__len__"()-1) {
|
|
49
|
+
set tbString = tbString _ $c(10)_$c(13) _ tb."__getitem__"(i)
|
|
50
|
+
}
|
|
51
|
+
w tbString
|
|
52
|
+
set tSC = $$$ERROR("Exception in Python - "_exType_" - "_exValue)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return tSC
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
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()
|