def get_worksheet_data(worksheet, data_range, expected_header=None):
    """Read a range of cells from a worksheet into a list of dictionaries
    treating the first row as a header.

    :param worksheet: a pygsheets Worksheet object
    :param data_range: cell range tuple, e.g. ('A', 'D'), ('A1', 'A17')
    :param expected_header: optional, if passed assert that the first row header
           matches the expected_header exactly
    :return: a list of rows as dictionaries, with the header as keys and
            pygsheet Cell objects as values
    """
    sheet_data = worksheet.get_values(*data_range, returnas="cell")
    header = [c.value for c in sheet_data[0]]
    if expected_header and header != expected_header:
        raise Exception(f"Sheet does not have the expected header: {expected_header}")
    return [{header[i]: row[i] for i in range(len(header))} for row in sheet_data[1:]]