Optionally limit ColumnType subclasses to specific SQLite types (#2673)

* ColumnTypes now have optional SQLite column types

Refs #2672
This commit is contained in:
Simon Willison 2026-03-18 11:37:09 -07:00 committed by GitHub
commit feaba9b18b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 198 additions and 10 deletions

View file

@ -1103,6 +1103,8 @@ These configure :ref:`full-text search <full_text_search>` for a table or view.
You can assign semantic column types to columns, which affect how values are rendered, validated, and transformed. Built-in column types include ``url``, ``email``, and ``json``. Plugins can register additional column types using the :ref:`register_column_types <plugin_register_column_types>` plugin hook.
Column types can optionally declare which SQLite column types they apply to using ``sqlite_types``. Datasette will reject incompatible assignments. The built-in ``url``, ``email``, and ``json`` column types are all restricted to ``TEXT`` columns.
The simplest form maps column names to type name strings:
.. [[[cog
@ -1210,4 +1212,3 @@ For column types that accept additional configuration, use an object with ``type
}
.. [[[end]]]

View file

@ -968,6 +968,7 @@ await .set_column_type(database, resource, column, column_type, config=None)
Optional configuration dict for the column type.
Assigns a column type to a column. Overwrites any existing assignment for that column.
Raises ``ValueError`` if the column type declares ``sqlite_types`` and the target column does not match one of those SQLite types.
.. code-block:: python

View file

@ -1004,13 +1004,14 @@ Return a list of :ref:`ColumnType <column_types>` **subclasses** (not instances)
.. code-block:: python
from datasette import hookimpl
from datasette.column_types import ColumnType
from datasette.column_types import ColumnType, SQLiteType
import markupsafe
class ColorColumnType(ColumnType):
name = "color"
description = "CSS color value"
sqlite_types = (SQLiteType.TEXT,)
async def render_cell(
self,
@ -1052,6 +1053,9 @@ Each ``ColumnType`` subclass must define the following class attributes:
``description`` - string
Human-readable label, e.g. ``"CSS color value"``.
``sqlite_types`` - tuple of ``SQLiteType`` values, optional
Restrict assignments of this column type to columns with matching SQLite types, e.g. ``(SQLiteType.TEXT,)``. If omitted, the column type can be assigned to any column.
And the following methods, all optional:
``render_cell(self, value, column, table, database, datasette, request)``
@ -2485,4 +2489,3 @@ Tokens can then be created and verified using :ref:`datasette.create_token() <da
actor = await datasette.verify_token(token)
If no handlers are registered, ``create_token()`` raises ``RuntimeError``. If the requested ``handler`` name is not found, it raises ``ValueError``.