fastapi-cli 0.0.27__tar.gz → 0.0.29__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/PKG-INFO +1 -4
  2. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/README.md +0 -3
  3. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/pyproject.toml +6 -2
  4. fastapi_cli-0.0.29/src/fastapi_cli/__init__.py +1 -0
  5. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/cli.py +10 -2
  6. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/utils/cli.py +11 -1
  7. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_cli.py +20 -0
  8. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_utils_cli.py +17 -2
  9. fastapi_cli-0.0.27/src/fastapi_cli/__init__.py +0 -1
  10. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/LICENSE +0 -0
  11. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/add_latest_release_date.py +0 -0
  12. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/format.sh +0 -0
  13. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/lint.sh +0 -0
  14. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/prepare_release.py +0 -0
  15. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/test-cov-html.sh +0 -0
  16. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/scripts/test.sh +0 -0
  17. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/__main__.py +0 -0
  18. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/config.py +0 -0
  19. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/discover.py +0 -0
  20. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/exceptions.py +0 -0
  21. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/logging.py +0 -0
  22. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/py.typed +0 -0
  23. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/src/fastapi_cli/utils/__init__.py +0 -0
  24. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/__init__.py +0 -0
  25. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/broken_package/mod/__init__.py +0 -0
  26. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/broken_package/mod/app.py +0 -0
  27. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/broken_package/utils.py +0 -0
  28. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_api/api.py +0 -0
  29. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app/api.py +0 -0
  30. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app/app.py +0 -0
  31. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_api/app/__init__.py +0 -0
  32. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_api/app/api.py +0 -0
  33. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_app/app/__init__.py +0 -0
  34. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_app/app/api.py +0 -0
  35. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_app/app/app.py +0 -0
  36. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_main/app/__init__.py +0 -0
  37. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_main/app/api.py +0 -0
  38. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_main/app/app.py +0 -0
  39. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_main/app/main.py +0 -0
  40. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_non_default/app/__init__.py +0 -0
  41. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_app_dir_non_default/app/nondefault.py +0 -0
  42. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_main/api.py +0 -0
  43. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_main/app.py +0 -0
  44. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/default_main/main.py +0 -0
  45. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/default_files/non_default/nonstandard.py +0 -0
  46. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/__init__.py +0 -0
  47. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/__init__.py +0 -0
  48. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/core/__init__.py +0 -0
  49. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/core/utils.py +0 -0
  50. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/mod/__init__.py +0 -0
  51. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/mod/api.py +0 -0
  52. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/mod/app.py +0 -0
  53. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/nested_package/package/mod/other.py +0 -0
  54. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/__init__.py +0 -0
  55. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/core/__init__.py +0 -0
  56. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/core/utils.py +0 -0
  57. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/mod/__init__.py +0 -0
  58. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/mod/api.py +0 -0
  59. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/mod/app.py +0 -0
  60. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/package/mod/other.py +0 -0
  61. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/pyproject_config/another_module.py +0 -0
  62. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/pyproject_config/my_module.py +0 -0
  63. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/pyproject_config/pyproject.toml +0 -0
  64. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/single_file_api.py +0 -0
  65. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/single_file_app.py +0 -0
  66. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/assets/single_file_other.py +0 -0
  67. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/conftest.py +0 -0
  68. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_cli_pyproject.py +0 -0
  69. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_discover.py +0 -0
  70. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_prepare_release.py +0 -0
  71. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_requirements.py +0 -0
  72. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_utils_default_dir.py +0 -0
  73. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_utils_default_file.py +0 -0
  74. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_utils_package.py +0 -0
  75. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/test_utils_single_file.py +0 -0
  76. {fastapi_cli-0.0.27 → fastapi_cli-0.0.29}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-cli
3
- Version: 0.0.27
3
+ Version: 0.0.29
4
4
  Summary: Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀
5
5
  Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
6
6
  License-Expression: MIT
@@ -48,9 +48,6 @@ Description-Content-Type: text/markdown
48
48
  <a href="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml" target="_blank">
49
49
  <img src="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml/badge.svg" alt="Test">
50
50
  </a>
51
- <a href="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml" target="_blank">
52
- <img src="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml/badge.svg" alt="Publish">
53
- </a>
54
51
  <a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi-cli" target="_blank">
55
52
  <img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi-cli.svg" alt="Coverage">
56
53
  <a href="https://pypi.org/project/fastapi-cli" target="_blank">
@@ -3,9 +3,6 @@
3
3
  <a href="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml" target="_blank">
4
4
  <img src="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml/badge.svg" alt="Test">
5
5
  </a>
6
- <a href="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml" target="_blank">
7
- <img src="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml/badge.svg" alt="Publish">
8
- </a>
9
6
  <a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi-cli" target="_blank">
10
7
  <img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi-cli.svg" alt="Coverage">
11
8
  <a href="https://pypi.org/project/fastapi-cli" target="_blank">
@@ -38,7 +38,7 @@ dependencies = [
38
38
  "rich-toolkit >= 0.14.8",
39
39
  "tomli >= 2.0.0; python_version < '3.11'",
40
40
  ]
41
- version = "0.0.27"
41
+ version = "0.0.29"
42
42
 
43
43
  [project.optional-dependencies]
44
44
  standard = [
@@ -171,10 +171,14 @@ error-on-warning = true
171
171
  extend-exclude = [
172
172
  "coverage/",
173
173
  "dist/",
174
- "release-notes.md",
175
174
  "htmlcov/",
176
175
  "uv.lock",
177
176
  ]
178
177
 
178
+ [tool.typos.default]
179
+ extend-ignore-re = [
180
+ "@[a-zA-Z0-9](?:-?[a-zA-Z0-9])*",
181
+ ]
182
+
179
183
  [tool.typos.default.extend-identifiers]
180
184
  alls = "alls"
@@ -0,0 +1 @@
1
+ __version__ = "0.0.29"
@@ -20,7 +20,11 @@ from fastapi_cli.exceptions import FastAPICLIException
20
20
 
21
21
  from . import __version__
22
22
  from .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
+ )
24
28
 
25
29
  app = typer.Typer(
26
30
  rich_markup_mode="rich", context_settings={"help_option_names": ["-h", "--help"]}
@@ -271,6 +275,10 @@ def _run(
271
275
  toolkit.print("Logs:")
272
276
  toolkit.print_line()
273
277
 
278
+ extra_uvicorn_kwargs: dict[str, Any] = (
279
+ {"log_config": get_uvicorn_log_config()} if should_use_rich_logs() else {}
280
+ )
281
+
274
282
  uvicorn.run(
275
283
  app=import_string,
276
284
  host=host,
@@ -285,7 +293,7 @@ def _run(
285
293
  root_path=root_path,
286
294
  proxy_headers=proxy_headers,
287
295
  forwarded_allow_ips=forwarded_allow_ips,
288
- log_config=get_uvicorn_log_config(),
296
+ **extra_uvicorn_kwargs,
289
297
  )
290
298
 
291
299
 
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import sys
2
3
  from typing import Any
3
4
 
4
5
  from rich_toolkit import RichToolkit, RichToolkitTheme
@@ -20,6 +21,11 @@ class CustomFormatter(DefaultFormatter):
20
21
  return result
21
22
 
22
23
 
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
+
23
29
  def get_uvicorn_log_config() -> dict[str, Any]:
24
30
  return {
25
31
  "version": 1,
@@ -48,7 +54,11 @@ def get_uvicorn_log_config() -> dict[str, Any]:
48
54
  },
49
55
  },
50
56
  "loggers": {
51
- "uvicorn": {"handlers": ["default"], "level": "INFO"},
57
+ "uvicorn": {
58
+ "handlers": ["default"],
59
+ "level": "INFO",
60
+ "propagate": False,
61
+ },
52
62
  "uvicorn.error": {"level": "INFO"},
53
63
  "uvicorn.access": {
54
64
  "handlers": ["access"],
@@ -16,6 +16,11 @@ runner = CliRunner()
16
16
  assets_path = Path(__file__).parent / "assets"
17
17
 
18
18
 
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
+
19
24
  def test_dev() -> None:
20
25
  with changing_dir(assets_path):
21
26
  with patch.object(uvicorn, "run") as mock_run:
@@ -51,6 +56,21 @@ def test_dev() -> None:
51
56
  assert "🐍 single_file_app.py" in result.output
52
57
 
53
58
 
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
+
54
74
  def test_dev_no_args_auto_discovery() -> None:
55
75
  """Test that auto-discovery works when no args and no pyproject.toml entrypoint"""
56
76
  with changing_dir(assets_path / "default_files" / "default_main"):
@@ -1,9 +1,15 @@
1
+ import io
1
2
  import logging
3
+ import sys
2
4
  from logging.config import dictConfig
3
5
 
4
- from pytest import LogCaptureFixture
6
+ from pytest import LogCaptureFixture, MonkeyPatch
5
7
 
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
+ )
7
13
 
8
14
 
9
15
  def test_get_uvicorn_config_uses_custom_formatter() -> None:
@@ -11,6 +17,15 @@ def test_get_uvicorn_config_uses_custom_formatter() -> None:
11
17
 
12
18
  assert config["formatters"]["default"]["()"] is CustomFormatter
13
19
  assert config["formatters"]["access"]["()"] is CustomFormatter
20
+ assert config["loggers"]["uvicorn"]["propagate"] is False
21
+
22
+
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
14
29
 
15
30
 
16
31
  def test_custom_formatter() -> None:
@@ -1 +0,0 @@
1
- __version__ = "0.0.27"
File without changes