"""Coerce source-DB values into types ``sqlite3`` can bind. pyodbc returns ``NUMERIC``/``DECIMAL``/``MONEY`` as :class:`decimal.Decimal` and date/time columns as :mod:`datetime` objects, none of which ``sqlite3`` binds natively. Cache columns are ``TEXT``, so stringifying is lossless and consistent with how the data is stored. This is done **locally** — never via a global ``sqlite3.register_adapter`` — so the host application's ``sqlite3`` behaviour is left untouched. """ import datetime import decimal import uuid from typing import Any Params = tuple | list | dict | None def to_sqlite(value: Any) -> Any: if isinstance(value, decimal.Decimal): return str(value) if isinstance(value, (datetime.datetime, datetime.date, datetime.time)): return value.isoformat() if isinstance(value, uuid.UUID): return str(value) if isinstance(value, bytearray): return bytes(value) return value def coerce_row(row: tuple) -> tuple: return tuple(to_sqlite(v) for v in row) def coerce_params(params: Params) -> tuple | dict | None: if params is None: return None if isinstance(params, dict): return {key: to_sqlite(val) for key, val in params.items()} return tuple(to_sqlite(val) for val in params)