https://simonwillison.net/atom/everything 11月07日 02:30
升级Datasette插件以兼容1.0 Alpha版本
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文记录了作者升级Datasette插件以兼容其1.0 Alpha版本的详细过程。作者通过录制视频并附带详细笔记,展示了如何使用`uv`工具运行测试,处理`pyproject.toml`依赖版本问题,以及如何手动调试和定位因`Datasette.permission_allowed()`方法缺失导致的500错误。文章还介绍了使用Codex进行自动化修复的实验性方法,以及如何通过`git commit`和发布新版本到PyPI来完成插件的更新。最后,作者分享了视频制作的经验和对未来内容创作的展望。

📦 **插件兼容性升级**: 作者旨在将现有的Datasette插件更新至兼容最新的1.0 Alpha版本。这一过程始于运行插件的测试,以发现潜在的不兼容问题。在升级过程中,作者发现`pyproject.toml`中对Datasette的依赖版本被固定,导致了冲突,通过将其修改为 `>=` 版本解决了这一问题。

🐞 **错误排查与定位**: 在初步的测试通过后,作者意识到测试覆盖不足,未能捕捉到预期的权限相关错误。通过手动运行插件并创建演示数据库,作者成功复现了因`Datasette.permission_allowed()`方法在1.0 Alpha版本中被移除而导致的500错误。随后,作者更新了测试用例,使其能够触发并验证此错误。

🤖 **自动化修复尝试**: 为了演示更高效的更新方式,作者尝试使用Codex工具结合`tadd`命令,自动读取Datasette升级文档并应用必要的修复,最终使测试通过。这被视为一种“代理循环”的设计,为AI提供了工具和目标,使其能够自主完成任务。

🚀 **发布与验证**: 完成代码修改后,作者使用`git commit`记录了更新内容,并按照既定模式将插件发布到PyPI。最后,通过`uvx`命令在新环境中安装并运行带有新发布插件的Datasette实例,以此验证插件的正常工作,确保了发布质量。

Video + notes on upgrading a Datasette plugin for the latest 1.0 alpha

6th November 2025

I’m upgrading various plugins for compatibility with the new Datasette 1.0a20 alpha release and I decided to record a video of the process. This post accompanies that video with detailed additional notes.

The datasette-checkbox plugin

I picked a very simple plugin to illustrate the upgrade process (possibly too simple). datasette-checkbox adds just one feature to Datasette: if you are viewing a table with boolean columns (detected as integer columns with names like is_active or has_attachments or should_notify) and your current user has permission to update rows in that table it adds an inline checkbox UI that looks like this:

I built the first version with the help of Claude back in August 2024—details in this issue comment.

Most of the implementation is JavaScript that makes calls to Datasette 1.0’s JSON write API. The Python code just checks that the user has the necessary permissions before including the extra JavaScript.

Running the plugin’s tests

The first step in upgrading any plugin is to run its tests against the latest Datasette version.

Thankfully uv makes it easy to run code in scratch virtual environments that include the different code versions you want to test against.

I have a test utility called tadd (for “test against development Datasette”) which I use for that purpose. I can run it in any plugin directory like this:

And it will run the existing plugin tests against whatever version of Datasette I have checked out in my ~/dev/datasette directory.

You can see the full implementation of tadd (and its friend radd described below) in this TIL—the basic version looks like this:

#!/bin/shuv run --no-project --isolated \  --with-editable '.[test]' --with-editable ~/dev/datasette \  python -m pytest "$@"

I started by running tadd in the datasette-checkbox directory, and got my first failure... but it wasn’t due to permissions, it was because the pyproject.toml for the plugin was pinned to a specific mismatched version of Datasette:

dependencies = [    "datasette==1.0a19"]

I fixed this problem by swapping == to >= and ran the tests again... and they passed! Which was a problem because I was expecting permission-related failures.

It turns out when I first wrote the plugin I was lazy with the tests—they weren’t actually confirming that the table page loaded without errors.

I needed to actually run the code myself to see the expected bug.

First I created myself a demo database using sqlite-utils create-table:

sqlite-utils create-table demo.db \  demo id integer is_checked integer --pk id

Then I ran it with Datasette against the plugin’s code like so:

Sure enough, visiting /demo/demo produced a 500 error about the missing Datasette.permission_allowed() method.

The next step was to update the test to also trigger this error:

@pytest.mark.asyncioasync def test_plugin_adds_javascript():    datasette = Datasette()    db = datasette.add_memory_database("demo")    await db.execute_write(        "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, is_active INTEGER)"    )    await datasette.invoke_startup()    response = await datasette.client.get("/demo/test")    assert response.status_code == 200

And now tadd fails as expected.

Upgrading the plugin with Codex

It this point I could have manually fixed the plugin itself—which would likely have been faster given the small size of the fix—but instead I demonstrated a bash one-liner I’ve been using to apply these kinds of changes automatically:

codex exec --dangerously-bypass-approvals-and-sandbox \"Run the command tadd and look at the errors and thenread ~/dev/datasette/docs/upgrade-1.0a20.md and applyfixes and run the tests again and get them to pass"

codex exec runs OpenAI Codex in non-interactive mode—it will loop until it has finished the prompt you give it.

I tell it to consult the subset of the Datasette upgrade documentation that talks about Datasette permissions and then get the tadd command to pass its tests.

This is an example of what I call designing agentic loops—I gave Codex the tools it needed (tadd) and a clear goal and let it get to work on my behalf.

The remainder of the video covers finishing up the work—testing the fix manually, commiting my work using:

git commit -a -m "$(basename "$PWD") for datasette>=1.0a20" \  -m "Refs https://github.com/simonw/datasette/issues/2577"

Then shipping a 0.1a4 release to PyPI using the pattern described in this TIL.Finally, I demonstrated that the shipped plugin worked in a fresh environment using uvx like this:

uvx --prerelease=allow --with datasette-checkbox \  datasette --root ~/dev/ecosystem/datasette-checkbox/demo.db

Executing this command installs and runs a fresh Datasette instance with a fresh copy of the new alpha plugin (--prerelease=allow). It’s a neat way of confirming that freshly released software works as expected.

A colophon for the video

This video was shot in a single take using Descript, with no rehearsal and perilously little preparation in advance. I recorded through my AirPods and applied the “Studio Sound” filter to clean up the audio. I pasted in a simonwillison.net closing slide from my previous video and exported it locally at 1080p, then uploaded it to YouTube.

Something I learned from the Software Carpentry instructor training course is that making mistakes in front of an audience is actively helpful—it helps them see a realistic version of how software development works and they can learn from watching you recover. I see this as a great excuse for not editing out all of my mistakes!

I’m trying to build new habits around video content that let me produce useful videos while minimizing the amount of time I spend on production.

I plan to iterate more on the format as I get more comfortable with the process. I’m hoping I can find the right balance between production time and value to viewers.

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Datasette 插件开发 Python Alpha 升级 AI Codex uv Plugin Development Python Alpha Upgrade AI Codex uv
相关文章