2222import logging
2323
2424
25- def get_folder_file_contents (session , path : str ) -> str :
25+ def get_folder_file_contents (session , path : str , http_timeout = None ) -> str :
2626 """
2727 Fetch a file from folder service
2828 :param session:
2929 :param path:
30+ :param http_timeout: Timeout for http connection
3031 :return:
3132 """
3233 member = get_member_by_path (session , path )
3334 if member ['contentType' ] != 'file' :
3435 raise RuntimeError (f"folder item is not a file: '{ path } '" )
3536
3637 uri = member ['uri' ] + '/content'
37- response = session .get (uri )
38+ response = session .get (uri , timeout = http_timeout )
3839 if not response .ok :
3940 raise RuntimeError (f"File { path } was not found or could not be accessed. error code: { response .status_code } " )
4041
4142 return response .text
4243
4344
44- def get_folder_by_path (session , path : str ) -> dict :
45+ def get_folder_by_path (session , path : str , http_timeout = None ) -> dict :
4546 """
4647 Get a folder given the path.
4748 Return a folder object, or raise an error
4849 """
49- response = session .get ('/folders/folders/@item' , params = {'path' : path })
50+ response = session .get ('/folders/folders/@item' , params = {'path' : path }, timeout = http_timeout )
5051 if response .ok :
5152 return response .json ()
5253 raise RuntimeError (response .text )
5354
5455
55- def get_member_by_path (session , path : str ) -> dict :
56+ def get_member_by_path (session , path : str , http_timeout = None ) -> dict :
5657 """
5758 Get a folder member given the full path.
5859 Return a folder member (object), or an empty dict if not found
@@ -61,12 +62,12 @@ def get_member_by_path(session, path: str) -> dict:
6162 if len (parts ) < 2 :
6263 raise RuntimeError (f"invalid path '{ path } '" )
6364
64- f = get_folder_by_path (session , parts [0 ])
65+ f = get_folder_by_path (session , parts [0 ], http_timeout = http_timeout )
6566
6667 uri = get_uri (f ['links' ], 'members' )
6768 if not uri :
6869 raise RuntimeError ("failed to find members uri link" )
69- response = session .get (uri , params = {'filter' : f'eq("name","{ parts [1 ]} ")' })
70+ response = session .get (uri , params = {'filter' : f'eq("name","{ parts [1 ]} ")' }, timeout = http_timeout )
7071
7172 if not response .ok :
7273 raise RuntimeError (f"failed to get folder members for '{ path } '" )
@@ -79,18 +80,19 @@ def get_member_by_path(session, path: str) -> dict:
7980 return member
8081
8182
82- def get_compute_session_file_contents (session , compute_session , path : str ) -> str :
83+ def get_compute_session_file_contents (session , compute_session , path : str , http_timeout = None ) -> str :
8384 """
8485 Fetch a file from the compute session file system
8586 :param session: the rest session that includes auth token
8687 :param compute_session: the compute session id
8788 :param path: full path to the file in the file system
89+ :param http_timeout: Timeout for http connection
8890 :return: contents of the file
8991 """
9092 p = f'{ path .replace ("/" , "~fs~" )} '
9193 uri = f'/compute/sessions/{ compute_session } /files/{ p } /content'
9294
93- response = session .get (uri , headers = {"Accept" : "application/octet-stream" })
95+ response = session .get (uri , headers = {"Accept" : "application/octet-stream" }, timeout = http_timeout )
9496 if response .ok :
9597 return response .text
9698 raise RuntimeError (f"File { path } was not found or could not be accessed. error code: { response .status_code } " )
@@ -107,19 +109,19 @@ def get_uri(links, rel):
107109 return link ["uri" ]
108110
109111
110- def stream_log (session ,job ,start ,limit = 99999 ) -> int :
112+ def stream_log (session ,job ,start ,limit = 99999 , http_timeout = None ) -> int :
111113 current_line = start
112114
113115 log_uri = get_uri (job ["links" ], "log" )
114116 if not log_uri :
115- logging .getLogger (name = None ).warning ("Warning: failed to retrieve log URI from links " )
117+ logging .getLogger (name = None ).warning ("Warning: failed to retrieve log URI. Maybe the log is too large. " )
116118 else :
117119 try :
118120 # Note if it is a files link (it will be that when the job have finished), this does not support the 'start' parameter, so we need to filter it by ourself.
119121 # We will ignore the limit parameter in that case
120122 is_files_link = log_uri .startswith ("/files/" )
121123
122- r = session .get (f"{ log_uri } /content?start={ start } &limit={ limit } " )
124+ r = session .get (f"{ log_uri } /content?start={ start } &limit={ limit } " , timeout = http_timeout )
123125 if r .ok :
124126 # Parse the json log format and print each line
125127 log_contents = r .text
@@ -134,26 +136,27 @@ def stream_log(session,job,start,limit=99999) -> int:
134136
135137 lines = lines + 1
136138 else :
137- logging .getLogger (name = None ).warning (f"Failed to retrieve part of the log from URI: { log_uri } /content " )
139+ logging .getLogger (name = None ).warning (f"Failed to retrieve parts of the log with status code { r . status_code } from URI: { log_uri } /content. Maybe the log is too large. " )
138140 except Exception as e :
139- logging .getLogger (name = None ).warning ("Unable to retrieve parts of the log." )
141+ logging .getLogger (name = None ).warning (f "Unable to retrieve parts of the log: { e } . Maybe the log is too large ." )
140142
141143 return current_line
142144
143145
144146
145- def dump_logs (session , job ):
147+ def dump_logs (session , job , http_timeout = None ):
146148 """
147149 Get the log from the job object
148150 :param session: rest session
149151 :param job: job object that should contain links object
152+ :param http_timeout: Timeout for http connection
150153 """
151154
152155 log_uri = get_uri (job ["links" ], "log" )
153156 if not log_uri :
154157 print ("Warning: failed to retrieve log uri from links. Log will not be displayed" )
155158 else :
156- r = session .get (f"{ log_uri } /content" )
159+ r = session .get (f"{ log_uri } /content" , timeout = http_timeout )
157160 if not r .ok :
158161 print ("Warning: failed to retrieve log content. Log will not be displayed" )
159162
@@ -165,9 +168,9 @@ def dump_logs(session, job):
165168 if t != "title" :
166169 print (f'{ line ["line" ]} ' )
167170
168- def find_named_compute_session (session : requests .Session , name : str ) -> dict :
171+ def find_named_compute_session (session : requests .Session , name : str , http_timeout = None ) -> dict :
169172 # find session with given name
170- response = session .get (f"/compute/sessions?filter=eq(name, { name } )" )
173+ response = session .get (f"/compute/sessions?filter=eq(name, { name } )" , timeout = http_timeout )
171174 if not response .ok :
172175 raise RuntimeError (f"Find sessions failed: { response .status_code } " )
173176 sessions = response .json ()
@@ -176,18 +179,19 @@ def find_named_compute_session(session: requests.Session, name: str) -> dict:
176179 return sessions ["items" ][0 ]
177180 return {}
178181
179- def create_or_connect_to_session (session : requests .Session , context_name : str , name = None ) -> dict :
182+ def create_or_connect_to_session (session : requests .Session , context_name : str , name = None , http_timeout = None ) -> dict :
180183 """
181184 Connect to an existing compute session by name. If that named session does not exist,
182185 one is created using the context name supplied
183186 :param session: rest session that includes oauth token
184187 :param context_name: the context name to use to create the session if the session was not found
185188 :param name: name of session to find
189+ :param http_timeout: Timeout for http connection
186190 :return: session object
187191
188192 """
189193 if name != None :
190- compute_session = find_named_compute_session (session , name )
194+ compute_session = find_named_compute_session (session , name , http_timeout = http_timeout )
191195 if compute_session :
192196 return compute_session
193197
@@ -197,7 +201,7 @@ def create_or_connect_to_session(session: requests.Session, context_name: str, n
197201
198202
199203 # find compute context
200- response = session .get ("/compute/contexts" , params = {"filter" : f'eq("name","{ context_name } ")' })
204+ response = session .get ("/compute/contexts" , params = {"filter" : f'eq("name","{ context_name } ")' }, timeout = http_timeout )
201205 if not response .ok :
202206 raise RuntimeError (f"Find context named { context_name } failed: { response .status_code } " )
203207 context_resp = response .json ()
@@ -216,7 +220,7 @@ def create_or_connect_to_session(session: requests.Session, context_name: str, n
216220 headers = {"Content-Type" : "application/vnd.sas.compute.session.request+json" }
217221
218222 req = json .dumps (session_request )
219- response = session .post (uri , data = req , headers = headers )
223+ response = session .post (uri , data = req , headers = headers , timeout = http_timeout )
220224
221225 if response .status_code != 201 :
222226 raise RuntimeError (f"Failed to create session: { response .text } " )
@@ -226,9 +230,9 @@ def create_or_connect_to_session(session: requests.Session, context_name: str, n
226230
227231 return json_response
228232
229- def end_compute_session (session : requests .Session , id ):
233+ def end_compute_session (session : requests .Session , id , http_timeout = None ):
230234 uri = f'/compute/sessions/{ id } '
231- response = session .delete (uri )
235+ response = session .delete (uri , timeout = http_timeout )
232236 if not response .ok :
233237 return False
234238 return True
0 commit comments