2424import io
2525import logging
2626
27+ from urllib import parse
28+
2729try :
2830 import simplejson as json
2931except ImportError :
@@ -143,7 +145,7 @@ def debug_request(method, url, **kwargs):
143145 json .dumps (json .loads (response .content ), indent = 4 )
144146 except Exception :
145147 response_content = response .content
146- response_content = response_content [0 :256 ] if short_debug else \
148+ response_content = response_content [0 : 256 ] if short_debug else \
147149 response_content
148150 logging .debug ("Response: %s\n " , response_content )
149151 return response
@@ -232,13 +234,17 @@ def __init__(self, username=None, api_key=None,
232234 " your environment" )
233235
234236 self .username = username
235- self .auth = "?username=%s;api_key=%s;" % (username , api_key )
237+ self .api_key = api_key
238+ self .qs_params = {"username" : self .username , "api_key" : self .api_key }
239+ self .auth = "?" + parse .urlencode (self .qs_params )
236240 self .project = None
237241 self .organization = None
238242 if project is not None :
239243 self .project = project
244+ self .qs_params .update ({"project" : self .project })
240245 if organization is not None :
241246 self .organization = organization
247+
242248 self .debug = debug
243249 self .short_debug = short_debug
244250 self .domain = None
@@ -254,18 +260,10 @@ def __init__(self, username=None, api_key=None,
254260 locale .setlocale (locale .LC_ALL , DEFAULT_LOCALE )
255261 self .storage = assign_dir (storage )
256262
257- def _set_api_urls (self , dev_mode = False , domain = None ):
263+ def _set_api_urls (self , domain = None ):
258264 """Sets the urls that point to the REST api methods for each resource
259265
260- dev_mode` has been deprecated. Now all resources coexist in the
261- same production environment. Existing resources generated in
262- development mode have been archived under a special project and
263- are now accessible in production mode.
264-
265266 """
266- if dev_mode :
267- LOGGER .warning ("Development mode is deprecated and the dev_mode"
268- " flag will be removed soon." )
269267 if domain is None :
270268 domain = Domain ()
271269 elif isinstance (domain , str ):
@@ -282,7 +280,8 @@ def _set_api_urls(self, dev_mode=False, domain=None):
282280 self .prediction_base_url = BIGML_URL % (
283281 self .domain .prediction_protocol , self .domain .prediction_domain , "" )
284282
285- def _add_credentials (self , url , organization = False , shared_auth = None ):
283+ def _add_credentials (self , qs_params ,
284+ organization = False , shared_auth = None ):
286285 """Adding the credentials and project or organization information
287286 for authentication
288287
@@ -291,17 +290,25 @@ def _add_credentials(self, url, organization=False, shared_auth=None):
291290 the organization ID is used to access the projects and tasks in an
292291 organization. If false, a particular project ID must be used.
293292
294- The shared_auth string provides the alternative credentials for
293+ The shared_auth dictionary provides the alternative credentials for
295294 shared resources.
296295
297296 """
298- auth = self .auth if shared_auth is None else shared_auth
299- auth = auth if "?" not in url else ";%s" % auth [1 :]
300- return "%s%s%s" % (url , auth ,
301- "organization=%s;" % self .organization if
302- organization and self .organization
303- else "project=%s;" % self .project if self .project
304- else "" )
297+ if qs_params is None :
298+ qs_params = {}
299+ params = {}
300+ params .update (qs_params )
301+ if shared_auth is None :
302+ params .update (self .qs_params )
303+ else :
304+ params .update (share_auth )
305+ if organization and self .organization :
306+ try :
307+ del params ["project" ]
308+ except KeyError :
309+ pass
310+ params .update ({"organization" : self .organization })
311+ return params
305312
306313 def _add_project (self , payload , include = True ):
307314 """Adding project id as attribute when it has been set in the
@@ -348,14 +355,14 @@ def _create(self, url, body, verify=None, organization=None):
348355 code = HTTP_ACCEPTED
349356 if verify is None :
350357 verify = self .domain .verify
351-
352- url = self . _add_credentials ( url , organization = organization )
358+ qs_params = self . _add_credentials ({}, organization = organization )
359+ qs_str = "?%s" % parse . urlencode ( qs_params ) if qs_params else ""
353360 body = self ._add_project (body , not organization )
354361 while code == HTTP_ACCEPTED :
355362 if GAE_ENABLED :
356363 try :
357364 req_options = {
358- 'url' : url ,
365+ 'url' : url + qs_str ,
359366 'method' : urlfetch .POST ,
360367 'headers' : SEND_JSON ,
361368 'payload' : body ,
@@ -371,6 +378,7 @@ def _create(self, url, body, verify=None, organization=None):
371378 else :
372379 try :
373380 response = requests .post (url ,
381+ params = qs_params ,
374382 headers = SEND_JSON ,
375383 data = body , verify = verify )
376384 except (requests .ConnectionError ,
@@ -429,21 +437,21 @@ def _get(self, url, query_string='',
429437 "status" : {
430438 "code" : HTTP_INTERNAL_SERVER_ERROR ,
431439 "message" : "The resource couldn't be retrieved" }}
432- auth = (self .auth if shared_username is None
433- else "?username=%s;api_key=%s" % (
434- shared_username , shared_api_key ))
435440
436441 kwargs = {"organization" : organization }
437442 if shared_username is not None and shared_api_key is not None :
438- kwargs .update ({"shared_auth" : auth })
443+ kwargs .update ({"shared_auth" : {"username" : shared_username ,
444+ "api_key" : shared_api_key }})
439445
440- url = self ._add_credentials (url , ** kwargs ) + query_string
446+ qs_params = self ._add_credentials ({} , ** kwargs )
441447 if shared_ref is not None :
442- url = "%sshared_ref=%s" % (url , shared_ref )
448+ qs_params .update ({"shared_ref" : shared_ref })
449+ qs_params .update (dict (parse .parse_qsl (query_string )))
450+ qs_str = "?%s" % parse .urlencode (qs_params ) if qs_params else ""
443451 if GAE_ENABLED :
444452 try :
445453 req_options = {
446- 'url' : url ,
454+ 'url' : url + qs_str ,
447455 'method' : urlfetch .GET ,
448456 'headers' : ACCEPT_JSON ,
449457 'validate_certificate' : self .domain .verify
@@ -457,7 +465,8 @@ def _get(self, url, query_string='',
457465 location , resource , error )
458466 else :
459467 try :
460- response = requests .get (url , headers = ACCEPT_JSON ,
468+ response = requests .get (url , params = qs_params ,
469+ headers = ACCEPT_JSON ,
461470 verify = self .domain .verify )
462471 except (requests .ConnectionError ,
463472 requests .Timeout ,
@@ -523,12 +532,13 @@ def _list(self, url, query_string='', organization=None):
523532 "code" : code ,
524533 "message" : "The resource couldn't be listed" }}
525534
526- url = self ._add_credentials (url , organization = organization ) + \
527- query_string
535+ qs_params = self ._add_credentials ({}, organization = organization )
536+ qs_params .update (dict (parse .parse_qsl (query_string )))
537+ qs_str = "?%s" % parse .urlencode (qs_params ) if qs_params else ""
528538 if GAE_ENABLED :
529539 try :
530540 req_options = {
531- 'url' : url ,
541+ 'url' : url + qs_str ,
532542 'method' : urlfetch .GET ,
533543 'headers' : ACCEPT_JSON ,
534544 'validate_certificate' : self .domain .verify
@@ -545,7 +555,8 @@ def _list(self, url, query_string='', organization=None):
545555 'error' : error }
546556 else :
547557 try :
548- response = requests .get (url , headers = ACCEPT_JSON ,
558+ response = requests .get (url , params = qs_params ,
559+ headers = ACCEPT_JSON ,
549560 verify = self .domain .verify )
550561 except (requests .ConnectionError ,
551562 requests .Timeout ,
@@ -605,12 +616,13 @@ def _update(self, url, body, organization=None, resource_id=None):
605616 "code" : code ,
606617 "message" : "The resource couldn't be updated" }}
607618
608- url = self ._add_credentials (url , organization = organization )
619+ qs_params = self ._add_credentials ({}, organization = organization )
620+ qs_str = "?%s" % parse .urlencode (qs_params ) if qs_params else ""
609621 body = self ._add_project (body , not organization )
610622 if GAE_ENABLED :
611623 try :
612624 req_options = {
613- 'url' : url ,
625+ 'url' : url + qs_str ,
614626 'method' : urlfetch .PUT ,
615627 'headers' : SEND_JSON ,
616628 'payload' : body ,
@@ -626,6 +638,7 @@ def _update(self, url, body, organization=None, resource_id=None):
626638 else :
627639 try :
628640 response = requests .put (url ,
641+ params = qs_params ,
629642 headers = SEND_JSON ,
630643 data = body , verify = self .domain .verify )
631644 except (requests .ConnectionError ,
@@ -672,13 +685,13 @@ def _delete(self, url, query_string='', organization=None,
672685 "status" : {
673686 "code" : code ,
674687 "message" : "The resource couldn't be deleted" }}
675-
676- url = self . _add_credentials ( url , organization = organization ) + \
677- query_string
688+ qs_params = self . _add_credentials ({}, organization = organization )
689+ qs_params . update ( dict ( parse . parse_qsl ( query_string )))
690+ qs_str = "?%s" % parse . urlencode ( qs_params ) if qs_params else ""
678691 if GAE_ENABLED :
679692 try :
680693 req_options = {
681- 'url' : url ,
694+ 'url' : url + qs_str ,
682695 'method' : urlfetch .DELETE ,
683696 'validate_certificate' : self .domain .verify
684697 }
@@ -693,7 +706,8 @@ def _delete(self, url, query_string='', organization=None,
693706 'error' : error }
694707 else :
695708 try :
696- response = requests .delete (url , verify = self .domain .verify )
709+ response = requests .delete (url , params = qs_params ,
710+ verify = self .domain .verify )
697711 except (requests .ConnectionError ,
698712 requests .Timeout ,
699713 requests .RequestException ) as exc :
@@ -740,11 +754,12 @@ def _download(self, url, filename=None, wait_time=10, retries=10,
740754 if counter > 2 * retries :
741755 LOGGER .error ("Retries exhausted trying to download the file." )
742756 return file_object
743-
757+ qs_params = self ._add_credentials ({})
758+ qs_str = "?%s" % parse .urlencode (qs_params ) if qs_params else ""
744759 if GAE_ENABLED :
745760 try :
746761 req_options = {
747- 'url' : self . _add_credentials ( url ) ,
762+ 'url' : url + qs_str ,
748763 'method' : urlfetch .GET ,
749764 'validate_certificate' : self .domain .verify
750765 }
@@ -755,7 +770,7 @@ def _download(self, url, filename=None, wait_time=10, retries=10,
755770 return file_object
756771 else :
757772 try :
758- response = requests .get (self . _add_credentials ( url ) ,
773+ response = requests .get (url , params = qs_params ,
759774 verify = self .domain .verify ,
760775 stream = True )
761776 except (requests .ConnectionError ,
@@ -856,13 +871,14 @@ def _status(self, url, query_string='', organization=None):
856871 "status" : {
857872 "code" : code ,
858873 "message" : "Failed to obtain the account status info" }}
874+ qs_params = self ._add_credentials ({}, organization = organization )
875+ qs_params .update (dict (parse .parse_qsl (query_string )))
876+ qs_str = "?%s" % parse .urlencode (qs_params ) if qs_params else ""
859877
860- url = self ._add_credentials (url , organization = organization ) \
861- + query_string
862878 if GAE_ENABLED :
863879 try :
864880 req_options = {
865- 'url' : url ,
881+ 'url' : url + qs_str ,
866882 'method' : urlfetch .GET ,
867883 'headers' : ACCEPT_JSON ,
868884 'validate_certificate' : self .domain .verify
@@ -877,7 +893,8 @@ def _status(self, url, query_string='', organization=None):
877893 'error' : error }
878894 else :
879895 try :
880- response = requests .get (url , headers = ACCEPT_JSON ,
896+ response = requests .get (url , params = qs_params ,
897+ headers = ACCEPT_JSON ,
881898 verify = self .domain .verify )
882899 except (requests .ConnectionError ,
883900 requests .Timeout ,
0 commit comments