Skip to content

Commit 4b6a822

Browse files
committed
✨ Add --reload-dir option to dev command
1 parent c8f27b3 commit 4b6a822

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/fastapi_cli/cli.py

Lines changed: 12 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,10 @@ 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 else None
226+
),
222227
workers=workers,
223228
root_path=root_path,
224229
proxy_headers=proxy_headers,
@@ -255,6 +260,12 @@ def dev(
255260
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development."
256261
),
257262
] = True,
263+
reload_dir: Annotated[
264+
Union[List[Path], None],
265+
typer.Option(
266+
help="Set reload directories explicitly, instead of using the current working directory."
267+
),
268+
] = None,
258269
root_path: Annotated[
259270
str,
260271
typer.Option(
@@ -318,6 +329,7 @@ def dev(
318329
host=host,
319330
port=port,
320331
reload=reload,
332+
reload_dirs=reload_dir,
321333
root_path=root_path,
322334
app=app,
323335
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)