Source code for openmnglab.util.iterables
from typing import TypeVar, Type, Iterable, Sequence, Callable
T = TypeVar('T')
[docs]def ensure_sequence(inp: Iterable[T] | T | None, type: Type[T],
sequence_constructor: Callable[[Iterable[T]], Sequence[T]] = tuple) -> Sequence[T]:
"""Ensures that the input is a sequence.
.. seealso::
:func:`ensure_iterable` for a varaint of this function which will return an interable
.. seealso::
:func:`unpack_sequence` for the inverse operation
Run checks:
1. ``inp`` is ``None``: returns an empty tuple
2. ``inp`` is an instace of ``type``: returns a tuple with ``inp`` as sole element
3. ``inp`` implements type ``Sequence``: return ``inp`` without modification
4. Attempts to convert ``inp`` to a ``Sequence`` by invoking ``sequence_constructor``
:param inp: Value to convert to a sequence
:param type: Type of the value(s) passed to ``inp``
:param sequence_constructor: Callable used to convert ``inp`` to a ``Sequence``, defaults to ``tuple``.
:return: A sequence of values
"""
if inp is None:
return tuple()
elif isinstance(inp, type):
return (inp,)
elif isinstance(inp, Sequence):
return inp
else:
return sequence_constructor(inp)
[docs]def ensure_iterable(inp: Iterable[T] | T | None, type: Type[T]) -> Iterable[T]:
"""Ensures that the input is an iterable of the given type.
.. warning::
Only works if ``inp`` is either ``None``, of type ``type`` or an iterable of said type (see checks)
.. seealso::
:func:`ensure_sequence` for a varaint of this function which will ensure a sequence
(including automatic conversion from iterable to tuple)
.. seealso::
:func:`unpack_sequence` for the inverse operation for sequences
performs the following checks:
1. ``inp`` is ``None``: returns an empty tuple
2. ``inp`` is an instace of ``type``: returns a tuple with ``inp`` as sole element
3. return ``inp`` without modification
:param inp: Iterable, a single item of type ``type`` or ``None``
:param type: Base type of data in ``inp``
:return: An iterable of element(s) from ``inp`` or an empty tuple if ``inp`` is ``None``
"""
if inp is None:
return tuple()
elif isinstance(inp, type):
return (inp,)
else:
return inp
[docs]def unpack_sequence(inp: Sequence[T]) -> Sequence[T] | T | None:
"""Unpacks a sequence, based on the following conditions:
.. seealso::
:func:`ensure_iterable` for the inverse operation
1. ``inp`` has no items: return ``None``
2. ``inp`` has one item: return that item
3. ``inp`` has more items: return ``inp``
:param inp: A sequence of items
:return: ``None`` if ``inp`` is empty, the single value of ``inp`` or ``inp`` if it contains more than one item
"""
if len(inp) == 0:
return None
elif len(inp) == 1:
return inp[0]
else:
return inp