def _apriori_gen(frequent_sets):
    """
    Generate candidate itemsets

    :param frequent_sets: list of tuples, containing frequent itemsets [ORDERED]

    >>> _apriori_gen([('A',), ('B',), ('C',)])
    [('A', 'B'), ('A', 'C'), ('B', 'C')]
    >>> _apriori_gen([('A', 'B'), ('A', 'C'), ('B', 'C')])
    [('A', 'B', 'C')]
    >>> _apriori_gen([tuple(item) for item in ['ABC', 'ABD', 'ABE', 'ACD', 'BCD', 'BCE', 'CDE']])
    [('A', 'B', 'C', 'D'), ('A', 'B', 'C', 'E'), ('A', 'B', 'D', 'E'), ('B', 'C', 'D', 'E')]
    >>> cc = [('55015', '55314'), ('55015', '55315'), ('55314', '55315'), ('57016', '57017'), ('57043', '57047'), ('581325', '582103')]
    >>> _apriori_gen(cc)
    [('55015', '55314', '55315')]
    """

    # Sanity check for the input
    errors = [freq for freq in frequent_sets if sorted(list(set(freq))) != sorted(list(freq))]
    assert not errors, errors

    assert sorted(list(set(frequent_sets))) == sorted(frequent_sets), \
        set([(x, frequent_sets.count(x)) for x in frequent_sets if frequent_sets.count(x) > 1])

    new_candidates = []
    for index, frequent_item in enumerate(frequent_sets):
        for next_item in frequent_sets[index + 1:]:
            if len(frequent_item) == 1:
                new_candidates.append(tuple(frequent_item) + tuple(next_item))
            elif frequent_item[:-1] == next_item[:-1]:
                new_candidates.append(tuple(frequent_item) + (next_item[-1],))
            else:
                break

    return new_candidates