8000 Added model migration util to convert Viya 3.5 models to Viya 4 · Christian06810/python-sasctl@f52bbe7 · GitHub
[go: up one dir, main page]

Skip to content

Commit f52bbe7

Browse files
committed
Added model migration util to convert Viya 3.5 models to Viya 4
1 parent 755da3f commit f52bbe7

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

src/sasctl/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
# SPDX-License-Identifier: Apache-2.0
66

77
from .astore import create_package, create_package_from_astore
8+
from .modelMigration import convertModelZip

src/sasctl/utils/modelMigration.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#!/usr/bin/env python
2+
# encoding: utf-8
3+
#
4+
# Copyright © 2022, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
import re
8+
import json
9+
import pandas as pd
10+
11+
from pathlib import Path
12+
13+
def convertMetadata(zPath, pythonScoreCode=None):
14+
'''Modify the model metadata to match new requirements in SAS Viya 4. The
15+
scoreCodeType in the ModelProperties.json file should be labelled as 'Python'.
16+
The file associated with the 'score' role should be a Python file.
17+
18+
Parameters
19+
----------
20+
zPath : string or Path object
21+
Location of files in the SAS Viya 3.5 model zip.
22+
pythonScoreCode : string, optional
23+
File name of the Python score code. If None, then the name is
24+
determined by the files in the model zip. Default value is None.
25+
26+
Returns
27+
-------
28+
scoreResource : string
29+
File name of the score resource file.
30+
pythonScoreCode : string
31+
File name of the Python score code file.
32+
33+
Raises
34+
------
35+
SyntaxError :
36+
If no pythonScoreCode name is provided, but there are multiple Python
37+
files in the zPath, then a SyntaxError is raised asking for further
38+
clarification as to which file is the Python score code.
39+
'''
40+
# Replace the value of scoreCodeType to 'Python' in ModelProperties.json
41+
with open(Path(zPath) / "ModelProperties.json", "r") as jFile:
42+
modelProperties = json.loads(jFile.read())
43+
44+
modelProperties.update({"scoreCodeType": "Python"})
45+
propIndex = list(modelProperties.keys())
46+
propValues = list(modelProperties.values())
47+
outputJSON = pd.Series(propValues, index=propIndex)
48+
49+
with open(Path(zPath) / "ModelProperties.json", "w") as jFile:
50+
dfDump = pd.Series.to_dict(outputJSON.transpose())
51+
json.dump(dfDump, jFile, indent=4, skipkeys=True)
52+
print("ModelProperties.json has been modified and rewritten for SAS Viya 4")
53+
54+
# Replace the 'score' role file with Python score code file
55+
with open(Path(zPath) / "fileMetaData.json", "r") as jFile:
56+
metaData = json.loads(jFile.read())
57+
if pythonScoreCode is None:
58+
numPyFiles = 0
59+
for file in zPath.glob('*.py'):
60+
pythonScoreCode = file.name
61+
numPyFiles = numPyFiles + 1
62+
if numPyFiles > 1:
63+
message = ("More than one Python file was found, therefore the score code" +
64+
" the score code could not be determined. Please provide the" +
65+
" name of the Python score code file as an argument.")
66+
raise SyntaxError(message)
67+
for i in range(len(metaData)):
68+
if metaData[i]["role"] == "score":
69+
metaData[i].update({"name" : pythonScoreCode})
70+
if metaData[i]["role"] == "scoreResource":
71+
scoreResource = metaData[i]["name"]
72+
with open(Path(zPath) / "fileMetaData.json", "w") as jFile:
73+
json.dump(metaData, jFile, indent=4, skipkeys=True)
74+
print("fileMetaData.json has been modified and rewritten for SAS Viya 4")
75+
76+
return scoreResource, pythonScoreCode
77+
78+
def convertScoreCode(zPath, scoreResource, pythonScoreCode):
79+
'''Convert the Python score code used in SAS Viya 3.5 into score code usable in
80+
SAS Viya 4. The two adjustments are including an 'import settings' statement and
81+
replacing score resource access calls that reference an explicit path with
82+
'settings.pickle_path' + <scoreResource>.
83+
84+
Parameters
85+
----------
86+
zPath : string or Path object
87+
Location of files in the SAS Viya 3.5 model zip.
88+
scoreResource : string
89+
File name of the score resource file.
90+
pythonScoreCode : string
91+
File name of the Python score code file.
92+
'''
93+
# Read entire text of score code
94+
with open(Path(zPath) / pythonScoreCode, "r") as pyFile:
95+
scoreCode = pyFile.read()
96+
97+
# Add the import settings line to the score code
98+
scoreCode = "import settings\n" + scoreCode
99+
100+
# Search for all directory paths in score code that contain the scoreResource
101+
oldString = re.findall(r"'\/.*?\.[\w:]+'", scoreCode)
102+
oldString = [s for s in oldString if scoreResource in s]
103+
# Remove duplicates, as .replace() checks for all instances
104+
oldString = list(set(oldString))
105+
# Replace Viya 3.5 style with Viya 4 style
106+
newString = "settings.pickle_path + '{}'".format(scoreResource)
107+
for oldStr in oldString:
108+
scoreCode = scoreCode.replace(oldStr, newString)
109+
110+
# Write new text of score code to file
111+
with open(Path(zPath) / pythonScoreCode, "w") as pyFile:
112+
pyFile.write(scoreCode)
113+
print("{} has been modified and rewritten for SAS Viya 4".format(pythonScoreCode))
114+
115+
def deleteSASFiles(zPath):
116+
'''Remove .sas score files created for SAS Viya 3.5, which are no longer
117+
needed in SAS Viya 4. These files are typically named score.sas,
118+
dmcas_packagescorecode.sas, or dmcas_epscorescode.sas.
119+
120+
Parameters
121+
----------
122+
zPath : string or Path object
123+
Location of files in the SAS Viya 3.5 model zip.
124+
'''
125+
zPath = Path(zPath)
126+
for file in zPath.glob('*.sas'):
127+
file.unlink()
128+
129+
def convertModelZip(zPath, pythonScoreCode=None):
130+
'''Pass the directory path of the model to be converted from SAS Viya 3.5 to
131+
SAS Viya 4. Then the function removes any .sas files, adjusts the ModelProperties.json
132+
and fileMetaData.json files, and modifies the score code.
133+
134+
Parameters
135+
----------
136+
zPath : string or Path object
137+
Location of files in the SAS Viya 3.5 model zip.
138+
pythonScoreCode : string, optional
139+
File name of the Python score code. If None, then the name is
140+
determined by the files in the model zip. Default value is None.
141+
'''
142+
deleteSASFiles(zPath)
143+
scoreResource, pythonScoreCode = convertMetadata(zPath, pythonScoreCode=None)
144+
convertScoreCode(zPath, scoreResource, pythonScoreCode)
145+

0 commit comments

Comments
 (0)
0