# Path: boris/portion/const.py
# class Bound(enum.Enum):
# class _Singleton():
# class _PInf(_Singleton):
# class _NInf(_Singleton):
#     CLOSED = True
#     OPEN = False
#     def __bool__(self):
#     def __invert__(self):
#     def __str__(self):
#     def __repr__(self):
#     def __new__(cls, *args, **kwargs):
#     def __neg__(self): return _NInf()
#     def __lt__(self, o): return False
#     def __le__(self, o): return isinstance(o, _PInf)
#     def __gt__(self, o): return not isinstance(o, _PInf)
#     def __ge__(self, o): return True
#     def __eq__(self, o): return isinstance(o, _PInf)
#     def __repr__(self): return '+inf'
#     def __hash__(self): return hash(float('+inf'))
#     def __neg__(self): return _PInf()
#     def __lt__(self, o): return not isinstance(o, _NInf)
#     def __le__(self, o): return True
#     def __gt__(self, o): return False
#     def __ge__(self, o): return isinstance(o, _NInf)
#     def __eq__(self, o): return isinstance(o, _NInf)
#     def __repr__(self): return '-inf'
#     def __hash__(self): return hash(float('-inf'))


import operator
from functools import partial
from .const import inf
    This function returns a (lazy) iterator over the values of given interval,
    starting from its lower bound and ending on its upper bound (if interval is not open).
    Each returned value merely corresponds to lower + i * step, where "step" defines
    the step between consecutive values.
    It also accepts a callable that is used to compute the next possible
    value based on the current one.

    When a non-atomic interval is provided, this function chains the iterators obtained
    by calling itself on the underlying atomic intervals.

    The values returned by the iterator can be aligned with a base value with the "base" parameter.
    This parameter must be a callable that accepts the lower bound of the (atomic) interval as
    input, and returns the first value that needs to be considered for the iteration.
    By default, the identity function is used. If reverse=True, then the upper bound will be
    passed instead of the lower one.

    :param interval: an interval.
    :param step: step between values, or a callable that returns the next value.
    :param base: a callable that accepts a bound and returns an initial value to consider.
    :param reverse: set to True for descending order.
    :return: a lazy iterator.
    """
    if base is None:
        base = (lambda x: x)

    exclude = operator.lt if not reverse else operator.gt
    include = operator.le if not reverse else operator.ge
    step = step if callable(step) else partial(operator.add, step)

    value = base(interval.lower if not reverse else interval.upper)

# Path: boris/portion/const.py
# class Bound(enum.Enum):
# class _Singleton():
# class _PInf(_Singleton):
# class _NInf(_Singleton):
#     CLOSED = True
#     OPEN = False
#     def __bool__(self):
#     def __invert__(self):
#     def __str__(self):
#     def __repr__(self):
#     def __new__(cls, *args, **kwargs):
#     def __neg__(self): return _NInf()
#     def __lt__(self, o): return False
#     def __le__(self, o): return isinstance(o, _PInf)
#     def __gt__(self, o): return not isinstance(o, _PInf)
#     def __ge__(self, o): return True
#     def __eq__(self, o): return isinstance(o, _PInf)
#     def __repr__(self): return '+inf'
#     def __hash__(self): return hash(float('+inf'))
#     def __neg__(self): return _PInf()
#     def __lt__(self, o): return not isinstance(o, _NInf)
#     def __le__(self, o): return True
#     def __gt__(self, o): return False
#     def __ge__(self, o): return isinstance(o, _NInf)
#     def __eq__(self, o): return isinstance(o, _NInf)
#     def __repr__(self): return '-inf'
#     def __hash__(self): return hash(float('-inf'))


# Path: boris/portion/func.py
import operator
from functools import partial
from .const import inf

    This function returns a (lazy) iterator over the values of given interval,
    starting from its lower bound and ending on its upper bound (if interval is not open).
    Each returned value merely corresponds to lower + i * step, where "step" defines
    the step between consecutive values.
    It also accepts a callable that is used to compute the next possible
    value based on the current one.

    When a non-atomic interval is provided, this function chains the iterators obtained
    by calling itself on the underlying atomic intervals.

    The values returned by the iterator can be aligned with a base value with the "base" parameter.
    This parameter must be a callable that accepts the lower bound of the (atomic) interval as
    input, and returns the first value that needs to be considered for the iteration.
    By default, the identity function is used. If reverse=True, then the upper bound will be
    passed instead of the lower one.

    :param interval: an interval.
    :param step: step between values, or a callable that returns the next value.
    :param base: a callable that accepts a bound and returns an initial value to consider.
    :param reverse: set to True for descending order.
    :return: a lazy iterator.
    """
    if base is None:
        base = (lambda x: x)

    exclude = operator.lt if not reverse else operator.gt
    include = operator.le if not reverse else operator.ge
    step = step if callable(step) else partial(operator.add, step)

    value = base(interval.lower if not reverse else interval.upper)

    if (value == -inf and not reverse) or (value == inf and reverse):