# Source code for sortedcollections.nearestdict

    """NearestDict implementation.

    One primary use case for this data structure is storing data by a
    `datetime.datetime` or `float` key.
    """

    from sortedcontainers import SortedDict

    class NearestDict(SortedDict):
        """A dict using nearest-key lookup.

        A :class:`SortedDict` subclass that uses nearest-key lookup instead of
        exact-key lookup. Optionally, you can specify a rounding mode to return the
        nearest key less than or equal to or greater than or equal to the provided
        key.

        When using :attr:`NearestDict.NEAREST` the keys must support subtraction to
        allow finding the nearest key (by find the key with the smallest difference
        to the given one).

        Additional methods:

        * :meth:`NearestDict.nearest_key`

        Example usage:

        >>> d = NearestDict({1.0: 'foo'})
        >>> d[1.0]
        'foo'
        >>> d[0.0]
        'foo'
        >>> d[2.0]
        'foo'
        """

        NEAREST_PREV = -1
        NEAREST = 0
        NEAREST_NEXT = 1

        def __init__(self, *args, **kwargs):
            """Initialize a NearestDict instance.

            Optional `rounding` argument dictates how
            :meth:`NearestDict.nearest_key` rounds. It must be one of
            :attr:`NearestDict.NEAREST_NEXT`, :attr:`NearestDict.NEAREST`, or
            :attr:`NearestDict.NEAREST_PREV`. (Default:
            :attr:`NearestDict.NEAREST`)

            :params rounding: how to round on nearest-key lookup (optional)
            :params args: positional arguments for :class:`SortedDict`.
            :params kwargs: keyword arguments for :class:`SortedDict`.
            """
            self.rounding = kwargs.pop('rounding', self.NEAREST)
            super().__init__(*args, **kwargs)

        def nearest_key(self, request):
            """Return nearest-key to `request`, respecting `self.rounding`.

            >>> d = NearestDict({1.0: 'foo'})
            >>> d.nearest_key(0.0)
            1.0
            >>> d.nearest_key(2.0)
            1.0

            >>> d = NearestDict({1.0: 'foo'}, rounding=NearestDict.NEAREST_PREV)
            >>> d.nearest_key(0.0)
            Traceback (most recent call last):
              ...
            KeyError: 'No key below 0.0 found'
            >>> d.nearest_key(2.0)
            1.0

            :param request: nearest-key lookup value
            :return: key nearest to `request`, respecting `rounding`
            :raises KeyError: if no appropriate key can be found
            """
            key_list = self.keys()

            if not key_list:
                raise KeyError('NearestDict is empty')

            index = self.bisect_left(request)

            if index >= len(key_list):
                if self.rounding == self.NEAREST_NEXT:
                    raise KeyError(f'No key above {request!r} found')
                return key_list[index - 1]
            if key_list[index] == request:
                return key_list[index]
            if index == 0 and self.rounding == self.NEAREST_PREV:
                raise KeyError(f'No key below {request!r} found')
            if self.rounding == self.NEAREST_PREV:
                return key_list[index - 1]
            if self.rounding == self.NEAREST_NEXT:
                return key_list[index]
            if abs(key_list[index - 1] - request) < abs(key_list[index] - request):
                return key_list[index - 1]
            return key_list[index]

        def __getitem__(self, request):
            """Return item corresponding to :meth:`.nearest_key`.

            :param request: nearest-key lookup value
            :return: item corresponding to key nearest `request`
            :raises KeyError: if no appropriate item can be found

            >>> d = NearestDict({1.0: 'foo'})
            >>> d[0.0]
            'foo'
            >>> d[2.0]
            'foo'

            >>> d = NearestDict({1.0: 'foo'}, rounding=NearestDict.NEAREST_NEXT)
            >>> d[0.0]
            'foo'
            >>> d[2.0]
            Traceback (most recent call last):
              ...
            KeyError: 'No key above 2.0 found'
            """
            key = self.nearest_key(request)
            return super().__getitem__(key)