docs: def _drain(self, cycles=None):
          """Activate the pump and let the flow go.
  
          This will call the process() method on each attached module until
          a StopIteration is raised, usually by a pump when it reached the EOF.
  
          A StopIteration is also raised when self.cycles was set and the
          number of cycles has reached that limit.
  
          """
          log.info("Now draining...")
          if not cycles:
              log.info("No cycle count, the pipeline may be drained forever.")
  
          if self.calibration:
              log.info("Setting up the detector calibration.")
              for module in self.modules:
                  module.detector = self.calibration.get_detector()
  
          try:
              while not self._stop:
                  cycle_start = timer()
                  cycle_start_cpu = process_time()
  
                  log.debug("Pumping blob #{0}".format(self._cycle_count))
                  self.blob = Blob()
  
                  for module in self.modules:
                      if self.blob is None:
                          log.debug(
                              "Skipping {0}, due to empty blob.".format(
                                  module.name
                              )
                          )
                          continue
                      if module.only_if and not module.only_if.issubset(set(
                              self.blob.keys())):
                          log.debug(
                              "Skipping {0}, due to missing required key"
                              "'{1}'.".format(module.name, module.only_if)
                          )
                          continue
  
                      if (self._cycle_count + 1) % module.every != 0:
                          log.debug(
                              "Skipping {0} (every {1} iterations).".format(
                                  module.name, module.every
                              )
                          )
                          continue
  
                      if module.blob_keys is not None:
                          blob_to_send = Blob({
                              k: self.blob[k]
                              for k in module.blob_keys
                              if k in self.blob
                          })
                      else:
                          blob_to_send = self.blob
  
                      log.debug("Processing {0} ".format(module.name))
                      start = timer()
                      start_cpu = process_time()
                      new_blob = module(blob_to_send)
                      if self.timeit or module.timeit:
                          self._timeit[module]['process'] \
                              .append(timer() - start)
                          self._timeit[module]['process_cpu'] \
                              .append(process_time() - start_cpu)
  
                      if module.blob_keys is not None:
                          if new_blob is not None:
                              for key in new_blob.keys():
                                  self.blob[key] = new_blob[key]
                      else:
                          self.blob = new_blob
  
                  self._timeit['cycles'].append(timer() - cycle_start)
                  self._timeit['cycles_cpu'].append(
                      process_time() - cycle_start_cpu
                  )
                  self._cycle_count += 1
                  if cycles and self._cycle_count >= cycles:
                      raise StopIteration
          except StopIteration:
              log.info("Nothing left to pump through.")
          return self.finish()