Coverage for tests/test_utils_cli.py: 100%

39 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-11-11 09:18 +0000

1import io 1abcdefghijklmn

2import logging 1abcdefghijklmn

3import sys 1abcdefghijklmn

4from logging.config import dictConfig 1abcdefghijklmn

5 

6from pytest import LogCaptureFixture, MonkeyPatch 1abcdefghijklmn

7 

8from fastapi_cli.utils.cli import ( 1abcdefghijklmn

9 CustomFormatter, 

10 get_uvicorn_log_config, 

11 should_use_rich_logs, 

12) 

13 

14 

15def test_get_uvicorn_config_uses_custom_formatter() -> None: 1abcdefghijklmn

16 config = get_uvicorn_log_config() 1456789!#$%'()*

17 

18 assert config["formatters"]["default"]["()"] is CustomFormatter 1456789!#$%'()*

19 assert config["formatters"]["access"]["()"] is CustomFormatter 1456789!#$%'()*

20 assert config["loggers"]["uvicorn"]["propagate"] is False 1456789!#$%'()*

21 

22 

23def test_should_use_rich_logs_is_false_without_tty( 1abcdefghijklmn

24 monkeypatch: MonkeyPatch, 

25) -> None: 

26 monkeypatch.setattr(sys, "stdout", io.StringIO()) 1+,-./:;=?@[]^_

27 

28 assert should_use_rich_logs() is False 1+,-./:;=?@[]^_

29 

30 

31def test_custom_formatter() -> None: 1abcdefghijklmn

32 formatter = CustomFormatter() 1CDEFGHIJKLMNOP

33 

34 record = logging.LogRecord( 1CDEFGHIJKLMNOP

35 name="uvicorn.access", 

36 level=logging.INFO, 

37 pathname="", 

38 lineno=0, 

39 msg="%(client_addr)s - '%(request_line)s' %(status_code)s", 

40 args={ 

41 "client_addr": "127.0.0.1", 

42 "request_line": "GET / HTTP/1.1", 

43 "status_code": 200, 

44 }, 

45 exc_info=None, 

46 ) 

47 

48 formatted = formatter.formatMessage(record) 1CDEFGHIJKLMNOP

49 

50 # the log level is shown as a colored bar bullet, like `fastapi cloud logs` 

51 assert "▕" in formatted 1CDEFGHIJKLMNOP

52 assert "127.0.0.1" in formatted 1CDEFGHIJKLMNOP

53 assert "GET / HTTP/1.1" in formatted 1CDEFGHIJKLMNOP

54 assert "200" in formatted 1CDEFGHIJKLMNOP

55 

56 

57def test_custom_formatter_shutdown_prepends_newline() -> None: 1abcdefghijklmn

58 formatter = CustomFormatter() 1QRSTUVWXYZ0123

59 

60 record = logging.LogRecord( 1QRSTUVWXYZ0123

61 name="uvicorn.error", 

62 level=logging.INFO, 

63 pathname="", 

64 lineno=0, 

65 msg="Shutting down", 

66 args=(), 

67 exc_info=None, 

68 ) 

69 

70 formatted = formatter.formatMessage(record) 1QRSTUVWXYZ0123

71 

72 assert formatted.startswith("\n") 1QRSTUVWXYZ0123

73 assert "Shutting down" in formatted 1QRSTUVWXYZ0123

74 

75 

76def test_log_config_does_not_disable_existing_loggers( 1abcdefghijklmn

77 caplog: LogCaptureFixture, 

78) -> None: 

79 logger1 = logging.getLogger(__name__) 1opqrstuvwxyzAB

80 logger1.setLevel(logging.INFO) 1opqrstuvwxyzAB

81 logger1.info("Message before configuration") 1opqrstuvwxyzAB

82 

83 dictConfig(get_uvicorn_log_config()) 1opqrstuvwxyzAB

84 

85 logger2 = logging.getLogger(__name__) 1opqrstuvwxyzAB

86 

87 logger1.info("Message after configuration from logger1") # Should not appear 1opqrstuvwxyzAB

88 logger2.info("Message from logger2") 1opqrstuvwxyzAB

89 

90 assert "Message before configuration" in caplog.text 1opqrstuvwxyzAB

91 assert "Message after configuration from logger1" in caplog.text 1opqrstuvwxyzAB

92 assert "Message from logger2" in caplog.text 1opqrstuvwxyzAB