Skip to content
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

Switch from watchgod to watchfiles #1437

Merged
merged 21 commits into from Jun 18, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -47,7 +47,7 @@ In this context, "Cython-based" means the following:
Moreover, "optional extras" means that:

- the websocket protocol will be handled by `websockets` (should you want to use `wsproto` you'd need to install it manually) if possible.
- the `--reload` flag in development mode will use `watchgod`.
- the `--reload` flag in development mode will use `watchfiles`.
- windows users will have `colorama` installed for the colored logs.
- `python-dotenv` will be installed should you want to use the `--env-file` option.
- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired.
Expand Down
4 changes: 2 additions & 2 deletions docs/deployment.md
Expand Up @@ -43,12 +43,12 @@ Options:
for files. Includes '*.py' by default; these
defaults can be overridden with `--reload-
exclude`. This option has no effect unless
watchgod is installed.
watchfiles is installed.
--reload-exclude TEXT Set glob patterns to exclude while watching
for files. Includes '.*, .py[cod], .sw.*,
~*' by default; these defaults can be
overridden with `--reload-include`. This
option has no effect unless watchgod is
option has no effect unless watchfiles is
installed.
--reload-delay FLOAT Delay between previous and next check if
application needs to be. Defaults to 0.25s.
Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Expand Up @@ -54,7 +54,7 @@ In this context, "Cython-based" means the following:
Moreover, "optional extras" means that:

- the websocket protocol will be handled by `websockets` (should you want to use `wsproto` you'd need to install it manually) if possible.
- the `--reload` flag in development mode will use `watchgod`.
- the `--reload` flag in development mode will use `watchfiles`.
- windows users will have `colorama` installed for the colored logs.
- `python-dotenv` will be installed should you want to use the `--env-file` option.
- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired.
Expand Down Expand Up @@ -110,12 +110,12 @@ Options:
for files. Includes '*.py' by default; these
defaults can be overridden with `--reload-
exclude`. This option has no effect unless
watchgod is installed.
watchfiles is installed.
--reload-exclude TEXT Set glob patterns to exclude while watching
for files. Includes '.*, .py[cod], .sw.*,
~*' by default; these defaults can be
overridden with `--reload-include`. This
option has no effect unless watchgod is
option has no effect unless watchfiles is
installed.
--reload-delay FLOAT Delay between previous and next check if
application needs to be. Defaults to 0.25s.
Expand Down
8 changes: 4 additions & 4 deletions docs/settings.md
Expand Up @@ -32,13 +32,13 @@ For example, in case you want to run the app on port `5000`, just set the enviro
* `--reload` - Enable auto-reload. Uvicorn supports two versions of auto-reloading behavior enabled by this option. There are important differences between them.
* `--reload-dir <path>` - Specify which directories to watch for python file changes. May be used multiple times. If unused, then by default the whole current directory will be watched. If you are running programmatically use `reload_dirs=[]` and pass a list of strings.

### Reloading without watchgod
### Reloading without watchfiles

If Uvicorn _cannot_ load [watchgod](https://pypi.org/project/watchgod/) at runtime, it will periodically look for changes in modification times to all `*.py` files (and only `*.py` files) inside of its monitored directories. See the `--reload-dir` option. Specifying other file extensions is not supported unless watchgod is installed. See the `--reload-include` and `--reload-exclude` options for details.
If Uvicorn _cannot_ load [watchfiles](https://pypi.org/project/watchfiles/) at runtime, it will periodically look for changes in modification times to all `*.py` files (and only `*.py` files) inside of its monitored directories. See the `--reload-dir` option. Specifying other file extensions is not supported unless watchfiles is installed. See the `--reload-include` and `--reload-exclude` options for details.

### Reloading with watchgod
### Reloading with watchfiles

For more nuanced control over which file modifications trigger reloads, install `uvicorn[standard]`, which includes watchgod as a dependency. Alternatively, install [watchgod](https://pypi.org/project/watchgod/) where Unvicorn can see it. This will enable the following options (which are otherwise ignored).
For more nuanced control over which file modifications trigger reloads, install `uvicorn[standard]`, which includes watchfiles as a dependency. Alternatively, install [watchfiles](https://pypi.org/project/watchfiles/) where Uvicorn can see it. This will enable the following options (which are otherwise ignored).

* `--reload-include <glob-pattern>` - Specify a glob pattern to match files or directories which will be watched. May be used multiple times. By default the following patterns are included: `*.py`. These defaults can be overwritten by including them in `--reload-exclude`.
* `--reload-exclude <glob-pattern>` - Specify a glob pattern to match files or directories which will excluded from watching. May be used multiple times. By default the following patterns are excluded: `.*, .py[cod], .sw.*, ~*`. These defaults can be overwritten by including them in `--reload-include`.
Expand Down
2 changes: 2 additions & 0 deletions main.py
@@ -0,0 +1,2 @@
async def app(scope, receive, send):
await send({"type": "http.response.start", "status": 200})
Kludex marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions requirements.txt
Expand Up @@ -23,6 +23,7 @@ coverage==6.3.2
coverage-conditional-plugin==0.5.0
httpx==1.0.0b0
pytest-asyncio==0.15.1
watchgod==0.8.2


# Documentation
Expand Down
5 changes: 4 additions & 1 deletion setup.cfg
Expand Up @@ -22,6 +22,7 @@ files =
uvicorn/supervisors/__init__.py,
uvicorn/middleware/debug.py,
uvicorn/middleware/wsgi.py,
uvicorn/supervisors/watchfilesreload.py,
samuelcolvin marked this conversation as resolved.
Show resolved Hide resolved
uvicorn/supervisors/watchgodreload.py,
uvicorn/_logging.py,
uvicorn/middleware/asgi2.py,
Expand Down Expand Up @@ -58,7 +59,7 @@ check_untyped_defs = True
profile = black
combine_as_imports = True
known_first_party = uvicorn,tests
known_third_party = click,does_not_exist,gunicorn,h11,httptools,pytest,requests,setuptools,urllib3,uvloop,watchgod,websockets,wsproto,yaml
known_third_party = click,does_not_exist,gunicorn,h11,httptools,pytest,requests,setuptools,urllib3,uvloop,watchgod,watchfiles,websockets,wsproto,yaml

[tool:pytest]
addopts = -rxXs
Expand All @@ -68,6 +69,7 @@ xfail_strict=True
filterwarnings=
# Turn warnings that aren't filtered into exceptions
error
ignore: \"watchgod\" is depreciated\, you should switch to watchfiles \(`pip install watchfiles`\)\.:DeprecationWarning

[coverage:run]
omit = venv/*
Expand All @@ -84,6 +86,7 @@ exclude_lines =
pragma: no cover
pragma: nocover
if TYPE_CHECKING:
raise NotImplementedError

[coverage:coverage_conditional_plugin]
rules =
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -56,7 +56,7 @@ def get_packages(package):
"httptools>=0.4.0",
"uvloop>=0.14.0,!=0.15.0,!=0.15.1; " + env_marker_cpython,
"colorama>=0.4;" + env_marker_win,
"watchgod>=0.6",
"watchfiles>=0.13",
"python-dotenv>=0.13",
"PyYAML>=5.1",
]
Expand Down
23 changes: 23 additions & 0 deletions tests/conftest.py
Expand Up @@ -4,6 +4,8 @@
from hashlib import md5
from pathlib import Path
from tempfile import TemporaryDirectory
from threading import Thread
from time import sleep
from uuid import uuid4

import pytest
Expand Down Expand Up @@ -176,3 +178,24 @@ def make_tmp_dir(base_dir):
sock_path = str(tmpd / "".join((identifier, socket_filename)))
yield sock_path
return


def sleep_touch(*paths: Path):
sleep(0.1)
for p in paths:
p.touch()


@pytest.fixture
def touch_soon():
threads = []

def start(*paths: Path):
thread = Thread(target=sleep_touch, args=paths)
thread.start()
threads.append(thread)

yield start

for t in threads:
t.join()