Skip to content

Importing the FastAPI adapter without its extra says 'No module named starlette' instead of naming the extra #51

Description

@AlexeyShalaev

Measured on 0.10.0 in a fresh venv with uv pip install servicewright and nothing else, importing each adapter subpackage:

servicewright.adapters.fastapi  -> ModuleNotFoundError: No module named 'starlette'
servicewright.adapters.litestar -> ImportError: Litestar support requires servicewright[litestar]; install it.
servicewright.adapters.grpc     -> ImportError: gRPC support requires servicewright[grpc]; install it.
servicewright.adapters.dishka   -> ImportError: Dishka support requires servicewright[dishka]; install it.

Three of the four say what to install. The FastAPI one says starlette, which is a package the user never asked for, never named in the extras table, and cannot obviously map back to servicewright[fastapi] — especially for someone who has installed FastAPI in some other environment and is now looking at a dependency they have never heard of.

docs/agents.md states the contract in the adapters section: "Each subpackage needs its extra; importing one without it raises ImportError naming what to install", and the errors table repeats it: "an adapter, sink or settings model imported without its extra — the message names the extra". ModuleNotFoundError is an ImportError subclass, so the type is right and the message is not.

The cause is import order: something in the FastAPI adapter's module graph imports starlette (directly or through a submodule) before the guarded fastapi import that produces the friendly message. Whichever import runs first is the one the user sees.

What I think it needs: the guard has to cover every third-party import the subpackage's __init__ can reach, not just the headline one — so either the guarded import moves ahead of everything else in adapters/fastapi/__init__.py, or the guard checks starlette too and names the same extra. Then a test per adapter that imports it in an environment without the extra and asserts the message names the extra; without one, this drifts back the next time an import moves. The other three adapters presumably pass such a test today, which is exactly why the FastAPI one is worth catching.

While you are there: servicewright.settings (the [settings] extra) raises ModuleNotFoundError: No module named 'servicewright.settings' in a bare install rather than an ImportError naming the extra. That reads as "this library has no settings module" rather than "install the extra", and the errors table promises the second. If the module genuinely is not shipped without the extra, the docs should say so; if it is, it needs the same guard.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions