Skip to content

Commit b19124c

Browse files
committed
More added features to git integration branch
1 parent b86c5a0 commit b19124c

File tree

2 files changed

+85
-21
lines changed

2 files changed

+85
-21
lines changed

src/sasctl/pzmm/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
from .zipModel import ZipModel
77
from .writeScoreCode import ScoreCode
88
from .importModel import ImportModel
9+
from .gitIntegration import GitIntegrate

src/sasctl/pzmm/gitIntegration.py

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import Path
66
from uuid import UUID
77
from warnings import warn
8-
import shutil
8+
import zipfile
99
from git import Repo
1010
import io
1111

@@ -36,16 +36,25 @@ def getZippedModel(model, gPath, project=None):
3636
projectName = project.name
3737
else:
3838
projectName = mr.get_project(project).name
39-
# Attempt to put model in project folder
40-
try:
41-
with open(Path(gPath) / (projectName + '/' + modelName + '.zip'), 'wb') as zFile:
42-
zFile.write(modelZip)
43-
# If the folder doesn't exist, create it and then put model into the project folder
44-
except FileNotFoundError:
45-
newDir = Path(projectName + '/')
39+
# Check to see if project folder exists
40+
if (Path(gPath) / projectName).exists():
41+
#Check to see if model folder exists
42+
if (Path(gPath) / projectName / modelName).exists():
43+
with open(Path(gPath) / projectName / modelName / (modelName + '.zip'), 'wb') as zFile:
44+
zFile.write(modelZip)
45+
else:
46+
newDir = Path(gPath) / projectName / modelName
47+
newDir.mkdir(parents=True, exist_ok=True)
48+
with open(Path(gPath) / projectName / modelName / (modelName + '.zip'), 'wb') as zFile:
49+
zFile.write(modelZip)
50+
else:
51+
newDir = Path(gPath) / projectName
52+
newDir.mkdir(parents=True, exist_ok=True)
53+
newDir = Path(gPath) / projectName / modelName
4654
newDir.mkdir(parents=True, exist_ok=True)
4755
with open(Path(gPath) / (projectName + '/' + modelName + '.zip'), 'wb') as zFile:
4856
zFile.write(modelZip)
57+
4958
return modelName, projectName
5059

5160
def project_exists(response, project):
@@ -84,7 +93,51 @@ def project_exists(response, project):
8493
return response
8594
else:
8695
return response
96+
97+
def model_exists(project, name, force):
98+
"""Checks if model already exists and either raises an error or deletes the redundant model.
8799
100+
Parameters
101+
----------
102+
project : string or dict
103+
The name or id of the model project, or a dictionary representation of the project.
104+
name : str or dict
105+
The name of the model.
106+
force : bool, optional
107+
Sets whether to overwrite models with the same name upon upload.
108+
109+
Raises
110+
------
111+
ValueError
112+
Model repository API cannot overwrite an already existing model with the upload model call.
113+
Alerts user of the force argument to allow multi-call API overwriting.
114+
"""
115+
project = mr.get_project(project)
116+
projectId = project["id"]
117+
projectModels = mr.get("/projects/{}/models".format(projectId))
118+
119+
for model in projectModels:
120+
# Throws a TypeError if only one model is in the project
121+
try:
122+
if model["name"] == name:
123+
if force:
124+
mr.delete_model(model.id)
125+
else:
126+
raise ValueError(
127+
"A model with the same model name exists in project {}. Include the force=True argument to overwrite models with the same name.".format(
128+
project.name
129+
)
130+
)
131+
except TypeError:
132+
if projectModels["name"] == name:
133+
if force:
134+
mr.delete_model(projectModels.id)
135+
else:
136+
raise ValueError(
137+
"A model with the same model name exists in project {}. Include the force=True argument to overwrite models with the same name.".format(
138+
project.name
139+
)
140+
)
88141
class GitIntegrate:
89142
@classmethod
90143
def pullViyaModel(
@@ -121,7 +174,7 @@ def pullViyaModel(
121174
else:
122175
UUID(model)
123176
projectName = mr.get_model(model).projectName
124-
modelName = getZippedModel(model, projectName, gPath)
177+
modelName, projectName = getZippedModel(model, gPath, projectName)
125178
# If a name is provided instead, use the provided project name or UUID to find the correct model
126179
except ValueError:
127180
projectResponse = mr.get_project(project)
@@ -137,15 +190,16 @@ def pullViyaModel(
137190
try:
138191
if model["name"] == model:
139192
modelId = model.id
140-
modelName = getZippedModel(modelId, projectName, gPath)
193+
modelName, projectName = getZippedModel(modelId, gPath, projectName)
141194
except TypeError:
142195
if projectModels["name"] == model:
143196
modelId = projectModels.id
144-
modelName = getZippedModel(modelId, projectName, gPath)
197+
modelName, projectName = getZippedModel(modelId, gPath, projectName)
145198

146199
# Unpack the pulled down zip model and overwrite any duplicate files
147200
mPath = Path(gPath) / '{projectName}/{modelName}'.format(projectName=projectName, modelName=modelName)
148-
shutil.unpack_archive(filename=(modelName + '.zip'), extract_dir=mPath)
201+
with zipfile.ZipFile(str(mPath / (modelName + '.zip')), mode='r') as zFile:
202+
zFile.extractall(str(mPath))
149203

150204
# Delete the zip model objects in the directory to minimize confusion when uploading back to SAS Model Manager
151205
for zipFile in mPath.glob('*.zip'):
@@ -159,21 +213,29 @@ def pushGitModel(cls, gPath, modelName=None, projectName=None):
159213
Parameters
160214
----------
161215
gPath : string or Path
162-
Base directory of the git repository.
216+
Base directory of the git repository or path which includes project and model directories.
163217
modelName : string, optional
164218
Name of model to be imported, by default None
165219
projectName : string, optional
166220
Name of project the model is imported from, by default None
167221
'''
168222
if modelName is None and projectName is None:
169223
modelDir = gPath
224+
modelName = modelDir.name
225+
projectName = modelDir.parent.name
170226
else:
171227
modelDir = Path(gPath) / (projectName + '/' + modelName)
172228
for zipFile in modelDir.glob('*.zip'):
173229
zipFile.unlink()
174-
shutil.make_archive(modelName, 'zip', modelDir)
175-
with open(modelDir / (modelName + '.zip'), 'rb') as zFile:
230+
fileNames = []
231+
fileNames.extend(sorted(Path(modelDir).glob('*')))
232+
with zipfile.ZipFile(str(modelDir / (modelDir.name + '.zip')), mode='w') as zFile:
233+
for file in fileNames:
234+
zFile.write(str(file), arcname=file.name)
235+
with open(modelDir / (modelDir.name + '.zip'), 'rb') as zFile:
176236
zipIOFile = io.BytesIO(zFile.read())
237+
# Check if model with same name already exists in project. Delete if it exists.
238+
model_exists(projectName, modelName, True)
177239
mr.import_model_from_zip(modelName, projectName, zipIOFile)
178240

179241
@classmethod
@@ -191,7 +253,7 @@ def gitRepoPush(cls, gPath, commitMessage, branch='origin'):
191253
Branch name for the remote repository, by default 'origin'
192254
'''
193255
repo = Repo(gPath)
194-
repo.git.add(update=True)
256+
repo.git.add(all=True)
195257
repo.index.commit(commitMessage)
196258
pushBranch = repo.remote(name=branch)
197259
pushBranch.push()
@@ -236,7 +298,7 @@ def pullGitProject(cls, gPath, project=None):
236298
models = [x for x in pPath.glob('*') if x.is_dir()]
237299
if len(models) == 0:
238300
print('No models were found in project {}.'.format(projectName))
239-
print('{numModels} were found in project {projectName}.'.format(numModels=len(models), projectName=projectName))
301+
print('{numModels} models were found in project {projectName}.'.format(numModels=len(models), projectName=projectName))
240302
else:
241303
raise FileNotFoundError('No directory with the name {} was found in the specified git path.'.format(project))
242304

@@ -275,10 +337,11 @@ def pullMMProject(cls, gPath, project):
275337
if modelResponse == []:
276338
raise FileNotFoundError('No models were found in the specified project. A new project folder ' +
277339
'has been created if it did not already exist within the git repository.')
278-
modelNames, modelId = []*2
279-
for i, model in enumerate(modelResponse):
280-
modelNames[i] = model.name
281-
modelId[i] = model.id
340+
modelNames = []
341+
modelId = []
342+
for model in modelResponse:
343+
modelNames.append(model.name)
344+
modelId.append(model.id)
282345

283346
# For each model, search for an appropriate model directory in the project directory and pull down the model
284347
for name, id in zip(modelNames, modelId):

0 commit comments

Comments
 (0)