44# Copyright © 2019, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
55# SPDX-License-Identifier: Apache-2.0
66
7+ import os
8+
79from .service import Service
810
11+ DEFAULT_SERVER = 'cas-shared-default'
12+ DEFAULT_CASLIB = 'casuser'
13+
914
1015class 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
0 commit comments