docs: def daterange(start, stop, step=1, inclusive=False):
      """In the spirit of :func:`range` and :func:`xrange`, the `daterange`
      generator that yields a sequence of :class:`~datetime.date`
      objects, starting at *start*, incrementing by *step*, until *stop*
      is reached.
  
      When *inclusive* is True, the final date may be *stop*, **if**
      *step* falls evenly on it. By default, *step* is one day. See
      details below for many more details.
  
      Args:
          start (datetime.date): The starting date The first value in
              the sequence.
          stop (datetime.date): The stopping date. By default not
              included in return. Can be `None` to yield an infinite
              sequence.
          step (int): The value to increment *start* by to reach
              *stop*. Can be an :class:`int` number of days, a
              :class:`datetime.timedelta`, or a :class:`tuple` of integers,
              `(year, month, day)`. Positive and negative *step* values
              are supported.
          inclusive (bool): Whether or not the *stop* date can be
              returned. *stop* is only returned when a *step* falls evenly
              on it.
  
      >>> christmas = date(year=2015, month=12, day=25)
      >>> boxing_day = date(year=2015, month=12, day=26)
      >>> new_year = date(year=2016, month=1,  day=1)
      >>> for day in daterange(christmas, new_year):
      ...     print(repr(day))
      datetime.date(2015, 12, 25)
      datetime.date(2015, 12, 26)
      datetime.date(2015, 12, 27)
      datetime.date(2015, 12, 28)
      datetime.date(2015, 12, 29)
      datetime.date(2015, 12, 30)
      datetime.date(2015, 12, 31)
      >>> for day in daterange(christmas, boxing_day):
      ...     print(repr(day))
      datetime.date(2015, 12, 25)
      >>> for day in daterange(date(2017, 5, 1), date(2017, 8, 1),
      ...                      step=(0, 1, 0), inclusive=True):
      ...     print(repr(day))
      datetime.date(2017, 5, 1)
      datetime.date(2017, 6, 1)
      datetime.date(2017, 7, 1)
      datetime.date(2017, 8, 1)
  
      *Be careful when using stop=None, as this will yield an infinite
      sequence of dates.*
      """
      if not isinstance(start, date):
          raise TypeError("start expected datetime.date instance")
      if stop and not isinstance(stop, date):
          raise TypeError("stop expected datetime.date instance or None")
      try:
          y_step, m_step, d_step = step
      except TypeError:
          y_step, m_step, d_step = 0, 0, step
      else:
          y_step, m_step = int(y_step), int(m_step)
      if isinstance(d_step, int):
          d_step = timedelta(days=int(d_step))
      elif isinstance(d_step, timedelta):
          pass
      else:
          raise ValueError('step expected int, timedelta, or tuple'
                           ' (year, month, day), not: %r' % step)
  
      if stop is None:
          finished = lambda t: False
      elif start < stop:
          finished = operator.gt if inclusive else operator.ge
      else:
          finished = operator.lt if inclusive else operator.le
      now = start
  
      while not finished(now, stop):
          yield now
          if y_step or m_step:
              m_y_step, cur_month = divmod(now.month + m_step, 12)
              now = now.replace(year=now.year + y_step + m_y_step,
                                month=cur_month or 12)
          now = now + d_step
      return