def _parse_stage_spec(stage_spec):
    """
    Handle alternate Stage specifications, returning name and Stage.

    Isolate this parsing logic from any iteration. TypeError as single
    exception type funnel also provides a more uniform way for callers to
    handle specification errors (e.g., skip a stage, warn, re-raise, etc.)

    :param (str, pypiper.Stage) | callable stage_spec: name and Stage
    :return (name, pypiper.Stage): Pair of name and Stage instance from parsing
        input specification
    :raise TypeError: if the specification of the stage is not a supported type
    """

    # The logic used here, a message to a user about how to specify Stage.
    req_msg = "Stage specification must be either a {0} itself, a " \
              "(<name>, {0}) pair, or a callable with a __name__ attribute " \
              "(e.g., a non-anonymous function)".format(Stage.__name__)

    # Simplest case is stage itself.
    if isinstance(stage_spec, Stage):
        return stage_spec.name, stage_spec

    # Handle alternate forms of specification.
    try:
        # Unpack pair of name and stage, requiring name first.
        name, stage = stage_spec
    except (TypeError, ValueError):
        # Normally, this sort of unpacking issue create a ValueError. Here,
        # though, we also need to catch TypeError since that's what arises
        # if an attempt is made to unpack a single function.
        # Attempt to parse stage_spec as a single named callable.
        try:
            name = stage_spec.__name__
        except AttributeError:
            raise TypeError(req_msg)
        else:
            # Control flow here indicates an anonymous function that was not
            # paired with a name. Prohibit that.
            if name == (lambda: None).__name__:
                raise TypeError(req_msg)
        stage = stage_spec

    # Ensure that the stage is callable.
    if not hasattr(stage, "__call__"):
        raise TypeError(req_msg)

    return name, Stage(stage, name=name)
Handle alternate Stage specifications, returning name and Stage.

    Isolate this parsing logic from any iteration. TypeError as single
    exception type funnel also provides a more uniform way for callers to
    handle specification errors (e.g., skip a stage, warn, re-raise, etc.)

    :param (str, pypiper.Stage) | callable stage_spec: name and Stage
    :return (name, pypiper.Stage): Pair of name and Stage instance from parsing
        input specification
    :raise TypeError: if the specification of the stage is not a supported type