Skip to content

Commit 83678e9

Browse files
vchudnov-gparthea
andauthored
feat: add 'strict' to flatten_query_params to lower-case bools (#433)
* feat: add 'strict' to flatten_query_params to lower-case bools * pylint Co-authored-by: Anthonios Partheniou <[email protected]>
1 parent 9066ed4 commit 83678e9

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

google/api_core/rest_helpers.py

Lines changed: 32 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,20 @@ 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
44+
result tuples be strings and, if boolean, lower-cased.
4245
4346
Returns: a list of tuples, with each tuple having a (possibly) multi-part name
4447
and a scalar value.
@@ -51,17 +54,17 @@ def flatten_query_params(obj):
5154
if obj is not None and not isinstance(obj, dict):
5255
raise TypeError("flatten_query_params must be called with dict object")
5356

54-
return _flatten(obj, key_path=[])
57+
return _flatten(obj, key_path=[], strict=strict)
5558

5659

57-
def _flatten(obj, key_path):
60+
def _flatten(obj, key_path, strict=False):
5861
if obj is None:
5962
return []
6063
if isinstance(obj, dict):
61-
return _flatten_dict(obj, key_path=key_path)
64+
return _flatten_dict(obj, key_path=key_path, strict=strict)
6265
if isinstance(obj, list):
63-
return _flatten_list(obj, key_path=key_path)
64-
return _flatten_value(obj, key_path=key_path)
66+
return _flatten_list(obj, key_path=key_path, strict=strict)
67+
return _flatten_value(obj, key_path=key_path, strict=strict)
6568

6669

6770
def _is_primitive_value(obj):
@@ -74,21 +77,33 @@ def _is_primitive_value(obj):
7477
return True
7578

7679

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

8083

81-
def _flatten_dict(obj, key_path):
82-
items = (_flatten(value, key_path=key_path + [key]) for key, value in obj.items())
84+
def _flatten_dict(obj, key_path, strict=False):
85+
items = (
86+
_flatten(value, key_path=key_path + [key], strict=strict)
87+
for key, value in obj.items()
88+
)
8389
return functools.reduce(operator.concat, items, [])
8490

8591

86-
def _flatten_list(elems, key_path):
92+
def _flatten_list(elems, key_path, strict=False):
8793
# Only lists of scalar values are supported.
8894
# The name (key_path) is repeated for each value.
8995
items = (
90-
_flatten_value(elem, key_path=key_path)
96+
_flatten_value(elem, key_path=key_path, strict=strict)
9197
for elem in elems
9298
if _is_primitive_value(elem)
9399
)
94100
return functools.reduce(operator.concat, items, [])
101+
102+
103+
def _canonicalize(obj, strict=False):
104+
if strict:
105+
value = str(obj)
106+
if isinstance(obj, bool):
107+
value = value.lower()
108+
return value
109+
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)