def first_process_containing_io(input_name, output_name, atlas_entities):
    """
    Return the first entity in a list that contains the inputs and outputs.
    If input_name and output_name are the only or one of the many inputs and
    outputs (respectively), it will count as a match.

    :param str inputs:
        The qualified name of an atlas entity or a '*' wildcard
        that matches to any input (empty list or filled in values)
    :param str outputs: The qualified name of an atlas entity.
    :param atlas_entities: The list of atlas entities to search over.
    :type atlas_entities: list(:class:`~pyapacheatlas.core.entity.AtlasEntity`)
    :raises ValueError:
        A matching entity was not found in the provided entities.
    :return: The atlas entity that maches.
    :rtype: :class:`~pyapacheatlas.core.entity.AtlasEntity`
    """
    output_entity = None
    for entity in atlas_entities:
        input_matches = False
        output_matches = False
        if "inputs" in entity.attributes and "outputs" in entity.attributes:
            num_inputs = len(entity.attributes["inputs"])
            num_outputs = len(entity.attributes["outputs"])
            input_matches = ((input_name == "*") or  # Wildcard
                             ((input_name is None) and (num_inputs == 0)) or
                             ((input_name is not None) and (num_inputs > 0) and
                              (any([e["qualifiedName"] ==
                                    input_name for e in entity.inputs]))
                              )
                             )
            output_matches = (
                ((output_name is None) and (num_outputs == 0)) or
                ((output_name is not None) and (num_outputs > 0) and
                    (any([e["qualifiedName"] == output_name for e in entity.outputs]))
                 )
            )
        if input_matches and output_matches:
            output_entity = entity

    if output_entity is None:
        num_entities = len(atlas_entities)
        raise ValueError(
            "Unable to find a process that includes input "
            f"qualified names: {input_name} and output "
            f"qualified names: {output_name} from the "
            f"{num_entities} provided."
            .format(
                input_name=input_name, output_name=output_name,
                num_entities=num_entities
            )
        )

    return output_entity