diff --git a/.gitignore b/.gitignore index fcda9da1..f15bd912 100644 --- a/.gitignore +++ b/.gitignore @@ -17,5 +17,3 @@ docs/_build/ /watchfiles/*.so /target/ /site/ -# i have a pet hate of the proliferation of files in the root directory -.rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..75306517 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 diff --git a/Makefile b/Makefile index ef5c3a16..6136e478 100644 --- a/Makefile +++ b/Makefile @@ -1,41 +1,40 @@ .DEFAULT_GOAL := all -isort = isort watchfiles tests -black = black watchfiles tests -ruff = ruff watchfiles tests .PHONY: install install: - pip install -U pip pre-commit + pip install -U pip pre-commit maturin pip install -r requirements/all.txt pip install -e . pre-commit install +.PHONY: update-lockfiles +update-lockfiles: + @echo "Updating requirements files using pip-compile" + pip-compile -q --strip-extras -o requirements/linting.txt requirements/linting.in + pip-compile -q --strip-extras -c requirements/linting.txt -o requirements/pyproject.txt pyproject.toml + pip-compile -q --strip-extras -c requirements/linting.txt -c requirements/pyproject.txt -o requirements/testing.txt requirements/testing.in + pip-compile -q --strip-extras -c requirements/linting.txt -c requirements/pyproject.txt -c requirements/testing.txt -o requirements/docs.txt requirements/docs.in + pip install --dry-run -r requirements/all.txt + .PHONY: build-dev build-dev: - pip uninstall -y watchfiles - @rm -f watchfiles/*.so - cargo build - @rm -f target/debug/lib_rust_notify.d - @mv target/debug/lib_rust_notify.* watchfiles/_rust_notify.so + maturin develop .PHONY: format format: - $(ruff) --fix-only - $(isort) - $(black) + ruff check --fix-only watchfiles tests + ruff format watchfiles tests @echo 'max_width = 120' > .rustfmt.toml cargo fmt .PHONY: lint-python lint-python: - $(ruff) - $(isort) --check-only --df - $(black) --check --diff + ruff check watchfiles tests + ruff format --check watchfiles tests .PHONY: lint-rust lint-rust: cargo fmt --version - @echo 'max_width = 120' > .rustfmt.toml cargo fmt --all -- --check cargo clippy --version cargo clippy -- -D warnings diff --git a/pyproject.toml b/pyproject.toml index aadd56b7..96775fa1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,24 +76,14 @@ exclude_lines = [ ] omit = ['*/__main__.py'] -[tool.black] -color = true -line-length = 120 -target-version = ['py39'] -skip-string-normalization = true - -[tool.isort] -line_length = 120 -multi_line_output = 3 -include_trailing_comma = true -force_grid_wrap = 0 -combine_as_imports = true -color_output = true - [tool.ruff] line-length = 120 -extend-select = ['Q'] -flake8-quotes = {inline-quotes = 'single', multiline-quotes = 'double'} +target-version = 'py38' +lint.mccabe = { max-complexity = 14 } +lint.extend-select = ['Q', 'RUF100', 'C90', 'UP', 'I'] +lint.flake8-quotes = {inline-quotes = 'single', multiline-quotes = 'double'} +lint.pydocstyle = { convention = 'google' } +format.quote-style = 'single' [tool.mypy] strict = true diff --git a/requirements/docs.txt b/requirements/docs.txt index d2257666..38dc5235 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,11 +1,11 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # -# pip-compile --output-file=requirements/docs.txt requirements/docs.in +# pip-compile --constraint=requirements/linting.txt --constraint=requirements/pyproject.txt --constraint=requirements/testing.txt --output-file=requirements/docs.txt requirements/docs.in # black==22.8.0 - # via -r docs.in + # via -r requirements/docs.in click==8.1.3 # via # black @@ -36,12 +36,12 @@ markupsafe==2.1.1 # jinja2 # mkdocstrings mdx-include==1.4.2 - # via -r docs.in + # via -r requirements/docs.in mergedeep==1.3.4 # via mkdocs mkdocs==1.3.1 # via - # -r docs.in + # -r requirements/docs.in # mkdocs-autorefs # mkdocs-material # mkdocs-simple-hooks @@ -49,33 +49,41 @@ mkdocs==1.3.1 mkdocs-autorefs==0.4.1 # via mkdocstrings mkdocs-material==8.4.3 - # via -r docs.in + # via -r requirements/docs.in mkdocs-material-extensions==1.0.3 # via mkdocs-material mkdocs-simple-hooks==0.1.5 - # via -r docs.in + # via -r requirements/docs.in mkdocstrings[python]==0.19.0 # via - # -r docs.in + # -r requirements/docs.in # mkdocstrings-python mkdocstrings-python==0.7.1 # via mkdocstrings mypy-extensions==0.4.3 - # via black + # via + # -c requirements/linting.txt + # black packaging==21.3 - # via mkdocs + # via + # -c requirements/testing.txt + # mkdocs pathspec==0.10.1 # via black platformdirs==2.5.2 # via black pygments==2.15.0 - # via mkdocs-material + # via + # -c requirements/testing.txt + # mkdocs-material pymdown-extensions==10.0 # via # mkdocs-material # mkdocstrings pyparsing==3.0.9 - # via packaging + # via + # -c requirements/testing.txt + # packaging python-dateutil==2.8.2 # via ghp-import pyyaml==6.0 @@ -89,6 +97,11 @@ rcslice==1.1.0 # via mdx-include six==1.16.0 # via python-dateutil +tomli==2.0.1 + # via + # -c requirements/linting.txt + # -c requirements/testing.txt + # black watchdog==2.1.9 # via mkdocs zipp==3.8.1 diff --git a/requirements/linting.in b/requirements/linting.in index 6193197e..4e29f927 100644 --- a/requirements/linting.in +++ b/requirements/linting.in @@ -1,5 +1,3 @@ -black -isort[colors] mypy ruff trio diff --git a/requirements/linting.txt b/requirements/linting.txt index c12e0ea2..84d02097 100644 --- a/requirements/linting.txt +++ b/requirements/linting.txt @@ -1,45 +1,31 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # # pip-compile --output-file=requirements/linting.txt requirements/linting.in # async-generator==1.10 # via trio attrs==22.1.0 - # via trio -black==22.8.0 - # via -r requirements/linting.in -click==8.1.3 - # via black -colorama==0.4.5 - # via isort + # via + # outcome + # trio idna==3.3 # via trio -isort[colors]==5.10.1 - # via -r requirements/linting.in mypy==0.971 # via -r requirements/linting.in mypy-extensions==0.4.3 - # via - # black - # mypy + # via mypy outcome==1.2.0 # via trio -pathspec==0.10.1 - # via black -platformdirs==2.5.2 - # via black -ruff==0.0.285 +ruff==0.4.3 # via -r requirements/linting.in sniffio==1.3.0 # via trio sortedcontainers==2.4.0 # via trio tomli==2.0.1 - # via - # black - # mypy + # via mypy trio==0.21.0 # via -r requirements/linting.in typing-extensions==4.3.0 diff --git a/requirements/pyproject.txt b/requirements/pyproject.txt index ee24a16b..672bfc4e 100644 --- a/requirements/pyproject.txt +++ b/requirements/pyproject.txt @@ -1,12 +1,16 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # -# pip-compile --output-file=requirements/pyproject.txt pyproject.toml +# pip-compile --constraint=requirements/linting.txt --output-file=requirements/pyproject.txt pyproject.toml # anyio==3.6.1 # via watchfiles (pyproject.toml) idna==3.3 - # via anyio + # via + # -c requirements/linting.txt + # anyio sniffio==1.3.0 - # via anyio + # via + # -c requirements/linting.txt + # anyio diff --git a/requirements/testing.txt b/requirements/testing.txt index efa7bdcf..584400c0 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -2,14 +2,16 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --output-file=requirements/testing.txt requirements/testing.in +# pip-compile --constraint=requirements/linting.txt --constraint=requirements/pyproject.txt --output-file=requirements/testing.txt requirements/testing.in # commonmark==0.9.1 # via rich coverage==6.4.4 - # via -r testing.in + # via -r requirements/testing.in dirty-equals==0.5.0 - # via -r testing.in + # via -r requirements/testing.in +exceptiongroup==1.2.1 + # via pytest iniconfig==1.1.1 # via pytest packaging==21.3 @@ -22,21 +24,25 @@ pyparsing==3.0.9 # via packaging pytest==7.4.2 # via - # -r testing.in + # -r requirements/testing.in # pytest-mock # pytest-pretty # pytest-timeout pytest-mock==3.8.2 - # via -r testing.in + # via -r requirements/testing.in pytest-pretty==0.0.1 - # via -r testing.in + # via -r requirements/testing.in pytest-timeout==2.1.0 - # via -r testing.in + # via -r requirements/testing.in pytz==2022.2.1 # via dirty-equals rich==12.6.0 # via pytest-pretty tomli==2.0.1 - # via pytest + # via + # -c requirements/linting.txt + # pytest typing-extensions==4.3.0 - # via dirty-equals + # via + # -c requirements/linting.txt + # dirty-equals diff --git a/tests/conftest.py b/tests/conftest.py index fdbcc973..ed9fed0b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -93,8 +93,9 @@ def close(self): from typing import Literal, Protocol class MockRustType(Protocol): - def __call__(self, changes: ChangesType, *, exit_code: Literal['signal', 'stop', 'timeout'] = 'stop') -> Any: - ... + def __call__( + self, changes: ChangesType, *, exit_code: Literal['signal', 'stop', 'timeout'] = 'stop' + ) -> Any: ... @pytest.fixture diff --git a/tests/test_watch.py b/tests/test_watch.py index 5dd064c0..163a3605 100644 --- a/tests/test_watch.py +++ b/tests/test_watch.py @@ -140,7 +140,7 @@ def test_watch_timeout(mock_rust_notify: 'MockRustType', caplog): assert change_list == [{(Change.added, 'spam.py')}] assert mock.watch_count == 2 assert caplog.text == ( - "watchfiles.main DEBUG: rust notify timeout, continuing\n" # noqa: Q000 + 'watchfiles.main DEBUG: rust notify timeout, continuing\n' "watchfiles.main DEBUG: 1 change detected: {(, 'spam.py')}\n" ) @@ -167,7 +167,7 @@ async def test_awatch_timeout(mock_rust_notify: 'MockRustType', caplog): assert change_list == [{(Change.added, 'spam.py')}] assert mock.watch_count == 2 assert caplog.text == ( - "watchfiles.main DEBUG: rust notify timeout, continuing\n" # noqa: Q000 + 'watchfiles.main DEBUG: rust notify timeout, continuing\n' "watchfiles.main DEBUG: 1 change detected: {(, 'spam.py')}\n" ) diff --git a/watchfiles/_rust_notify.pyi b/watchfiles/_rust_notify.pyi index 63eacda6..e08cfff8 100644 --- a/watchfiles/_rust_notify.pyi +++ b/watchfiles/_rust_notify.pyi @@ -1,4 +1,4 @@ -from typing import Any, List, Literal, Optional, Protocol, Set, Tuple, Union +from typing import Any, Literal, Protocol __all__ = 'RustNotify', 'WatchfilesRustInternalError' @@ -16,7 +16,7 @@ class RustNotify: def __init__( self, - watch_paths: List[str], + watch_paths: list[str], debug: bool, force_polling: bool, poll_delay_ms: int, @@ -42,8 +42,8 @@ class RustNotify: debounce_ms: int, step_ms: int, timeout_ms: int, - stop_event: Optional[AbstractEvent], - ) -> Union[Set[Tuple[int, str]], Literal['signal', 'stop', 'timeout']]: + stop_event: AbstractEvent | None, + ) -> set[tuple[int, str]] | Literal['signal', 'stop', 'timeout']: """ Watch for changes. @@ -74,7 +74,7 @@ class RustNotify: * `'stop'` string, if the `stop_event` was set * `'timeout'` string, if `timeout_ms` was exceeded """ - def __enter__(self) -> 'RustNotify': + def __enter__(self) -> RustNotify: """ Does nothing, but allows `RustNotify` to be used as a context manager. diff --git a/watchfiles/main.py b/watchfiles/main.py index 1df7e547..48625b56 100644 --- a/watchfiles/main.py +++ b/watchfiles/main.py @@ -46,8 +46,7 @@ def raw_str(self) -> str: AnyEvent = Union[anyio.Event, asyncio.Event, trio.Event] class AbstractEvent(Protocol): - def is_set(self) -> bool: - ... + def is_set(self) -> bool: ... def watch( @@ -142,7 +141,7 @@ def watch( logger.debug('all changes filtered out, raw_changes=%s', raw_changes) -async def awatch( # noqa C901 +async def awatch( # C901 *paths: Union[Path, str], watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), debounce: int = 1_600,