Skip to content

Commit 6a9adb3

Browse files
tswastplamut
andauthored
fix: handle query_params tuples in JSONConnection.build_api_url (#34)
* fix: handle query_params tuples in JSONConnection.build_api_url The docstring says both dictionary and list of tuples are allowed, following the signature of [urlencode](https://docs.python.org/3.8/library/urllib.parse.html#urllib.parse.urlencode). Discovered while investigating test regression in the `google-cloud-translate` library. * Update google/cloud/_http.py Co-authored-by: Peter Lamut <plamut@users.noreply.github.com>
1 parent 20f787a commit 6a9adb3

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

google/cloud/_http.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414

1515
"""Shared implementation of connections to API servers."""
1616

17+
import collections
1718
import json
1819
import platform
1920
import warnings
2021

2122
from pkg_resources import get_distribution
23+
from six.moves import collections_abc
2224
from six.moves.urllib.parse import urlencode
2325

2426
from google.api_core.client_info import ClientInfo
@@ -212,9 +214,15 @@ def build_api_url(
212214

213215
query_params = query_params or {}
214216

215-
if "prettyPrint" not in query_params:
217+
if isinstance(query_params, collections_abc.Mapping):
216218
query_params = query_params.copy()
217-
query_params["prettyPrint"] = "false"
219+
else:
220+
query_params_dict = collections.defaultdict(list)
221+
for key, value in query_params:
222+
query_params_dict[key].append(value)
223+
query_params = query_params_dict
224+
225+
query_params.setdefault("prettyPrint", "false")
218226

219227
url += "?" + urlencode(query_params, doseq=True)
220228

tests/unit/test__http.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,25 @@ def test_build_api_url_w_extra_query_params(self):
210210
parms = dict(parse_qs(qs))
211211
self.assertEqual(parms["bar"], ["baz"])
212212
self.assertEqual(parms["qux"], ["quux", "corge"])
213+
self.assertEqual(parms["prettyPrint"], ["false"])
214+
215+
def test_build_api_url_w_extra_query_params_tuples(self):
216+
from six.moves.urllib.parse import parse_qs
217+
from six.moves.urllib.parse import urlsplit
218+
219+
client = object()
220+
conn = self._make_mock_one(client)
221+
uri = conn.build_api_url("/foo", [("bar", "baz"), ("qux", "quux"), ("qux", "corge")])
222+
223+
scheme, netloc, path, qs, _ = urlsplit(uri)
224+
self.assertEqual("%s://%s" % (scheme, netloc), conn.API_BASE_URL)
225+
# Intended to emulate mock_template
226+
PATH = "/".join(["", "mock", conn.API_VERSION, "foo"])
227+
self.assertEqual(path, PATH)
228+
parms = dict(parse_qs(qs))
229+
self.assertEqual(parms["bar"], ["baz"])
230+
self.assertEqual(parms["qux"], ["quux", "corge"])
231+
self.assertEqual(parms["prettyPrint"], ["false"])
213232

214233
def test__make_request_no_data_no_content_type_no_headers(self):
215234
from google.cloud._http import CLIENT_INFO_HEADER

0 commit comments

Comments
 (0)