Skip to content

Commit

Permalink
Allow setting app via environment variable UVICORN_APP (#2106)
Browse files Browse the repository at this point in the history
Co-authored-by: Marcelo Trylesinski <[email protected]>
  • Loading branch information
aceat64 and Kludex authored Sep 21, 2023
1 parent e2a3979 commit 8e68642
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 24 deletions.
2 changes: 1 addition & 1 deletion scripts/check
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export SOURCE_FILES="uvicorn tests"
set -x

./scripts/sync-version
${PREFIX}black --check --diff --target-version=py37 $SOURCE_FILES
${PREFIX}black --check --diff --target-version=py38 $SOURCE_FILES
${PREFIX}mypy $SOURCE_FILES
${PREFIX}ruff check $SOURCE_FILES
${PREFIX}python -m tools.cli_usage --check
2 changes: 1 addition & 1 deletion scripts/lint
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ export SOURCE_FILES="uvicorn tests"

set -x

${PREFIX}black --target-version=py37 $SOURCE_FILES
${PREFIX}black --target-version=py38 $SOURCE_FILES
${PREFIX}ruff --fix $SOURCE_FILES
${PREFIX}python -m tools.cli_usage
58 changes: 37 additions & 21 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import contextlib
import importlib
import os
import platform
import sys
from pathlib import Path
from textwrap import dedent
from typing import Iterator
from unittest import mock

import pytest
Expand All @@ -19,6 +21,15 @@
main = importlib.import_module("uvicorn.main")


@contextlib.contextmanager
def load_env_var(key: str, value: str) -> Iterator[None]:
old_environ = dict(os.environ)
os.environ[key] = value
yield
os.environ.clear()
os.environ.update(old_environ)


class App:
pass

Expand Down Expand Up @@ -146,29 +157,23 @@ def test_cli_event_size() -> None:
assert mock_run.call_args[1]["h11_max_incomplete_event_size"] == 32768


@pytest.fixture()
def load_env_h11_protocol():
old_environ = dict(os.environ)
os.environ["UVICORN_HTTP"] = "h11"
yield
os.environ.clear()
os.environ.update(old_environ)


def test_env_variables(load_env_h11_protocol: None):
runner = CliRunner(env=os.environ)
with mock.patch.object(main, "run") as mock_run:
runner.invoke(cli, ["tests.test_cli:App"])
_, kwargs = mock_run.call_args
assert kwargs["http"] == "h11"
@pytest.mark.parametrize("http_protocol", ["h11", "httptools"])
def test_env_variables(http_protocol: str):
with load_env_var("UVICORN_HTTP", http_protocol):
runner = CliRunner(env=os.environ)
with mock.patch.object(main, "run") as mock_run:
runner.invoke(cli, ["tests.test_cli:App"])
_, kwargs = mock_run.call_args
assert kwargs["http"] == http_protocol


def test_mistmatch_env_variables(load_env_h11_protocol: None):
runner = CliRunner(env=os.environ)
with mock.patch.object(main, "run") as mock_run:
runner.invoke(cli, ["tests.test_cli:App", "--http=httptools"])
_, kwargs = mock_run.call_args
assert kwargs["http"] == "httptools"
def test_ignore_environment_variable_when_set_on_cli():
with load_env_var("UVICORN_HTTP", "h11"):
runner = CliRunner(env=os.environ)
with mock.patch.object(main, "run") as mock_run:
runner.invoke(cli, ["tests.test_cli:App", "--http=httptools"])
_, kwargs = mock_run.call_args
assert kwargs["http"] == "httptools"


def test_app_dir(tmp_path: Path, caplog: pytest.LogCaptureFixture) -> None:
Expand All @@ -191,3 +196,14 @@ async def app(scope, receive, send):
assert result.exit_code == 3
mock_run.assert_called_once()
assert sys.path[0] == str(app_dir)


def test_set_app_via_environment_variable():
app_path = "tests.test_cli:App"
with load_env_var("UVICORN_APP", app_path):
runner = CliRunner(env=os.environ)
with mock.patch.object(main, "run") as mock_run:
result = runner.invoke(cli)
args, _ = mock_run.call_args
assert result.exit_code == 0
assert args == (app_path,)
2 changes: 1 addition & 1 deletion uvicorn/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No


@click.command(context_settings={"auto_envvar_prefix": "UVICORN"})
@click.argument("app")
@click.argument("app", envvar="UVICORN_APP")
@click.option(
"--host",
type=str,
Expand Down

0 comments on commit 8e68642

Please sign in to comment.