Skip to content

Commit fd3b08b

Browse files
committed
Added new 'Len' and 'double_chain' functions to utils.
1 parent aa30ae8 commit fd3b08b

File tree

2 files changed

+83
-4
lines changed

2 files changed

+83
-4
lines changed

domdf_python_tools/utils.py

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,11 @@ def strtobool(val: Union[str, bool]) -> bool:
245245
246246
If val is an integer then its boolean representation is returned. If val is a boolean it is returned as-is.
247247
248-
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
249-
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
250-
'val' is anything else.
248+
:py:obj:`True` values are ``'y'``, ``'yes'``, ``'t'``, ``'true'``, ``'on'``, ``'1'``, and ``1``.
249+
250+
:py:obj:`False` values are ``'n'``, ``'no'``, ``'f'``, ``'false'``, ``'off'``, ``'0'``, and ``0``.
251+
252+
:raises: :py:exc:`ValueError` if 'val' is anything else.
251253
252254
Based on distutils
253255
"""
@@ -281,3 +283,52 @@ def enquote_value(value: Any) -> Union[str, bool, float]:
281283
return repr(value)
282284
else:
283285
return f"'{value}'"
286+
287+
288+
def Len(obj: Any, start: int = 0, step: int = 1) -> range:
289+
"""
290+
Shorthand for ``range(len(obj))``.
291+
292+
Returns an object that produces a sequence of integers from start (inclusive)
293+
to len(obj) (exclusive) by step.
294+
295+
:param obj: The object to iterate over the length of.
296+
:param start: The start value of the range.
297+
:param step: The step of the range.
298+
299+
.. versionadded:: 0.4.7
300+
"""
301+
302+
return range(start, len(obj), step)
303+
304+
305+
def double_chain(iterable: Iterable[Iterable]):
306+
"""
307+
Flatten a list of lists of lists into a single list.
308+
309+
Literally just:
310+
311+
.. code-block:: python
312+
313+
chain.from_iterable(chain.from_iterable(iterable))
314+
315+
Converts
316+
317+
.. code-block:: python
318+
319+
[[(1, 2), (3, 4)], [(5, 6), (7, 8)]]
320+
321+
to
322+
323+
.. code-block:: python
324+
325+
[1, 2, 3, 4, 5, 6, 7, 8]
326+
327+
328+
:param iterable: The iterable to
329+
:return:
330+
331+
.. versionadded:: 0.4.7
332+
"""
333+
334+
yield from itertools.chain.from_iterable(itertools.chain.from_iterable(iterable))

tests/test_utils.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
# this package
2121
from domdf_python_tools import utils
22-
from domdf_python_tools.utils import chunks, list2str, list2string, pyversion, str2tuple, tuple2str
22+
from domdf_python_tools.utils import Len, chunks, double_chain, list2str, list2string, pyversion, str2tuple
2323

2424

2525
def test_pyversion():
@@ -389,3 +389,31 @@ def test_cmp():
389389

390390
assert isinstance(utils.cmp(20, 20), int)
391391
assert utils.cmp(20, 20) == 0
392+
393+
394+
@pytest.mark.parametrize(
395+
"value, expects",
396+
[
397+
([[(1, 2), (3, 4)], [(5, 6), (7, 8)]], [1, 2, 3, 4, 5, 6, 7, 8]),
398+
([[(1, 2), (3, 4)], ((5, 6), (7, 8))], [1, 2, 3, 4, 5, 6, 7, 8]),
399+
([((1, 2), (3, 4)), [(5, 6), (7, 8)]], [1, 2, 3, 4, 5, 6, 7, 8]),
400+
([((1, 2), (3, 4)), ((5, 6), (7, 8))], [1, 2, 3, 4, 5, 6, 7, 8]),
401+
((((1, 2), (3, 4)), ((5, 6), (7, 8))), [1, 2, 3, 4, 5, 6, 7, 8]),
402+
((("12", "34"), ("56", "78")), ["1", "2", "3", "4", "5", "6", "7", "8"]),
403+
]
404+
)
405+
def test_double_chain(value, expects):
406+
assert list(double_chain(value)) == expects
407+
408+
409+
def test_len(capsys):
410+
assert list(Len("Hello")) == [0, 1, 2, 3, 4]
411+
assert list(Len("Hello World")) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
412+
413+
for val in Len("Hello World"):
414+
print(val)
415+
416+
captured = capsys.readouterr()
417+
assert captured.out.splitlines() == ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
418+
419+
assert Len("Hello") == range(5)

0 commit comments

Comments
 (0)