-
-
Notifications
You must be signed in to change notification settings - Fork 753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix watchfiles file filtering #1770
Conversation
The module `uvicorn.supervisors.watchfilesreload` implements watchfiles file watching. The module includes a `FileFilter` class. Currently, the `FileFilter` class is instantiated when initializing `class WatchFilesReload`, but not passed to `watchfiles.watch()`. Instead, `watchfiles.watch(watch_filter=None)` is used. As a result, `watchfiles` does not filter out the expected changes. It detects changes to `.mypy_cache` and `.pyc` files that should be ignored. This commit will: - Update the arguments to `FileFilter.__call__` to match those expected by `watchfiles.watch()`. - Pass the `FileFilter` instance to `watchfiles.watch()`. `watchfiles` will correctly filter `.mypy_cache`/`.pyc` file changes. https://watchfiles.helpmanual.io/api/watch/
Are you sure what this doesn't mean we're calling the filter logic twice on every reload? |
The `uvicorn.supervisors.watchfilesreload.FileFilter.__call__` method was being called twice when reloading with watchfiles: 1. `watchfiles.main._prep_changes` 2. `uvicorn.supervisors.watchfilesreload.WatchFilesReload.should_restart`. This commit will drop the duplicate call from `should_restart`, and add a test that patches `FileFilter.__call__` and tracks the call count. #1770 (comment)
Thank you for pointing that out @samuelcolvin. It was being called twice:
I've dropped the duplicate call from I've also added a test that patches over |
Humm, but I would still recommend the previous approach, since it avoids calling I'm not sure why you were seeing reloads from changes which should have been ignored as I thought the old solution was correct. It could definitely do with a comment explaining why we don't pass the filter to |
We're having to call
Happy to get some PRs to |
Okay, I've looked into this and as i thought, the implementation is already correct, this PR should be closed. Changes to The change you've proposed here causes extra unnecessary processing in python which IMHO is worse than a log message on a logger which is not enabled by default. The other solution here would be a wholesale change to how reload file filtering works so we could pass |
IMHO watchfiles is fine as it is, it minimises the amount of python logic by operating on raw strings, not |
One of the reasons we do that is so we could move the calls to the filter function into rust in future, hence I don't want to change the signature. |
ping @br3ndonland 👀 |
🤷 |
Thanks @br3ndonland for reporting this, definitely worth investigating this and confirming things are working as I thought. 👍 |
Description
PR #1437 added file watching with
watchfiles
to a new module,uvicorn.supervisors.watchfilesreload
. The module included aFileFilter
class.uvicorn/uvicorn/supervisors/watchfilesreload.py
Line 11 in b06cc63
Currently, the
FileFilter
class is instantiated when initializingclass WatchFilesReload
, but not passed towatchfiles.watch()
. Instead,watchfiles.watch(watch_filter=None)
is used.uvicorn/uvicorn/supervisors/watchfilesreload.py
Lines 74 to 82 in b06cc63
As a result,
watchfiles
does not filter out the expected changes. It detects changes to.mypy_cache
and.pyc
files that should be ignored.Minimal repro:
main.py
:Start it up:
Save
main.py
, check the server logs, and note thatwatchfiles
is detecting changes to.mypy_cache
and.pyc
files:Changes
This PR will:
FileFilter.__call__
to match those expected bywatchfiles.watch()
.FileFilter
instance towatchfiles.watch()
.When the changes from this PR are used with the minimal repro above,
watchfiles
will correctly filter out changes to.mypy_cache
and.pyc
files.Tests pass without any changes, but it would be great to update the tests to prevent this problem from recurring.
In the future, we could simplify file filtering by removing the
FileFilter
class and usingwatchfiles
filters instead. The main limitation is thatwatchfiles
filters accept regular expressions for pattern matching (withre.compile
). Uvicorn accepts globs instead of regexes.Related
watchgod
towatchfiles
#1437FileNotFoundError
during development samuelcolvin/watchfiles#207