From c55af77fe9a4da99ac594e15ab9ee07b34ef669c Mon Sep 17 00:00:00 2001 From: Michael Oliver Date: Fri, 8 Dec 2023 12:02:18 +0000 Subject: [PATCH] bug: allow explicit hidden file paths in `--reload-include` (#2176) * bug: allow explicit hidden file paths in `--reload-include` * remove modifying `default_excludes` array * modify `should_watch_file` to handle explicit patching path * modify watchfiles filter to handle explicit paths --------- Co-authored-by: Michael Oliver --- tests/conftest.py | 3 +++ tests/supervisors/test_reload.py | 26 +++++++++++++++++++++++++ uvicorn/supervisors/watchfilesreload.py | 3 +++ uvicorn/supervisors/watchgodreload.py | 3 +++ 4 files changed, 35 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index c1c136022..400351d55 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -124,6 +124,9 @@ def reload_directory_structure(tmp_path_factory: pytest.TempPathFactory): │   └── sub.py ├── ext │   └── ext.jpg + ├── .dotted + ├── .dotted_dir + │   └── file.txt └── main.py """ root = tmp_path_factory.mktemp("reload_directory") diff --git a/tests/supervisors/test_reload.py b/tests/supervisors/test_reload.py index b677af3a1..4e3822375 100644 --- a/tests/supervisors/test_reload.py +++ b/tests/supervisors/test_reload.py @@ -279,6 +279,32 @@ def test_override_defaults(self, touch_soon) -> None: reloader.shutdown() + @pytest.mark.parametrize( + "reloader_class", + [ + pytest.param(WatchFilesReload, marks=skip_if_m1), + WatchGodReload, + ], + ) + def test_explicit_paths(self, touch_soon) -> None: + dotted_file = self.reload_path / ".dotted" + non_dotted_file = self.reload_path / "ext" / "ext.jpg" + python_file = self.reload_path / "main.py" + + with as_cwd(self.reload_path): + config = Config( + app="tests.test_config:asgi_app", + reload=True, + reload_includes=[".dotted", "ext/ext.jpg"], + ) + reloader = self._setup_reloader(config) + + assert self._reload_tester(touch_soon, reloader, dotted_file) + assert self._reload_tester(touch_soon, reloader, non_dotted_file) + assert self._reload_tester(touch_soon, reloader, python_file) + + reloader.shutdown() + @pytest.mark.skipif(WatchFilesReload is None, reason="watchfiles not available") @pytest.mark.parametrize("reloader_class", [WatchFilesReload]) def test_watchfiles_no_changes(self) -> None: diff --git a/uvicorn/supervisors/watchfilesreload.py b/uvicorn/supervisors/watchfilesreload.py index 186368312..0d5f807ce 100644 --- a/uvicorn/supervisors/watchfilesreload.py +++ b/uvicorn/supervisors/watchfilesreload.py @@ -43,6 +43,9 @@ def __init__(self, config: Config): def __call__(self, path: Path) -> bool: for include_pattern in self.includes: if path.match(include_pattern): + if str(path).endswith(include_pattern): + return True + for exclude_dir in self.exclude_dirs: if exclude_dir in path.parents: return False diff --git a/uvicorn/supervisors/watchgodreload.py b/uvicorn/supervisors/watchgodreload.py index d8bceacef..363d9c4db 100644 --- a/uvicorn/supervisors/watchgodreload.py +++ b/uvicorn/supervisors/watchgodreload.py @@ -56,6 +56,9 @@ def should_watch_file(self, entry: "DirEntry") -> bool: self.watched_files[entry.path] = False return False for include_pattern in self.includes: + if str(entry_path).endswith(include_pattern): + self.watched_files[entry.path] = True + return True if entry_path.match(include_pattern): for exclude_pattern in self.excludes: if entry_path.match(exclude_pattern):