code: def prev_item(self, key, default=_sentinel):
          
          # removed graingets version, because it was little slower on CPython and much slower on pypy
          # this version runs about 4x faster with pypy than the Cython version
          # Note: Code sharing of prev_item() and floor_item() is possible, but has always a speed penalty.
          node = self._root
          prev_node = None
  
          while node is not None:
              cmp = self._cmp(self._cmp_data, key, node.key)
              if cmp == 0:
                  break
              elif cmp < 0:
                  node = node.left
              else:
                  if (prev_node is None) or self._cmp(self._cmp_data, prev_node.key, node.key) < 0:
                      prev_node = node
                  node = node.right
  
          if node is None:  # stay at dead end (None)
              if default is _sentinel:
                  raise KeyError(str(key))
              return default
          # found node of key
          if node.left is not None:
              # find biggest node of left subtree
              node = node.left
              while node.right is not None:
                  node = node.right
              if prev_node is None:
                  prev_node = node
              elif self._cmp(self._cmp_data, prev_node.key, node.key) < 0:
                  prev_node = node
          elif prev_node is None:  # given key is smallest in tree
              if default is _sentinel:
                  raise KeyError(str(key))
              return default
          return prev_node.key, prev_node.value
docs: Get predecessor (k,v) pair of key, raises KeyError if key is min key
          or key does not exist. optimized for pypy.