Conversation
Implements the column types feature that lets Datasette and plugins annotate columns with semantic types beyond SQLite storage types (e.g. markdown, email, url, json, file, point). This enables type-appropriate rendering, validation, form widgets, and API behavior. Key changes: - New `column_types` internal DB table for storing assignments - `ColumnType` dataclass in datasette/column_types.py with render_cell, validate, and transform_value methods - `register_column_types` plugin hook for registering types - Built-in url, email, and json column types - Datasette API methods: get/set/remove_column_type(s), get_column_type_class - Config loading from datasette.json `column_types` table config key - `column_types` extra on the table JSON endpoint - Column type info in display_columns extra - Column type render_cell gets priority in rendering pipeline - column_type/column_type_config args added to render_cell hookspec - Write-path validation on insert and update https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
- Add transform_value integration in table JSON endpoint rows - Add tests for: duplicate type name error, row endpoint rendering, transform_value in JSON output, column type priority over plugins, row detail HTML rendering, table HTML rendering, upsert validation, unknown type warning logging, config overwrite on restart, and no-config edge case - Total: 34 column type tests, all passing https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
SQLite allows NULLs in primary key columns by default, so mark database_name, resource_name, and column_name as NOT NULL explicitly. https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
- Add register_column_types(datasette) hook documentation with example - Update render_cell signature to include column_type and column_type_config parameters - Fixes test_plugin_hooks_are_documented https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
Add documentation for get_column_type, get_column_types, set_column_type, remove_column_type, and get_column_type_class methods on the Datasette instance. https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2667 +/- ##
==========================================
+ Coverage 90.50% 90.59% +0.09%
==========================================
Files 53 55 +2
Lines 8132 8308 +176
==========================================
+ Hits 7360 7527 +167
- Misses 772 781 +9 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
datasette/views/database.py
Outdated
| column_type=None, | ||
| column_type_config=None, |
There was a problem hiding this comment.
These are None because here we are displaying rows in an arbitrary SQL query so we can't (easily) look up column types.
datasette/views/table.py
Outdated
| else: | ||
| col_dict["column_type"] = None | ||
| col_dict["column_type_config"] = None |
There was a problem hiding this comment.
Moving this into the original col_dict = {...
Set column_type and column_type_config to None in the initial col_dict instead of using an else branch. https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
datasette/default_column_types.py
Outdated
| UrlColumnType(name="url", description="URL"), | ||
| EmailColumnType(name="email", description="Email address"), | ||
| JsonColumnType(name="json", description="JSON data"), |
There was a problem hiding this comment.
I don't like how we have to pass name= and description= here, I want those on the classes.
docs/internals.rst
Outdated
| Returns a ``(column_type_name, config)`` tuple for the specified column. ``column_type_name`` is a string like ``"email"`` or ``"url"``, and ``config`` is a dict or ``None``. If no column type is assigned, returns ``(None, None)``. | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| ct_name, config = await datasette.get_column_type( | ||
| "mydb", "mytable", "email_col" | ||
| ) |
There was a problem hiding this comment.
I'm not sure the return type of this is right. Can we return an instantiated ColumnType class instead perhaps?
Instead of passing name= and description= as constructor arguments, define them as class attributes on each subclass. This better reflects that they are intrinsic to the type, not configurable per-instance. https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
docs/plugin_hooks.rst
Outdated
| register_column_types(datasette) | ||
| -------------------------------- | ||
|
|
||
| Return a list of :ref:`ColumnType <column_types>` instances to register custom column types. Column types define how values in specific columns are rendered, validated, and transformed. |
There was a problem hiding this comment.
I think this should return a list of classes, not instances. We can then use instances for column types that have had their config attached to them.
- register_column_types() now returns classes instead of instances
- ColumnType.__init__ takes optional config=, baking it into the instance
- get_column_type() returns a ColumnType instance (or None) instead of a
(name, config) tuple
- get_column_types() returns {col: ColumnType instance} instead of tuples
- Remove get_column_type_class() - no longer needed
- render_cell/validate/transform_value methods no longer take config arg;
use self.config instead
- render_cell hook takes column_type (ColumnType or None) instead of
column_type + column_type_config
https://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
tests/test_column_types.py
Outdated
|
|
||
| ct = TestType(config={"key": "value"}) | ||
| assert ct.config == {"key": "value"} | ||
| assert ct.name == "test" |
Implements the column types feature that lets Datasette and plugins annotate
columns with semantic types beyond SQLite storage types (e.g. markdown, email,
url, json, file, point). This enables type-appropriate rendering, validation,
form widgets, and API behavior.
Key changes:
column_typesinternal DB table for storing assignmentsColumnTypedataclass in datasette/column_types.py with render_cell,validate, and transform_value methods
register_column_typesplugin hook for registering typesget_column_type_class
column_typestable config keycolumn_typesextra on the table JSON endpointhttps://claude.ai/code/session_01SvPEPqHgURTWESRp28pTC3
📚 Documentation preview 📚: https://datasette--2667.org.readthedocs.build/en/2667/