Skip to content

Commit 1c9f830

Browse files
committed
feat: add 'strict' to flatten_query_params to lower-case bools
1 parent 922f468 commit 1c9f830

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

google/api_core/rest_helpers.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import operator
1919

2020

21-
def flatten_query_params(obj):
22-
"""Flatten a nested dict into a list of (name,value) tuples.
21+
def flatten_query_params(obj, strict=False):
22+
"""Flatten a dict into a list of (name,value) tuples.
2323
2424
The result is suitable for setting query params on an http request.
2525
@@ -28,17 +28,19 @@ def flatten_query_params(obj):
2828
>>> obj = {'a':
2929
... {'b':
3030
... {'c': ['x', 'y', 'z']} },
31-
... 'd': 'uvw', }
32-
>>> flatten_query_params(obj)
33-
[('a.b.c', 'x'), ('a.b.c', 'y'), ('a.b.c', 'z'), ('d', 'uvw')]
31+
... 'd': 'uvw',
32+
... 'e': True, }
33+
>>> flatten_query_params(obj, strict=True)
34+
[('a.b.c', 'x'), ('a.b.c', 'y'), ('a.b.c', 'z'), ('d', 'uvw'), ('e', 'true')]
3435
3536
Note that, as described in
3637
https://github.com/googleapis/googleapis/blob/48d9fb8c8e287c472af500221c6450ecd45d7d39/google/api/http.proto#L117,
3738
repeated fields (i.e. list-valued fields) may only contain primitive types (not lists or dicts).
3839
This is enforced in this function.
3940
4041
Args:
41-
obj: a nested dictionary (from json), or None
42+
obj: a possibly nested dictionary (from json), or None
43+
strict: a bool, defaulting to False, to enforce that all values in the result tuples be strings and, if boolean, lower-cased.
4244
4345
Returns: a list of tuples, with each tuple having a (possibly) multi-part name
4446
and a scalar value.
@@ -51,17 +53,17 @@ def flatten_query_params(obj):
5153
if obj is not None and not isinstance(obj, dict):
5254
raise TypeError("flatten_query_params must be called with dict object")
5355

54-
return _flatten(obj, key_path=[])
56+
return _flatten(obj, key_path=[], strict=strict)
5557

5658

57-
def _flatten(obj, key_path):
59+
def _flatten(obj, key_path, strict=False):
5860
if obj is None:
5961
return []
6062
if isinstance(obj, dict):
61-
return _flatten_dict(obj, key_path=key_path)
63+
return _flatten_dict(obj, key_path=key_path, strict=strict)
6264
if isinstance(obj, list):
63-
return _flatten_list(obj, key_path=key_path)
64-
return _flatten_value(obj, key_path=key_path)
65+
return _flatten_list(obj, key_path=key_path, strict=strict)
66+
return _flatten_value(obj, key_path=key_path, strict=strict)
6567

6668

6769
def _is_primitive_value(obj):
@@ -74,21 +76,30 @@ def _is_primitive_value(obj):
7476
return True
7577

7678

77-
def _flatten_value(obj, key_path):
78-
return [(".".join(key_path), obj)]
79+
def _flatten_value(obj, key_path, strict=False):
80+
return [(".".join(key_path), _canonicalize(obj, strict=strict))]
7981

8082

81-
def _flatten_dict(obj, key_path):
82-
items = (_flatten(value, key_path=key_path + [key]) for key, value in obj.items())
83+
def _flatten_dict(obj, key_path, strict=False):
84+
items = (_flatten(value, key_path=key_path + [key], strict=strict) for key, value in obj.items())
8385
return functools.reduce(operator.concat, items, [])
8486

8587

86-
def _flatten_list(elems, key_path):
88+
def _flatten_list(elems, key_path, strict=False):
8789
# Only lists of scalar values are supported.
8890
# The name (key_path) is repeated for each value.
8991
items = (
90-
_flatten_value(elem, key_path=key_path)
92+
_flatten_value(elem, key_path=key_path, strict=strict)
9193
for elem in elems
9294
if _is_primitive_value(elem)
9395
)
9496
return functools.reduce(operator.concat, items, [])
97+
98+
99+
def _canonicalize(obj, strict=False):
100+
if strict:
101+
value = str(obj)
102+
if isinstance(obj, bool):
103+
value = value.lower()
104+
return value
105+
return obj

tests/unit/test_rest_helpers.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,26 @@ def test_flatten_empty_dict():
3636

3737

3838
def test_flatten_simple_dict():
39-
assert rest_helpers.flatten_query_params({"a": "abc", "b": "def"}) == [
39+
obj = {"a": "abc", "b": "def", "c": True, "d": False, "e": 10, "f": -3.76}
40+
assert rest_helpers.flatten_query_params(obj) == [
4041
("a", "abc"),
4142
("b", "def"),
43+
("c", True),
44+
("d", False),
45+
("e", 10),
46+
("f", -3.76),
47+
]
48+
49+
50+
def test_flatten_simple_dict_strict():
51+
obj = {"a": "abc", "b": "def", "c": True, "d": False, "e": 10, "f": -3.76}
52+
assert rest_helpers.flatten_query_params(obj, strict=True) == [
53+
("a", "abc"),
54+
("b", "def"),
55+
("c", "true"),
56+
("d", "false"),
57+
("e", "10"),
58+
("f", "-3.76"),
4259
]
4360

4461

0 commit comments

Comments
 (0)