✨ Add support for apps created by factory functions #37
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change adds support for using return-typed factory functions, as well as auto-detecting some function names.
I've identified factory functions by inspecting the return-type of the function (
def create_app() -> FastAPI
). This does require the function to be typed, but that seemed preferable to calling the function and booting the app.I've added two default factory-function names to auto-detect:
create_app()
andcreate_api()
. I've seencreate_app
in use in the GH issues, and addedcreate_api
to match the existing default names. These work in the same way as the other auto-detection. You can of course pass your own function name withfastapi run --app=build_app
.I decided not to copy the first-FastAPI-instance-found behaviour, as I've worked on a project before that had multiple app factories in a single file for different use-cases. One example could be a second factory that enables the debug option.
In order to pass the
--factory
argument to uvicorn, I changed the return signature ofget_import_string()
to return atuple[str, bool]
of import-string, and whether the object is a factory function or not. Unfortunately this is a breaking change if this function is used externally. We could import that object again and check it if that's an issue.In keeping with the other tests, I opted not to use
@pytest.mark.parametrize
to fill in the package/factory dynamically - but if you're happy with that I'd like to refactor to use that (and reduce 1k lines 🙂).FYI pre-commit was fighting with my local ruff from requirements-dev.lock - bumping the ruff hook version seemed to fix it (89ac14b).
Thanks again for FastAPI!