Skip to content

Commit 5e72ded

Browse files
patrick91pre-commit-ci[bot]tiangolo
authored
✨ Add --reload-dir option to dev command (#267)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
1 parent 30edf85 commit 5e72ded

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

src/fastapi_cli/cli.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ def _run(
104104
host: str = "127.0.0.1",
105105
port: int = 8000,
106106
reload: bool = True,
107+
reload_dirs: Union[list[Path], None] = None,
107108
workers: Union[int, None] = None,
108109
root_path: str = "",
109110
command: str,
@@ -219,6 +220,11 @@ def _run(
219220
host=host,
220221
port=port,
221222
reload=reload,
223+
reload_dirs=(
224+
[str(directory.resolve()) for directory in reload_dirs]
225+
if reload_dirs
226+
else None
227+
),
222228
workers=workers,
223229
root_path=root_path,
224230
proxy_headers=proxy_headers,
@@ -255,6 +261,12 @@ def dev(
255261
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development."
256262
),
257263
] = True,
264+
reload_dir: Annotated[
265+
Union[list[Path], None],
266+
typer.Option(
267+
help="Set reload directories explicitly, instead of using the current working directory."
268+
),
269+
] = None,
258270
root_path: Annotated[
259271
str,
260272
typer.Option(
@@ -318,6 +330,7 @@ def dev(
318330
host=host,
319331
port=port,
320332
reload=reload,
333+
reload_dirs=reload_dir,
321334
root_path=root_path,
322335
app=app,
323336
entrypoint=entrypoint,

tests/test_cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def test_dev() -> None:
2727
"host": "127.0.0.1",
2828
"port": 8000,
2929
"reload": True,
30+
"reload_dirs": None,
3031
"workers": None,
3132
"root_path": "",
3233
"proxy_headers": True,
@@ -72,6 +73,7 @@ def test_dev_package() -> None:
7273
"host": "127.0.0.1",
7374
"port": 8000,
7475
"reload": True,
76+
"reload_dirs": None,
7577
"workers": None,
7678
"root_path": "",
7779
"proxy_headers": True,
@@ -121,6 +123,7 @@ def test_dev_args() -> None:
121123
"host": "192.168.0.2",
122124
"port": 8080,
123125
"reload": False,
126+
"reload_dirs": None,
124127
"workers": None,
125128
"root_path": "/api",
126129
"proxy_headers": False,
@@ -151,6 +154,7 @@ def test_dev_env_vars() -> None:
151154
"host": "127.0.0.1",
152155
"port": 8111,
153156
"reload": True,
157+
"reload_dirs": None,
154158
"workers": None,
155159
"root_path": "",
156160
"proxy_headers": True,
@@ -188,6 +192,7 @@ def test_dev_env_vars_and_args() -> None:
188192
"host": "127.0.0.1",
189193
"port": 8080,
190194
"reload": True,
195+
"reload_dirs": None,
191196
"workers": None,
192197
"root_path": "",
193198
"proxy_headers": True,
@@ -233,6 +238,7 @@ def test_run() -> None:
233238
"host": "0.0.0.0",
234239
"port": 8000,
235240
"reload": False,
241+
"reload_dirs": None,
236242
"workers": None,
237243
"root_path": "",
238244
"proxy_headers": True,
@@ -259,6 +265,7 @@ def test_run_trust_proxy() -> None:
259265
"host": "0.0.0.0",
260266
"port": 8000,
261267
"reload": False,
268+
"reload_dirs": None,
262269
"workers": None,
263270
"root_path": "",
264271
"proxy_headers": True,
@@ -305,6 +312,7 @@ def test_run_args() -> None:
305312
"host": "192.168.0.2",
306313
"port": 8080,
307314
"reload": False,
315+
"reload_dirs": None,
308316
"workers": 2,
309317
"root_path": "/api",
310318
"proxy_headers": False,
@@ -336,6 +344,7 @@ def test_run_env_vars() -> None:
336344
"host": "0.0.0.0",
337345
"port": 8111,
338346
"reload": False,
347+
"reload_dirs": None,
339348
"workers": None,
340349
"root_path": "",
341350
"proxy_headers": True,
@@ -369,6 +378,7 @@ def test_run_env_vars_and_args() -> None:
369378
"host": "0.0.0.0",
370379
"port": 8080,
371380
"reload": False,
381+
"reload_dirs": None,
372382
"workers": None,
373383
"root_path": "",
374384
"proxy_headers": True,
@@ -404,6 +414,7 @@ def test_dev_help() -> None:
404414
assert "The host to serve on." in result.output
405415
assert "The port to serve on." in result.output
406416
assert "Enable auto-reload of the server when (code) files change." in result.output
417+
assert "Set reload directories explicitly" in result.output
407418
assert "The root path is used to tell your app" in result.output
408419
assert "The name of the variable that contains the FastAPI app" in result.output
409420
assert "Use multiple worker processes." not in result.output
@@ -443,6 +454,30 @@ def test_version() -> None:
443454
assert "FastAPI CLI version:" in result.output
444455

445456

457+
def test_dev_reload_dir() -> None:
458+
with changing_dir(assets_path):
459+
with patch.object(uvicorn, "run") as mock_run:
460+
result = runner.invoke(
461+
app,
462+
[
463+
"dev",
464+
"single_file_app.py",
465+
"--reload-dir",
466+
"src",
467+
"--reload-dir",
468+
"lib",
469+
],
470+
)
471+
assert result.exit_code == 0, result.output
472+
assert mock_run.called
473+
assert mock_run.call_args
474+
# Paths are resolved to absolute paths
475+
reload_dirs = mock_run.call_args.kwargs["reload_dirs"]
476+
assert len(reload_dirs) == 2
477+
assert reload_dirs[0] == str((assets_path / "src").resolve())
478+
assert reload_dirs[1] == str((assets_path / "lib").resolve())
479+
480+
446481
def test_dev_with_import_string() -> None:
447482
with changing_dir(assets_path):
448483
with patch.object(uvicorn, "run") as mock_run:
@@ -456,6 +491,7 @@ def test_dev_with_import_string() -> None:
456491
"host": "127.0.0.1",
457492
"port": 8000,
458493
"reload": True,
494+
"reload_dirs": None,
459495
"workers": None,
460496
"root_path": "",
461497
"proxy_headers": True,
@@ -477,6 +513,7 @@ def test_run_with_import_string() -> None:
477513
"host": "0.0.0.0",
478514
"port": 8000,
479515
"reload": False,
516+
"reload_dirs": None,
480517
"workers": None,
481518
"root_path": "",
482519
"proxy_headers": True,

0 commit comments

Comments
 (0)