docs: def watch_run_status(server, project, run, apikey, timeout=None, update_period=1):
      """
      Monitor a linkage run and yield status updates. Will immediately yield an update and then
      only yield further updates when the status object changes. If a timeout is provided and the
      run hasn't entered a terminal state (error or completed) when the timeout is reached,
      updates will cease and a TimeoutError will be raised.
  
      :param server: Base url of the upstream server.
      :param project:
      :param run:
      :param apikey:
      :param timeout: Stop waiting after this many seconds. The default (None) is to never give you up.
      :param update_period: Time in seconds between queries to the run's status.
      :raises TimeoutError
      """
      start_time = time.time()
      status = old_status = run_get_status(server, project, run, apikey)
      yield status
  
      def time_not_up():
          return (
              (timeout is None) or
              (time.time() - start_time < timeout)
          )
  
      while time_not_up():
  
          if status['state'] in {'error', 'completed'}:
              # No point continuing as run has entered a terminal state
              yield status
              return
  
          if old_status != status:
              yield status
  
          time.sleep(update_period)
          old_status = status
          try:
              status = run_get_status(server, project, run, apikey)
          except RateLimitedClient:
              time.sleep(1)
      raise TimeoutError("Timeout exceeded before run {} terminated".format(run))