Skip to content

Migrating to 0.18

From 0.17 to 0.18

Protean 0.18 right-sizes the runtime dependency surface. A plain pip install protean no longer forces a web server, an ASGI stack, an interactive REPL, and a project scaffolder onto every install. Those concerns now live behind install extras, matching how the database and broker adapters have always worked. See ADR-0029 for the boundary and the rationale.

This is a Tier-1 breaking change, but a small one: nothing in your code changes, and the fix when you hit it is a one-word extra. If a feature you use now needs an extra, the CLI or the import tells you exactly which one.

On this page:


What moved behind extras

Five packages that used to be hard runtime dependencies are now install extras:

Package(s) Extra Feature it gates
fastapi, uvicorn, jinja2 protean[server] protean observatory, protean.integrations.fastapi
ipython protean[shell] protean shell
copier protean[scaffold] protean new

Two convenience bundles are also available:

  • protean[cli]: the full interactive CLI experience (shell + scaffold).
  • protean[all]: everything that used to ship in the core install (server + cli).

import protean and defining a domain, persisting through the memory adapter, and running protean server (the async engine) need none of these: they were already lazy, and they stay in the lean core.

The one-line fix

If your project relied on the old fat install and you would rather not think about which extras you need, install all:

pip install "protean[all]"

That restores every package that shipped in the 0.17 core. From there you can trim to the specific extras you actually use whenever you like.

What each feature needs now

You only need to act if you use one of these features and you install a trimmed set of dependencies (for example in a production image that installs protean without [all]):

  • Running the Observatory (protean observatory) or using the FastAPI integration (from protean.integrations.fastapi import ...):
pip install "protean[server]"
  • Opening the domain shell (protean shell):
pip install "protean[shell]"
  • Scaffolding a project (protean new):
pip install "protean[scaffold]"

If you run one of these without its extra, the command fails with a clear message naming the extra to install, not a raw ModuleNotFoundError:

Error: 'protean observatory' requires the 'fastapi' package. Install it with 'pip install "protean[server]"'.

Field sanitization is unaffected: bleach stays in the core install, because String and Text fields sanitize by default.


cffi and greenlet left the core install

0.17 installed cffi and greenlet as hard dependencies, but nothing in Protean imports either package. They only ever arrived as transitive dependencies: SQLAlchemy (the postgresql, sqlite, and mssql extras) requires greenlet on common platforms, and cryptography (pulled in by the sendgrid extra) requires cffi.

In 0.18 both are out of the core install. Their version floors moved onto the extras that pull them (greenlet>=3.2.3,<4 on the SQLAlchemy extras, cffi>=2.0.0 on sendgrid), so installing one of those extras still resolves a version with wheels for the newest supported Python.

You only need to act if your own code imports cffi or greenlet and relied on Protean to provide it. Declare the package in your own project instead.


werkzeug left the core install

0.17 used Werkzeug's LocalProxy/LocalStack to back current_domain, current_uow, and g. In 0.18 these context locals are backed by stdlib contextvars, and werkzeug is no longer a core dependency.

For nearly all code this is transparent: the same push/pop nesting, the same proxy behavior, and the same async support (in fact, contextvars follows asyncio tasks and await boundaries natively). The public surface of current_domain, current_uow, and g is unchanged.

You only need to act if your own code depends on Werkzeug-specific details of the proxy or stack, such as inspecting the underlying LocalStack directly. Internal helpers like _domain_context_stack and _uow_context_stack remain private and have changed their implementation type.