fastapi-cli 0.0.4__py3-none-any.whl → 0.0.6__py3-none-any.whl
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/__init__.py +1 -1
- fastapi_cli/cli.py +114 -43
- fastapi_cli/discover.py +38 -77
- fastapi_cli/logging.py +4 -2
- fastapi_cli/utils/__init__.py +0 -0
- fastapi_cli/utils/cli.py +75 -0
- {fastapi_cli-0.0.4.dist-info → fastapi_cli-0.0.6.dist-info}/METADATA +44 -56
- fastapi_cli-0.0.6.dist-info/RECORD +14 -0
- {fastapi_cli-0.0.4.dist-info → fastapi_cli-0.0.6.dist-info}/WHEEL +1 -1
- {fastapi_cli-0.0.4.dist-info → fastapi_cli-0.0.6.dist-info}/entry_points.txt +2 -0
- fastapi_cli-0.0.4.dist-info/RECORD +0 -12
- {fastapi_cli-0.0.4.dist-info → fastapi_cli-0.0.6.dist-info}/licenses/LICENSE +0 -0
fastapi_cli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.6"
|
fastapi_cli/cli.py
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Any, Union
|
|
3
|
+
from typing import Any, List, Union
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
from rich import print
|
|
7
|
-
from rich.
|
|
8
|
-
from rich.panel import Panel
|
|
7
|
+
from rich.tree import Tree
|
|
9
8
|
from typing_extensions import Annotated
|
|
10
9
|
|
|
11
|
-
from fastapi_cli.discover import
|
|
10
|
+
from fastapi_cli.discover import get_import_data
|
|
12
11
|
from fastapi_cli.exceptions import FastAPICLIException
|
|
13
12
|
|
|
14
13
|
from . import __version__
|
|
15
14
|
from .logging import setup_logging
|
|
15
|
+
from .utils.cli import get_rich_toolkit, get_uvicorn_log_config
|
|
16
16
|
|
|
17
17
|
app = typer.Typer(rich_markup_mode="rich")
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
23
|
import uvicorn
|
|
@@ -39,15 +39,41 @@ def callback(
|
|
|
39
39
|
"--version", help="Show the version and exit.", callback=version_callback
|
|
40
40
|
),
|
|
41
41
|
] = None,
|
|
42
|
+
verbose: bool = typer.Option(False, help="Enable verbose output"),
|
|
42
43
|
) -> None:
|
|
43
44
|
"""
|
|
44
45
|
FastAPI CLI - The [bold]fastapi[/bold] command line app. 😎
|
|
45
46
|
|
|
46
47
|
Manage your [bold]FastAPI[/bold] projects, run your FastAPI apps, and more.
|
|
47
48
|
|
|
48
|
-
Read more in the docs: [link]https://fastapi.tiangolo.com/fastapi-cli/[/link].
|
|
49
|
+
Read more in the docs: [link=https://fastapi.tiangolo.com/fastapi-cli/]https://fastapi.tiangolo.com/fastapi-cli/[/link].
|
|
49
50
|
"""
|
|
50
51
|
|
|
52
|
+
log_level = logging.DEBUG if verbose else logging.INFO
|
|
53
|
+
|
|
54
|
+
setup_logging(level=log_level)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _get_module_tree(module_paths: List[Path]) -> Tree:
|
|
58
|
+
root = module_paths[0]
|
|
59
|
+
name = f"🐍 {root.name}" if root.is_file() else f"📁 {root.name}"
|
|
60
|
+
|
|
61
|
+
root_tree = Tree(name)
|
|
62
|
+
|
|
63
|
+
if root.is_dir():
|
|
64
|
+
root_tree.add("[dim]🐍 __init__.py[/dim]")
|
|
65
|
+
|
|
66
|
+
tree = root_tree
|
|
67
|
+
for sub_path in module_paths[1:]:
|
|
68
|
+
sub_name = (
|
|
69
|
+
f"🐍 {sub_path.name}" if sub_path.is_file() else f"📁 {sub_path.name}"
|
|
70
|
+
)
|
|
71
|
+
tree = tree.add(sub_name)
|
|
72
|
+
if sub_path.is_dir():
|
|
73
|
+
tree.add("[dim]🐍 __init__.py[/dim]")
|
|
74
|
+
|
|
75
|
+
return root_tree
|
|
76
|
+
|
|
51
77
|
|
|
52
78
|
def _run(
|
|
53
79
|
path: Union[Path, None] = None,
|
|
@@ -61,43 +87,88 @@ def _run(
|
|
|
61
87
|
app: Union[str, None] = None,
|
|
62
88
|
proxy_headers: bool = False,
|
|
63
89
|
) -> None:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
with get_rich_toolkit() as toolkit:
|
|
91
|
+
server_type = "development" if command == "dev" else "production"
|
|
92
|
+
|
|
93
|
+
toolkit.print_title(f"Starting {server_type} server 🚀", tag="FastAPI")
|
|
94
|
+
toolkit.print_line()
|
|
95
|
+
|
|
96
|
+
toolkit.print(
|
|
97
|
+
"Searching for package file structure from directories with [blue]__init__.py[/blue] files"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
import_data = get_import_data(path=path, app_name=app)
|
|
102
|
+
except FastAPICLIException as e:
|
|
103
|
+
toolkit.print_line()
|
|
104
|
+
toolkit.print(f"[error]{e}")
|
|
105
|
+
raise typer.Exit(code=1) from None
|
|
106
|
+
|
|
107
|
+
logger.debug(f"Importing from {import_data.module_data.extra_sys_path}")
|
|
108
|
+
logger.debug(f"Importing module {import_data.module_data.module_import_str}")
|
|
109
|
+
|
|
110
|
+
module_data = import_data.module_data
|
|
111
|
+
import_string = import_data.import_string
|
|
112
|
+
|
|
113
|
+
toolkit.print(f"Importing from {module_data.extra_sys_path}")
|
|
114
|
+
toolkit.print_line()
|
|
115
|
+
|
|
116
|
+
root_tree = _get_module_tree(module_data.module_paths)
|
|
117
|
+
|
|
118
|
+
toolkit.print(root_tree, tag="module")
|
|
119
|
+
toolkit.print_line()
|
|
120
|
+
|
|
121
|
+
toolkit.print(
|
|
122
|
+
"Importing the FastAPI app object from the module with the following code:",
|
|
123
|
+
tag="code",
|
|
78
124
|
)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
f"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
125
|
+
toolkit.print_line()
|
|
126
|
+
toolkit.print(
|
|
127
|
+
f"[underline]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.app_name}[/bold]"
|
|
128
|
+
)
|
|
129
|
+
toolkit.print_line()
|
|
130
|
+
|
|
131
|
+
toolkit.print(
|
|
132
|
+
f"Using import string: [blue]{import_string}[/]",
|
|
133
|
+
tag="app",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
url = f"http://{host}:{port}"
|
|
137
|
+
url_docs = f"{url}/docs"
|
|
138
|
+
|
|
139
|
+
toolkit.print_line()
|
|
140
|
+
toolkit.print(
|
|
141
|
+
f"Server started at [link={url}]{url}[/]",
|
|
142
|
+
f"Documentation at [link={url_docs}]{url_docs}[/]",
|
|
143
|
+
tag="server",
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if command == "dev":
|
|
147
|
+
toolkit.print_line()
|
|
148
|
+
toolkit.print(
|
|
149
|
+
"Running in development mode, for production use: [bold]fastapi run[/]",
|
|
150
|
+
tag="tip",
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if not uvicorn:
|
|
154
|
+
raise FastAPICLIException(
|
|
155
|
+
"Could not import Uvicorn, try running 'pip install uvicorn'"
|
|
156
|
+
) from None
|
|
157
|
+
|
|
158
|
+
toolkit.print_line()
|
|
159
|
+
toolkit.print("Logs:")
|
|
160
|
+
toolkit.print_line()
|
|
161
|
+
|
|
162
|
+
uvicorn.run(
|
|
163
|
+
app=import_string,
|
|
164
|
+
host=host,
|
|
165
|
+
port=port,
|
|
166
|
+
reload=reload,
|
|
167
|
+
workers=workers,
|
|
168
|
+
root_path=root_path,
|
|
169
|
+
proxy_headers=proxy_headers,
|
|
170
|
+
log_config=get_uvicorn_log_config(),
|
|
86
171
|
)
|
|
87
|
-
print(Padding(panel, 1))
|
|
88
|
-
if not uvicorn:
|
|
89
|
-
raise FastAPICLIException(
|
|
90
|
-
"Could not import Uvicorn, try running 'pip install uvicorn'"
|
|
91
|
-
) from None
|
|
92
|
-
uvicorn.run(
|
|
93
|
-
app=use_uvicorn_app,
|
|
94
|
-
host=host,
|
|
95
|
-
port=port,
|
|
96
|
-
reload=reload,
|
|
97
|
-
workers=workers,
|
|
98
|
-
root_path=root_path,
|
|
99
|
-
proxy_headers=proxy_headers,
|
|
100
|
-
)
|
|
101
172
|
|
|
102
173
|
|
|
103
174
|
@app.command()
|
fastapi_cli/discover.py
CHANGED
|
@@ -3,13 +3,7 @@ import sys
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from logging import getLogger
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Union
|
|
7
|
-
|
|
8
|
-
from rich import print
|
|
9
|
-
from rich.padding import Padding
|
|
10
|
-
from rich.panel import Panel
|
|
11
|
-
from rich.syntax import Syntax
|
|
12
|
-
from rich.tree import Tree
|
|
6
|
+
from typing import List, Union
|
|
13
7
|
|
|
14
8
|
from fastapi_cli.exceptions import FastAPICLIException
|
|
15
9
|
|
|
@@ -22,24 +16,20 @@ except ImportError: # pragma: no cover
|
|
|
22
16
|
|
|
23
17
|
|
|
24
18
|
def get_default_path() -> Path:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return path
|
|
40
|
-
path = Path("app/api.py")
|
|
41
|
-
if path.is_file():
|
|
42
|
-
return path
|
|
19
|
+
potential_paths = (
|
|
20
|
+
"main.py",
|
|
21
|
+
"app.py",
|
|
22
|
+
"api.py",
|
|
23
|
+
"app/main.py",
|
|
24
|
+
"app/app.py",
|
|
25
|
+
"app/api.py",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
for full_path in potential_paths:
|
|
29
|
+
path = Path(full_path)
|
|
30
|
+
if path.is_file():
|
|
31
|
+
return path
|
|
32
|
+
|
|
43
33
|
raise FastAPICLIException(
|
|
44
34
|
"Could not find a default file to run, please provide an explicit path"
|
|
45
35
|
)
|
|
@@ -49,12 +39,10 @@ def get_default_path() -> Path:
|
|
|
49
39
|
class ModuleData:
|
|
50
40
|
module_import_str: str
|
|
51
41
|
extra_sys_path: Path
|
|
42
|
+
module_paths: List[Path]
|
|
52
43
|
|
|
53
44
|
|
|
54
45
|
def get_module_data_from_path(path: Path) -> ModuleData:
|
|
55
|
-
logger.info(
|
|
56
|
-
"Searching for package file structure from directories with [blue]__init__.py[/blue] files"
|
|
57
|
-
)
|
|
58
46
|
use_path = path.resolve()
|
|
59
47
|
module_path = use_path
|
|
60
48
|
if use_path.is_file() and use_path.stem == "__init__":
|
|
@@ -68,37 +56,12 @@ def get_module_data_from_path(path: Path) -> ModuleData:
|
|
|
68
56
|
extra_sys_path = parent.parent
|
|
69
57
|
else:
|
|
70
58
|
break
|
|
71
|
-
|
|
72
|
-
root = module_paths[0]
|
|
73
|
-
name = f"🐍 {root.name}" if root.is_file() else f"📁 {root.name}"
|
|
74
|
-
root_tree = Tree(name)
|
|
75
|
-
if root.is_dir():
|
|
76
|
-
root_tree.add("[dim]🐍 __init__.py[/dim]")
|
|
77
|
-
tree = root_tree
|
|
78
|
-
for sub_path in module_paths[1:]:
|
|
79
|
-
sub_name = (
|
|
80
|
-
f"🐍 {sub_path.name}" if sub_path.is_file() else f"📁 {sub_path.name}"
|
|
81
|
-
)
|
|
82
|
-
tree = tree.add(sub_name)
|
|
83
|
-
if sub_path.is_dir():
|
|
84
|
-
tree.add("[dim]🐍 __init__.py[/dim]")
|
|
85
|
-
title = "[b green]Python module file[/b green]"
|
|
86
|
-
if len(module_paths) > 1 or module_path.is_dir():
|
|
87
|
-
title = "[b green]Python package file structure[/b green]"
|
|
88
|
-
panel = Padding(
|
|
89
|
-
Panel(
|
|
90
|
-
root_tree,
|
|
91
|
-
title=title,
|
|
92
|
-
expand=False,
|
|
93
|
-
padding=(1, 2),
|
|
94
|
-
),
|
|
95
|
-
1,
|
|
96
|
-
)
|
|
97
|
-
print(panel)
|
|
59
|
+
|
|
98
60
|
module_str = ".".join(p.stem for p in module_paths)
|
|
99
|
-
logger.info(f"Importing module [green]{module_str}[/green]")
|
|
100
61
|
return ModuleData(
|
|
101
|
-
module_import_str=module_str,
|
|
62
|
+
module_import_str=module_str,
|
|
63
|
+
extra_sys_path=extra_sys_path.resolve(),
|
|
64
|
+
module_paths=module_paths,
|
|
102
65
|
)
|
|
103
66
|
|
|
104
67
|
|
|
@@ -140,32 +103,30 @@ def get_app_name(*, mod_data: ModuleData, app_name: Union[str, None] = None) ->
|
|
|
140
103
|
raise FastAPICLIException("Could not find FastAPI app in module, try using --app")
|
|
141
104
|
|
|
142
105
|
|
|
143
|
-
|
|
106
|
+
@dataclass
|
|
107
|
+
class ImportData:
|
|
108
|
+
app_name: str
|
|
109
|
+
module_data: ModuleData
|
|
110
|
+
import_string: str
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_import_data(
|
|
144
114
|
*, path: Union[Path, None] = None, app_name: Union[str, None] = None
|
|
145
|
-
) ->
|
|
115
|
+
) -> ImportData:
|
|
146
116
|
if not path:
|
|
147
117
|
path = get_default_path()
|
|
148
|
-
|
|
149
|
-
logger.
|
|
118
|
+
|
|
119
|
+
logger.debug(f"Using path [blue]{path}[/blue]")
|
|
120
|
+
logger.debug(f"Resolved absolute path {path.resolve()}")
|
|
121
|
+
|
|
150
122
|
if not path.exists():
|
|
151
123
|
raise FastAPICLIException(f"Path does not exist {path}")
|
|
152
124
|
mod_data = get_module_data_from_path(path)
|
|
153
125
|
sys.path.insert(0, str(mod_data.extra_sys_path))
|
|
154
126
|
use_app_name = get_app_name(mod_data=mod_data, app_name=app_name)
|
|
155
|
-
|
|
156
|
-
f"from {mod_data.module_import_str} import {use_app_name}", "python"
|
|
157
|
-
)
|
|
158
|
-
import_panel = Padding(
|
|
159
|
-
Panel(
|
|
160
|
-
import_example,
|
|
161
|
-
title="[b green]Importable FastAPI app[/b green]",
|
|
162
|
-
expand=False,
|
|
163
|
-
padding=(1, 2),
|
|
164
|
-
),
|
|
165
|
-
1,
|
|
166
|
-
)
|
|
167
|
-
logger.info("Found importable FastAPI app")
|
|
168
|
-
print(import_panel)
|
|
127
|
+
|
|
169
128
|
import_string = f"{mod_data.module_import_str}:{use_app_name}"
|
|
170
|
-
|
|
171
|
-
return
|
|
129
|
+
|
|
130
|
+
return ImportData(
|
|
131
|
+
app_name=use_app_name, module_data=mod_data, import_string=import_string
|
|
132
|
+
)
|
fastapi_cli/logging.py
CHANGED
|
@@ -5,7 +5,9 @@ from rich.console import Console
|
|
|
5
5
|
from rich.logging import RichHandler
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def setup_logging(
|
|
8
|
+
def setup_logging(
|
|
9
|
+
terminal_width: Union[int, None] = None, level: int = logging.INFO
|
|
10
|
+
) -> None:
|
|
9
11
|
logger = logging.getLogger("fastapi_cli")
|
|
10
12
|
console = Console(width=terminal_width) if terminal_width else None
|
|
11
13
|
rich_handler = RichHandler(
|
|
@@ -19,5 +21,5 @@ def setup_logging(terminal_width: Union[int, None] = None) -> None:
|
|
|
19
21
|
rich_handler.setFormatter(logging.Formatter("%(message)s"))
|
|
20
22
|
logger.addHandler(rich_handler)
|
|
21
23
|
|
|
22
|
-
logger.setLevel(
|
|
24
|
+
logger.setLevel(level)
|
|
23
25
|
logger.propagate = False
|
|
File without changes
|
fastapi_cli/utils/cli.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from rich_toolkit import RichToolkit, RichToolkitTheme
|
|
5
|
+
from rich_toolkit.styles import TaggedStyle
|
|
6
|
+
from uvicorn.logging import DefaultFormatter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CustomFormatter(DefaultFormatter):
|
|
10
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
11
|
+
super().__init__(*args, **kwargs)
|
|
12
|
+
self.toolkit = get_rich_toolkit()
|
|
13
|
+
|
|
14
|
+
def formatMessage(self, record: logging.LogRecord) -> str:
|
|
15
|
+
return self.toolkit.print_as_string(record.getMessage(), tag=record.levelname)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_uvicorn_log_config() -> Dict[str, Any]:
|
|
19
|
+
return {
|
|
20
|
+
"version": 1,
|
|
21
|
+
"formatters": {
|
|
22
|
+
"default": {
|
|
23
|
+
"()": CustomFormatter,
|
|
24
|
+
"fmt": "%(levelprefix)s %(message)s",
|
|
25
|
+
"use_colors": None,
|
|
26
|
+
},
|
|
27
|
+
"access": {
|
|
28
|
+
"()": CustomFormatter,
|
|
29
|
+
"fmt": "%(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
"handlers": {
|
|
33
|
+
"default": {
|
|
34
|
+
"formatter": "default",
|
|
35
|
+
"class": "logging.StreamHandler",
|
|
36
|
+
"stream": "ext://sys.stderr",
|
|
37
|
+
},
|
|
38
|
+
"access": {
|
|
39
|
+
"formatter": "access",
|
|
40
|
+
"class": "logging.StreamHandler",
|
|
41
|
+
"stream": "ext://sys.stdout",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
"loggers": {
|
|
45
|
+
"uvicorn": {"handlers": ["default"], "level": "INFO"},
|
|
46
|
+
"uvicorn.error": {"level": "INFO"},
|
|
47
|
+
"uvicorn.access": {
|
|
48
|
+
"handlers": ["access"],
|
|
49
|
+
"level": "INFO",
|
|
50
|
+
"propagate": False,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
logger = logging.getLogger(__name__)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_rich_toolkit() -> RichToolkit:
|
|
60
|
+
theme = RichToolkitTheme(
|
|
61
|
+
style=TaggedStyle(tag_width=11),
|
|
62
|
+
theme={
|
|
63
|
+
"tag.title": "white on #009485",
|
|
64
|
+
"tag": "white on #007166",
|
|
65
|
+
"placeholder": "grey85",
|
|
66
|
+
"text": "white",
|
|
67
|
+
"selected": "#007166",
|
|
68
|
+
"result": "grey85",
|
|
69
|
+
"progress": "on #007166",
|
|
70
|
+
"error": "red",
|
|
71
|
+
"log.info": "black on blue",
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return RichToolkit(theme=theme)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastapi-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.6
|
|
4
4
|
Summary: Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀
|
|
5
|
-
Home-page: https://github.com/tiangolo/fastapi-cli
|
|
6
5
|
Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
|
|
7
6
|
License: MIT
|
|
8
7
|
Classifier: Intended Audience :: Information Technology
|
|
@@ -20,40 +19,42 @@ Classifier: Framework :: FastAPI
|
|
|
20
19
|
Classifier: Intended Audience :: Developers
|
|
21
20
|
Classifier: License :: OSI Approved :: MIT License
|
|
22
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
24
22
|
Classifier: Programming Language :: Python :: 3.8
|
|
25
23
|
Classifier: Programming Language :: Python :: 3.9
|
|
26
24
|
Classifier: Programming Language :: Python :: 3.10
|
|
27
25
|
Classifier: Programming Language :: Python :: 3.11
|
|
28
26
|
Classifier: Programming Language :: Python :: 3.12
|
|
29
27
|
Classifier: License :: OSI Approved :: MIT License
|
|
30
|
-
Project-URL:
|
|
31
|
-
Project-URL:
|
|
32
|
-
Project-URL: Repository, https://github.com/
|
|
28
|
+
Project-URL: Homepage, https://github.com/fastapi/fastapi-cli
|
|
29
|
+
Project-URL: Documentation, https://fastapi.tiangolo.com/fastapi-cli/
|
|
30
|
+
Project-URL: Repository, https://github.com/fastapi/fastapi-cli
|
|
31
|
+
Project-URL: Issues, https://github.com/fastapi/fastapi-cli/issues
|
|
32
|
+
Project-URL: Changelog, https://github.com/fastapi/fastapi-cli/blob/main/release-notes.md
|
|
33
33
|
Requires-Python: >=3.8
|
|
34
34
|
Requires-Dist: typer>=0.12.3
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
Requires-Dist:
|
|
35
|
+
Requires-Dist: uvicorn[standard]>=0.15.0
|
|
36
|
+
Requires-Dist: rich-toolkit>=0.11.1
|
|
37
37
|
Provides-Extra: standard
|
|
38
|
+
Requires-Dist: uvicorn[standard]>=0.15.0; extra == "standard"
|
|
38
39
|
Description-Content-Type: text/markdown
|
|
39
40
|
|
|
40
41
|
# FastAPI CLI
|
|
41
42
|
|
|
42
|
-
<a href="https://github.com/
|
|
43
|
-
<img src="https://github.com/
|
|
43
|
+
<a href="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml" target="_blank">
|
|
44
|
+
<img src="https://github.com/fastapi/fastapi-cli/actions/workflows/test.yml/badge.svg" alt="Test">
|
|
44
45
|
</a>
|
|
45
|
-
<a href="https://github.com/
|
|
46
|
-
<img src="https://github.com/
|
|
46
|
+
<a href="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml" target="_blank">
|
|
47
|
+
<img src="https://github.com/fastapi/fastapi-cli/actions/workflows/publish.yml/badge.svg" alt="Publish">
|
|
47
48
|
</a>
|
|
48
|
-
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/
|
|
49
|
-
<img src="https://coverage-badge.samuelcolvin.workers.dev/
|
|
49
|
+
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi-cli" target="_blank">
|
|
50
|
+
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi-cli.svg" alt="Coverage">
|
|
50
51
|
<a href="https://pypi.org/project/fastapi-cli" target="_blank">
|
|
51
52
|
<img src="https://img.shields.io/pypi/v/fastapi-cli?color=%2334D058&label=pypi%20package" alt="Package version">
|
|
52
53
|
</a>
|
|
53
54
|
|
|
54
55
|
---
|
|
55
56
|
|
|
56
|
-
**Source Code**: <a href="https://github.com/
|
|
57
|
+
**Source Code**: <a href="https://github.com/fastapi/fastapi-cli" target="_blank">https://github.com/fastapi/fastapi-cli</a>
|
|
57
58
|
|
|
58
59
|
---
|
|
59
60
|
|
|
@@ -63,7 +64,7 @@ Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀
|
|
|
63
64
|
|
|
64
65
|
**FastAPI CLI** is a command line program `fastapi` that you can use to serve your FastAPI app, manage your FastAPI project, and more.
|
|
65
66
|
|
|
66
|
-
When you install FastAPI (e.g. with `pip install fastapi`), it includes a package called `fastapi-cli`, this package provides the `fastapi` command in the terminal.
|
|
67
|
+
When you install FastAPI (e.g. with `pip install "fastapi[standard]"`), it includes a package called `fastapi-cli`, this package provides the `fastapi` command in the terminal.
|
|
67
68
|
|
|
68
69
|
To run your FastAPI app for development, you can use the `fastapi dev` command:
|
|
69
70
|
|
|
@@ -71,46 +72,33 @@ To run your FastAPI app for development, you can use the `fastapi dev` command:
|
|
|
71
72
|
|
|
72
73
|
```console
|
|
73
74
|
$ fastapi dev main.py
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
│ │
|
|
102
|
-
│ Running in development mode, for production use: │
|
|
103
|
-
│ │
|
|
104
|
-
│ fastapi run │
|
|
105
|
-
│ │
|
|
106
|
-
╰─────────────────────────────────────────────────────╯
|
|
107
|
-
|
|
108
|
-
INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
|
|
109
|
-
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
|
110
|
-
INFO: Started reloader process [56345] using WatchFiles
|
|
111
|
-
INFO: Started server process [56352]
|
|
112
|
-
INFO: Waiting for application startup.
|
|
113
|
-
INFO: Application startup complete.
|
|
75
|
+
|
|
76
|
+
FastAPI Starting development server 🚀
|
|
77
|
+
|
|
78
|
+
Searching for package file structure from directories with __init__.py files
|
|
79
|
+
Importing from /home/user/code/awesomeapp
|
|
80
|
+
|
|
81
|
+
module 🐍 main.py
|
|
82
|
+
|
|
83
|
+
code Importing the FastAPI app object from the module with the following code:
|
|
84
|
+
|
|
85
|
+
from main import app
|
|
86
|
+
|
|
87
|
+
app Using import string: main:app
|
|
88
|
+
|
|
89
|
+
server Server started at http://127.0.0.1:8000
|
|
90
|
+
server Documentation at http://127.0.0.1:8000/docs
|
|
91
|
+
|
|
92
|
+
tip Running in development mode, for production use: fastapi run
|
|
93
|
+
|
|
94
|
+
Logs:
|
|
95
|
+
|
|
96
|
+
INFO Will watch for changes in these directories: ['/home/user/code/awesomeapp']
|
|
97
|
+
INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
|
98
|
+
INFO Started reloader process [4106097] using WatchFiles
|
|
99
|
+
INFO Started server process [4106120]
|
|
100
|
+
INFO Waiting for application startup.
|
|
101
|
+
INFO Application startup complete.
|
|
114
102
|
```
|
|
115
103
|
|
|
116
104
|
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
fastapi_cli-0.0.6.dist-info/METADATA,sha256=0desl40Ac-GLGIF6wFXHnFyQHTNzQFmUCLBfWLXPOAY,6152
|
|
2
|
+
fastapi_cli-0.0.6.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
|
|
3
|
+
fastapi_cli-0.0.6.dist-info/entry_points.txt,sha256=L-dwDLGAhOlBVadq5cDBAB1i8y4oSFueX02A4gmMKco,65
|
|
4
|
+
fastapi_cli-0.0.6.dist-info/licenses/LICENSE,sha256=FqD5B4VbXJnefprQseE0U8llL6FxojC-i8muZy7YmSU,1086
|
|
5
|
+
fastapi_cli/__init__.py,sha256=QiiYsv0kcJaB8wCWyT-FnI2b6be87HA-CrrIUn8LQhg,22
|
|
6
|
+
fastapi_cli/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
|
|
7
|
+
fastapi_cli/cli.py,sha256=qFLyywyl-oXewhijF68AiQGH9RGwIhzZSNobpN1m3Gw,11391
|
|
8
|
+
fastapi_cli/discover.py,sha256=Q3CSEWt2V68JcNuAv31l7IcO_-146n2dBUSdtexJPYE,3971
|
|
9
|
+
fastapi_cli/exceptions.py,sha256=AHRSqd43fbqN5IpX-Fq389k9MoEK_q28wVFL7oqPNcc,47
|
|
10
|
+
fastapi_cli/logging.py,sha256=Yh2Nx5eC8XE_a3psTMO0kA5BM8lf63bBCqSMyDxUN7s,690
|
|
11
|
+
fastapi_cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
fastapi_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
fastapi_cli/utils/cli.py,sha256=pZJQRvwniAtlrHHd8Tzgz_UR-hYytbqqaI80kIZjoZ8,2225
|
|
14
|
+
fastapi_cli-0.0.6.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
fastapi_cli-0.0.4.dist-info/METADATA,sha256=BygSIC-5T6QJPYcaT2vP8vnOAcv8zA1JAV6OmhxuNr4,7022
|
|
2
|
-
fastapi_cli-0.0.4.dist-info/WHEEL,sha256=vnE8JVcI2Wz7GRKorsPArnBdnW2SWKWGow5gu5tHlRU,90
|
|
3
|
-
fastapi_cli-0.0.4.dist-info/entry_points.txt,sha256=RLUGtkrAf9gNKxCS3EeJNYN8AF1Er364vjW7bnEcCA8,50
|
|
4
|
-
fastapi_cli-0.0.4.dist-info/licenses/LICENSE,sha256=FqD5B4VbXJnefprQseE0U8llL6FxojC-i8muZy7YmSU,1086
|
|
5
|
-
fastapi_cli/__init__.py,sha256=1mptEzQihbdyqqzMgdns_j5ZGK9gz7hR2bsgA_TnjO4,22
|
|
6
|
-
fastapi_cli/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
|
|
7
|
-
fastapi_cli/cli.py,sha256=o7dRxEfZ_lBO72b6RZEAa_wKua2pkK5kp6Rr5PhZML4,9278
|
|
8
|
-
fastapi_cli/discover.py,sha256=MxXPVqd9X-cgUdikVECjs8BtXcXygX8g3zppUEyqK5Y,5570
|
|
9
|
-
fastapi_cli/exceptions.py,sha256=AHRSqd43fbqN5IpX-Fq389k9MoEK_q28wVFL7oqPNcc,47
|
|
10
|
-
fastapi_cli/logging.py,sha256=lI7rIsioTJQsxDuWpG5YR_brWpIAUY4vDnhYm5p91ws,664
|
|
11
|
-
fastapi_cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
fastapi_cli-0.0.4.dist-info/RECORD,,
|
|
File without changes
|