Skip to content

Commit 7ee29b5

Browse files
committed
New isc.py.Main interface for user.
1 parent eb2b210 commit 7ee29b5

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed

isc/py/Main.cls

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/// Public entry point to call Python Context
2+
Class isc.py.Main
3+
{
4+
5+
/// This method assumes that variable value is less than $$$MaxStringLength limit
6+
/// Eval code vaiable in initialized context and
7+
/// optionally return value of variable str evaluation
8+
/// serialization - currenlty: 0 - string serialization, 1 - repr serialization.
9+
/// write ##class(isc.py.Main).SimpleString()
10+
ClassMethod SimpleString(code As %String = "", variable As %String = "", serialization As %Integer = 0, Output result) As %Status
11+
{
12+
#dim sc As %Status = $$$OK
13+
14+
try {
15+
set result = ##class(isc.py.Callout).SimpleString(code, variable, serialization)
16+
} catch ex {
17+
set result = ""
18+
#dim ex As %Exception.General
19+
if (ex.Name = "<FUNCTION>") {
20+
set sc = $$$ERROR($$$GeneralError, "Unable to allocate memory")
21+
} else {
22+
set sc = ex.AsStatus()
23+
}
24+
}
25+
26+
set sc = $$$ADDSC(sc, ..GetStatus())
27+
28+
quit sc
29+
}
30+
31+
/// Executes code. If variable is not empty sets variable=code.
32+
/// If variable is undefined
33+
/// code may be a string or a stream
34+
/// write ##class(isc.py.Main).ExcuteCode()
35+
ClassMethod ExcuteCode(code As %Stream.Object, variable As %String = "") As %Status
36+
{
37+
#dim sc As %Status = $$$OK
38+
quit:$d(code)'=1 $$$ERROR($$$GeneralError, "Code argument should be set to stream or to string")
39+
40+
if $isObject(code) {
41+
do code.Rewind()
42+
set codeLength = code.Size
43+
} else {
44+
set codeLength = $l(code)
45+
}
46+
47+
#dim hasVar As %Boolean = $l($g(variable))>0
48+
49+
// length of code + length of var name + 1 char for '='
50+
set length = codeLength + $select(hasVar :$l(variable) + 1, 1:0)
51+
52+
53+
if length>$$$MaxStringLength {
54+
set sc = ##class(isc.py.Callout).StreamInit(length)
55+
quit:$$$ISERR(sc) sc
56+
set sc = ##class(isc.py.Callout).StreamWrite(variable _ "=")
57+
quit:$$$ISERR(sc) sc
58+
59+
if $isObject(code) {
60+
while 'code.AtEnd {
61+
set codePiece = code.Read($$$MaxStringLength)
62+
set sc = ##class(isc.py.Callout).StreamWrite(codePiece)
63+
quit:$$$ISERR(sc)
64+
}
65+
} else {
66+
set sc = ##class(isc.py.Callout).StreamWrite(code)
67+
quit:$$$ISERR(sc)
68+
}
69+
quit:$$$ISERR(sc) sc
70+
set sc = ##class(isc.py.Callout).StreamExecute()
71+
} else {
72+
set tempCode = $select(hasVar : variable _ "=", 1:"")
73+
if $isObject(code) {
74+
set tempCode = tempCode _ code.Read($$$MaxStringLength)
75+
} else {
76+
set tempCode = tempCode _ code
77+
}
78+
79+
do ##class(isc.py.Callout).SimpleString(tempCode)
80+
}
81+
82+
set sc = $$$ADDSC(sc, ..GetStatus())
83+
84+
quit sc
85+
}
86+
87+
/// variable - variable name
88+
/// useString - if variable length is less than $$$MaxStringLength, return string instead of stream. Ignored if variable length is more than $$$MaxStringLength
89+
/// set sc = ##class(isc.py.Main).GetVariable()
90+
ClassMethod GetVariable(variable As %String, serialization As %Integer = 0, ByRef stream As %Stream.Object, useString As %Boolean = {$$$NO}) As %Status
91+
{
92+
#dim sc As %Status = $$$OK
93+
set sc = ..GetVariableInfo(variable, serialization, .defined, .type, .length)
94+
quit:$$$ISERR(sc) sc
95+
quit:'defined $$$ERROR($$$GeneralError, "Variable '" _ variable _ "' is not defined")
96+
97+
if ((length<=$$$MaxStringLength) && useString) {
98+
set stream = ##class(isc.py.Callout).SimpleString(, variable, serialization)
99+
} else {
100+
set:'$isObject($g(stream)) stream = ##class(%Stream.GlobalCharacter).%New()
101+
102+
if (length<=$$$MaxStringLength) {
103+
set zzzvar = ##class(isc.py.Callout).SimpleString(, variable, serialization)
104+
do stream.Write(zzzvar)
105+
} else {
106+
set step = $$$MaxStringLength
107+
for i=0:step:length+1 {
108+
if serialization = ##class(isc.py.Callout).#SerializationRepr {
109+
set zzzvar = ##class(isc.py.Callout).SimpleString("zzzvar=repr(" _ variable _ ")[" _ i _ ":" _ (i + step) _ "]", "zzzvar")
110+
} else {
111+
set zzzvar = ##class(isc.py.Callout).SimpleString("zzzvar=" _ variable _ "[" _ i _ ":" _ (i + step) _ "]", "zzzvar", serialization)
112+
}
113+
do stream.Write(zzzvar)
114+
}
115+
do ##class(isc.py.Callout).SimpleString("del zzzvar")
116+
}
117+
set sc = stream.%Save()
118+
do stream.Rewind()
119+
}
120+
121+
set sc = $$$ADDSC(sc, ..GetStatus())
122+
123+
quit sc
124+
}
125+
126+
/// Get variable metainformation.
127+
/// variable - variable name
128+
/// serialization - serialization type. See isc.py.Callout Serialization* parameters for details
129+
/// defined - is variable defined
130+
/// type - variable type
131+
/// length - length (in symbols) of variable chosen serialization
132+
/// set sc = ##class(isc.py.Main).GetVariableInfo()
133+
ClassMethod GetVariableInfo(variable As %String, serialization As %Integer = 0, Output defined As %Boolean, Output type As %String, Output length As %String) As %Status
134+
{
135+
#dim sc As %Status = $$$OK
136+
kill defined, type, length
137+
138+
set defined = ##class(isc.py.Callout).SimpleString("zzzdef='" _ variable _ "' in vars() or '" _ variable _ "' in globals()", "zzzdef")
139+
set defined = $case(defined, "True":$$$YES, "False":$$$NO, :"")
140+
141+
if defined {
142+
set type = ##class(isc.py.Callout).SimpleString("zzztype=type(" _ variable _ ").__name__", "zzztype")
143+
144+
if serialization = ##class(isc.py.Callout).#SerializationRepr {
145+
set length = ##class(isc.py.Callout).SimpleString("zzzlen=len(repr(" _ variable _ "))", "zzzlen")
146+
} else {
147+
set length = ##class(isc.py.Callout).SimpleString("zzzlen=len(str(" _ variable _ "))", "zzzlen")
148+
}
149+
150+
do ..SimpleString("del zzztype, zzzlen")
151+
}
152+
153+
do ..SimpleString("del zzzdef")
154+
set sc = ..GetStatus()
155+
156+
quit sc
157+
}
158+
159+
/// Returns last occured exception in Python and clears it
160+
/// zwrite ##class(isc.py.Main).GetStatus()
161+
ClassMethod GetStatus() As %Status
162+
{
163+
do ##class(isc.py.Callout).SimpleString("import sys, traceback;")
164+
set haxExc = ##class(isc.py.Callout).SimpleString("zzzerr = hasattr(sys, 'last_type')", "zzzerr")
165+
do ##class(isc.py.Callout).SimpleString("del zzzerr")
166+
quit:haxExc="False" $$$OK
167+
168+
set excText = ##class(isc.py.Callout).SimpleString("zzzerr = traceback.format_exception(sys.last_type, sys.last_value, sys.last_traceback)", "zzzerr")
169+
set excText = $zcvt($zcvt(excText, "I", "UTF8"), "I", "JSON")
170+
do ##class(isc.py.Callout).SimpleString("del zzzerr, sys.last_type, sys.last_value, sys.last_traceback")
171+
172+
quit $$$ERROR($$$GeneralError, excText)
173+
}
174+
175+
/// Returns last occured exception in Python and clears it
176+
/// zwrite ##class(isc.py.Main).GetVariableJson()
177+
ClassMethod GetVariableJson(variable As %String, ByRef stream As %Stream.Object, useString As %Boolean = {$$$NO}) As %Status
178+
{
179+
set sc = ..GetVariableInfo(variable, ##class(isc.py.Callout).#SerializationStr, .defined, .type, .length)
180+
quit:$$$ISERR(sc) sc
181+
quit:'defined $$$ERROR($$$GeneralError, "Variable '" _ variable _ "' is not defined")
182+
183+
do ##class(isc.py.Callout).SimpleString("import json;")
184+
do ##class(isc.py.Callout).SimpleString("def zzzempty(obj):" _ $c(10) _ " return ''")
185+
186+
if type = "DataFrame" {
187+
set sc = ..ExcuteCode(variable _ ".to_json()", "zzzjson")
188+
/*} elseif type="DatetimeIndex" { TODO*/
189+
} else {
190+
set sc = ..ExcuteCode("json.dumps(" _variable _ ", default=zzzempty)", "zzzjson")
191+
}
192+
if $$$ISOK(sc) {
193+
set sc = ##class(isc.py.Main).GetVariable("zzzjson", ##class(isc.py.Callout).#SerializationStr, .stream, useString)
194+
do ..SimpleString("del zzzjson")
195+
196+
if $$$ISOK(sc) {
197+
if $isObject(stream) {
198+
if (stream.Size=2) {
199+
set content = stream.Read()
200+
do:content="""""" stream.Clear()
201+
do stream.%Save()
202+
do stream.Rewind()
203+
}
204+
} else {
205+
set:stream="""""" stream = ""
206+
}
207+
}
208+
}
209+
quit sc
210+
}
211+
212+
/// Get Variable Pickle form
213+
/// zwrite ##class(isc.py.Main).GetVariableJson()
214+
ClassMethod GetVariablePickle(variable As %String, ByRef stream As %Stream.Object, useString As %Boolean = {$$$NO}) As %Status
215+
{
216+
set sc = ..GetVariableInfo(variable, ##class(isc.py.Callout).#SerializationStr, .defined, .type, .length)
217+
quit:$$$ISERR(sc) sc
218+
quit:'defined $$$ERROR($$$GeneralError, "Variable '" _ variable _ "' is not defined")
219+
220+
do ##class(isc.py.Callout).SimpleString("import pickle;")
221+
222+
set sc = ##class(isc.py.Main).ExcuteCode("pickle.dumps(" _ variable _ ")", "zzzpickle")
223+
if $$$ISERR(sc) {
224+
// can't pickle xyz objects
225+
if $system.Status.GetErrorText(sc) [ "can't pickle" {
226+
if useString {
227+
set stream = ""
228+
} else {
229+
if $isObject($g(stream)) {
230+
do stream.Clear()
231+
do stream.%Save()
232+
do stream.Rewind()
233+
} else {
234+
set stream = ##class(%Stream.GlobalCharacter).%New()
235+
}
236+
}
237+
set sc = $$$OK
238+
}
239+
} else {
240+
set sc = ##class(isc.py.Main).GetVariable("zzzpickle", ##class(isc.py.Callout).#SerializationStr, .stream, useString)
241+
do ##class(isc.py.Callout).SimpleString("del zzzpickle")
242+
}
243+
244+
quit sc
245+
}
246+
247+
}
248+

0 commit comments

Comments
 (0)