Skip to content

Commit f18bf54

Browse files
authored
service cleanup
1 parent c9b5ef7 commit f18bf54

20 files changed

+391
-362
lines changed

doc/api/sasctl.pzmm.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sasctl.pzmm package
2+
====================
3+
4+
Module contents
5+
---------------
6+
7+
.. automodule:: sasctl.pzmm
8+
:members:
9+
:undoc-members:
10+
:show-inheritance:

doc/api/sasctl.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ Subpackages
2323
.. toctree::
2424

2525
sasctl.services
26-
sasctl.utils
26+
sasctl.utils
27+
sasctl.pzmm

src/sasctl/__init__.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,28 @@
1313
'Cary, NC, USA. All Rights Reserved.'
1414

1515
import logging
16+
import warnings
1617

1718

18-
from .core import current_session, delete, get, get_link, platform_version, post, put, request_link
19+
from .core import (
20+
current_session,
21+
delete,
22+
get,
23+
get_link,
24+
platform_version,
25+
post,
26+
put,
27+
request_link,
28+
)
1929
from .core import RestObj, Session, HTTPError
20-
from .tasks import register_model, publish_model, update_model_performance
30+
from .tasks import (
31+
publish_model,
32+
register_model,
33+
update_model_performance,
34+
)
35+
36+
# Ensure deprecation warnings are shown to users.
37+
warnings.filterwarnings('always', category=DeprecationWarning, module=r'^sasctl\.')
2138

2239

2340
# Prevent package from emitting log records unless consuming

src/sasctl/_services/cas_management.py

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

7+
import os
8+
79
from .service import Service
810

11+
DEFAULT_SERVER = 'cas-shared-default'
12+
DEFAULT_CASLIB = 'casuser'
13+
914

1015
class CASManagement(Service):
1116
"""The CAS Management service provides the ability to manage and perform
@@ -16,14 +21,15 @@ class CASManagement(Service):
1621

1722
list_servers, get_server, _, _ = Service._crud_funcs('/servers', 'server')
1823

19-
def list_caslibs(self, server, filter=None):
24+
@classmethod
25+
def list_caslibs(cls, server, filter_=None):
2026
"""List caslibs available on a server.
2127
2228
Parameters
2329
----------
2430
server : str or dict
2531
Name, ID, or dictionary representation of the server.
26-
filter : str, optional
32+
filter_ : str, optional
2733
A `formatted <https://developer.sas.com/reference/filtering>`_
2834
filter string.
2935
@@ -33,10 +39,12 @@ def list_caslibs(self, server, filter=None):
3339
A collection of :class:`.RestObj` instances.
3440
3541
"""
36-
return self._get_rel(server, 'caslibs', func=self.get_server,
37-
filter=filter) or []
42+
return (
43+
cls._get_rel(server, 'caslibs', func=cls.get_server, filter_=filter_) or []
44+
)
3845

39-
def get_caslib(self, name, server=None):
46+
@classmethod
47+
def get_caslib(cls, name, server=None):
4048
"""Get a caslib by name.
4149
4250
Parameters
@@ -51,14 +59,15 @@ def get_caslib(self, name, server=None):
5159
RestObj
5260
5361
"""
54-
server = server or 'cas-shared-default'
55-
caslibs = self.list_caslibs(server,
56-
filter='eq($primary,name, "%s")' % name)
62+
server = server or DEFAULT_SERVER
63+
caslibs = cls.list_caslibs(server, filter_='eq($primary,name, "%s")' % name)
5764

5865
if caslibs:
5966
return caslibs[0]
67+
return None
6068

61-
def list_tables(self, caslib, server=None, filter=None):
69+
@classmethod
70+
def list_tables(cls, caslib, server=None, filter_=None):
6271
"""List tables available in a caslib.
6372
6473
Parameters
@@ -67,7 +76,7 @@ def list_tables(self, caslib, server=None, filter=None):
6776
Name, ID, or dictionary representation of the caslib.
6877
server : str, optional
6978
Server where the `caslib` is registered.
70-
filter : str, optional
79+
filter_ : str, optional
7180
Filter string in the `https://developer.sas.com/reference/filtering
7281
/` format.
7382
@@ -77,18 +86,19 @@ def list_tables(self, caslib, server=None, filter=None):
7786
A collection of :class:`.RestObj` instances.
7887
7988
"""
80-
return self._get_rel(caslib, 'tables', self.get_caslib, filter,
81-
server) or []
89+
return cls._get_rel(caslib, 'tables', server, func=cls.get_caslib, filter_=filter_) or []
8290

83-
def get_table(self, name, caslib, server=None):
91+
@classmethod
92+
def get_table(cls, name, caslib=None, server=None):
8493
"""Get a table by name.
8594
8695
Parameters
8796
----------
8897
name : str
8998
Name of the table.
90-
caslib : str or dict
91-
Name, ID, or dictionary representation of the caslib.
99+
caslib : str or dict, optional
100+
Name, ID, or dictionary representation of the caslib. Defaults to
101+
CASUSER.
92102
server : str, optional
93103
Server where the `caslib` is registered.
94104
@@ -97,9 +107,77 @@ def get_table(self, name, caslib, server=None):
97107
RestObj
98108
99109
"""
100-
tables = self.list_tables(caslib,
101-
server=server,
102-
filter='eq($primary,name, "%s")' % name)
110+
caslib = caslib or DEFAULT_CASLIB
111+
tables = cls.list_tables(
112+
caslib, server=server, filter_='eq($primary,name, "%s")' % name
113+
)
103114

104115
if tables:
105116
return tables[0]
117+
return None
118+
119+
@classmethod
120+
def upload_file(
121+
cls, file, name, caslib=None, server=None, header=None, format_=None
122+
):
123+
"""Upload a file to a CAS table.
124+
125+
Uploads the contents of a CSV, XLS, XLSX, SAS7BDT or SASHDAT file to a
126+
newly created CAS table.
127+
128+
Parameters
129+
----------
130+
file : str or file-like object
131+
File containing data to upload or path to the file.
132+
name : str
133+
Name of the table to create
134+
caslib : str, optional
135+
caslib in which the table will be created. Defaults to CASUSER.
136+
server : str, optional
137+
CAS server on which the table will be created. Defaults to
138+
cas-shared-default.
139+
header : bool, optional
140+
Whether the first row of data contains column headers. Defaults to
141+
True.
142+
format_ : {"csv", "xls", "xlsx", "sas7bdat", "sashdat"}, optional
143+
File of input `file`. Not required if format can be discerned from
144+
the file path.
145+
146+
Returns
147+
-------
148+
RestObj
149+
Table reference
150+
151+
"""
152+
name = str(name)
153+
caslib = caslib or DEFAULT_CASLIB
154+
server = server or DEFAULT_SERVER
155+
header = True if header is None else bool(header)
156+
157+
# Not a file-like object, assuming it's a file path
158+
if not hasattr(file, 'read'):
159+
path = os.path.abspath(os.path.expanduser(file))
160+
format_ = os.path.splitext(path)[-1].lstrip('.').lower()
161+
162+
# Extension should be supported & needs to be explicitly set in
163+
# the "format" parameter to avoid errors.
164+
if format_ not in ('csv', 'xls', 'xlsx', 'sas7bdat', 'sashdat'):
165+
raise ValueError("File '%s' has an unsupported file type." % file)
166+
167+
with open(path, 'rb') as f:
168+
file = f.read()
169+
170+
data = {
171+
'tableName': name,
172+
'containsHeaderRow': header,
173+
}
174+
175+
if format_ is not None:
176+
data['format'] = format_
177+
178+
tbl = cls.post(
179+
'/servers/%s/caslibs/%s/tables' % (server, caslib),
180+
data=data,
181+
files={name: file},
182+
)
183+
return tbl

src/sasctl/_services/concepts.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class Concepts(Service):
1515

1616
_SERVICE_ROOT = '/concepts'
1717

18+
@classmethod
1819
def assign_concepts(
19-
self,
20+
cls,
2021
documents,
2122
caslib=None,
2223
id_column=None,
@@ -123,4 +124,4 @@ def assign_concepts(
123124
'Accept': 'application/vnd.sas.text.concepts.job+json',
124125
}
125126

126-
return self.post(url, json=data, headers=headers)
127+
return cls.post(url, json=data, headers=headers)

0 commit comments

Comments
 (0)