File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2020
2121from . import __version__
2222from .logging import setup_logging
23- from .utils .cli import get_rich_toolkit , get_uvicorn_log_config
23+ from .utils .cli import (
24+ get_rich_toolkit ,
25+ get_uvicorn_log_config ,
26+ should_use_rich_logs ,
27+ )
2428
2529app = typer .Typer (
2630 rich_markup_mode = "rich" , context_settings = {"help_option_names" : ["-h" , "--help" ]}
@@ -271,6 +275,10 @@ def _run(
271275 toolkit .print ("Logs:" )
272276 toolkit .print_line ()
273277
278+ extra_uvicorn_kwargs : dict [str , Any ] = (
279+ {"log_config" : get_uvicorn_log_config ()} if should_use_rich_logs () else {}
280+ )
281+
274282 uvicorn .run (
275283 app = import_string ,
276284 host = host ,
@@ -285,7 +293,7 @@ def _run(
285293 root_path = root_path ,
286294 proxy_headers = proxy_headers ,
287295 forwarded_allow_ips = forwarded_allow_ips ,
288- log_config = get_uvicorn_log_config () ,
296+ ** extra_uvicorn_kwargs ,
289297 )
290298
291299
Original file line number Diff line number Diff line change 11import logging
2+ import sys
23from typing import Any
34
45from rich_toolkit import RichToolkit , RichToolkitTheme
@@ -20,6 +21,11 @@ def formatMessage(self, record: logging.LogRecord) -> str:
2021 return result
2122
2223
24+ def should_use_rich_logs () -> bool :
25+ """Return True when stdout is a TTY and rich logs should be used, False otherwise."""
26+ return sys .stdout .isatty ()
27+
28+
2329def get_uvicorn_log_config () -> dict [str , Any ]:
2430 return {
2531 "version" : 1 ,
Original file line number Diff line number Diff line change 1616assets_path = Path (__file__ ).parent / "assets"
1717
1818
19+ @pytest .fixture (autouse = True )
20+ def force_rich_logs (monkeypatch : pytest .MonkeyPatch ) -> None :
21+ monkeypatch .setattr ("fastapi_cli.cli.should_use_rich_logs" , lambda : True )
22+
23+
1924def test_dev () -> None :
2025 with changing_dir (assets_path ):
2126 with patch .object (uvicorn , "run" ) as mock_run :
@@ -51,6 +56,21 @@ def test_dev() -> None:
5156 assert "🐍 single_file_app.py" in result .output
5257
5358
59+ def test_run_uses_uvicorn_default_log_config_without_rich_logs (
60+ monkeypatch : pytest .MonkeyPatch ,
61+ ) -> None :
62+ monkeypatch .setattr ("fastapi_cli.cli.should_use_rich_logs" , lambda : False )
63+
64+ with changing_dir (assets_path ):
65+ with patch .object (uvicorn , "run" ) as mock_run :
66+ result = runner .invoke (app , ["run" , "single_file_app.py" ])
67+ assert result .exit_code == 0 , result .output
68+ assert mock_run .called
69+ assert mock_run .call_args
70+
71+ assert "log_config" not in mock_run .call_args .kwargs
72+
73+
5474def test_dev_no_args_auto_discovery () -> None :
5575 """Test that auto-discovery works when no args and no pyproject.toml entrypoint"""
5676 with changing_dir (assets_path / "default_files" / "default_main" ):
Original file line number Diff line number Diff line change 1+ import io
12import logging
3+ import sys
24from logging .config import dictConfig
35
4- from pytest import LogCaptureFixture
6+ from pytest import LogCaptureFixture , MonkeyPatch
57
6- from fastapi_cli .utils .cli import CustomFormatter , get_uvicorn_log_config
8+ from fastapi_cli .utils .cli import (
9+ CustomFormatter ,
10+ get_uvicorn_log_config ,
11+ should_use_rich_logs ,
12+ )
713
814
915def test_get_uvicorn_config_uses_custom_formatter () -> None :
@@ -14,6 +20,14 @@ def test_get_uvicorn_config_uses_custom_formatter() -> None:
1420 assert config ["loggers" ]["uvicorn" ]["propagate" ] is False
1521
1622
23+ def test_should_use_rich_logs_is_false_without_tty (
24+ monkeypatch : MonkeyPatch ,
25+ ) -> None :
26+ monkeypatch .setattr (sys , "stdout" , io .StringIO ())
27+
28+ assert should_use_rich_logs () is False
29+
30+
1731def test_custom_formatter () -> None :
1832 formatter = CustomFormatter ()
1933
You can’t perform that action at this time.
0 commit comments