import itertools


def build_src_summary(sources, convert_ints=False):
    """
    Condenses sources by merging consecutive integers into a string range.

    For example, [1, 2, 3, 5] => ["1-3", 5]. Non-integers are simply copied to the result,
    so for example [1, 2, 3, "18-36", 42] =>  ["1-3", "18-36", 42].

    :param sources: an iterable of integer values, e.g. line numbers
    :param convert_ints: if True, convert any single integers in the result to strings
    :return: a list of source ranges, where ranges are strings and any single sources are
        either ints or strings as determined by convert_ints
    """
    src_ranges = []

    def pairwise(iterable):
        # make two independent iterators
        a, b = itertools.tee(iterable)
        # advance the second by one
        next(b, None)
        # return pairwise groupings from two iterators
        return zip(a, b)

    range_start = None
    next_val = None
    if len(sources) < 2:
        return [str(v) if convert_ints else v for v in sources]
    for current, next_val in pairwise(sources):
        if range_start is None and isinstance(current, int):
            range_start = current
        if not isinstance(current, int):
            src_ranges.append(current)
        elif next_val != current + 1:
            if range_start != current:
                src_ranges.append(f"{range_start}-{current}")
            else:
                src_ranges.append(str(current) if convert_ints else current)
            range_start = None
    else:
        if range_start is not None:
            src_ranges.append(f"{range_start}-{next_val}")
        else:
            src_ranges.append(str(next_val) if convert_ints else next_val)
    return src_ranges