11import requests
22import platform
3+ import urllib .parse
34
45from .tasks import Task
56from .batches import Batch
@@ -63,11 +64,11 @@ class Batchlist(Paginator):
6364
6465
6566class ScaleClient (object ):
66- def __init__ (self , api_key ):
67+ def __init__ (self , api_key , user_agent_extension = None ):
6768 self .api_key = api_key
6869 self ._headers = {
6970 "Content-Type" : "application/json" ,
70- "User-Agent" : _generate_useragent ()
71+ "User-Agent" : _generate_useragent (user_agent_extension )
7172 }
7273
7374 def _getrequest (self , endpoint , params = None ):
@@ -171,15 +172,15 @@ def create_batch(self, project, batch_name, callback):
171172 return Batch (batchdata , self )
172173
173174 def finalize_batch (self , batch_name ):
174- batchdata = self ._postrequest ('batches/%s/finalize' % batch_name )
175+ batchdata = self ._postrequest ('batches/%s/finalize' % quote_string ( batch_name ) )
175176 return Batch (batchdata , self )
176177
177178 def batch_status (self , batch_name ):
178- batchdata = self ._getrequest ('batches/%s/status' % batch_name )
179- return Batch . get_status ( self )
179+ status_data = self ._getrequest ('batches/%s/status' % quote_string ( batch_name ) )
180+ return status_data
180181
181182 def get_batch (self , batch_name ):
182- batchdata = self ._getrequest ('batches/%s' % batch_name )
183+ batchdata = self ._getrequest ('batches/%s' % quote_string ( batch_name ) )
183184 return Batch (batchdata , self )
184185
185186 def list_batches (self , ** kwargs ):
@@ -202,7 +203,7 @@ def create_project(self, project_name, type, params):
202203 return Project (projectdata , self )
203204
204205 def get_project (self , project_name ):
205- projectdata = self ._getrequest ('projects/%s' % project_name )
206+ projectdata = self ._getrequest ('projects/%s' % quote_string ( project_name ) )
206207 return Project (projectdata , self )
207208
208209 def projects (self ):
@@ -215,19 +216,38 @@ def update_project(self, project_name, **kwargs):
215216 if key not in allowed_kwargs :
216217 raise ScaleInvalidRequest ('Illegal parameter %s for ScaleClient.update_project()'
217218 % key , None )
218- projectdata = self ._postrequest ('projects/%s/setParams' % project_name , payload = kwargs )
219+ projectdata = self ._postrequest ('projects/%s/setParams' % quote_string ( project_name ) , payload = kwargs )
219220 return projectdata
220221
221- def _generate_useragent ():
222+ def _generate_useragent (extension = None ):
222223 try :
223224 python_version = platform .python_version ()
224225 os_platform = platform .platform ()
225226
226- user_agent = '%s/%s Python/%s OS/%s' % (__name__ , __version__ , python_version , os_platform )
227+ user_agent = " " .join (
228+ filter (
229+ None ,
230+ [
231+ "{}/{}" .format (__name__ , __version__ ),
232+ "Python/{}" .format (python_version ),
233+ "OS/{}" .format (os_platform ),
234+ extension ,
235+ ],
236+ )
237+ )
227238 return user_agent
228- except :
239+
240+ except Exception :
229241 return "scaleapi-python-client"
230242
243+ def quote_string (text ):
244+ """`quote_string('a bc/def')` -> `a%20bc%2Fdef`
245+ Project and Batch names can be a part of URL, which causes an error
246+ in case of a special character used. Quotation assures
247+ the right object to be retrieved from API.
248+ """
249+ return urllib .parse .quote (text , safe = "" )
250+
231251def _AddTaskTypeCreator (task_type ):
232252 def create_task_wrapper (self , ** kwargs ):
233253 return self .create_task (task_type , ** kwargs )
0 commit comments