Skip to content

Commit 85552f5

Browse files
Merge pull request #1 from sassoftware/bugfix
Bugfix
2 parents 1013229 + cb16335 commit 85552f5

File tree

8 files changed

+103
-75
lines changed

8 files changed

+103
-75
lines changed

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11

22
Unreleased
33
----------
4-
5-
-
6-
4+
**Bugfixes**
5+
- Fixed DS2 score code for CAS that was generated when registering a Python model.
6+
- `PyMAS.score_code(dest='ESP')` corrected to `dest='EP'`
7+
- Fixed an issue where long user-defined properties prevented model registration.
8+
79

810
v1.1.1 (2019-8-6)
911
-----------------

src/sasctl/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
# Copyright © 2019, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
55
# SPDX-License-Identifier: Apache-2.0
66

7-
__version__ = '1.1.1'
7+
__version__ = '1.1.2'
88
__author__ = 'SAS'
9-
__credits__ = ['Yi Jian Ching, Lucas De Paula, Peter Tobac, Chris Toth, Jon '
10-
'Walker']
9+
__credits__ = ['Yi Jian Ching, Lucas De Paula, James Kochuba, Peter Tobac, '
10+
'Chris Toth, Jon Walker']
1111
__license__ = 'Apache 2.0'
1212
__copyright__ = 'Copyright © 2019, SAS Institute Inc., ' \
1313
'Cary, NC, USA. All Rights Reserved.'

src/sasctl/_services/model_management.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ class ModelManagement(Service):
2121

2222
# TODO: set ds2MultiType
2323
def publish_model(self, model, destination, name=None, force=False):
24+
"""
25+
26+
Parameters
27+
----------
28+
model
29+
destination
30+
name
31+
force
32+
33+
Returns
34+
-------
35+
36+
"""
2437
from .model_repository import ModelRepository
2538
from .model_publish import ModelPublish
2639

src/sasctl/tasks.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,43 @@
2525

2626

2727
def _sklearn_to_dict(model):
28+
# As of Viya 3.4 model registration fails if character fields are longer
29+
# than 1024 characters
30+
DESC_MAXLEN = 1024
31+
32+
# As of Viya 3.4 model registration fails if user-defined properties are
33+
# longer than 512 characters.
34+
PROP_MAXLEN = 512
35+
2836
# Convert Scikit-learn values to built-in Model Manager values
2937
mappings = {'LogisticRegression': 'Logistic regression',
3038
'LinearRegression': 'Linear regression',
3139
'SVC': 'Support vector machine',
3240
'GradientBoostingClassifier': 'Gradient boosting',
41+
'XGBClassifier': 'Gradient boosting',
42+
'XGBRegressor': 'Gradient boosting',
3343
'RandomForestClassifier': 'Forest',
3444
'DecisionTreeClassifier': 'Decision tree',
3545
'DecisionTreeRegressor': 'Decision tree',
3646
'classifier': 'Classification',
3747
'regressor': 'Prediction'}
3848

49+
if hasattr(model, '_final_estimator'):
50+
estimator = type(model._final_estimator)
51+
else:
52+
estimator = type(model)
53+
3954
# Can tell if multi-class .multi_class
4055
result = dict(
41-
description=str(model),
42-
algorithm=mappings.get(type(model).__name__, type(model).__name__),
56+
description=str(model)[:DESC_MAXLEN],
57+
algorithm=mappings.get(estimator.__name__, estimator.__name__),
4358
scoreCodeType='ds2MultiType',
4459
trainCodeType='Python',
4560
function=mappings.get(model._estimator_type, model._estimator_type),
4661
tool='Python %s.%s'
4762
% (sys.version_info.major, sys.version_info.minor),
48-
properties=[{'name': k, 'value': v}
63+
properties=[{'name': str(k)[:PROP_MAXLEN],
64+
'value': str(v)[:PROP_MAXLEN]}
4965
for k, v in model.get_params().items()]
5066
)
5167

@@ -156,9 +172,6 @@ def register_model(model, name, project, repository=None, input=None,
156172
files.append({'name': 'dmcas_packagescorecode.sas',
157173
'file': mas_module.score_code(),
158174
'role': 'Score Code'})
159-
files.append({'name': 'dmcas_espscorecode.sas',
160-
'file': mas_module.score_code(dest='ESP'),
161-
'role': 'Score Code'})
162175
files.append({'name': 'dmcas_epscorecode.sas',
163176
'file': mas_module.score_code(dest='CAS'),
164177
'role': 'score'})
@@ -251,7 +264,8 @@ def publish_model(model, destination, code=None, max_retries=60,
251264
def submit_request():
252265
# Submit a publishing request
253266
if code is None:
254-
publish_req = mm.publish_model(model, destination, force=replace, **kwargs)
267+
publish_req = mm.publish_model(model, destination,
268+
force=replace, **kwargs)
255269
else:
256270
publish_req = mp.publish_model(model, destination,
257271
code=code, **kwargs)
@@ -265,7 +279,9 @@ def submit_request():
265279
# Submit and wait for status
266280
job = submit_request()
267281

268-
if job.state.lower() == 'completed' and job.destination.destinationType != 'microAnalyticService':
282+
# If model was successfully published and it isn't a MAS module, we're done
283+
if job.state.lower() == 'completed' \
284+
and job.destination.destinationType != 'microAnalyticService':
269285
return request_link(job,'self')
270286

271287
# If MAS publish failed and replace=True, attempt to delete the module

src/sasctl/utils/pymas/core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def score_code(self, input_table=None, output_table=None, columns=None, dest='MA
345345
The name of the table where execution results will be written
346346
columns : list of str
347347
Names of the columns from `table` that will be passed to `func`
348-
dest : str {'MAS', 'ESP', 'CAS'}
348+
dest : str {'MAS', 'EP', 'CAS'}
349349
350350
Returns
351351
-------
@@ -365,7 +365,7 @@ def score_code(self, input_table=None, output_table=None, columns=None, dest='MA
365365
# Get package code
366366
code = tuple(self.package.code().split('\n'))
367367

368-
if dest == 'ESP':
368+
if dest == 'EP':
369369
code = ('data sasep.out;', ) + code + (' method run();',
370370
' set SASEP.IN;',
371371
' end;',

tests/cassettes/tests.integration.test_tasks.TestModels.test_register_sklearn.json

Lines changed: 54 additions & 54 deletions
Large diffs are not rendered by default.

tests/integration/test_tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def test_register_sklearn(self, sklearn_model):
9393
files = mr.get_model_contents(model)
9494
filenames = [f.name for f in files]
9595
assert 'model.pkl' in filenames
96-
assert 'dmcas_espscorecode.sas' in filenames
96+
assert 'dmcas_epscorecode.sas' in filenames
9797
assert 'dmcas_packagescorecode.sas' in filenames
9898

9999
def test_publish_sklearn(self):

tests/unit/test_pymas.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,11 @@ def test_score_code():
3333
assert isinstance(p, PyMAS)
3434

3535
mas_code = p.score_code()
36-
esp_code = p.score_code(dest='esp')
36+
esp_code = p.score_code(dest='ep')
3737

3838
assert mas_code.lower().startswith('package _')
3939
assert esp_code.lower().startswith('data sasep.out;')
4040

41-
with pytest.raises(ValueError):
42-
cas_code = p.score_code(dest='cas')
43-
4441
cas_code = p.score_code('in_table', 'out_table', ['in1', 'in2'], dest='cas')
4542

4643
pytest.xfail('Not implemented.')

0 commit comments

Comments
 (0)