Apply only the with_plugs that the phase knows.

  This will determine the subset of plug overrides for only plugs the phase
  actually has.

  Args:
    phase: phase_descriptor.PhaseDescriptor or PhaseGroup or callable, or
        iterable of those, the phase or phase group (or iterable) to apply the
        plug changes to.
    **subplugs: mapping from plug name to derived plug class, the subplugs to
        apply.

  Raises:
    openhtf.plugs.InvalidPlugError: if a specified subplug class is not a valid
        replacement for the specified plug name.

  Returns:
    phase_descriptor.PhaseDescriptor or PhaseGroup or iterable with the updated
    plugs.

def optionally_with_plugs(phase, **subplugs):
  """Apply only the with_plugs that the phase knows.

  This will determine the subset of plug overrides for only plugs the phase
  actually has.

  Args:
    phase: phase_descriptor.PhaseDescriptor or PhaseGroup or callable, or
        iterable of those, the phase or phase group (or iterable) to apply the
        plug changes to.
    **subplugs: mapping from plug name to derived plug class, the subplugs to
        apply.

  Raises:
    openhtf.plugs.InvalidPlugError: if a specified subplug class is not a valid
        replacement for the specified plug name.

  Returns:
    phase_descriptor.PhaseDescriptor or PhaseGroup or iterable with the updated
    plugs.
  """
  if isinstance(phase, PhaseGroup):
    return phase.with_plugs(**subplugs)
  if isinstance(phase, collections.Iterable):
    return [optionally_with_plugs(p, **subplugs) for p in phase]

  if not isinstance(phase, phase_descriptor.PhaseDescriptor):
    phase = phase_descriptor.PhaseDescriptor.wrap_or_copy(phase)
  return phase.with_known_plugs(**subplugs)