Repository: niconoe/pyinaturalist
Pull request #18 (2020-05-06 16:44:27)

Convert python bool parameters to javascript-style boolean strings
Fixes Issue #17
Also adds a fix for handling parameters that accept integer lists (for example, `place_id` in `GET /observations`).

- [x] Confirm working with manual tests
- [x] Add unit tests


Patch:
diff --git a/pyinaturalist/helpers.py b/pyinaturalist/helpers.py
index 85c41be..3571102 100644
--- a/pyinaturalist/helpers.py
+++ b/pyinaturalist/helpers.py
@@ -17,16 +17,24 @@ def get_user_agent(user_agent: str = None) -> str:
         return pyinaturalist.user_agent
 
 
-def concat_list_params(params) -> Dict[str, Any]:
+def convert_bool_params(params: Dict[str, Any]) -> Dict[str, Any]:
+    """Convert any boolean request parameters to javascript-style boolean strings"""
+    for k, v in params.items():
+        if isinstance(v, bool):
+            params[k] = str(v).lower()
+    return params
+
+
+def convert_list_params(params: Dict[str, Any]) -> Dict[str, Any]:
     """Convert any list parameters into an API-compatible (comma-delimited) string.
     Will be url-encoded by requests. For example: `['k1', 'k2', 'k3'] -> k1%2Ck2%2Ck3`
     """
     for k, v in params.items():
         if isinstance(v, list):
-            params[k] = ",".join(v)
+            params[k] = ",".join(map(str, v))
     return params
 
 
-def strip_empty_params(params) -> Dict[str, Any]:
+def strip_empty_params(params: Dict[str, Any]) -> Dict[str, Any]:
     """Remove any request parameters with empty or ``None`` values."""
-    return {k: v for k, v in params.items() if v}
+    return {k: v for k, v in params.items() if v or v is False}
diff --git a/pyinaturalist/node_api.py b/pyinaturalist/node_api.py
index 72ab691..c2c9187 100644
--- a/pyinaturalist/node_api.py
+++ b/pyinaturalist/node_api.py
@@ -12,7 +12,8 @@ from pyinaturalist.exceptions import ObservationNotFound
 from pyinaturalist.helpers import (
     merge_two_dicts,
     get_user_agent,
-    concat_list_params,
+    convert_bool_params,
+    convert_list_params,
     strip_empty_params,
 )
 
@@ -31,8 +32,9 @@ def make_inaturalist_api_get_call(
     kwargs are passed to requests.request
     Returns a requests.Response object
     """
+    params = convert_bool_params(params)
+    params = convert_list_params(params)
     params = strip_empty_params(params)
-    params = concat_list_params(params)
     headers = {"Accept": "application/json", "User-Agent": get_user_agent(user_agent)}
 
     response = requests.get(


Test patch:
diff --git a/test/test_helpers.py b/test/test_helpers.py
new file mode 100644
index 0000000..6b4ca50
--- /dev/null
+++ b/test/test_helpers.py
@@ -0,0 +1,35 @@
+from pyinaturalist.helpers import (
+    convert_bool_params,
+    convert_list_params,
+    strip_empty_params,
+)
+
+
+TEST_PARAMS = {
+    "parent_id": 1,
+    "rank": ["phylum", "class"],
+    "is_active": False,
+    "only_id": "true",
+    "q": "",
+    "locale": None,
+    "preferred_place_id": [1, 2],
+}
+
+
+def test_convert_bool_params():
+    params = convert_bool_params(TEST_PARAMS)
+    assert params["is_active"] == "false"
+    assert params["only_id"] == "true"
+
+
+def test_convert_list_params():
+    params = convert_list_params(TEST_PARAMS)
+    assert params["preferred_place_id"] == "1,2"
+    assert params["rank"] == "phylum,class"
+
+
+def test_strip_empty_params():
+    params = strip_empty_params(TEST_PARAMS)
+    assert len(params) == 5
+    assert "q" not in params and "locale" not in params
+    assert "is_active" in params and "only_id" in params