One Character That Broke Everything: The Dependency Pin Trap in Python Plugins
Simon Willison's datasette-export-database 0.3a2 fixed a classic Python packaging mistake — a strict `==` pin that silently locked out most users.
By TRAGenX Desk
Not every release deserves a blog post. But this one — a three-line fix to a pyproject.toml — is worth a minute of your time because it illustrates one of Python packaging's most silently destructive mistakes.
What Happened
Simon Willison, creator of the Datasette data-exploration framework, shipped datasette-export-database 0.3a2 on June 25, 2026. The entire change: swap datasette==1.0a27 for datasette>=1.0a27 in pyproject.toml. That exact-version pin had made the plugin installable only alongside one specific alpha of Datasette — silently refusing to resolve on any newer or older release.
The == vs >= Trap
In Python packaging, datasette==1.0a27 tells pip 'I require this exact version and nothing else.' For an application you fully control, an exact pin can be intentional — a reproducible environment lock. For a plugin that must coexist with whatever version of the host framework the user already has installed, it is almost always wrong.
datasette>=1.0a27 says 'I need at least 1.0a27, but I'm fine with anything newer.' Users on 1.0a28, 1.0, or 1.1 can install without conflict. The plugin stays compatible as the host evolves, without the author shipping a new release every time upstream bumps a digit.
Why Plugin Authors Get This Wrong
The typical failure path: a developer tests against one specific version, copies that version string into pyproject.toml, and ships. The tests pass, CI is green, and nobody notices until a user on a different version hits a resolver conflict. In Willison's own words, the release is 'embarrassingly tiny' — but it unblocked every Datasette user who had moved past 1.0a27.
Practical Rules for Dependency Constraints
- Libraries and plugins: use
>=minimum_tested_versionas the lower bound. Add an upper bound (e.g.,<2.0) only if you have a documented breaking change at that boundary. - Applications and deployable services: use exact pins (
==) or lock files (pip-compile, uv lock) to guarantee reproducible builds. - Pre-release host packages: be aware that
>=1.0a27may require users to opt into pre-releases; test your install instructions against a clean environment. - Automate the check:
pip checkoruv's resolver will surface conflicts before your users do.
The Vibecoding Angle
When you build with AI assistance, your coding agent will generate pyproject.toml dependency lines based on what it knows about the ecosystem. Both == and >= are valid Python syntax — the model won't warn you that one fits apps and the other fits plugins. Knowing *why* the constraint exists is still on you. Adding a packaging-conventions check to your review prompt — 'is every plugin dependency using a minimum bound, not an exact pin?' — costs two seconds and prevents the kind of silent incompatibility Willison caught here.
FAQ
Frequently asked questions
- What is the difference between `==` and `>=` in a Python pyproject.toml dependency?
- `==` requires an exact version match; the resolver will reject any other version. `>=` sets a minimum floor and allows any newer compatible release. For plugins and libraries meant to work alongside a host package, `>=` is almost always the right choice.
- Should I ever use an exact pin in a plugin's pyproject.toml?
- Rarely. An exact pin is appropriate only when there is a known, documented API break in the host at a specific version and you have not yet tested beyond it. Even then, a tight range like `>=1.0a27,<2.0` is more user-friendly than a single-version lock.
- Can AI coding tools make this same dependency-pinning mistake?
- Yes. LLM-based coding assistants generate syntactically valid constraints but do not automatically apply the library-vs-application distinction. Reviewing generated pyproject.toml files for constraint style is a quick, high-value step in any AI-assisted Python project setup.
Sources
- datasette-export-database 0.3a2 — Simon Willison
- Datasette — An open source multi-tool for exploring and publishing data — Datasette Project
- install_requires vs requirements files — Python Packaging User Guide — Python Packaging Authority (PyPA)