(cls, tables)
return [
            (name, (cls(row) for row in coerce_to_list_of_rows(rows)))
            for name, rows in tables
        ]
Take a list of tuples (name, SINGLE_ROW) or (name, (ROW, ROW, ...)). The rows can be generators.
Take a list of tuples (name, SINGLE_ROW) or (name, (ROW, ROW, ...)). The rows can be generators.
Take a list of tuples ( name SINGLE_ROW ) or ( name ( ROW ROW ... )) . The rows can be generators .
def wrap_all_rows(cls, tables):
        """
        Take a list of tuples (name, SINGLE_ROW) or (name, (ROW, ROW, ...)). The rows can be generators.
        """

        def coerce_to_list_of_rows(rows):
            rows = iter(rows)
            # peek at the first element, then add it back
            try:
                first_entry = next(rows)
            except StopIteration:
                return rows
            rows = itertools.chain([first_entry], rows)
            if first_entry and (not hasattr(first_entry, '__iter__') or isinstance(first_entry, str)):
                # `rows` is actually just a single row, so wrap it
                return [rows]
            return rows

        return [
            (name, (cls(row) for row in coerce_to_list_of_rows(rows)))
            for name, rows in tables
        ]
def wrap_all_rows ( cls , tables ) : def coerce_to_list_of_rows ( rows ) : rows = iter ( rows ) # peek at the first element, then add it back try : first_entry = next ( rows ) except StopIteration : return rows rows = itertools . chain ( [ first_entry ] , rows ) if first_entry and ( not hasattr ( first_entry , '__iter__' ) or isinstance ( first_entry , str ) ) : # `rows` is actually just a single row, so wrap it return [ rows ] return rows return [ ( name , ( cls ( row ) for row in coerce_to_list_of_rows ( rows ) ) ) for name , rows in tables ]