Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/build-test-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
LANG: en_US.UTF-8
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
os-version: ['ubuntu-latest', 'windows-latest', 'macos-latest']
# os-version: [ubuntu-latest, windows-latest, macos-latest]

Expand All @@ -40,11 +40,15 @@ jobs:
sudo apt-get update
sudo apt-get install build-essential libkrb5-dev

- name: Install dependencies (macOS)
if: startsWith(matrix.os-version, 'macos')
run: brew install libomp

- name: Install dependencies (Common)
run: |
# Setup tox & code coverage
pip install --upgrade pip
pip install tox tox-gh-actions pytest pytest-cov 'scikit-learn<=1.5.0' 'numpy<2.0.0'
pip install tox tox-gh-actions pytest pytest-cov 'scikit-learn' 'numpy'

- name: Run Tests
run: |
Expand Down
6 changes: 3 additions & 3 deletions src/sasctl/_services/score_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def create_score_definition(
# Checking if the model exists and if it's in a project

try:
inputMapping = []
mappings = []
for input_item in model.get("inputVariables"):
if input_mapping and input_item["name"] in input_mapping:
var = {
Expand All @@ -116,7 +116,7 @@ def create_score_definition(
"mappingType": "datasource",
"variableName": input_item["name"],
}
inputMapping.append(var)
mappings.append(var)

except:
print("This model does not have the optional 'inputVariables' parameter.")
Expand Down Expand Up @@ -164,7 +164,7 @@ def create_score_definition(
"publishDestination": "",
"versionedModel": f"{model_name} ({model_version})",
},
"mappings": inputMapping,
"mappings": mappings,
}
# Consolidating all of the model and table information to create the score definition information

Expand Down
4 changes: 1 addition & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,7 @@ def sklearn_classification_model(iris_dataset):

with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = sk.LogisticRegression(
multi_class="multinomial", solver="lbfgs", max_iter=1000
)
model = sk.LogisticRegression(solver="lbfgs", max_iter=1000)
model.fit(X, y)
return model

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_model_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def sklearn_model(train_data):
X, y = train_data
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = LogisticRegression(multi_class="multinomial", solver="lbfgs")
model = LogisticRegression(solver="lbfgs")
model.fit(X, y)
return model

Expand Down
4 changes: 1 addition & 3 deletions tests/integration/test_pymas.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ def sklearn_model(train_data):
X, y = train_data
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = LogisticRegression(
multi_class="multinomial", solver="lbfgs", max_iter=10000
)
model = LogisticRegression(solver="lbfgs", max_iter=10000)
model.fit(X, y)
return model

Expand Down
4 changes: 1 addition & 3 deletions tests/integration/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ def sklearn_logistic_model():

with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = LogisticRegression(
multi_class="multinomial", solver="lbfgs", max_iter=10000
)
model = LogisticRegression(solver="lbfgs", max_iter=10000)
model.fit(iris.iloc[:, 0:4], iris["Species"])

return model, iris.iloc[:, 0:4]
Expand Down
11 changes: 4 additions & 7 deletions tests/unit/test_model_parameters.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import ast
import copy
import json
import tempfile
import unittest
import uuid
import warnings
from pathlib import Path
from unittest import mock

import numpy as np
import pandas as pd
import pytest
from requests.models import Response
Expand All @@ -14,9 +16,6 @@

from sasctl import RestObj, current_session
from sasctl.pzmm import ModelParameters as mp
import unittest
import uuid
import numpy as np


class BadModel:
Expand Down Expand Up @@ -47,9 +46,7 @@ def sklearn_model(train_data):
X, y = train_data
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = LogisticRegression(
multi_class="multinomial", solver="lbfgs", max_iter=1000
)
model = LogisticRegression(solver="lbfgs", max_iter=1000)
model.fit(X, y)
return model

Expand Down
73 changes: 73 additions & 0 deletions tests/unit/test_score_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,76 @@ def test_create_score_definition():
json_data["properties"]["versionedModel"]
== "test_model (1.0)"
)

# Input mapping test case
get_model.return_value = {
"id": "12345",
"projectId": "p",
"projectVersionId": "pv",
"name": "test_model",
"inputVariables": [
{"name": "first"},
{"name": "second"},
],
}
get_table.return_value = {"tableName": "t"}
input_mapping = {"first": "mapped_first"}
sd.create_score_definition(
score_def_name="sd_test",
model="12345",
table_name="t",
input_mapping=input_mapping,
)
assert response
assert post.call_count == 7
data = post.call_args
json_data = json.loads(data.kwargs["data"])

assert json_data["mappings"] == [
{
"mappingValue": "mapped_first",
"mappingType": "datasource",
"variableName": "first",
},
{
"mappingValue": "second",
"mappingType": "datasource",
"variableName": "second",
},
]
# Input mapping is provided, but model has no input variables
get_model.return_value = {
"id": "12345",
"projectId": "p",
"projectVersionId": "pv",
"name": "test_model",
"inputVariables": [
{"name": "first"},
{"name": "second"},
],
}
get_table.return_value = {"tableName": "t"}
input_mapping = {"third": "mapped_third"}
sd.create_score_definition(
score_def_name="sd_test",
model="12345",
table_name="t",
input_mapping=input_mapping,
)
assert response
assert post.call_count == 8
data = post.call_args
json_data = json.loads(data.kwargs["data"])

assert json_data["mappings"] == [
{
"mappingValue": "first",
"mappingType": "datasource",
"variableName": "first",
},
{
"mappingValue": "second",
"mappingType": "datasource",
"variableName": "second",
},
]
4 changes: 1 addition & 3 deletions tests/unit/test_write_json_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ def sklearn_model(train_data):
X, y = train_data
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model = LogisticRegression(
multi_class="multinomial", solver="lbfgs", max_iter=1000
)
model = LogisticRegression(solver="lbfgs", max_iter=1000)
model.fit(X, y)
return model

Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_write_score_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import pandas as pd
import pytest
from packaging.version import Version

from sasctl import current_session
from sasctl.core import RestObj, VersionInfo
Expand Down Expand Up @@ -1165,7 +1166,10 @@ def test_input_var_lists():
data = pd.DataFrame(data=[[1, "A"], [5, "B"]], columns=["First", "Second"])
var_list, dtypes_list = sc._input_var_lists(data)
assert var_list == ["First", "Second"]
assert dtypes_list == ["int64", "object"]
if Version(pd.__version__) < Version("3.0.0"):
assert dtypes_list == ["int64", "object"]
else:
assert dtypes_list == ["int64", "str"]

data = [{"name": "First", "type": "int"}, {"name": "Second", "type": "string"}]
var_list, dtypes_list = sc._input_var_lists(data)
Expand Down
17 changes: 9 additions & 8 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@

[tox]
requires = tox>=4
envlist = py{38,39,310,311}-tests-{clean,unit,integration}
envlist = py{310,311,312,313,314}-tests-{clean,unit,integration}

# Allow execution even if all Python versions are not present
skip_missing_interpreters = {env:TOX_SKIP_MISSING_INTERPRETERS:True}

# Required by tox-gh-actions GH action. Maps GH Python runtime to tox envlist.
[gh-actions]
python =
3.8: py38
3.9: py39
3.10: py310
3.11: py311
3.12: py312
3.13: py313
3.14: py314

[testenv]
description = run standard unit and integration tests
Expand All @@ -43,14 +44,14 @@ deps =
tests: pytest-cov
tests: betamax >= 0.8.1
tests: betamax_serializers >= 0.2.0
tests: scikit-learn < 1.5.0
tests: pandas < 2.0.0
tests: numpy < 2.0.0
tests: scikit-learn
tests: pandas
tests: numpy
tests: cython # required to install pandas from source
tests: swat >= 1.8
tests: kerberos ; platform_system != "Windows" and platform_system != "Darwin"
tests: xgboost == 1.7.3
tests: urllib3 < 2.0.0
tests: xgboost
tests: urllib3
tests: nbconvert
tests: nbformat
# tests: torch
Expand Down
Loading