Skip to content

Commit 737d2a2

Browse files
committed
Add Python settings management to IOP classes and update component registration
1 parent b0fe535 commit 737d2a2

File tree

4 files changed

+167
-11
lines changed

4 files changed

+167
-11
lines changed

src/iop/_utils.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import os
22
import sys
3-
import ast
4-
import inspect
53
import importlib
64
import importlib.util
75
import importlib.resources
86
import json
9-
from typing import Any, Dict, Optional, Union
7+
import inspect
8+
import ast
9+
from typing import Any, Dict, Optional, Union, Tuple
1010

1111
import xmltodict
1212
from pydantic import TypeAdapter
@@ -80,6 +80,28 @@ def register_schema(schema_name:str, schema_str:str,categories:str):
8080
"""
8181
_Utils.raise_on_error(_iris.get_iris().cls('IOP.Message.JSONSchema').Import(schema_str,categories,schema_name))
8282

83+
@staticmethod
84+
def get_python_settings() -> Tuple[str,str,str]:
85+
import iris_utils._cli
86+
87+
pythonlib = iris_utils._cli.find_libpython()
88+
pythonpath = _Utils._get_python_path()
89+
pythonversion = sys.version[:4]
90+
91+
return pythonlib, pythonpath, pythonversion
92+
93+
@staticmethod
94+
def _get_python_path() -> str:
95+
96+
if "VIRTUAL_ENV" in os.environ:
97+
return os.path.join(
98+
os.environ["VIRTUAL_ENV"],
99+
"lib",
100+
f"python{sys.version[:4]}",
101+
"site-packages"
102+
)
103+
return ""
104+
83105
@staticmethod
84106
def register_component(module:str,classname:str,path:str,overwrite:int=1,iris_classname:str='Python'):
85107
"""
@@ -99,8 +121,9 @@ def register_component(module:str,classname:str,path:str,overwrite:int=1,iris_cl
99121
"""
100122
path = os.path.abspath(os.path.normpath(path))
101123
fullpath = _Utils.guess_path(module,path)
124+
pythonlib, pythonpath, pythonversion = _Utils.get_python_settings()
102125
try:
103-
_iris.get_iris().cls('IOP.Utils').dispatchRegisterComponent(module,classname,path,fullpath,overwrite,iris_classname)
126+
_iris.get_iris().cls('IOP.Utils').dispatchRegisterComponent(module,classname,path,fullpath,overwrite,iris_classname,pythonlib,pythonpath,pythonversion)
104127
except RuntimeError as e:
105128
# New message error : Make sure the iop package is installed in iris
106129
raise RuntimeError("Iris class : IOP.Utils not found. Make sure the iop package is installed in iris eg: iop --init.") from e

src/iop/cls/IOP/BusinessProcess.cls

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ Storage Default
131131
<Value name="10">
132132
<Value>%traceback</Value>
133133
</Value>
134+
<Value name="11">
135+
<Value>%PythonPath</Value>
136+
</Value>
137+
<Value name="12">
138+
<Value>%PythonRuntimeLibrary</Value>
139+
</Value>
140+
<Value name="13">
141+
<Value>%PythonRuntimeLibraryVersion</Value>
142+
</Value>
134143
</Data>
135144
<Data name="persistentProperties">
136145
<Attribute>persistentProperties</Attribute>

src/iop/cls/IOP/Common.cls

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ Property %PythonInterpreterPath As %String(MAXLEN = 255);
2929

3030
Property %traceback As %Boolean [ InitialExpression = 1 ];
3131

32+
Property %PythonPath As %String(MAXLEN = 255);
33+
34+
Property %PythonRuntimeLibrary As %String(MAXLEN = 255);
35+
36+
Property %PythonRuntimeLibraryVersion As %String;
37+
3238
/// Get Class
3339
Method GetClass() As %SYS.Python
3440
{
@@ -79,9 +85,18 @@ Method OnInit() As %Status
7985
{
8086
set tSC = $$$OK
8187
try {
88+
LOCK +^PythonSettings:5
89+
do ..SetPythonSettings(..%PythonRuntimeLibrary, ..%PythonPath, ..%PythonRuntimeLibraryVersion)
90+
91+
do ..DisplayPythonVersion()
92+
8293
do $system.Python.Debugging(..%traceback)
94+
8395
$$$ThrowOnError(..Connect())
96+
LOCK -^PythonSettings
97+
8498
do ..%class."_debugpy"($this)
99+
85100
do ..%class."_dispatch_on_init"($this)
86101
} catch ex {
87102

@@ -90,6 +105,52 @@ Method OnInit() As %Status
90105
quit tSC
91106
}
92107

108+
ClassMethod SetPythonSettings(
109+
pPythonLib,
110+
pPythonPath,
111+
pPythonVersion)
112+
{
113+
set currentNS = $namespace
114+
set $NAMESPACE = "%SYS"
115+
try {
116+
// Get Config
117+
$$$ThrowOnError(##Class(Config.config).Get(.Properties))
118+
// Set the Python interpreter path
119+
if ..%PythonInterpreterPath'="" {
120+
set Properties("PythonPath") = pPythonPath
121+
}
122+
123+
// Set the Python runtime library
124+
if ..%PythonRuntimeLibrary'="" {
125+
set Properties("PythonRuntimeLibrary") = pPythonLib
126+
}
127+
128+
// Set the Python runtime library version
129+
if ..%PythonRuntimeLibraryVersion'="" {
130+
set Properties("PythonRuntimeLibraryVersion") = pPythonVersion
131+
}
132+
$$$ThrowOnError(##Class(Config.config).Modify(.Properties))
133+
} catch ex {
134+
135+
}
136+
set $NAMESPACE = currentNS
137+
}
138+
139+
Method DisplayPythonVersion()
140+
{
141+
set sys = ##class(%SYS.Python).Import("sys")
142+
set version = sys.version
143+
set versionInfo = sys."version_info"
144+
set major = versionInfo.major
145+
set minor = versionInfo.minor
146+
set micro = versionInfo.micro
147+
set releaseLevel = versionInfo.releaselevel
148+
set serial = versionInfo.serial
149+
150+
$$$LOGINFO("Python Version: "_ version)
151+
$$$LOGINFO("Version Info: "_ major_ "."_ minor_ "."_ micro_" ("_ releaseLevel_ ", "_serial_ ")")
152+
}
153+
93154
ClassMethod SetPythonPath(pClasspaths)
94155
{
95156
set sys = ##class(%SYS.Python).Import("sys")

src/iop/cls/IOP/Utils.cls

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,44 @@ ClassMethod dispatchRegisterComponent(
1313
pCLASSPATHS As %String = "",
1414
pFullpath As %String = "",
1515
pOverwrite As %Boolean = 0,
16-
pProxyClassname As %String = "") As %Status
16+
pProxyClassname As %String = "",
17+
pPythonLib,
18+
pPythonPath,
19+
pPythonVersion) As %Status
1720
{
1821
set tSc = $$$OK
19-
$$$ThrowOnError(##class(IOP.Utils).RegisterComponent(pModule, pRemoteClassname, pCLASSPATHS, pFullpath, pOverwrite , pProxyClassname))
22+
$$$ThrowOnError(##class(IOP.Utils).RegisterComponent(pModule, pRemoteClassname, pCLASSPATHS, pFullpath, pOverwrite , pProxyClassname,pPythonLib, pPythonPath, pPythonVersion))
2023
return tSc
2124
}
2225

26+
ClassMethod SetPythonSettings(
27+
pPythonLib As %String = "",
28+
pPythonPath As %String = "",
29+
pPythonVersion As %String = "") As %Status
30+
{
31+
#dim tSC As %Status = $$$OK
32+
#dim ex As %Exception.AbstractException
33+
34+
Try {
35+
Do ##class(IOP.Common).SetPythonSettings(pPythonLib, pPythonPath, pPythonVersion)
36+
} Catch ex {
37+
Set tSC = ex.AsStatus()
38+
}
39+
40+
Quit tSC
41+
}
42+
2343
/// "bo","Duplex","/irisdev/app/src/python/demo/duplex/",1,"Duplex.Duplex"
2444
ClassMethod RegisterComponent(
2545
pModule As %String,
2646
pRemoteClassname As %String,
2747
pCLASSPATHS As %String = "",
2848
pFullpath As %String = "",
2949
pOverwrite As %Boolean = 0,
30-
pProxyClassname As %String = "") As %Status
50+
pProxyClassname As %String = "",
51+
pPythonLib,
52+
pPythonPath,
53+
pPythonVersion) As %Status
3154
{
3255
#dim tSC As %Status = $$$OK
3356
#dim ex As %Exception.AbstractException
@@ -39,6 +62,9 @@ ClassMethod RegisterComponent(
3962
Quit:(""=pModule) $$$ERROR($$$EnsErrGeneral,"Must specify the module of the remote code.")
4063

4164
Try {
65+
LOCK +^PythonSettings:10
66+
// Set the Python settings
67+
$$$ThrowOnError(##class(IOP.Utils).SetPythonSettings(pPythonLib, pPythonPath, pPythonVersion))
4268

4369
$$$ThrowOnError(..GetRemoteClassInfo(pRemoteClassname,pModule,pCLASSPATHS,pFullpath,.tClassDetails,.tRemoteSettings))
4470

@@ -47,13 +73,13 @@ ClassMethod RegisterComponent(
4773
Set tConnectionSettings("Classname") = pRemoteClassname
4874
Set:(""=pProxyClassname) pProxyClassname = "User."_pRemoteClassname
4975

50-
$$$ThrowOnError(..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite))
76+
$$$ThrowOnError(..GenerateProxyClass(pProxyClassname,.tConnectionSettings,tClassDetails,tRemoteSettings,pOverwrite, pPythonLib, pPythonPath, pPythonVersion))
5177

5278
} Catch ex {
5379
set msg = $System.Status.GetOneStatusText(ex.AsStatus(),1)
5480
set tSC = $$$ERROR($$$EnsErrGeneral,msg)
5581
}
56-
82+
LOCK -PythonSettings
5783
Quit tSC
5884
}
5985

@@ -165,7 +191,10 @@ ClassMethod GenerateProxyClass(
165191
ByRef pConnectionSettings,
166192
pClassDetails As %String = "",
167193
pRemoteSettings As %String = "",
168-
pOverwrite As %Boolean = 0) As %Status [ Internal, Private ]
194+
pOverwrite As %Boolean = 0,
195+
pPythonLib,
196+
pPythonPath,
197+
pPythonVersion) As %Status [ Internal, Private ]
169198
{
170199
#dim tSC As %Status = $$$OK
171200
#dim ex As %Exception.AbstractException
@@ -226,7 +255,9 @@ ClassMethod GenerateProxyClass(
226255
}
227256

228257
#; 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,%enable:Python Debug $type,%timeout:Python Debug $type,%port:Python Debug $type,%PythonInterpreterPath:Python Debug $type,%traceback:Python Debug $type"
258+
#dim tSETTINGSParamValue As %String = "%classname:Python $type,%module:Python $type,%settings:Python $type,%classpaths:Python $type"
259+
set tSETTINGSParamValue = tSETTINGSParamValue_","_"%enable:Python Debug $type,%timeout:Python Debug $type,%port:Python Debug $type,%PythonInterpreterPath:Python Debug $type,%traceback:Python Debug $type"
260+
set tSETTINGSParamValue = tSETTINGSParamValue_","_"%PythonPath:Python Settings $type,%PythonRuntimeLibrary:Python Settings $type,%PythonRuntimeLibraryVersion:Python Settings $type"
230261

231262
#dim tPropClassname As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
232263
Set tPropClassname.Name = "%classname"
@@ -255,6 +286,38 @@ ClassMethod GenerateProxyClass(
255286
Set tPropLanguage.InitialExpression = $$$quote(pConnectionSettings("Module"))
256287
Set tSC = tCOSClass.Properties.Insert(tPropLanguage)
257288
Quit:$$$ISERR(tSC)
289+
290+
if pPythonLib'="" {
291+
#dim tPropPythonLib As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
292+
Set tPropPythonLib.Name = "%PythonRuntimeLibrary"
293+
Set tPropPythonLib.Type = "%String"
294+
Set tPropPythonLib.Internal = 1
295+
Set tSC = tPropPythonLib.Parameters.SetAt("","MAXLEN")
296+
Quit:$$$ISERR(tSC)
297+
Set tPropPythonLib.InitialExpression = $$$quote(pPythonLib)
298+
Set tSC = tCOSClass.Properties.Insert(tPropPythonLib)
299+
Quit:$$$ISERR(tSC)
300+
}
301+
if pPythonPath'="" {
302+
#dim tPropPythonPath As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
303+
Set tPropPythonPath.Name = "%PythonPath"
304+
Set tPropPythonPath.Type = "%String"
305+
Set tSC = tPropPythonPath.Parameters.SetAt("","MAXLEN")
306+
Quit:$$$ISERR(tSC)
307+
Set tPropPythonPath.Internal = 1
308+
Set tPropPythonPath.InitialExpression = $$$quote(pPythonPath)
309+
Set tSC = tCOSClass.Properties.Insert(tPropPythonPath)
310+
Quit:$$$ISERR(tSC)
311+
}
312+
if pPythonVersion'="" {
313+
#dim tPropPythonVersion As %Dictionary.PropertyDefinition = ##class(%Dictionary.PropertyDefinition).%New()
314+
Set tPropPythonVersion.Name = "%PythonRuntimeLibraryVersion"
315+
Set tPropPythonVersion.Type = "%String"
316+
Set tPropPythonVersion.Internal = 1
317+
Set tPropPythonVersion.InitialExpression = $$$quote(pPythonVersion)
318+
Set tSC = tCOSClass.Properties.Insert(tPropPythonVersion)
319+
Quit:$$$ISERR(tSC)
320+
}
258321

259322
If $Case(tSuperClass,"IOP.BusinessService":1,"IOP.BusinessOperation":1,"IOP.DuplexService":1,"IOP.DuplexOperation":1,:0) {
260323
set builtins = ##class(%SYS.Python).Import("builtins")

0 commit comments

Comments
 (0)