          except Exception:
              self.queue.put(None)
              raise
  
      def iterator(self):
          """ Iterate items out of the queue """
          while True:
              next_item = self.queue.get()
              self.check_and_raise_error()
              if next_item is None or next_item == "EOF":
                  logger.debug("Got EOF OR NONE in BackgroundGenerator")
 
</s> remove     def _run(self):
        """ Put until queue size is reached.
            Note: put blocks only if put is called while queue has already
            reached max size => this makes prefetch + thread_count prefetched items!
            N in the the queue, one waiting for insertion per thread! """
 </s> add     def _run(self) -> None:
        """ Run the :attr:`_generator` and put into the queue until until queue size is reached.

        Raises
        ------
        Exception
            If there is a failure to run the generator and put to the queue
        """ </s> remove         self._gen_kwargs = kwargs or dict()
 </s> add         self._gen_kwargs = kwargs or {} </s> remove     """ Run a queue in the background. From:
        https://stackoverflow.com/questions/7323664/ """
    # See below why prefetch count is flawed
    def __init__(self, generator, prefetch=1, thread_count=2,
                 queue=None, args=None, kwargs=None):
        # pylint:disable=too-many-arguments
        super().__init__(target=self._run, thread_count=thread_count)
        self.queue = queue or Queue.Queue(prefetch)
 </s> add     """ Run a task in the background background and queue data for consumption

    Parameters
    ----------
    generator: iterable
        The generator to run in the background
    prefetch, int, optional
        The number of items to pre-fetch from the generator before blocking (see Notes). Default: 1
    name: str, optional
        The thread name. if ``None`` a unique name is constructed of the form
        {generator.__name__}_N where N is an incrementing integer. Default: ``None``
   args: tuple, Optional
        The argument tuple for generator invocation. Default: ``None``.
    kwargs: dict, Optional
        keyword arguments for the generator invocation. Default: ``None``.

    Notes
    -----
    Putting to the internal queue only blocks if put is called while queue has already
    reached max size. Therefore this means prefetch is actually 1 more than the parameter
    supplied (N in the queue, one waiting for insertion)

    References
    ----------
    https://stackoverflow.com/questions/7323664/
    """
    def __init__(self,
                 generator: Callable,
                 prefetch: int = 1,
                 name: Optional[str] = None,
                 args: Optional[Tuple] = None,
                 kwargs: Optional[Dict[str, Any]] = None) -> None:
        super().__init__(name=name, target=self._run)
        self.queue: Queue.Queue = Queue.Queue(prefetch) </s> remove     def run(self):
 </s> add     def run(self) -> None:
        """ Runs the target, reraising any errors from within the thread in the caller. """
    def iterator(self) -> Generator:
        """ Iterate items out of the queue

        Yields
        ------
        Any
            The items from the generator
        """
          except Exception:
              self.queue.put(None)
              raise
  
    def iterator(self) -> Generator:
        """ Iterate items out of the queue

        Yields
        ------
        Any
            The items from the generator
        """
    def iterator(self) -> Generator:
        """ Iterate items out of the queue

        Yields
        ------
        Any
            The items from the generator
        """
          while True:
              next_item = self.queue.get()
              self.check_and_raise_error()
              if next_item is None or next_item == "EOF":
                  logger.debug("Got EOF OR NONE in BackgroundGenerator")
keep keep keep keep replace replace keep keep keep keep keep
 bugfix - timelapse image loader
multithreading.py - typing + docs 
lib/multithreading.py