Skip to content

Commit 41f3d8d

Browse files
committed
Add type hints
1 parent 560e0ce commit 41f3d8d

File tree

162 files changed

+2077
-1225
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

162 files changed

+2077
-1225
lines changed

benedict/core/clean.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
def _clean_dict(d, strings, collections):
1+
from collections.abc import MutableMapping, MutableSequence
2+
from typing import Any, TypeVar
3+
4+
_K = TypeVar("_K")
5+
_V = TypeVar("_V")
6+
_T = TypeVar("_T")
7+
8+
9+
def _clean_dict(
10+
d: MutableMapping[_K, _V], strings: bool, collections: bool
11+
) -> MutableMapping[_K, _V]:
212
keys = list(d.keys())
313
for key in keys:
414
d[key] = _clean_value(d[key], strings=strings, collections=collections)
@@ -7,41 +17,47 @@ def _clean_dict(d, strings, collections):
717
return d
818

919

10-
def _clean_list(ls, strings, collections):
20+
def _clean_list(
21+
ls: MutableSequence[_T], strings: bool, collections: bool
22+
) -> MutableSequence[_T]:
1123
for i in range(len(ls) - 1, -1, -1):
1224
ls[i] = _clean_value(ls[i], strings=strings, collections=collections)
1325
if ls[i] is None:
1426
ls.pop(i)
1527
return ls
1628

1729

18-
def _clean_set(values, strings, collections):
30+
def _clean_set(values: set[_T], strings: bool, collections: bool) -> set[_T]:
1931
return {
2032
value
2133
for value in values
2234
if _clean_value(value, strings=strings, collections=collections) is not None
2335
}
2436

2537

26-
def _clean_str(s, strings, collections):
38+
def _clean_str(s: str, strings: bool, collections: bool) -> str | None:
2739
return s if s and s.strip() else None
2840

2941

30-
def _clean_tuple(values, strings, collections):
42+
def _clean_tuple(
43+
values: tuple[_T, ...], strings: bool, collections: bool
44+
) -> tuple[_T, ...]:
3145
return tuple(
3246
value
3347
for value in values
3448
if _clean_value(value, strings=strings, collections=collections) is not None
3549
)
3650

3751

38-
def _clean_value(value, strings, collections):
52+
def _clean_value(value: Any, strings: bool, collections: bool) -> Any:
3953
if value is None:
4054
return value
41-
elif isinstance(value, list) and collections:
55+
elif isinstance(value, MutableSequence) and collections:
4256
value = _clean_list(value, strings=strings, collections=collections) or None
43-
elif isinstance(value, dict) and collections:
44-
value = _clean_dict(value, strings=strings, collections=collections) or None
57+
elif isinstance(value, MutableMapping) and collections:
58+
value = (
59+
_clean_dict(dict(value), strings=strings, collections=collections) or None
60+
)
4561
elif isinstance(value, set) and collections:
4662
value = _clean_set(value, strings=strings, collections=collections) or None
4763
elif isinstance(value, str) and strings:
@@ -51,5 +67,5 @@ def _clean_value(value, strings, collections):
5167
return value
5268

5369

54-
def clean(d, strings=True, collections=True):
70+
def clean(d: Any, strings: bool = True, collections: bool = True) -> Any:
5571
return _clean_dict(d, strings=strings, collections=collections)

benedict/core/clone.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
11
import copy
2+
from collections.abc import Mapping, MutableMapping
3+
from typing import Any, Literal, TypeVar, overload
24

5+
_K = TypeVar("_K")
6+
_V = TypeVar("_V")
37

4-
def clone(obj, empty=False, memo=None):
8+
9+
@overload
10+
def clone(
11+
obj: MutableMapping[_K, _V],
12+
empty: Literal[True],
13+
memo: dict[int, Any] | None = None,
14+
) -> MutableMapping[_K, _V]: ...
15+
16+
17+
@overload
18+
def clone(
19+
obj: Mapping[_K, _V], empty: Literal[False], memo: dict[int, Any] | None = None
20+
) -> Mapping[_K, _V]: ...
21+
22+
23+
@overload
24+
def clone(obj: Any, empty: bool = False, memo: dict[int, Any] | None = None) -> Any: ...
25+
26+
27+
def clone(
28+
obj: Any | MutableMapping[_K, _V] | Mapping[_K, _V],
29+
empty: bool = False,
30+
memo: dict[int, Any] | None = None,
31+
) -> MutableMapping[_K, _V] | Mapping[_K, _V] | Any:
532
d = copy.deepcopy(obj, memo)
6-
if empty:
33+
if empty and isinstance(d, MutableMapping):
734
d.clear()
835
return d

benedict/core/dump.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
from typing import Any
2+
13
from benedict.serializers import JSONSerializer
24

35

4-
def dump(obj, **kwargs):
6+
def dump(obj: Any, **kwargs: Any) -> str:
57
serializer = JSONSerializer()
68
options = {"indent": 4, "sort_keys": True}
79
options.update(**kwargs)

benedict/core/filter.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1-
from benedict.core import clone
1+
from collections.abc import Callable, MutableMapping
2+
from typing import TypeVar
23

4+
from benedict.core.clone import clone
35

4-
def filter(d, predicate):
6+
_V = TypeVar("_V")
7+
8+
9+
def filter(
10+
d: MutableMapping[str, _V | None], predicate: Callable[[str, _V | None], bool]
11+
) -> MutableMapping[str, _V | None]:
512
if not callable(predicate):
613
raise ValueError("predicate argument must be a callable.")
714
new_dict = clone(d, empty=True)
815
keys = list(d.keys())
916
for key in keys:
10-
value = d.get(key, None)
17+
value = d.get(key)
1118
if predicate(key, value):
1219
new_dict[key] = value
1320
return new_dict

benedict/core/find.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
def find(d, keys, default=None):
1+
from collections.abc import Iterable, Mapping
2+
from typing import TypeVar
3+
4+
_K = TypeVar("_K")
5+
_V = TypeVar("_V")
6+
7+
8+
def find(
9+
d: Mapping[_K, _V], keys: Iterable[_K], default: _V | None = None
10+
) -> _V | None:
211
for key in keys:
312
if key in d:
4-
return d.get(key, default)
13+
return d[key]
514
return default

benedict/core/flatten.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1-
from benedict.core import clone
2-
from benedict.utils import type_util
1+
from collections.abc import Mapping, MutableMapping
2+
from typing import TypeVar
33

4+
from benedict.core.clone import clone
45

5-
def _flatten_key(base_key, key, separator):
6+
_V = TypeVar("_V")
7+
8+
9+
def _flatten_key(base_key: str, key: str, separator: str) -> str:
610
if base_key and separator:
711
return f"{base_key}{separator}{key}"
812
return key
913

1014

11-
def _flatten_item(d, base_dict, base_key, separator):
15+
def _flatten_item(
16+
d: Mapping[str, _V],
17+
base_dict: MutableMapping[str, _V],
18+
base_key: str,
19+
separator: str,
20+
) -> MutableMapping[str, _V]:
1221
new_dict = base_dict
1322
keys = list(d.keys())
1423
for key in keys:
1524
new_key = _flatten_key(base_key, key, separator)
16-
value = d.get(key, None)
17-
if type_util.is_dict(value):
25+
value = d.get(key, None) # type: ignore[arg-type]
26+
if isinstance(value, Mapping):
1827
new_value = _flatten_item(
1928
value, base_dict=new_dict, base_key=new_key, separator=separator
2029
)
@@ -26,6 +35,8 @@ def _flatten_item(d, base_dict, base_key, separator):
2635
return new_dict
2736

2837

29-
def flatten(d, separator="_"):
30-
new_dict = clone(d, empty=True)
38+
def flatten(
39+
d: MutableMapping[str, _V], separator: str = "_"
40+
) -> MutableMapping[str, _V]:
41+
new_dict: MutableMapping[str, _V] = clone(d, empty=True)
3142
return _flatten_item(d, base_dict=new_dict, base_key="", separator=separator)

benedict/core/groupby.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1+
from collections.abc import Mapping, MutableSequence, Sequence
2+
from typing import Any, TypeVar
3+
14
from benedict.utils import type_util
25

6+
_K = TypeVar("_K")
7+
_V = TypeVar("_V", bound=MutableSequence[Any])
8+
39

4-
def groupby(items, key):
10+
def groupby(
11+
items: Sequence[Mapping[_K, _V | None]], key: _K
12+
) -> dict[_K | None, _V | list[Any]]:
513
if not type_util.is_list(items):
614
raise ValueError("items should be a list of dicts.")
7-
items_grouped = {}
15+
items_grouped: dict[_K | None, _V | list[Any]] = {}
816
for item in items:
917
if not type_util.is_dict(item):
1018
raise ValueError("item should be a dict.")
11-
group = item.get(key)
19+
group: _K | None = item.get(key)
1220
if group not in items_grouped:
1321
items_grouped[group] = []
1422
items_grouped[group].append(item.copy())

benedict/core/invert.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
1-
from benedict.core import clone
1+
from collections.abc import MutableMapping, Sequence
2+
from typing import Any, TypeVar
3+
4+
from benedict.core.clone import clone
25
from benedict.utils import type_util
36

7+
_K = TypeVar("_K")
8+
_V = TypeVar("_V")
9+
410

5-
def _invert_item(d, key, value, flat):
11+
def _invert_item(
12+
d: MutableMapping[_V, _K | list[_K]], key: _K, value: _V, flat: bool
13+
) -> None:
614
if flat:
7-
d.setdefault(value, key)
15+
d[value] = key
816
else:
9-
d.setdefault(value, []).append(key)
17+
d[value] = [key]
1018

1119

12-
def _invert_list(d, key, value, flat):
20+
def _invert_list(
21+
d: MutableMapping[_V, _K | list[_K]], key: _K, value: Sequence[Any], flat: bool
22+
) -> None:
1323
for value_item in value:
1424
_invert_item(d, key, value_item, flat)
1525

1626

17-
def invert(d, flat=False):
18-
new_dict = clone(d, empty=True)
19-
for key, value in d.items():
27+
def invert(
28+
d: MutableMapping[_K, _V], flat: bool = False
29+
) -> MutableMapping[_V, _K | list[_K]]:
30+
orig_dict = clone(d, empty=True)
31+
new_dict: dict[_V, _K | list[_K]] = {}
32+
for key, value in orig_dict.items():
2033
if type_util.is_list_or_tuple(value):
2134
_invert_list(new_dict, key, value, flat)
2235
else:

benedict/core/items_sorted.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
1-
def _items_sorted_by_item_at_index(d, index, reverse):
1+
from collections.abc import Mapping
2+
3+
from useful_types import SupportsRichComparisonT
4+
5+
6+
def _items_sorted_by_item_at_index(
7+
d: Mapping[SupportsRichComparisonT, SupportsRichComparisonT],
8+
index: int,
9+
reverse: bool,
10+
) -> list[tuple[SupportsRichComparisonT, SupportsRichComparisonT]]:
211
return sorted(d.items(), key=lambda item: item[index], reverse=reverse)
312

413

5-
def items_sorted_by_keys(d, reverse=False):
14+
def items_sorted_by_keys(
15+
d: Mapping[SupportsRichComparisonT, SupportsRichComparisonT], reverse: bool = False
16+
) -> list[tuple[SupportsRichComparisonT, SupportsRichComparisonT]]:
617
return _items_sorted_by_item_at_index(d, 0, reverse)
718

819

9-
def items_sorted_by_values(d, reverse=False):
20+
def items_sorted_by_values(
21+
d: Mapping[SupportsRichComparisonT, SupportsRichComparisonT], reverse: bool = False
22+
) -> list[tuple[SupportsRichComparisonT, SupportsRichComparisonT]]:
1023
return _items_sorted_by_item_at_index(d, 1, reverse)

benedict/core/keylists.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
from collections.abc import Mapping, Sequence
2+
from typing import Any
3+
14
from benedict.utils import type_util
25

36

4-
def _get_keylist_for_dict(d, parent_keys, indexes):
7+
def _get_keylist_for_dict(
8+
d: Mapping[Any, Any], parent_keys: list[Any], indexes: bool
9+
) -> list[list[Any]]:
510
keylist = []
611
for key, value in d.items():
712
keys = parent_keys + [key]
@@ -10,7 +15,9 @@ def _get_keylist_for_dict(d, parent_keys, indexes):
1015
return keylist
1116

1217

13-
def _get_keylist_for_list(ls, parent_keys, indexes):
18+
def _get_keylist_for_list(
19+
ls: Sequence[Any], parent_keys: list[Any], indexes: bool
20+
) -> list[list[Any]]:
1421
keylist = []
1522
for key, value in enumerate(ls):
1623
keys = list(parent_keys)
@@ -20,13 +27,17 @@ def _get_keylist_for_list(ls, parent_keys, indexes):
2027
return keylist
2128

2229

23-
def _get_keylist_for_value(value, parent_keys, indexes):
30+
def _get_keylist_for_value(
31+
value: Mapping[Any, Any] | Sequence[Any], parent_keys: list[Any], indexes: bool
32+
) -> list[list[Any]]:
2433
if type_util.is_dict(value):
2534
return _get_keylist_for_dict(value, parent_keys, indexes)
2635
elif type_util.is_list(value) and indexes:
2736
return _get_keylist_for_list(value, parent_keys, indexes)
2837
return []
2938

3039

31-
def keylists(d, indexes=False):
40+
def keylists(
41+
d: Mapping[Any, Any] | Sequence[Any], indexes: bool = False
42+
) -> list[list[Any]]:
3243
return _get_keylist_for_value(d, [], indexes)

0 commit comments

Comments
 (0)