Skip to content

Commit eef8b98

Browse files
Merge pull request #1 from sassoftware/master
sync from master
2 parents 8656a43 + 512cf21 commit eef8b98

File tree

45 files changed

+6196
-2447
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+6196
-2447
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
.ipynb_checkpoints
2222
.tags
2323
*.iml
24+
_scratch
2425

2526
## Python files
2627
# setup.py working directory
@@ -60,3 +61,4 @@ Thumbs.db
6061
doc/build
6162
doc/source/generated
6263
doc/_build
64+
doc/.doctrees

CHANGELOG.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11

22
Unreleased
33
----------
4-
54
-
65

6+
7+
v1.2.0 (2019-8-16)
8+
------------------
9+
**Improvements**
10+
- Added `create_model_version` and `list_model_versions` to `model_repository`
11+
- Added an explicit `ValueError` when attempting to register an ASTORE that can't be downloaded.
12+
- Added `start` and `limit` pagination parameters to all default `list_*` service methods.
13+
- Added `create_destination`, `create_cas_destination` and `create_mas_destination` methods for `model_publish` service.
14+
15+
**Changes**
16+
- `Session.add_stderr_logger` default logging level changed to `DEBUG`.
17+
18+
**Bugfixes**
19+
- Fixed an issue where `model_repository` did not find models, projects, or repositories by name once pagination limits were reached.
20+
21+
722
v1.1.4 (2019-8-16)
823
-----------------
9-
1024
**Bugfixes**
1125
- The `register_model` task now generates dmcas_epscorecode.sas files for ASTORE models.
1226

1327

1428
v1.1.3 (2019-8-14)
1529
-----------------
16-
1730
**Bugfixes**
1831
- Fixed problem causing `register_model` task to include output variables in the input variables list.
1932

src/sasctl/__init__.py

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

7-
__version__ = '1.1.4'
7+
__version__ = '1.2.0'
88
__author__ = 'SAS'
99
__credits__ = ['Yi Jian Ching, Lucas De Paula, James Kochuba, Peter Tobac, '
1010
'Chris Toth, Jon Walker']

src/sasctl/_services/microanalytic_score.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import re
1010
from collections import OrderedDict
1111

12+
import six
13+
1214
from .service import Service
1315

1416

@@ -116,7 +118,18 @@ def execute_module_step(self, module, step, return_dict=True, **kwargs):
116118
module = module.id
117119
step = step.id if hasattr(step, 'id') else step
118120

119-
body = {'inputs': [{'name': k, 'value': v} for k, v in kwargs.items()]}
121+
# Make sure all inputs are JSON serializable
122+
# Common types such as numpy.int64 and numpy.float64 are NOT serializable
123+
for k in kwargs.keys():
124+
type_name = type(kwargs[k]).__name__
125+
if type_name == 'float64':
126+
kwargs[k] = float(kwargs[k])
127+
elif type_name == 'int64':
128+
kwargs[k] = int(kwargs[k])
129+
130+
131+
body = {'inputs': [{'name': k, 'value': v}
132+
for k, v in six.iteritems(kwargs)]}
120133
r = self.post('/modules/{}/steps/{}'.format(module, step), json=body)
121134

122135
# Convert list of name/value pair dictionaries to single dict

src/sasctl/_services/model_publish.py

Lines changed: 154 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import re
1010

11-
from .service import Service
1211
from .model_repository import ModelRepository
12+
from .service import Service
1313

1414

1515
class ModelPublish(Service):
@@ -59,9 +59,13 @@ def list_models(cls):
5959
'destination')
6060

6161
@classmethod
62-
def publish_model(cls, model, destination, name=None, code=None,
62+
def publish_model(cls,
63+
model,
64+
destination,
65+
name=None,
66+
code=None,
6367
notes=None):
64-
"""
68+
"""Publish a model to an existing publishing destination.
6569
6670
Parameters
6771
----------
@@ -118,3 +122,150 @@ def publish_model(cls, model, destination, name=None, code=None,
118122
return cls.post('/models', json=request, headers={
119123
'Content-Type':
120124
'application/vnd.sas.models.publishing.request+json'})
125+
126+
@classmethod
127+
def create_cas_destination(cls, name,
128+
library,
129+
table,
130+
server=None,
131+
description=None):
132+
"""Define a new CAS publishing destination.
133+
134+
Parameters
135+
----------
136+
name : str
137+
Name of the publishing destination.
138+
library : str
139+
The CAS library in which `table` will be stored.
140+
table : str
141+
Name of the CAS table in which models will be stored.
142+
server : str, optional
143+
Name of the CAS server. Defaults to 'cas-shared-default'.
144+
description : str, optional
145+
Description of the publishing destination.
146+
147+
Returns
148+
-------
149+
RestObj
150+
151+
"""
152+
server = server or 'cas-shared-default'
153+
154+
return cls.create_destination(name, cas_server=server,
155+
cas_library=library, cas_table=table,
156+
type_='cas', description=description)
157+
158+
@classmethod
159+
def create_mas_destination(cls, name, uri, description=None):
160+
"""Define a new Micro Analytic Server (MAS) publishing destination.
161+
162+
Parameters
163+
----------
164+
name : str
165+
Name of the publishing destination.
166+
uri : str
167+
The base URI that contains the host, the protocol, and optionally
168+
the port, which addresses the remote SAS Micro Analytic Service to
169+
use. Example: http://spam.com
170+
description : str, optional
171+
Description of the publishing destination.
172+
173+
Returns
174+
-------
175+
RestObj
176+
177+
"""
178+
return cls.create_destination(name, mas_uri=uri, type_='mas',
179+
description=description)
180+
181+
@classmethod
182+
def create_destination(cls,
183+
name,
184+
type_,
185+
cas_server=None,
186+
cas_library=None,
187+
cas_table=None,
188+
description=None,
189+
mas_uri=None,
190+
hdfs_dir=None,
191+
conf_dir=None,
192+
user=None,
193+
database_library=None):
194+
"""Define a new publishing destination.
195+
196+
Parameters
197+
----------
198+
name : str
199+
Name of the publishing destination.
200+
type_ : {'cas', 'mas', 'hadoop', 'teradata'}
201+
Type of publishing definition being created
202+
cas_server : str, optional
203+
Name of the CAS server. Defaults to 'cas-shared-default'.
204+
Required if `type_` is 'cas', otherwise ignored.
205+
cas_library : str, optional
206+
The CAS library in which `cas_table` will be stored. Required if
207+
`type_` is 'cas', otherwise ignored.
208+
cas_table : str, optional
209+
Name of the CAS table in which models will be stored. Required
210+
if `type_` is 'cas', otherwise ignored.
211+
description : str, optional
212+
Description of the publishing destination.
213+
mas_uri : str, optional
214+
Required if `type_` is 'mas', otherwise ignored.
215+
hdfs_dir : str, optional
216+
Required if `type_` is 'hadoop', otherwise ignored.
217+
conf_dir : str, optional
218+
Required if `type_` is 'hadoop', otherwise ignored.
219+
user : str, optional
220+
Required if `type_` is 'hadoop', otherwise ignored.
221+
database_library : str, optional
222+
Required if `type_` is 'teradata', otherwise ignored.
223+
224+
Returns
225+
-------
226+
RestObj
227+
228+
"""
229+
type_ = str(type_).lower()
230+
assert type_ in ('cas', 'microanalyticservice', 'mas',
231+
'teradata', 'hadoop')
232+
233+
# As of Viya 3.4 capitalization matters.
234+
if type_ in ('microanalyticservice', 'mas'):
235+
type_ = 'microAnalyticService'
236+
237+
request = {'name': str(name),
238+
'destinationType': type_,
239+
'casServerName': cas_server,
240+
'casLibrary': cas_library,
241+
'description': description,
242+
'destinationTable': cas_table,
243+
'databaseCasLibrary': database_library,
244+
'user': user,
245+
'hdfsDirectory': hdfs_dir,
246+
'configurationDirectory': conf_dir,
247+
'masUri': mas_uri
248+
}
249+
250+
drop_list = {
251+
'cas':
252+
('databaseCasLibrary', 'user', 'hdfsDirectory', 'masUri',
253+
'configurationDirectory'),
254+
'microAnalyticService':
255+
('casServerName', 'casLibrary', 'destinationTable', 'user',
256+
'databaseCasLibrary', 'hdfsDirectory',
257+
'configurationDirectory'),
258+
'hadoop':
259+
('casServerName', 'casLibrary', 'destinationTable',
260+
'databaseCasLibrary', 'masUri'),
261+
'teradata':
262+
('casServerName', 'casLibrary', 'destinationTable', 'user',
263+
'hdfsDirectory', 'masUri', 'configurationDirectory')
264+
}
265+
266+
for k in drop_list[request['destinationType']]:
267+
request.pop(k, None)
268+
269+
return cls.post('/destinations', json=request, headers={
270+
'Content-Type':
271+
'application/vnd.sas.models.publishing.destination+json'})

0 commit comments

Comments
 (0)