<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def wait(self, progress=None):
 """ Allow background threads to process until the task queue is empty. If there are no threads, in theory the queue should always be empty as processing happens immediately on the main thread. Optional: progress: (bool or str) show a tqdm progress bar optionally with a description if a string is provided Returns: self (for chaining) Raises: The first exception recieved from threads """

    if not len(self._threads):
      return self

    desc = None
    if type(progress) is str:
      desc = progress

    last = self._inserted
    with tqdm(total=self._inserted, disable=(not progress), desc=desc) as pbar:
      # Allow queue to consume, but check up on
      # progress and errors every tenth of a second
      while not self._queue.empty():
        size = self._queue.qsize()
        delta = last - size
        if delta != 0: # We should crash on negative numbers
          pbar.update(delta)
        last = size
        self._check_errors()
        time.sleep(0.1)

      # Wait until all tasks in the queue are 
      # fully processed. queue.task_done must be
      # called for each task.
      self._queue.join() 
      self._check_errors()

      final = self._inserted - last
      if final:
        pbar.update(final)

    if self._queue.empty():
      self._inserted = 0

    return self