docs: def _get_internal_status(pipeline_key=None,
                           pipeline_dict=None,
                           slot_dict=None,
                           barrier_dict=None,
                           status_dict=None):
    """Gets the UI dictionary of a pipeline from a set of status dictionaries.
  
    Args:
      pipeline_key: The key of the pipeline to lookup.
      pipeline_dict: Dictionary mapping pipeline db.Key to _PipelineRecord.
        Default is an empty dictionary.
      slot_dict: Dictionary mapping slot db.Key to _SlotRecord.
        Default is an empty dictionary.
      barrier_dict: Dictionary mapping barrier db.Key to _BarrierRecord.
        Default is an empty dictionary.
      status_dict: Dictionary mapping status record db.Key to _StatusRecord.
        Default is an empty dictionary.
  
    Returns:
      Dictionary with the keys:
        classPath: The pipeline function being run.
        args: List of positional argument slot dictionaries.
        kwargs: Dictionary of keyword argument slot dictionaries.
        outputs: Dictionary of output slot dictionaries.
        children: List of child pipeline IDs.
        queueName: Queue on which this pipeline is running.
        afterSlotKeys: List of Slot Ids after which this pipeline runs.
        currentAttempt: Number of the current attempt, starting at 1.
        maxAttempts: Maximum number of attempts before aborting.
        backoffSeconds: Constant factor for backoff before retrying.
        backoffFactor: Exponential factor for backoff before retrying.
        status: Current status of the pipeline.
        startTimeMs: When this pipeline ran or will run due to retries, if present.
        endTimeMs: When this pipeline finalized, if present.
        lastRetryMessage: Why the pipeline failed during the last retry, if there
          was a failure; may be empty.
        abortMessage: For root pipelines, why the pipeline was aborted if it was
          aborted; may be empty.
  
      Dictionary will contain these keys if explicit status is set:
        statusTimeMs: When the status was set as milliseconds since the epoch.
        statusMessage: Status message, if present.
        statusConsoleUrl: The relative URL for the console of this pipeline.
        statusLinks: Dictionary mapping human-readable names to relative URLs
          for related URLs to this pipeline.
  
    Raises:
      PipelineStatusError if any input is bad.
    """
    if pipeline_dict is None:
      pipeline_dict = {}
    if slot_dict is None:
      slot_dict = {}
    if barrier_dict is None:
      barrier_dict = {}
    if status_dict is None:
      status_dict = {}
  
    pipeline_record = pipeline_dict.get(pipeline_key)
    if pipeline_record is None:
      raise PipelineStatusError(
          'Could not find pipeline ID "%s"' % pipeline_key.name())
  
    params = pipeline_record.params
    root_pipeline_key = \
        _PipelineRecord.root_pipeline.get_value_for_datastore(pipeline_record)
    default_slot_key = db.Key(params['output_slots']['default'])
    start_barrier_key = db.Key.from_path(
        _BarrierRecord.kind(), _BarrierRecord.START, parent=pipeline_key)
    finalize_barrier_key = db.Key.from_path(
        _BarrierRecord.kind(), _BarrierRecord.FINALIZE, parent=pipeline_key)
    status_record_key = db.Key.from_path(
        _StatusRecord.kind(), pipeline_key.name())
  
    start_barrier = barrier_dict.get(start_barrier_key)
    finalize_barrier = barrier_dict.get(finalize_barrier_key)
    default_slot = slot_dict.get(default_slot_key)
    status_record = status_dict.get(status_record_key)
    if finalize_barrier is None:
      raise PipelineStatusError(
          'Finalization barrier missing for pipeline ID "%s"' %
          pipeline_key.name())
    if default_slot is None:
      raise PipelineStatusError(
          'Default output slot with key=%s missing for pipeline ID "%s"' % (
          default_slot_key, pipeline_key.name()))
  
    output = {
      'classPath': pipeline_record.class_path,
      'args': list(params['args']),
      'kwargs': params['kwargs'].copy(),
      'outputs': params['output_slots'].copy(),
      'children': [key.name() for key in pipeline_record.fanned_out],
      'queueName': params['queue_name'],
      'afterSlotKeys': [str(key) for key in params['after_all']],
      'currentAttempt': pipeline_record.current_attempt + 1,
      'maxAttempts': pipeline_record.max_attempts,
      'backoffSeconds': pipeline_record.params['backoff_seconds'],
      'backoffFactor': pipeline_record.params['backoff_factor'],
    }
  
    # TODO(user): Truncate args, kwargs, and outputs to < 1MB each so we
    # can reasonably return the whole tree of pipelines and their outputs.
    # Coerce each value to a string to truncate if necessary. For now if the
    # params are too big it will just cause the whole status page to break.
  
    # Fix the key names in parameters to match JavaScript style.
    for value_dict in itertools.chain(
        output['args'], output['kwargs'].itervalues()):
      if 'slot_key' in value_dict:
        value_dict['slotKey'] = value_dict.pop('slot_key')
  
    # Figure out the pipeline's status.
    if pipeline_record.status in (_PipelineRecord.WAITING, _PipelineRecord.RUN):
      if default_slot.status == _SlotRecord.FILLED:
        status = 'finalizing'
      elif (pipeline_record.status == _PipelineRecord.WAITING and
            pipeline_record.next_retry_time is not None):
        status = 'retry'
      elif start_barrier and start_barrier.status == _BarrierRecord.WAITING:
        # start_barrier will be missing for root pipelines
        status = 'waiting'
      else:
        status = 'run'
    elif pipeline_record.status == _PipelineRecord.DONE:
      status = 'done'
    elif pipeline_record.status == _PipelineRecord.ABORTED:
      status = 'aborted'
  
    output['status'] = status
  
    if status_record:
      output['statusTimeMs'] = _get_timestamp_ms(status_record.status_time)
      if status_record.message:
        output['statusMessage'] = status_record.message
      if status_record.console_url:
        output['statusConsoleUrl'] = status_record.console_url
      if status_record.link_names:
        output['statusLinks'] = dict(
            zip(status_record.link_names, status_record.link_urls))
  
    # Populate status-depenedent fields.
    if status in ('run', 'finalizing', 'done', 'retry'):
      if pipeline_record.next_retry_time is not None:
        output['startTimeMs'] = _get_timestamp_ms(pipeline_record.next_retry_time)
      elif start_barrier:
        # start_barrier will be missing for root pipelines
        output['startTimeMs'] = _get_timestamp_ms(start_barrier.trigger_time)
      elif pipeline_record.start_time:
        # Assume this pipeline ran immediately upon spawning with no
        # start barrier or it's the root pipeline.
        output['startTimeMs'] = _get_timestamp_ms(pipeline_record.start_time)
  
    if status in ('finalizing',):
      output['endTimeMs'] = _get_timestamp_ms(default_slot.fill_time)
  
    if status in ('done',):
      output['endTimeMs'] = _get_timestamp_ms(pipeline_record.finalized_time)
  
    if pipeline_record.next_retry_time is not None:
      output['lastRetryMessage'] = pipeline_record.retry_message
  
    if pipeline_record.abort_message:
      output['abortMessage'] = pipeline_record.abort_message
  
    return output