import csv from dataclasses import dataclass, fields, is_dataclass from typing import TypeVar @dataclass class Widget: name: str amount: int T = TypeVar('T') def deserialize_csv_row(typ: type[T], row: str) -> T: if not is_dataclass(typ): raise TypeError( f'Cannot deserialize type from CSV row: {type(x)}' ) values = [] for cells in csv.reader([row]): x_fields = fields(x) x_fields_len = len(x_fields) cells_len = len(cells) if x_fields_len != cells_len: raise ValueError( f'Row length mismatch: type {typ} expects {x_fields_len} cells ' f'but got {cells_len}' ) for f, cell in zip(x_fields, cells): values.append(deserialize_csv_cell(f.type, cell)) return typ(*values) def deserialize_csv_cell(typ: type[T], cell: str) -> T: if typ is str: return cell if typ is int: return int(cell) raise TypeError( f'Cannot deserialize type from CSV cell: type was {type(x)}' )