From 7298b2c2d60e1d0a3a9cfca346a26d943ab6e868 Mon Sep 17 00:00:00 2001 From: djm21 Date: Mon, 28 Apr 2025 11:46:42 -0700 Subject: [PATCH 1/3] feat: upload local model without any extra file generation (PMMODEL-682) --- src/sasctl/tasks.py | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/sasctl/tasks.py b/src/sasctl/tasks.py index d466c10f..b08fb570 100644 --- a/src/sasctl/tasks.py +++ b/src/sasctl/tasks.py @@ -15,6 +15,7 @@ from pathlib import Path from typing import Union from warnings import warn +import zipfile import pandas as pd @@ -998,3 +999,55 @@ def score_model_with_cas( print(score_execution_poll) score_results = se.get_score_execution_results(score_execution, use_cas_gateway) return score_results + +def upload_local_model( + path: Union[str, Path], + model_name: str, + project_name: str, + repo_name: Union[str, dict] = None, + version: str = "latest", + ): + """A barebones function to upload a model and any associated files to the model repository. + Parameters + ---------- + path : Union[str, Path] + The path to the model and any associated files. + model_name : str + The name of the model. + project_name : str + The name of the project to which the model will be uploaded. + """ + # Use default repository if not specified + try: + if repo_name is None: + repository = mr.default_repository() + else: + repository = mr.get_repository(repo_name) + except HTTPError as e: + if e.code == 403: + raise AuthorizationError( + "Unable to register model. User account does not have read permissions " + "for the /modelRepository/repositories/ URL. Please contact your SAS " + "Viya administrator." + ) + raise e + + # Unable to find or create the repo. + if repository is None and repo_name is None: + raise ValueError("Unable to find a default repository") + + if repository is None: + raise ValueError("Unable to find repository '{}'".format(repository)) + p = mr.get_project(project_name) + if p is None: + mr.create_project(project_name, repository) + zip_name = str(Path(path) / (model_name + ".zip")) + file_names = sorted(Path(path).glob("*[!zip]")) + with zipfile.ZipFile( + str(zip_name), mode="w" + ) as zFile: + for file in file_names: + zFile.write(str(file), arcname=file.name) + with open(zip_name, "rb") as zip_file: + model = mr.import_model_from_zip(model_name, project_name, zip_file, version=version) + return model From b3c2912e51bf18376bda9e32b98e56e421de4ad9 Mon Sep 17 00:00:00 2001 From: djm21 Date: Mon, 28 Apr 2025 12:17:18 -0700 Subject: [PATCH 2/3] black reformatting --- src/sasctl/tasks.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/sasctl/tasks.py b/src/sasctl/tasks.py index b08fb570..44c7b430 100644 --- a/src/sasctl/tasks.py +++ b/src/sasctl/tasks.py @@ -1000,13 +1000,14 @@ def score_model_with_cas( score_results = se.get_score_execution_results(score_execution, use_cas_gateway) return score_results + def upload_local_model( - path: Union[str, Path], - model_name: str, - project_name: str, - repo_name: Union[str, dict] = None, - version: str = "latest", - ): + path: Union[str, Path], + model_name: str, + project_name: str, + repo_name: Union[str, dict] = None, + version: str = "latest", +): """A barebones function to upload a model and any associated files to the model repository. Parameters ---------- @@ -1043,11 +1044,11 @@ def upload_local_model( mr.create_project(project_name, repository) zip_name = str(Path(path) / (model_name + ".zip")) file_names = sorted(Path(path).glob("*[!zip]")) - with zipfile.ZipFile( - str(zip_name), mode="w" - ) as zFile: - for file in file_names: - zFile.write(str(file), arcname=file.name) + with zipfile.ZipFile(str(zip_name), mode="w") as zFile: + for file in file_names: + zFile.write(str(file), arcname=file.name) with open(zip_name, "rb") as zip_file: - model = mr.import_model_from_zip(model_name, project_name, zip_file, version=version) + model = mr.import_model_from_zip( + model_name, project_name, zip_file, version=version + ) return model From 6ac153b3c9638087072e586bc74702d9da3e3b1f Mon Sep 17 00:00:00 2001 From: djm21 Date: Tue, 29 Apr 2025 08:33:03 -0700 Subject: [PATCH 3/3] updates to error handling for repository finding --- src/sasctl/tasks.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sasctl/tasks.py b/src/sasctl/tasks.py index 44c7b430..dfa07e64 100644 --- a/src/sasctl/tasks.py +++ b/src/sasctl/tasks.py @@ -1034,11 +1034,10 @@ def upload_local_model( raise e # Unable to find or create the repo. - if repository is None and repo_name is None: + if not repository and not repo_name: raise ValueError("Unable to find a default repository") - - if repository is None: - raise ValueError("Unable to find repository '{}'".format(repository)) + elif not repository: + raise ValueError(f"Unable to find repository '{repo_name}'") p = mr.get_project(project_name) if p is None: mr.create_project(project_name, repository)