Skip to content

Commit

Permalink
Support UVICORN_APP
Browse files Browse the repository at this point in the history
Uvicorn 0.24.0 adds support for setting the app instance with the
environment variable `UVICORN_APP`. inboard already has an environment
variable for this purpose, `APP_MODULE`.

This commit will add support for `UVICORN_APP`. Either `APP_MODULE` or
`UVICORN_APP` can be used to set the app module for inboard, with
precendence given to `APP_MODULE` for backward compatibility.

https://github.com/encode/uvicorn/releases/tag/0.24.0
encode/uvicorn#2106
  • Loading branch information
br3ndonland committed Dec 31, 2023
1 parent 65883a9 commit 0d5ec23
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 4 deletions.
11 changes: 9 additions & 2 deletions docs/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ ENV APP_MODULE="package.custom.module:api" WORKERS_PER_CORE="2"

## General

`APP_MODULE`
`APP_MODULE`/`UVICORN_APP`

- Python module with app instance.
- Default: The appropriate app module from inboard.
- Custom: For a module at `/app/package/custom/module.py` and app instance object `api`, `APP_MODULE="package.custom.module:api"`
- Custom: For a module at `/app/package/custom/module.py` and app instance object `api`, either `APP_MODULE` (like `APP_MODULE="package.custom.module:api"`) or `UVICORN_APP` (like `UVICORN_APP="package.custom.module:api"`, _new in inboard 0.62_)

!!!example "Example of a custom FastAPI app module"

Expand Down Expand Up @@ -188,6 +188,8 @@ ENV APP_MODULE="package.custom.module:api" WORKERS_PER_CORE="2"

These settings are mostly used for local development.

[Uvicorn supports environment variables named with the `UVICORN_` prefix](https://www.uvicorn.org/settings/) (via the [Click `auto_envvar_prefix` feature](https://click.palletsprojects.com/en/7.x/options/#dynamic-defaults-for-prompts)), but these environment variables are only read when running from the CLI. inboard runs Uvicorn programmatically with `uvicorn.run()` instead of running with the CLI, so most of these variables will not apply. The exception is `UVICORN_APP`, as explained in the [general section](#general).

`WITH_RELOAD`

- Configure the [Uvicorn auto-reload setting](https://www.uvicorn.org/settings/).
Expand Down Expand Up @@ -249,6 +251,11 @@ ENV APP_MODULE="package.custom.module:api" WORKERS_PER_CORE="2"
- `uvicorn.run` equivalent: `reload_includes`
- Uvicorn CLI equivalent: `--reload-include`
`UVICORN_APP` _(new in inboard 0.62)_
- `UVICORN_APP` can be used interchangeably with `APP_MODULE`.
- See the [general section](#general) for further details.
`UVICORN_CONFIG_OPTIONS` _(advanced usage, new in inboard 0.11)_
- JSON-formatted string containing arguments to pass directly to Uvicorn.
Expand Down
2 changes: 1 addition & 1 deletion inboard/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def run_pre_start_script(logger: logging.Logger = logging.getLogger()) -> str:
def set_app_module(logger: logging.Logger = logging.getLogger()) -> str:
"""Set the name of the Python module with the app instance to run."""
try:
app_module = os.getenv("APP_MODULE")
app_module = os.getenv("APP_MODULE") or os.getenv("UVICORN_APP")
if not app_module:
raise ValueError("Please set the APP_MODULE environment variable")
if not importlib.util.find_spec((module := app_module.split(sep=":")[0])):
Expand Down
4 changes: 3 additions & 1 deletion tests/test_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,19 @@ def test_set_app_module(
assert mocker.call(f"App module set to inboard.app.main_{module}:app.")

@pytest.mark.parametrize("module", ("base", "fastapi", "starlette"))
@pytest.mark.parametrize("module_variable_name", ("APP_MODULE", "UVICORN_APP"))
def test_set_app_module_custom(
self,
app_module_tmp_path: Path,
module: str,
module_variable_name: str,
mocker: MockerFixture,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Test `start.set_app_module` with custom module path."""
logger = mocker.patch.object(logging, "root", autospec=True)
monkeypatch.syspath_prepend(app_module_tmp_path)
monkeypatch.setenv("APP_MODULE", f"tmp_app.main_{module}:app")
monkeypatch.setenv(module_variable_name, f"tmp_app.main_{module}:app")
start.set_app_module(logger=logger)
assert mocker.call(f"App module set to tmp_app.main_{module}:app.")

Expand Down

0 comments on commit 0d5ec23

Please sign in to comment.