Source code for better_dict.utils
"""
Module defines helper functions for the ``better_dict`` package.
Functions
---------
- :func:`.iterable_not_string`: Check if the value is iterable but not a string.
- :func:`.same_length`: Check if the keys and values have the same length.
- :func:`.make_list`: Make a list from the value.
- :func:`.flatten`: Flatten the iterable object.
"""
from __future__ import annotations
from typing import Any, Generator, Iterable, List
__all__ = [
"flatten",
"iterable_not_string",
"make_list",
"same_length",
]
[docs]def iterable_not_string(value: object) -> bool:
"""Check if the value is iterable but not a string.
Parameters
----------
value : object
Value to check.
Returns
-------
bool
``True`` if the value is iterable but not a string, ``False`` otherwise.
Examples
--------
>>> iterable_not_string([1, 2, 3])
True
>>> iterable_not_string('abc')
False
>>> iterable_not_string(1)
False
"""
return isinstance(value, Iterable) and not isinstance(value, str)
[docs]def same_length(keys: Any, values: Any) -> bool:
"""Check if the keys and values have the same length.
Parameters
----------
keys : Any
Keys to check.
values : Any
Values to check.
Returns
-------
bool
True if the keys and values are iterables and have the same length,
False otherwise.
Examples
--------
>>> same_length([1, 2, 3], [4, 5, 6])
True
>>> same_length([1, 2, 3], [4, 5])
False
>>> same_length([1, 2, 3], 4)
False
"""
if all(
iterable_not_string(value) and hasattr(value, "__len__")
for value in [keys, values]
):
return len(keys) == len(values)
return False
[docs]def make_list(value: Any) -> List[Any]:
"""Make a list from the value.
Parameters
----------
value : Any
Value to make a list from.
Returns
-------
List[Any]
List with the value.
"""
if value is None:
return []
return list(value) if iterable_not_string(value) else [value]
[docs]def flatten(line: Any) -> Generator:
"""Flatten an arbitrarily nested sequence.
Parameters
----------
line : Any
The possibly nested sequence to flatten.
Returns
-------
flattened : generator
A generator that yields the flattened sequence.
Examples
--------
>>> list(flatten([[1, 2, 3], 4, [5, [6, 7, 8]]]))
[1, 2, 3, 4, 5, 6, 7, 8]
>>> list(flatten(1))
[1]
Notes
-----
- This function doesn't consider strings sequences.
- If the input is not a sequence, it is returned as a single element list.
"""
for element in make_list(line):
if iterable_not_string(element):
yield from flatten(element)
else:
yield element