@@ -91,7 +91,6 @@ def callback(
9191 "--version" , help = "Show the version and exit." , callback = version_callback
9292 ),
9393 ] = None ,
94- verbose : bool = typer .Option (False , help = "Enable verbose output" ),
9594) -> None :
9695 """
9796 FastAPI CLI - The [bold]fastapi[/bold] command line app. 😎
@@ -101,9 +100,7 @@ def callback(
101100 Read more in the docs: [link=https://fastapi.tiangolo.com/fastapi-cli/]https://fastapi.tiangolo.com/fastapi-cli/[/link].
102101 """
103102
104- log_level = logging .DEBUG if verbose else logging .INFO
105-
106- setup_logging (level = log_level )
103+ setup_logging ()
107104
108105
109106def _get_module_tree (module_paths : list [Path ]) -> Tree :
@@ -142,17 +139,25 @@ def _run(
142139 proxy_headers : bool = False ,
143140 forwarded_allow_ips : str | None = None ,
144141 public_url : str | None = None ,
142+ verbose : bool = False ,
145143) -> None :
144+ # setup_logging() in the root callback runs before command options are
145+ # parsed, so the per-command --verbose only adjusts the level here
146+ logging .getLogger ("fastapi_cli" ).setLevel (
147+ logging .DEBUG if verbose else logging .INFO
148+ )
149+
146150 with get_rich_toolkit () as toolkit :
147151 server_type = "development" if command == "dev" else "production"
148152
149153 toolkit .print (f"Starting FastAPI in { server_type } mode" , emoji = "⚡️" )
150154
151- toolkit .print_line ()
152- toolkit .print (
153- "Searching for package file structure from directories with [blue]__init__.py[/blue] files" ,
154- emoji = "🔎" ,
155- )
155+ if verbose :
156+ toolkit .print_line ()
157+ toolkit .print (
158+ "Searching for package file structure from directories with [blue]__init__.py[/blue] files" ,
159+ emoji = "🔎" ,
160+ )
156161
157162 if entrypoint and (path or app ):
158163 toolkit .print_line ()
@@ -194,40 +199,54 @@ def _run(
194199
195200 module_data = import_data .module_data
196201 import_string = import_data .import_string
202+ is_auto_discovery = import_data .module_config_source == "auto-discovery"
197203
198- toolkit .print_line ()
199- toolkit .print (f"Importing from { module_data .extra_sys_path } " , emoji = "📂" )
200- toolkit .print_line ()
204+ if verbose :
205+ toolkit .print_line ()
206+ toolkit .print (f"Importing from { module_data .extra_sys_path } " , emoji = "📂" )
207+ toolkit .print_line ()
201208
202- if module_data .module_paths :
203- root_tree = _get_module_tree (module_data .module_paths )
209+ if module_data .module_paths :
210+ root_tree = _get_module_tree (module_data .module_paths )
204211
205- toolkit .print (root_tree )
212+ toolkit .print (root_tree )
206213
207- toolkit .print_line ()
214+ toolkit .print_line ()
215+
216+ toolkit .print (
217+ "Importing the FastAPI app object from the module with the following code:" ,
218+ )
219+ toolkit .print_line ()
220+ toolkit .print (
221+ f"[blue]from [bold]{ module_data .module_import_str } [/bold] import [bold]{ import_data .app_name } [/bold]" ,
222+ )
223+
224+ # Outside --verbose, fold the resolution source into the import string
225+ # line and point newcomers at --verbose for the full explanation
226+ if is_auto_discovery and not verbose :
227+ app_note = " [dim](auto-discovered, use --verbose to learn more)[/]"
228+ else :
229+ app_note = ""
208230
209- toolkit .print (
210- "Importing the FastAPI app object from the module with the following code:" ,
211- )
212231 toolkit .print_line ()
213232 toolkit .print (
214- f"[blue]from [bold] { module_data . module_import_str } [/bold] import [bold] { import_data . app_name } [/bold]" ,
233+ f"Using import string: [blue] { import_string } [/] { app_note } " , emoji = "🐍"
215234 )
216235
217- toolkit .print_line ()
218- toolkit .print (f"Using import string: [blue]{ import_string } [/]" , emoji = "🐍" )
219-
220- toolkit .print_line ()
221- mod_source_desc = SOURCE_DESCRIPTIONS [import_data .module_config_source ]
222- app_source_desc = SOURCE_DESCRIPTIONS [import_data .app_name_config_source ]
223- toolkit .print ("Configuration sources:" , emoji = "📋" )
224- if mod_source_desc == app_source_desc :
225- toolkit .print (f"• Import string: { mod_source_desc } " )
226- else :
227- toolkit .print (f"• Module: { mod_source_desc } " )
228- toolkit .print (f"• App name: { app_source_desc } " )
236+ if verbose :
237+ toolkit .print_line ()
238+ mod_source_desc = SOURCE_DESCRIPTIONS [import_data .module_config_source ]
239+ app_source_desc = SOURCE_DESCRIPTIONS [import_data .app_name_config_source ]
240+ toolkit .print ("Configuration sources:" , emoji = "📋" )
241+ if mod_source_desc == app_source_desc :
242+ toolkit .print (f"• Import string: { mod_source_desc } " )
243+ else :
244+ toolkit .print (f"• Module: { mod_source_desc } " )
245+ toolkit .print (f"• App name: { app_source_desc } " )
229246
230- if import_data .module_config_source == "auto-discovery" :
247+ # Nudge to pin the entrypoint whenever it was auto-discovered, so it's
248+ # explicit next time — shown in the default output, not just --verbose
249+ if is_auto_discovery :
231250 toolkit .print_line ()
232251 toolkit .print (
233252 "You can configure an entrypoint in [blue]pyproject.toml[/] for this app with:" ,
@@ -252,13 +271,6 @@ def _run(
252271 toolkit .print (f"Server started at [link={ url } ]{ url } [/]" , emoji = "🌐" )
253272 toolkit .print (f"Documentation at [link={ url_docs } ]{ url_docs } [/]" )
254273
255- if command == "dev" :
256- toolkit .print_line ()
257- toolkit .print (
258- "Running in development mode, for production use: [bold]fastapi run[/]" ,
259- emoji = "💡" ,
260- )
261-
262274 if not uvicorn :
263275 raise FastAPICLIException (
264276 "Could not import Uvicorn, try running 'pip install uvicorn'"
@@ -356,6 +368,14 @@ def dev(
356368 help = "Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
357369 ),
358370 ] = None ,
371+ verbose : Annotated [
372+ bool ,
373+ typer .Option (
374+ "--verbose" ,
375+ "-v" ,
376+ help = "Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured." ,
377+ ),
378+ ] = False ,
359379) -> Any :
360380 """
361381 Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. 🧪
@@ -395,6 +415,7 @@ def dev(
395415 proxy_headers = proxy_headers ,
396416 forwarded_allow_ips = forwarded_allow_ips ,
397417 public_url = os .getenv ("FASTAPI_PUBLIC_URL" ),
418+ verbose = verbose ,
398419 )
399420
400421
@@ -464,6 +485,14 @@ def run(
464485 help = "Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
465486 ),
466487 ] = None ,
488+ verbose : Annotated [
489+ bool ,
490+ typer .Option (
491+ "--verbose" ,
492+ "-v" ,
493+ help = "Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured." ,
494+ ),
495+ ] = False ,
467496) -> Any :
468497 """
469498 Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. 🚀
@@ -503,6 +532,7 @@ def run(
503532 proxy_headers = proxy_headers ,
504533 forwarded_allow_ips = forwarded_allow_ips ,
505534 public_url = os .getenv ("FASTAPI_PUBLIC_URL" ),
535+ verbose = verbose ,
506536 )
507537
508538
0 commit comments