fastapi-cli 0.0.14__tar.gz → 0.0.15__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.
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/PKG-INFO +5 -5
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/pyproject.toml +6 -6
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/requirements-tests.txt +1 -1
- fastapi_cli-0.0.15/src/fastapi_cli/__init__.py +1 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/cli.py +31 -3
- fastapi_cli-0.0.15/src/fastapi_cli/config.py +42 -0
- fastapi_cli-0.0.15/tests/assets/pyproject_config/another_module.py +8 -0
- fastapi_cli-0.0.15/tests/assets/pyproject_config/my_module.py +8 -0
- fastapi_cli-0.0.15/tests/assets/pyproject_config/pyproject.toml +2 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_cli.py +32 -0
- fastapi_cli-0.0.15/tests/test_cli_pyproject.py +97 -0
- fastapi_cli-0.0.14/src/fastapi_cli/__init__.py +0 -1
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/LICENSE +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/README.md +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/pdm_build.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/requirements-github-actions.txt +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/requirements.txt +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/scripts/format.sh +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/scripts/lint.sh +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/scripts/test-cov-html.sh +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/scripts/test.sh +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/__main__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/discover.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/exceptions.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/logging.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/py.typed +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/utils/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/src/fastapi_cli/utils/cli.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/broken_package/mod/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/broken_package/mod/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/broken_package/utils.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_api/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_api/app/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_api/app/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_app/app/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_app/app/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_app/app/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/main.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_non_default/app/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_non_default/app/nondefault.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_main/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_main/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_main/main.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/non_default/nonstandard.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/core/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/core/utils.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/mod/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/mod/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/mod/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/mod/other.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/core/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/core/utils.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/mod/__init__.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/mod/api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/mod/app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/package/mod/other.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/single_file_api.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/single_file_app.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/single_file_other.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/conftest.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_discover.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_requirements.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_utils_cli.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_utils_default_dir.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_utils_default_file.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_utils_package.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/test_utils_single_file.py +0 -0
- {fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/utils.py +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
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
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
7
8
|
Classifier: Intended Audience :: Information Technology
|
|
8
9
|
Classifier: Intended Audience :: System Administrators
|
|
9
10
|
Classifier: Operating System :: OS Independent
|
|
@@ -17,7 +18,6 @@ Classifier: Typing :: Typed
|
|
|
17
18
|
Classifier: Development Status :: 4 - Beta
|
|
18
19
|
Classifier: Framework :: FastAPI
|
|
19
20
|
Classifier: Intended Audience :: Developers
|
|
20
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
21
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.8
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -26,7 +26,6 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
26
26
|
Classifier: Programming Language :: Python :: 3.12
|
|
27
27
|
Classifier: Programming Language :: Python :: 3.13
|
|
28
28
|
Classifier: Programming Language :: Python :: 3.14
|
|
29
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
30
29
|
Project-URL: Homepage, https://github.com/fastapi/fastapi-cli
|
|
31
30
|
Project-URL: Documentation, https://fastapi.tiangolo.com/fastapi-cli/
|
|
32
31
|
Project-URL: Repository, https://github.com/fastapi/fastapi-cli
|
|
@@ -36,6 +35,7 @@ Requires-Python: >=3.8
|
|
|
36
35
|
Requires-Dist: typer>=0.15.1
|
|
37
36
|
Requires-Dist: uvicorn[standard]>=0.15.0
|
|
38
37
|
Requires-Dist: rich-toolkit>=0.14.8
|
|
38
|
+
Requires-Dist: tomli>=2.0.0; python_version < "3.11"
|
|
39
39
|
Provides-Extra: standard
|
|
40
40
|
Requires-Dist: uvicorn[standard]>=0.15.0; extra == "standard"
|
|
41
41
|
Requires-Dist: fastapi-cloud-cli>=0.1.1; extra == "standard"
|
|
@@ -7,6 +7,10 @@ authors = [
|
|
|
7
7
|
]
|
|
8
8
|
requires-python = ">=3.8"
|
|
9
9
|
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = [
|
|
12
|
+
"LICENSE",
|
|
13
|
+
]
|
|
10
14
|
classifiers = [
|
|
11
15
|
"Intended Audience :: Information Technology",
|
|
12
16
|
"Intended Audience :: System Administrators",
|
|
@@ -21,7 +25,6 @@ classifiers = [
|
|
|
21
25
|
"Development Status :: 4 - Beta",
|
|
22
26
|
"Framework :: FastAPI",
|
|
23
27
|
"Intended Audience :: Developers",
|
|
24
|
-
"License :: OSI Approved :: MIT License",
|
|
25
28
|
"Programming Language :: Python :: 3 :: Only",
|
|
26
29
|
"Programming Language :: Python :: 3.8",
|
|
27
30
|
"Programming Language :: Python :: 3.9",
|
|
@@ -30,17 +33,14 @@ classifiers = [
|
|
|
30
33
|
"Programming Language :: Python :: 3.12",
|
|
31
34
|
"Programming Language :: Python :: 3.13",
|
|
32
35
|
"Programming Language :: Python :: 3.14",
|
|
33
|
-
"License :: OSI Approved :: MIT License",
|
|
34
36
|
]
|
|
35
37
|
dependencies = [
|
|
36
38
|
"typer >= 0.15.1",
|
|
37
39
|
"uvicorn[standard] >= 0.15.0",
|
|
38
40
|
"rich-toolkit >= 0.14.8",
|
|
41
|
+
"tomli >= 2.0.0; python_version < '3.11'",
|
|
39
42
|
]
|
|
40
|
-
version = "0.0.
|
|
41
|
-
|
|
42
|
-
[project.license]
|
|
43
|
-
text = "MIT"
|
|
43
|
+
version = "0.0.15"
|
|
44
44
|
|
|
45
45
|
[project.optional-dependencies]
|
|
46
46
|
standard = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.15"
|
|
@@ -3,10 +3,12 @@ from pathlib import Path
|
|
|
3
3
|
from typing import Any, List, Union
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
|
+
from pydantic import ValidationError
|
|
6
7
|
from rich import print
|
|
7
8
|
from rich.tree import Tree
|
|
8
9
|
from typing_extensions import Annotated
|
|
9
10
|
|
|
11
|
+
from fastapi_cli.config import FastAPIConfig
|
|
10
12
|
from fastapi_cli.discover import get_import_data, get_import_data_from_import_string
|
|
11
13
|
from fastapi_cli.exceptions import FastAPICLIException
|
|
12
14
|
|
|
@@ -111,11 +113,37 @@ def _run(
|
|
|
111
113
|
"Searching for package file structure from directories with [blue]__init__.py[/blue] files"
|
|
112
114
|
)
|
|
113
115
|
|
|
116
|
+
if entrypoint and (path or app):
|
|
117
|
+
toolkit.print_line()
|
|
118
|
+
toolkit.print(
|
|
119
|
+
"[error]Cannot use --entrypoint together with path or --app arguments"
|
|
120
|
+
)
|
|
121
|
+
toolkit.print_line()
|
|
122
|
+
raise typer.Exit(code=1)
|
|
123
|
+
|
|
114
124
|
try:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
125
|
+
config = FastAPIConfig.resolve(entrypoint=entrypoint)
|
|
126
|
+
except ValidationError as e:
|
|
127
|
+
toolkit.print_line()
|
|
128
|
+
toolkit.print("[error]Invalid configuration in pyproject.toml:")
|
|
129
|
+
toolkit.print_line()
|
|
130
|
+
|
|
131
|
+
for error in e.errors():
|
|
132
|
+
field = ".".join(str(loc) for loc in error["loc"])
|
|
133
|
+
toolkit.print(f" [red]•[/red] {field}: {error['msg']}")
|
|
134
|
+
|
|
135
|
+
toolkit.print_line()
|
|
136
|
+
|
|
137
|
+
raise typer.Exit(code=1) from None
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
# Resolve import data with priority: CLI path/app > config entrypoint > auto-discovery
|
|
141
|
+
if path or app:
|
|
118
142
|
import_data = get_import_data(path=path, app_name=app)
|
|
143
|
+
elif config.entrypoint:
|
|
144
|
+
import_data = get_import_data_from_import_string(config.entrypoint)
|
|
145
|
+
else:
|
|
146
|
+
import_data = get_import_data()
|
|
119
147
|
except FastAPICLIException as e:
|
|
120
148
|
toolkit.print_line()
|
|
121
149
|
toolkit.print(f"[error]{e}")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FastAPIConfig(BaseModel):
|
|
11
|
+
entrypoint: Optional[str] = None
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def _read_pyproject_toml(cls) -> Dict[str, Any]:
|
|
15
|
+
"""Read FastAPI configuration from pyproject.toml in current directory."""
|
|
16
|
+
pyproject_path = Path.cwd() / "pyproject.toml"
|
|
17
|
+
|
|
18
|
+
if not pyproject_path.exists():
|
|
19
|
+
return {}
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
import tomllib # type: ignore[import-not-found, unused-ignore]
|
|
23
|
+
except ImportError:
|
|
24
|
+
try:
|
|
25
|
+
import tomli as tomllib # type: ignore[no-redef, import-not-found, unused-ignore]
|
|
26
|
+
except ImportError: # pragma: no cover
|
|
27
|
+
logger.debug("tomli not available, skipping pyproject.toml")
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
with open(pyproject_path, "rb") as f:
|
|
31
|
+
data = tomllib.load(f)
|
|
32
|
+
|
|
33
|
+
return data.get("tool", {}).get("fastapi", {}) # type: ignore
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def resolve(cls, entrypoint: Optional[str] = None) -> "FastAPIConfig":
|
|
37
|
+
config = cls._read_pyproject_toml()
|
|
38
|
+
|
|
39
|
+
if entrypoint is not None:
|
|
40
|
+
config["entrypoint"] = entrypoint
|
|
41
|
+
|
|
42
|
+
return FastAPIConfig.model_validate(config)
|
|
@@ -45,6 +45,21 @@ def test_dev() -> None:
|
|
|
45
45
|
assert "🐍 single_file_app.py" in result.output
|
|
46
46
|
|
|
47
47
|
|
|
48
|
+
def test_dev_no_args_auto_discovery() -> None:
|
|
49
|
+
"""Test that auto-discovery works when no args and no pyproject.toml entrypoint"""
|
|
50
|
+
with changing_dir(assets_path / "default_files" / "default_main"):
|
|
51
|
+
with patch.object(uvicorn, "run") as mock_run:
|
|
52
|
+
result = runner.invoke(app, ["dev"]) # No path argument
|
|
53
|
+
assert result.exit_code == 0, result.output
|
|
54
|
+
assert mock_run.called
|
|
55
|
+
assert mock_run.call_args
|
|
56
|
+
assert mock_run.call_args.kwargs["app"] == "main:app"
|
|
57
|
+
assert mock_run.call_args.kwargs["host"] == "127.0.0.1"
|
|
58
|
+
assert mock_run.call_args.kwargs["port"] == 8000
|
|
59
|
+
assert mock_run.call_args.kwargs["reload"] is True
|
|
60
|
+
assert "Using import string: main:app" in result.output
|
|
61
|
+
|
|
62
|
+
|
|
48
63
|
def test_dev_package() -> None:
|
|
49
64
|
with changing_dir(assets_path):
|
|
50
65
|
with patch.object(uvicorn, "run") as mock_run:
|
|
@@ -189,6 +204,23 @@ def test_dev_env_vars_and_args() -> None:
|
|
|
189
204
|
)
|
|
190
205
|
|
|
191
206
|
|
|
207
|
+
def test_entrypoint_mutually_exclusive_with_path() -> None:
|
|
208
|
+
result = runner.invoke(app, ["dev", "mymodule.py", "--entrypoint", "other:app"])
|
|
209
|
+
|
|
210
|
+
assert result.exit_code == 1
|
|
211
|
+
assert (
|
|
212
|
+
"Cannot use --entrypoint together with path or --app arguments" in result.output
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def test_entrypoint_mutually_exclusive_with_app() -> None:
|
|
217
|
+
result = runner.invoke(app, ["dev", "--app", "myapp", "--entrypoint", "other:app"])
|
|
218
|
+
assert result.exit_code == 1
|
|
219
|
+
assert (
|
|
220
|
+
"Cannot use --entrypoint together with path or --app arguments" in result.output
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
|
|
192
224
|
def test_run() -> None:
|
|
193
225
|
with changing_dir(assets_path):
|
|
194
226
|
with patch.object(uvicorn, "run") as mock_run:
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
4
|
+
import uvicorn
|
|
5
|
+
from typer.testing import CliRunner
|
|
6
|
+
|
|
7
|
+
from fastapi_cli.cli import app
|
|
8
|
+
from tests.utils import changing_dir
|
|
9
|
+
|
|
10
|
+
runner = CliRunner()
|
|
11
|
+
|
|
12
|
+
assets_path = Path(__file__).parent / "assets"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_dev_with_pyproject_app_config_uses() -> None:
|
|
16
|
+
with changing_dir(assets_path / "pyproject_config"), patch.object(
|
|
17
|
+
uvicorn, "run"
|
|
18
|
+
) as mock_run:
|
|
19
|
+
result = runner.invoke(app, ["dev"])
|
|
20
|
+
assert result.exit_code == 0, result.output
|
|
21
|
+
|
|
22
|
+
assert mock_run.call_args.kwargs["app"] == "my_module:app"
|
|
23
|
+
assert mock_run.call_args.kwargs["host"] == "127.0.0.1"
|
|
24
|
+
assert mock_run.call_args.kwargs["port"] == 8000
|
|
25
|
+
assert mock_run.call_args.kwargs["reload"] is True
|
|
26
|
+
|
|
27
|
+
assert "Using import string: my_module:app" in result.output
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_run_with_pyproject_app_config() -> None:
|
|
31
|
+
with changing_dir(assets_path / "pyproject_config"), patch.object(
|
|
32
|
+
uvicorn, "run"
|
|
33
|
+
) as mock_run:
|
|
34
|
+
result = runner.invoke(app, ["run"])
|
|
35
|
+
assert result.exit_code == 0, result.output
|
|
36
|
+
|
|
37
|
+
assert mock_run.call_args.kwargs["app"] == "my_module:app"
|
|
38
|
+
assert mock_run.call_args.kwargs["host"] == "0.0.0.0"
|
|
39
|
+
assert mock_run.call_args.kwargs["port"] == 8000
|
|
40
|
+
assert mock_run.call_args.kwargs["reload"] is False
|
|
41
|
+
|
|
42
|
+
assert "Using import string: my_module:app" in result.output
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_cli_arg_overrides_pyproject_config() -> None:
|
|
46
|
+
with changing_dir(assets_path / "pyproject_config"), patch.object(
|
|
47
|
+
uvicorn, "run"
|
|
48
|
+
) as mock_run:
|
|
49
|
+
result = runner.invoke(app, ["dev", "another_module.py"])
|
|
50
|
+
|
|
51
|
+
assert result.exit_code == 0, result.output
|
|
52
|
+
|
|
53
|
+
assert mock_run.call_args.kwargs["app"] == "another_module:app"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_pyproject_app_config_invalid_format() -> None:
|
|
57
|
+
test_dir = assets_path / "pyproject_invalid_config"
|
|
58
|
+
test_dir.mkdir(exist_ok=True)
|
|
59
|
+
|
|
60
|
+
pyproject_file = test_dir / "pyproject.toml"
|
|
61
|
+
pyproject_file.write_text("""
|
|
62
|
+
[tool.fastapi]
|
|
63
|
+
entrypoint = "invalid_format_without_colon"
|
|
64
|
+
""")
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
with changing_dir(test_dir):
|
|
68
|
+
result = runner.invoke(app, ["dev"])
|
|
69
|
+
assert result.exit_code == 1
|
|
70
|
+
assert (
|
|
71
|
+
"Import string must be in the format module.submodule:app_name"
|
|
72
|
+
in result.output
|
|
73
|
+
)
|
|
74
|
+
finally:
|
|
75
|
+
pyproject_file.unlink()
|
|
76
|
+
test_dir.rmdir()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_pyproject_validation_error() -> None:
|
|
80
|
+
test_dir = assets_path / "pyproject_validation_error"
|
|
81
|
+
test_dir.mkdir(exist_ok=True)
|
|
82
|
+
|
|
83
|
+
pyproject_file = test_dir / "pyproject.toml"
|
|
84
|
+
pyproject_file.write_text("""
|
|
85
|
+
[tool.fastapi]
|
|
86
|
+
entrypoint = 123
|
|
87
|
+
""")
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
with changing_dir(test_dir):
|
|
91
|
+
result = runner.invoke(app, ["dev"])
|
|
92
|
+
assert result.exit_code == 1
|
|
93
|
+
assert "Invalid configuration in pyproject.toml:" in result.output
|
|
94
|
+
assert "entrypoint" in result.output.lower()
|
|
95
|
+
finally:
|
|
96
|
+
pyproject_file.unlink()
|
|
97
|
+
test_dir.rmdir()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.14"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_api/app/api.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_app/app/api.py
RENAMED
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_app/app/app.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/api.py
RENAMED
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/default_app_dir_main/app/app.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/default_files/non_default/nonstandard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/core/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_cli-0.0.14 → fastapi_cli-0.0.15}/tests/assets/nested_package/package/mod/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|