Datasette gives plugins a documented database interface
Datasette 0.36 documents the application object, adds database registration methods, and supplies database context to connection hooks.
A plugin that receives an application object still needs to know which methods it can rely on. An object can expose implementation details without making them a supported interface. Datasette 0.36 addresses that distinction by documenting selected methods on its Datasette class. Its release announcement, published on February 22, also introduces methods for adding and removing databases and expands the context available when preparing SQLite connections.
The change matters for applications that use SQLite files as separately managed datasets. A plugin can register a database through a named operation instead of depending on undocumented application internals. Connection preparation can distinguish the database being opened. Together, these changes give extensions more control over which databases the application serves and how their connections behave.
I like SQLite's direct relationship between an application and its database file. Datasette adds a publishing application around that file, so the quality of its extension interface matters independently of the SQL engine. A small documented interface is easier to reason about than a large object whose supported methods are unclear.
Documentation establishes the supported methods
The class documentation in the 0.36 tag explicitly distinguishes documented methods from the other methods on the object. It says the class should not be considered stable before Datasette 1.0, except for the methods documented there. This is a specific compatibility boundary. Receiving the object does not imply that every attribute or method belongs to the supported plugin contract.
The documented methods cover database registration and removal, plugin configuration, and template rendering. Those operations correspond to tasks extensions need to perform without reconstructing the application's internal organization. The documentation gives their argument meanings and examples, which makes the intended use inspectable without treating the entire implementation as an API specification.
Database registration takes both a unique name and a Database instance. The name also determines the URL path under which Datasette serves the database. This means registration establishes an application-level identity as well as associating a file with the running application. A filename and a public database name are different inputs, even when an application chooses similar strings for them.
The release's documented form looks like this:
from datasette.database import Database
datasette.add_database(
"reports",
Database(
datasette,
path="path/to/reports.db",
is_mutable=True,
),
)
This is a fragment for code that already has the datasette application instance. It registers a mutable database under the name reports. The corresponding removal operation is datasette.remove_database("reports"), using the registered name. Removal describes taking the database out of the application, and should not be read as a promise to delete the underlying file.
Mutability is part of registration
The Database constructor accepts the application instance and a path, with optional is_mutable and is_memory arguments. The documentation instructs plugin authors to use is_mutable when updates to the database are possible. Otherwise Datasette opens the database in immutable mode, and the documentation warns that changes can cause undesired behavior.
That argument carries information about the file's lifecycle into the application. Serving a file does not itself establish that the file will remain unchanged. A plugin that registers externally updated data needs to describe that possibility at registration time. The documented constructor makes this a visible decision in the code that introduces the database.
An in-memory database has its own is_memory option. The interface therefore represents more than a list of filenames. It describes the kind of database the application is attaching and how the application should regard its contents. This is useful separation when plugins become responsible for supplying datasets instead of merely formatting existing pages.
Connection hooks receive database context
The 0.36 plugin documentation describes prepare_connection(conn, database, datasette). Datasette calls the hook when it creates a SQLite connection. The connection allows an extension to register SQL functions, aggregates or collations. The new optional arguments identify the database and provide access to the application object.
Previously written hooks can still request only the connection, as the example in the release documentation does. Extensions that need additional context can request it. The database argument is the database's name, while the application object allows access to plugin configuration. Those meanings are specific enough for a hook to distinguish between databases without deducing identity from unrelated connection behavior.
This is a useful place to make configuration explicit. A connection customization that belongs to one dataset need not become an assumption about every SQLite database the application serves. The hook receives the information needed to make that distinction where the connection is prepared. It does not require changing the SQL engine's own interface.
I see the value of this release in those documented responsibilities. Registration identifies the dataset and its mutability, while the connection hook receives enough context to customize its SQLite connection. Plugin authors still need to stay within the documented methods, because the release explicitly leaves the rest of the application object outside that stability promise.