Skip to content

Commit e75580c

Browse files
committed
fix dict cleaning & added tests
1 parent 51c2df2 commit e75580c

5 files changed

Lines changed: 75 additions & 25 deletions

File tree

hyperleda/client.py

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,7 @@
66
import pandas
77
import requests
88

9-
from hyperleda import config, error, model
10-
11-
12-
def _clean_dict(d):
13-
"""
14-
Recursively remove keys with None values from the dictionary.
15-
"""
16-
clean = {}
17-
for k, v in d.items():
18-
if isinstance(v, dict):
19-
nested = _clean_dict(v)
20-
if nested: # Only add non-empty nested dictionaries
21-
clean[k] = nested
22-
elif isinstance(v, list):
23-
clean[k] = [_clean_dict(item) for item in v]
24-
elif v is not None:
25-
clean[k] = v
26-
return clean
9+
from hyperleda import config, error, model, utils
2710

2811

2912
def _marshaller(obj):
@@ -53,7 +36,7 @@ def _request(
5336
kwargs = {}
5437

5538
if body is not None:
56-
body = _clean_dict(body) if body is not None else None
39+
body = utils.clean_dict(body) if body is not None else None
5740
data = json.dumps(body, default=_marshaller)
5841
kwargs["data"] = data
5942

hyperleda/utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from typing import Any
2+
3+
4+
def clean_dict(d: Any) -> Any:
5+
"""
6+
Recursively remove keys with None values from the dictionary.
7+
"""
8+
if isinstance(d, list):
9+
return [clean_dict(item) for item in d]
10+
11+
if isinstance(d, dict):
12+
clean = {}
13+
for k, v in d.items():
14+
if isinstance(v, dict):
15+
nested = clean_dict(v)
16+
17+
if nested: # Only add non-empty nested dictionaries
18+
clean[k] = nested
19+
elif v is not None:
20+
clean[k] = clean_dict(v)
21+
return clean
22+
23+
return d

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies = [
2020
"build>=1.2.2.post1",
2121
"datamodel-code-generator>=0.26.5",
2222
"pandas>=2.2.3",
23+
"parameterized>=0.9.0",
2324
"requests>=2.32.3",
2425
"ruff>=0.9.4",
2526
"setuptools>=75.8.0",

requirements.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/utils_test.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
3+
from parameterized import param, parameterized
4+
5+
from hyperleda import utils
6+
7+
8+
class DictCleaningTest(unittest.TestCase):
9+
@parameterized.expand(
10+
[
11+
param(
12+
"no cleaning",
13+
{"a": 1, "b": 2},
14+
{"a": 1, "b": 2},
15+
),
16+
param(
17+
"first level",
18+
{"a": 1, "b": None},
19+
{"a": 1},
20+
),
21+
param(
22+
"third level",
23+
{"a": 1, "b": {"c": {"d": None}}},
24+
{"a": 1},
25+
),
26+
param(
27+
"list",
28+
[{"a": 1, "b": None}, {"a": 2, "b": 3}],
29+
[{"a": 1}, {"a": 2, "b": 3}],
30+
),
31+
param(
32+
"list in dict",
33+
{"a": 1, "b": {"c": [{"d": None}, {"e": 2}]}},
34+
{"a": 1, "b": {"c": [{}, {"e": 2}]}},
35+
),
36+
param(
37+
"list in list",
38+
[[{"c": 2}], [{"a": 1, "b": None}]],
39+
[[{"c": 2}], [{"a": 1}]],
40+
),
41+
param(
42+
"list of primitives",
43+
[1, None, 3],
44+
[1, None, 3],
45+
),
46+
]
47+
)
48+
def test_table(self, name, data, expected):
49+
self.assertEqual(utils.clean_dict(data), expected)

0 commit comments

Comments
 (0)