docs: def populate(self, *restrictions, suppress_errors=False, return_exception_objects=False,
                   reserve_jobs=False, order="original", limit=None, max_calls=None,
                   display_progress=False):
          """
          rel.populate() calls rel.make(key) for every primary key in self.key_source
          for which there is not already a tuple in rel.
          :param restrictions: a list of restrictions each restrict (rel.key_source - target.proj())
          :param suppress_errors: if True, do not terminate execution.
          :param return_exception_objects: return error objects instead of just error messages
          :param reserve_jobs: if true, reserves job to populate in asynchronous fashion
          :param order: "original"|"reverse"|"random"  - the order of execution
          :param display_progress: if True, report progress_bar
          :param limit: if not None, checks at most that many keys
          :param max_calls: if not None, populates at max that many keys
          """
          if self.connection.in_transaction:
              raise DataJointError('Populate cannot be called during a transaction.')
  
          valid_order = ['original', 'reverse', 'random']
          if order not in valid_order:
              raise DataJointError('The order argument must be one of %s' % str(valid_order))
          error_list = [] if suppress_errors else None
          jobs = self.connection.schemas[self.target.database].jobs if reserve_jobs else None
  
          # define and setup signal handler for SIGTERM
          if reserve_jobs:
              def handler(signum, frame):
                  logger.info('Populate terminated by SIGTERM')
                  raise SystemExit('SIGTERM received')
              old_handler = signal.signal(signal.SIGTERM, handler)
  
          keys = (self._jobs_to_do(restrictions) - self.target).fetch("KEY", limit=limit)
          if order == "reverse":
              keys.reverse()
          elif order == "random":
              random.shuffle(keys)
  
          call_count = 0
          logger.info('Found %d keys to populate' % len(keys))
  
          make = self._make_tuples if hasattr(self, '_make_tuples') else self.make
  
          for key in (tqdm(keys) if display_progress else keys):
              if max_calls is not None and call_count >= max_calls:
                  break
              if not reserve_jobs or jobs.reserve(self.target.table_name, self._job_key(key)):
                  self.connection.start_transaction()
                  if key in self.target:  # already populated
                      self.connection.cancel_transaction()
                      if reserve_jobs:
                          jobs.complete(self.target.table_name, self._job_key(key))
                  else:
                      logger.info('Populating: ' + str(key))
                      call_count += 1
                      self._allow_insert = True
                      try:
                          make(dict(key))
                      except (KeyboardInterrupt, SystemExit, Exception) as error:
                          try:
                              self.connection.cancel_transaction()
                          except OperationalError:
                              pass
                          error_message = '{exception}{msg}'.format(
                              exception=error.__class__.__name__,
                              msg=': ' + str(error) if str(error) else '')
                          if reserve_jobs:
                              # show error name and error message (if any)
                              jobs.error(
                                  self.target.table_name, self._job_key(key),
                                  error_message=error_message, error_stack=traceback.format_exc())
                          if not suppress_errors or isinstance(error, SystemExit):
                              raise
                          else:
                              logger.error(error)
                              error_list.append((key, error if return_exception_objects else error_message))
                      else:
                          self.connection.commit_transaction()
                          if reserve_jobs:
                              jobs.complete(self.target.table_name, self._job_key(key))
                      finally:
                          self._allow_insert = False
  
          # place back the original signal handler
          if reserve_jobs:
              signal.signal(signal.SIGTERM, old_handler)
          return error_list