iris-pex-embedded-python 2.3.28b3__py3-none-any.whl → 3.0.0b1__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 (70) hide show
  1. grongier/cls/Grongier/PEX/BusinessOperation.cls +1 -28
  2. grongier/cls/Grongier/PEX/BusinessProcess.cls +1 -112
  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 +1 -152
  25. grongier/pex/_common.py +1 -347
  26. grongier/pex/_director.py +1 -286
  27. grongier/pex/_utils.py +1 -369
  28. iop/__init__.py +24 -0
  29. iop/__main__.py +4 -0
  30. iop/_business_host.py +511 -0
  31. {grongier/pex → iop}/_business_operation.py +1 -1
  32. {grongier/pex → iop}/_business_process.py +1 -1
  33. {grongier/pex → iop}/_business_service.py +1 -1
  34. iop/_cli.py +152 -0
  35. iop/_common.py +349 -0
  36. iop/_director.py +286 -0
  37. {grongier/pex → iop}/_inbound_adapter.py +1 -1
  38. {grongier/pex → iop}/_outbound_adapter.py +1 -1
  39. {grongier/pex → iop}/_private_session_duplex.py +1 -1
  40. {grongier/pex → iop}/_private_session_process.py +2 -2
  41. iop/_utils.py +374 -0
  42. iop/cls/IOP/BusinessOperation.cls +35 -0
  43. iop/cls/IOP/BusinessProcess.cls +124 -0
  44. iop/cls/IOP/BusinessService.cls +35 -0
  45. iop/cls/IOP/Common.cls +203 -0
  46. iop/cls/IOP/Director.cls +57 -0
  47. iop/cls/IOP/Duplex/Operation.cls +29 -0
  48. iop/cls/IOP/Duplex/Process.cls +229 -0
  49. iop/cls/IOP/Duplex/Service.cls +9 -0
  50. iop/cls/IOP/InboundAdapter.cls +22 -0
  51. iop/cls/IOP/Message.cls +128 -0
  52. iop/cls/IOP/OutboundAdapter.cls +36 -0
  53. iop/cls/IOP/PickleMessage.cls +58 -0
  54. iop/cls/IOP/PrivateSession/Duplex.cls +260 -0
  55. iop/cls/IOP/PrivateSession/Message/Ack.cls +32 -0
  56. iop/cls/IOP/PrivateSession/Message/Poll.cls +32 -0
  57. iop/cls/IOP/PrivateSession/Message/Start.cls +32 -0
  58. iop/cls/IOP/PrivateSession/Message/Stop.cls +48 -0
  59. iop/cls/IOP/Service/WSGI.cls +310 -0
  60. iop/cls/IOP/Test.cls +62 -0
  61. iop/cls/IOP/Utils.cls +374 -0
  62. iop/wsgi/handlers.py +104 -0
  63. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/METADATA +28 -28
  64. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/RECORD +70 -42
  65. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/WHEEL +1 -1
  66. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/top_level.txt +1 -0
  67. {grongier/pex → iop}/_message.py +0 -0
  68. {grongier/pex → iop}/_pickle_message.py +0 -0
  69. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/LICENSE +0 -0
  70. {iris_pex_embedded_python-2.3.28b3.dist-info → iris_pex_embedded_python-3.0.0b1.dist-info}/entry_points.txt +0 -0
@@ -4,371 +4,7 @@
4
4
 
5
5
  Include Ensemble
6
6
 
7
- Class Grongier.PEX.Utils Extends %RegisteredObject
7
+ Class Grongier.PEX.Utils Extends IOP.Utils
8
8
  {
9
9
 
10
- ClassMethod dispatchRegisterComponent(
11
- pModule As %String,
12
- pRemoteClassname As %String,
13
- pCLASSPATHS As %String = "",
14
- pOverwrite As %Boolean = 0,
15
- pProxyClassname As %String = "") As %Status
16
- {
17
- set tSc = $$$OK
18
- $$$ThrowOnError(##class(Grongier.PEX.Utils).RegisterComponent(pModule, pRemoteClassname, pCLASSPATHS, pOverwrite , pProxyClassname))
19
- return tSc
20
- }
21
-
22
- /// "bo","Duplex","/irisdev/app/src/python/demo/duplex/",1,"Duplex.Duplex"
23
- ClassMethod RegisterComponent(
24
- pModule As %String,
25
- pRemoteClassname As %String,
26
- pCLASSPATHS As %String = "",
27
- pOverwrite As %Boolean = 0,
28
- pProxyClassname As %String = "") As %Status
29
- {
30
- #dim tSC As %Status = $$$OK
31
- #dim ex As %Exception.AbstractException
32
- #dim tLanguage,tExtraClasspaths,tDelimiter,tOnePath As %String = ""
33
- #dim tClassDetails,tRemoteSettings As %String = ""
34
- #dim tClasspaths As %ListOfDataTypes
35
-
36
- Quit:(""=pRemoteClassname) $$$ERROR($$$EnsErrGeneral,"Remote Classname must be specified in order to register a Production EXtensions component")
37
- Quit:(""=pModule) $$$ERROR($$$EnsErrGeneral,"Must specify the module of the remote code.")
38
-
39
- Try {
40
-
41
- $$$ThrowOnError(..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,.tClassDetails,.tRemoteSettings))
42
-
43
- Set tConnectionSettings("Classpaths") = pCLASSPATHS
44
- Set tConnectionSettings("Module") = pModule
45
- Set tConnectionSettings("Classname") = pRemoteClassname
46
- Set:(""=pProxyClassname) pProxyClassname = "User."_pRemoteClassname
47
-
48
- $$$ThrowOnError(..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite))
49
-
50
- } Catch ex {
51
- set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
52
- set tSC = $$$ERROR($$$EnsErrGeneral,msg)
53
- }
54
-
55
- Quit tSC
56
- }
57
-
58
- ClassMethod DeleteComponentProxy(pClassname As %String = "") As %Status
59
- {
60
- #dim tSC As %Status = $$$OK
61
- #dim ex As %Exception.AbstractException
62
- #dim tIsPEX As %Boolean = 0
63
- #dim tClass As %Dictionary.CompiledClass
64
-
65
- Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Remote class name must be specified.")
66
-
67
- Try {
68
-
69
- If '##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
70
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("No proxy class defined for remote class '%1'.",pClassname))
71
- Quit
72
- }
73
- If $classmethod(pClassname,"%Extends","Grongier.PEX.Common") {
74
- Set tClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname,,.tSC)
75
- Quit:$$$ISERR(tSC)
76
- If '$IsObject(tClass) {
77
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class for remote class '%1' could not be opened.",pClassname))
78
- Quit
79
- }
80
- Set tIsPEX = ("Grongier.PEX.Utils" = tClass.GeneratedBy)
81
- }
82
- If tIsPEX {
83
- Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
84
- If $$$ISERR(tSC) {
85
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete proxy class for remote class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
86
- Quit
87
- }
88
- } Else {
89
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot delete class '%1' because it is not a PEX proxy class.",pClassname))
90
- Quit
91
- }
92
-
93
- } Catch ex {
94
- Set tSC = ex.AsStatus()
95
- }
96
-
97
- Quit tSC
98
- }
99
-
100
- // ..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,.tClassDetails,.tRemoteSettings)
101
-
102
- ClassMethod GetRemoteClassInfo(
103
- pRemoteClassname As %String,
104
- pModule As %String,
105
- pClasspaths As %String,
106
- ByRef pClassDetails,
107
- ByRef pRemoteSettings) As %Status [ Internal, Private ]
108
- {
109
- #dim tSC As %Status = $$$OK
110
- #dim ex As %Exception.AbstractException
111
- #dim tGateway As %External.Gateway
112
- #dim tGatewayProxy As %Net.Remote.Object
113
-
114
- Try {
115
- if pClasspaths '="" {
116
- set sys = ##class(%SYS.Python).Import("sys")
117
- set delimiter = $s($system.Version.GetOS()="Windows":";",1:":")
118
- set extraClasspaths = $tr(pClasspaths,delimiter,"|")
119
- for i=1:1:$l(extraClasspaths,"|") {
120
- set onePath = $p(extraClasspaths,"|",i)
121
- set onePath = ##class(%File).NormalizeDirectory(onePath)
122
- if onePath?1"$$IRISHOME"1P.E set onePath = $e($system.Util.InstallDirectory(),1,*-1)_$e(onePath,11,*)
123
- if onePath'="" do sys.path.append(onePath)
124
- }
125
- }
126
- ;
127
-
128
- set importlib = ##class(%SYS.Python).Import("importlib")
129
- set builtins = ##class(%SYS.Python).Import("builtins")
130
- set module = importlib."import_module"(pModule)
131
- set class = builtins.getattr(module, pRemoteClassname)
132
- set tClass = class."__new__"(class)
133
-
134
-
135
- If $IsObject(tClass) {
136
- #; List of information about the class as a whole - $lb(SuperClass, Description, InfoURL, IconURL, Adapter)
137
- Set pClassDetails = tClass."_get_info"()
138
- #; List of information about the various properties of the class
139
- #; List of lists of form $lb(propName,dataType,defaultVal,required,category,description)
140
- Set pRemoteSettings = tClass."_get_properties"()
141
- } Else {
142
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Error opening gateway proxy for class '%1'"),pRemoteClassname)
143
- }
144
- } Catch ex {
145
- set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
146
- set tSC = $$$ERROR($$$EnsErrGeneral,msg)
147
- }
148
-
149
- Quit tSC
150
- }
151
-
152
- /// Set tConnectionSettings("Classpaths") = pCLASSPATHS
153
- /// Set tConnectionSettings("Module") = pModule
154
- /// Set tConnectionSettings("Classname") = pRemoteClassname
155
- /// Set:(""=pProxyClassname) pProxyClassname = pRemoteClassname
156
- ///
157
- /// Set tSC = ..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite)
158
- /// "bo","Duplex","/irisdev/app/src/python/demo/duplex/",1,"Duplex.Duplex"
159
- ClassMethod GenerateProxyClass(
160
- pClassname As %String,
161
- ByRef pConnectionSettings,
162
- pClassDetails As %String = "",
163
- pRemoteSettings As %String = "",
164
- pOverwrite As %Boolean = 0) As %Status [ Internal, Private ]
165
- {
166
- #dim tSC As %Status = $$$OK
167
- #dim ex As %Exception.AbstractException
168
-
169
- Quit:(""=pClassname) $$$ERROR($$$EnsErrGeneral,"Class name must be specified in order to generate a proxy class for this Production EXtensions component")
170
-
171
- Try {
172
-
173
- If ##class(%Dictionary.ClassDefinition).%ExistsId(pClassname) {
174
- If 'pOverwrite {
175
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Proxy class '%1' already exists.",pClassname))
176
- Quit
177
- } Else {
178
- #dim tIsPEX As %Boolean = 0
179
- If $classmethod(pClassname,"%Extends","Grongier.PEX.Common") {
180
- #dim tClass As %Dictionary.CompiledClass = ##class(%Dictionary.CompiledClass).%OpenId(pClassname)
181
- If '$IsObject(tClass) {
182
- Set tSC = $$$ERROR($$$EnsErrGeneral,"Class not found")
183
- Quit
184
- }
185
- Set tIsPEX = ("Grongier.PEX.Utils" = tClass.GeneratedBy)
186
- }
187
- If tIsPEX {
188
- Set tSC = ##class(%Dictionary.ClassDefinition).%DeleteId(pClassname)
189
- If $$$ISERR(tSC) {
190
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Unable to delete existing proxy class '%1' : '%2'.",pClassname,$System.Status.GetErrorText(tSC)))
191
- Quit
192
- }
193
- } Else {
194
- Set tSC = $$$ERROR($$$EnsErrGeneral,$$$FormatText("Cannot overwrite class '%1' because it is not a PEX proxy class.",pClassname))
195
- Quit
196
- }
197
- }
198
- }
199
-
200
- #; create subclass of the ObjectScript Business Host
201
- #dim tCOSClass As %Dictionary.ClassDefinition
202
- Set tCOSClass = ##class(%Dictionary.ClassDefinition).%New()
203
- Set tCOSClass.Name = pClassname
204
-
205
- #dim tSuperClass As %String = pClassDetails."__getitem__"(0)
206
- If (""=tSuperClass) {
207
- Set tSC = $$$ERROR($$$EnsErrGeneral,"No PEX superclass found.")
208
- Quit
209
- }
210
- If '$Case($P(tSuperClass,".",*),"DuplexProcess":1,"DuplexService":1,"DuplexOperation":1,"InboundAdapter":1,"OutboundAdapter":1,"BusinessService":1,"BusinessProcess":1,"BusinessOperation":1,:0) {
211
- Set tSC = $$$ERROR($$$EnsErrGeneral,"Invalid superclass")
212
- Quit
213
- }
214
- Set tSuperClass = "Grongier.PEX."_$P(tSuperClass,".",*)
215
-
216
- Set tCOSClass.Super = tSuperClass
217
- Set tCOSClass.GeneratedBy = $CLASSNAME()
218
- Set tCOSClass.ClassVersion = $$$CLASSDEFINITIONVERSION
219
- #dim tDescription As %String = pClassDetails."__getitem__"(1)
220
- If (""'=tDescription) {
221
- Set tCOSClass.Description = $Replace(tDescription,$C(10),$C(13,10))
222
- }
223
-
224
- #; Do not display any of the connection settings
225
- #dim tSETTINGSParamValue As %String = "%classname:Python $type,%module:Python $type,%settings:Python $type,%classpaths:Python $type"
226
-
227
- #dim tPropClassname As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
228
- Set tPropClassname.Name = "%classname"
229
- Set tPropClassname.Type = "%String"
230
- Set tPropClassname.InitialExpression = $$$quote(pConnectionSettings("Classname"))
231
- Set tPropClassname.Internal = 1
232
- Set tSC = tCOSClass.Properties.Insert(tPropClassname)
233
- Quit:$$$ISERR(tSC)
234
-
235
-
236
- #dim tPropClasspaths As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
237
- Set tPropClasspaths.Name = "%classpaths"
238
- Set tPropClasspaths.Type = "%String"
239
- Set tSC = tPropClasspaths.Parameters.SetAt("","MAXLEN")
240
- Quit:$$$ISERR(tSC)
241
- Set tPropClasspaths.InitialExpression = $$$quote(pConnectionSettings("Classpaths"))
242
- Set tPropClasspaths.Description = "One or more Classpaths (separated by '|' character) needed in addition to the ones configured in the Remote Gateway"
243
- Set tSC = tCOSClass.Properties.Insert(tPropClasspaths)
244
- Quit:$$$ISERR(tSC)
245
-
246
-
247
- #dim tPropLanguage As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
248
- Set tPropLanguage.Name = "%module"
249
- Set tPropLanguage.Type = "%String"
250
- Set tPropLanguage.Internal = 1
251
- Set tPropLanguage.InitialExpression = $$$quote(pConnectionSettings("Module"))
252
- Set tSC = tCOSClass.Properties.Insert(tPropLanguage)
253
- Quit:$$$ISERR(tSC)
254
-
255
- If $Case(tSuperClass,"Grongier.PEX.BusinessService":1,"Grongier.PEX.BusinessOperation":1,"Grongier.PEX.DuplexService":1,"Grongier.PEX.DuplexOperation":1,:0) {
256
- set builtins = ##class(%SYS.Python).Import("builtins")
257
- If (builtins.len(pClassDetails)>4) { //Adaptor
258
-
259
- #dim tAdapterClass = pClassDetails."__getitem__"(4)
260
- #; May want to issue a warning in the UI if the Adapter class does not exist
261
- #; 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
262
- #dim tADAPTERParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
263
- Set tADAPTERParam.Name = "ADAPTER"
264
- Set tADAPTERParam.Default = tAdapterClass
265
- Set tSC = tCOSClass.Parameters.Insert(tADAPTERParam)
266
- Quit:$$$ISERR(tSC)
267
- }
268
- }
269
-
270
- set type = ""
271
- set:($Case(tSuperClass,"Grongier.PEX.InboundAdapter":1,"Grongier.PEX.OutboundAdapter":1,:0)) type = "Adapter"
272
- set tSETTINGSParamValue = $REPLACE(tSETTINGSParamValue,"$type",type)
273
-
274
- #dim tSETTINGSParam As %Dictionary.ParameterDefinition = ##class(%Dictionary.ParameterDefinition).%New()
275
- Set tSETTINGSParam.Name = "SETTINGS"
276
- Set tSETTINGSParam.Default = tSETTINGSParamValue
277
- Set tSC = tCOSClass.Parameters.Insert(tSETTINGSParam)
278
- Quit:$$$ISERR(tSC)
279
-
280
- Set tSC = tCOSClass.%Save()
281
- Quit:$$$ISERR(tSC)
282
-
283
- Set tSC = $System.OBJ.Compile(pClassname,"-d")
284
-
285
- } Catch ex {
286
- Set tSC = ex.AsStatus()
287
- }
288
-
289
- Quit tSC
290
- }
291
-
292
- ClassMethod CreateProduction(
293
- package As %String = "test",
294
- name As %String = "AutoCreatedProduction",
295
- xdata As %CharacterStream) As %Status
296
- {
297
- #Dim produtionClassName As %String = package _ "." _ name
298
- If ('$ZName(produtionClassName, 4))
299
- {
300
- Return $System.Status.Error(5001, "Invalid Production package or name.")
301
- }
302
- #Dim productionDefinition As %Dictionary.ClassDefinition
303
- // Check if the production already exists
304
- If (##class(%Dictionary.ClassDefinition).%ExistsId(produtionClassName))
305
- {
306
- // Open the production
307
- set productionDefinition = ##class(%Dictionary.ClassDefinition).%OpenId(produtionClassName)
308
- }
309
- Else
310
- {
311
- // Create the production definition
312
- set productionDefinition = ##Class(%Dictionary.ClassDefinition).%New()
313
- }
314
- //
315
- Set productionDefinition.Name = produtionClassName
316
- Set productionDefinition.Super = "Ens.Production"
317
- Set productionDefinition.ClassVersion = 25
318
- //
319
- // Check if the XData Definition already exists
320
- If (##Class(%Dictionary.XDataDefinition).%ExistsId(produtionClassName_"||ProductionDefinition"))
321
- {
322
- // delete the XData Definition
323
- $$$ThrowOnError(##Class(%Dictionary.XDataDefinition).%DeleteId(produtionClassName_"||ProductionDefinition"))
324
- }
325
- #Dim xdataDefinition As %Dictionary.XDataDefinition = ##Class(%Dictionary.XDataDefinition).%New()
326
- //
327
- Set xdataDefinition.Name = "ProductionDefinition"
328
- //
329
- Do xdataDefinition.Data.CopyFrom(xdata)
330
- //
331
- // Insert XData Definition into Production Definition
332
- Do productionDefinition.XDatas.Insert(xdataDefinition)
333
- //
334
- #Dim statusCode As %Status = productionDefinition.%Save()
335
- //
336
- If ($System.Status.IsError(statusCode))
337
- {
338
- Return statusCode
339
- }
340
- // Compile the production class
341
- return $System.OBJ.Compile(produtionClassName,"k-d")
342
- }
343
-
344
- /// Export a production to an XML string
345
- ClassMethod ExportProduction(pProductionName As %String) As %String
346
- {
347
- Set sc = $$$OK
348
- set xdata = ""
349
- // Check if the XData Definition exists
350
- If (##Class(%Dictionary.XDataDefinition).%ExistsId(pProductionName_"||ProductionDefinition"))
351
- {
352
- // Open the XData Definition
353
- Set xdataDefinition = ##Class(%Dictionary.XDataDefinition).%OpenId(pProductionName_"||ProductionDefinition")
354
- Set xdata = xdataDefinition.Data
355
- }
356
- Else
357
- {
358
- $$$ThrowOnError($System.Status.Error(5001, "Production does not exist."))
359
- }
360
- Return xdata
361
- }
362
-
363
- ClassMethod dispatchTestComponent(
364
- pTargetName As %String,
365
- pInput As Ens.Request) As Ens.Response
366
- {
367
- #dim tService as EnsLib.Testing.Service
368
- set tOutput = ""
369
- $$$ThrowOnError(##class(Ens.Director).CreateBusinessService("EnsLib.Testing.Service", .tService))
370
- $$$ThrowOnError(tService.SendTestRequest(pTargetName, pInput, .tOutput, .sessionID , 1))
371
- Quit tOutput
372
- }
373
-
374
10
  }
@@ -1,310 +1,4 @@
1
- Class Grongier.Service.WSGI Extends %CSP.REST [ ServerOnly = 1 ]
1
+ Class Grongier.Service.WSGI Extends IOP.Service.WSGI [ ServerOnly = 1 ]
2
2
  {
3
3
 
4
- Parameter CLASSPATHS;
5
-
6
- Parameter MODULENAME;
7
-
8
- Parameter APPNAME;
9
-
10
- Parameter DEVMODE = 1;
11
-
12
- /// This method matches the request and method and calls the dispatcher
13
- ClassMethod Page(skipheader As %Boolean = 0) As %Status [ ProcedureBlock = 1 ]
14
- {
15
- #dim tSC As %Status = $$$OK
16
- #dim e As %Exception.AbstractException
17
-
18
- #dim tAuthorized,tRedirected As %Boolean
19
- #dim tRedirectRoutine,tURL As %String = ""
20
- #dim %response As %CSP.Response
21
-
22
- Try {
23
-
24
- #; Ensure that we honor the requested charset
25
- Set %response.CharSet=..#CHARSET
26
-
27
- #; Ensure that we honor the requested CONTENTTYPE
28
- If ..#CONTENTTYPE'="" Set %response.ContentType=..#CONTENTTYPE
29
-
30
- #; Ensure that we honor the requested HTTP_ACCEPT_LANGUAGE
31
- Set %response.Domain = ..#DOMAIN
32
- Do %response.MatchLanguage()
33
-
34
-
35
-
36
- #; Record if device re-direction is already active
37
- Set tRedirected=##class(%Library.Device).ReDirectIO()
38
-
39
- #; Record the redirect routine
40
- Set tRedirectRoutine=$System.Device.GetMnemonicRoutine()
41
-
42
- #; Now switch to using THIS routine for device redirection
43
- Use $io::("^%SYS.cspServer2")
44
-
45
- #; Switch device redirection on (may already be on but thats ok)
46
- Do ##class(%Library.Device).ReDirectIO(1)
47
-
48
- #; Ensure that the application is defined (security check)
49
- If $$$GetSecurityApplicationsDispatchClass(%request.AppData)="" {
50
-
51
- #; Report not authorized
52
- Set tSC=..Http403()
53
-
54
- #; Done
55
- Quit
56
- }
57
-
58
- #; GgiEnvs are not defined in the CSP shell
59
- Set tURL=$Get(%request.CgiEnvs("CSPLIB"))
60
- If tURL="" Set tURL=%request.URL
61
-
62
- #; Do an access check
63
- Set tSC=..AccessCheck(.tAuthorized)
64
- If $$$ISERR(tSC) Quit
65
-
66
- If tAuthorized=0 {
67
-
68
- #; Don't want the session token
69
- Set %response.OutputSessionToken=0
70
-
71
- #; Set the Http Status
72
- Set %response.Status=..#HTTP403FORBIDDEN
73
-
74
- #; Done
75
- Quit
76
- }
77
-
78
- #; Extract the match url from the application name
79
- Set tMatchUrl = "/"_$Extract(tURL,$Length(%request.Application)+1,*)
80
-
81
- #; Dispatch the request
82
- Set tSC=..DispatchRequest(tMatchUrl,%request.Method)
83
-
84
- } Catch (e) {
85
- Set tSC=e.AsStatus()
86
- }
87
-
88
- If $$$ISERR(tSC) {
89
-
90
- #; Don't want the session token
91
- Set %response.OutputSessionToken=0
92
-
93
- Do ..Http500(##class(%Exception.StatusException).CreateFromStatus(tSC))
94
- }
95
-
96
- #; Ensure that at least something is written out as the body
97
- #; This will trigger the device redirect capture and force headers to be written
98
- #; (if not already done)
99
- Write ""
100
-
101
- #; Reset redirect device if necessary
102
- If tRedirected {
103
-
104
- #; Use the original redirected routine
105
- Use $io::("^"_tRedirectRoutine)
106
-
107
- #; Switch device redirection on
108
- Do ##class(%Library.Device).ReDirectIO(1)
109
- }
110
-
111
- if ..#DEVMODE {
112
- #; Close the device to ensure next request starts with a new process
113
- Close 0
114
- }
115
-
116
- Quit $$$OK
117
- }
118
-
119
- ClassMethod OnPreDispatch(
120
- pUrl As %String,
121
- pMethod As %String,
122
- ByRef pContinue As %Boolean) As %Status
123
- {
124
- Set path = ..#CLASSPATHS
125
- Set appName = ..#APPNAME
126
- Set module = ..#MODULENAME
127
- Set devmode = ..#DEVMODE
128
- Set pContinue = 1
129
- Do ..DispatchREST(pUrl, path, appName, module, devmode)
130
- Quit $$$OK
131
- }
132
-
133
- ClassMethod DispatchREST(
134
- PathInfo As %String,
135
- appPath As %String,
136
- appName As %String,
137
- module As %String,
138
- devmode As %Boolean = 1) As %Status
139
- {
140
- Set builtins = ##CLASS(%SYS.Python).Builtins()
141
- Set interface = ##CLASS(%SYS.Python).Import("grongier.pex.wsgi.handlers")
142
- Set rawformdata = ""
143
- Set environ = builtins.dict()
144
- Set key = %request.NextCgiEnv("")
145
-
146
- // Let's check if the WSGI application has been loaded or not for this session.
147
-
148
- If (($DATA(%session.Data("application")) && $ISOBJECT(%session.Data("application"))) && 'devmode) {
149
- Set application = %session.Data("Application")
150
- }
151
- Else{
152
-
153
- Set application = ..GetPythonClass(appName, module, appPath)
154
- If application = "" {
155
- throw ##class(%Exception.General).%New("Error loading WSGI application: "_module_"."_appName_" from "_appPath)
156
- }
157
- Else {
158
- Set %session.Data("Application") = application
159
- }
160
- }
161
-
162
- // Editing some CGI variables that may be incorrect in %request
163
- // Also filling in environ with as many CGI variables as possible from %request
164
- // WSGI states that all CGI variables are valid and should be included if possible
165
- While (key'="") {
166
- Set value = %request.GetCgiEnv(key)
167
- If key = "PATH_INFO" {
168
- Set app=$$getapp^%SYS.cspServer(%request.URL,.path,.match,.updatedurl)
169
- Set value = $EXTRACT(updatedurl,$LENGTH(path),*)
170
- }
171
- If key = "SCRIPT_NAME" {
172
- //%request will sometimes have Script_name include Path_info
173
- Set value = $PIECE(%request.Application, "/",1,*-1)
174
- }
175
- Do environ."__setitem__"(key,value)
176
- Set key = %request.NextCgiEnv(key)
177
- }
178
-
179
- //Have to set up a correct wsgi.input stream from %request
180
- Set stream = %request.Content
181
-
182
- Set contentType = %request.ContentType
183
- Set contentLength = 0
184
-
185
- If contentType = "application/x-www-form-urlencoded" {
186
- Set formdict = builtins.dict()
187
- Set key = $ORDER(%request.Data(""))
188
- While (key'="") {
189
- Set value = $GET(%request.Data(key,1))
190
- Do formdict."__setitem__"(key,value)
191
- Set key = $ORDER(%request.Data(key))
192
- }
193
- Do environ."__setitem__"("formdata", formdict)
194
- }
195
- ElseIf contentType = "multipart/form-data" {
196
- Set boundary = $PIECE(%request.GetCgiEnv("CONTENT_TYPE"), "=",2)
197
- Set stream = ##CLASS(%CSP.BinaryStream).%New()
198
-
199
- Do stream.Write($CHAR(13,10))
200
-
201
- //Get the Form Data values
202
-
203
- Set key = $ORDER(%request.Data(""))
204
- While (key'="") {
205
- Do stream.Write("--")
206
- Do stream.Write(boundary)
207
- Do stream.Write($CHAR(13,10))
208
- Set value = $GET(%request.Data(key,1))
209
- Do stream.Write("Content-Disposition: form-data; name=")
210
- Do stream.Write(""""_key_"""")
211
- Do stream.Write($CHAR(13,10,13,10))
212
- Do stream.Write(value)
213
- Do stream.Write($CHAR(13,10))
214
- Set key = $ORDER(%request.Data(key))
215
- }
216
-
217
- //Now get the possible MIME data streams
218
- Set key = %request.NextMimeData("")
219
- While key'="" {
220
- Set numMimeStreams = %request.CountMimeData(key)
221
- Set index = %request.NextMimeDataIndex(key, "")
222
- Do stream.Write("--")
223
- Do stream.Write(boundary)
224
- Do stream.Write($CHAR(13,10))
225
- If numMimeStreams > 1 {
226
- //I need to create a boundary for a nested multipart content type
227
- Set internalboundary = "--"
228
- For i = 1 : 1 : 7 {
229
- Set internalboundary = internalboundary _ $RANDOM(10)
230
- }
231
- While index '= "" {
232
- Set mimestream = %request.GetMimeData(key, index)
233
- Set headers = mimestream.Headers
234
- Do stream.Write("--")
235
- Do stream.Write(internalboundary)
236
- Do stream.Write($CHAR(13,10))
237
- Do stream.Write(headers)
238
- Do stream.Write($CHAR(13,10,13,10))
239
- Set sc = stream.CopyFrom(mimestream)
240
- //TODO error handling
241
- Do stream.Write($CHAR(13,10))
242
- Set index = %request.NextMimeDataIndex(key, index)
243
- }
244
- Do stream.Write("--")
245
- Do stream.Write(internalboundary)
246
- Do stream.Write("--")
247
- }
248
- Else {
249
- Set mimestream = %request.GetMimeData(key, index)
250
- Set headers = mimestream.Headers
251
- Do stream.Write(headers)
252
- Do stream.Write($CHAR(13,10,13,10))
253
- Set sc = stream.CopyFrom(mimestream)
254
- //TODO error handling
255
- Do stream.Write($CHAR(13,10))
256
- }
257
- Set key = %request.NextMimeData(key)
258
- }
259
- Do stream.Write("--")
260
- Do stream.Write(boundary)
261
- Do stream.Write("--")
262
- Do stream.Rewind()
263
- }
264
-
265
-
266
- Try {
267
- Do interface."make_request"(environ, stream, application, appPath)
268
- }
269
- Catch exception {
270
- throw exception
271
- }
272
- Quit $$$OK
273
- }
274
-
275
- ClassMethod GetPythonClass(
276
- pClassname As %String,
277
- pModule As %String,
278
- pClasspath As %String) As %SYS.Python
279
- {
280
- Try {
281
- If pClasspath '="" {
282
- set sys = ##class(%SYS.Python).Import("sys")
283
-
284
- for i=0:1:(sys.path."__len__"()-1) {
285
- Try {
286
- if sys.path."__getitem__"(i) = pClasspath {
287
- do sys.path."__delitem__"(i)
288
- }
289
- }
290
- Catch ex {
291
- // do nothing
292
- }
293
-
294
- }
295
- do sys.path.insert(0, pClasspath)
296
- }
297
-
298
- Set importlib = ##class(%SYS.Python).Import("importlib")
299
- Set builtins = ##class(%SYS.Python).Import("builtins")
300
- Set module = importlib."import_module"(pModule)
301
- Set class = builtins.getattr(module, pClassname)
302
- }
303
- Catch ex {
304
- throw ##class(%Exception.General).%New("Error loading WSGI application: "_pModule_"."_pClassname_" from "_pClasspath)
305
- }
306
-
307
- Quit class
308
- }
309
-
310
4
  }