Skip to content

Commit c8bc292

Browse files
committed
Changing query string separator in API calls
1 parent 2269890 commit c8bc292

File tree

7 files changed

+93
-66
lines changed

7 files changed

+93
-66
lines changed

HISTORY.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
History
44
-------
55

6+
9.7.0 (2023-12-06)
7+
------------------
8+
9+
- Changing query string separator in internall API calls.
10+
611
9.6.2 (2023-08-02)
712
------------------
813

bigml/api_handlers/sourcehandler.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
import sys
2525
import os
2626
import numbers
27+
28+
from urllib import parse
29+
2730
try:
2831
#added to allow GAE to work
2932
from google.appengine.api import urlfetch
@@ -183,13 +186,13 @@ def _create_local_source(self, file_name, args=None):
183186
file_handler = file_name
184187
except IOError:
185188
sys.exit("ERROR: cannot read training set")
186-
187-
url = self._add_credentials(self.source_url)
189+
qs_params = self._add_credentials({})
190+
qs_str = "?%s" % parse.urlencode(qs_params) if qs_params else ""
188191
create_args = self._add_project(create_args, True)
189192
if GAE_ENABLED:
190193
try:
191194
req_options = {
192-
'url': url,
195+
'url': self.source_url + qs_str,
193196
'method': urlfetch.POST,
194197
'headers': SEND_JSON,
195198
'data': create_args,
@@ -210,7 +213,8 @@ def _create_local_source(self, file_name, args=None):
210213
files.update(create_args)
211214
multipart = MultipartEncoder(fields=files)
212215
response = requests.post( \
213-
url,
216+
self.source_url,
217+
params=qs_params,
214218
headers={'Content-Type': multipart.content_type},
215219
data=multipart, verify=self.domain.verify)
216220
except (requests.ConnectionError,

bigml/bigmlconnection.py

Lines changed: 66 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io
2525
import logging
2626

27+
from urllib import parse
28+
2729
try:
2830
import simplejson as json
2931
except 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,

bigml/dataset.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"""
2121
import os
2222
import logging
23+
import warnings
2324

2425
from bigml.fields import Fields, sorted_headers, get_new_fields
2526
from bigml.api import get_api_connection, get_dataset_id, get_status
@@ -29,13 +30,13 @@
2930
from bigml.flatline import Flatline
3031
from bigml.featurizer import Featurizer
3132

32-
# avoiding tensorflow info logging
33-
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
34-
logging.getLogger('tensorflow').setLevel(logging.ERROR)
35-
3633
#pylint: disable=locally-disabled,bare-except,ungrouped-imports
3734
try:
35+
# avoiding tensorflow info logging
36+
warnings.filterwarnings("ignore", category=DeprecationWarning)
37+
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
3838
import tensorflow as tf
39+
tf.get_logger().setLevel('ERROR')
3940
tf.autograph.set_verbosity(0)
4041
from bigml.images.featurizers import ImageFeaturizer as Featurizer
4142
except:

bigml/deepnet.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,10 @@
4242
"""
4343
import logging
4444
import os
45+
import warnings
4546

4647
from functools import cmp_to_key
4748

48-
# avoiding tensorflow info logging
49-
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
50-
logging.getLogger('tensorflow').setLevel(logging.ERROR)
51-
5249
from bigml.api import FINISHED
5350
from bigml.api import get_status, get_api_connection, get_deepnet_id
5451
from bigml.util import cast, use_cache, load, get_data_transformations, \
@@ -65,7 +62,11 @@
6562
import bigml.laminar.preprocess_np as pp
6663

6764
try:
65+
# avoiding tensorflow info logging
66+
warnings.filterwarnings("ignore", category=DeprecationWarning)
67+
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
6868
import tensorflow as tf
69+
tf.get_logger().setLevel('ERROR')
6970
tf.autograph.set_verbosity(0)
7071
LAMINAR_VERSION = False
7172
except Exception:

0 commit comments

Comments
 (0)