41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""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)
|