watchmedo: default "*" and documented "*.py"-style patterns match nothing since the full_match change (#1101)
Environment
- watchdog master
dda279c(7.0.0-dev), native Windows 11 Home 10.0.26200, Python 3.13.13 - Not present in any release:
git tag --contains 3d98d59is empty; v6.0.0 (2024-11-01) predates it
Symptom
watchmedo auto-restart never restarts its command, and by the same mechanism watchmedo shell-command / log never fire, when watching an absolute directory — including with the default --patterns "*" and with the --patterns="*.py;*.txt" style the help text documents.
Live check on this machine: watchmedo auto-restart -d <absolute-dir> --patterns "*.txt" --debounce-interval 1 -- python -u child.py starts the child once; creating trigger.txt in the watched directory produces no restart (child output still shows a single CHILD STARTED after the event, and the same run with the pre-#1101 matcher semantics restarts).
Mechanism
#1101 deliberately switched _match_path from PurePath.match() (right-anchored) to full_match() (whole-path), and the 7.0.0-dev changelog documents the library-level consequence: users must write **/*.py instead of *.py. But watchmedo was not adapted to the new semantics — parse_patterns() still hands the user's (or default) patterns straight to the tricks, and event paths are multi-segment, so:
from watchdog.utils.patterns import match_any_paths as m
m([r"C:\w\a.txt"], included_patterns=["*"], case_sensitive=False) # False (watchmedo default)
m([r"C:\w\a.txt"], included_patterns=["*.txt"], case_sensitive=False) # False (documented style)
m([r"C:\w\a.txt"], included_patterns=["**"], case_sensitive=False) # True
m([r".\a.txt"], included_patterns=["*"], case_sensitive=False) # True (depth-1 relative still works)
m([r".\sub\a.txt"],included_patterns=["*"], case_sensitive=False) # FalseOn the commit before #1101, all five rows are True — path.match("*") matched any tail. So the breakage is total for absolute watch paths and partial (depth-1 only) for relative ones, which is presumably why casual testing looks fine.
Why the test suite stays green
The auto-restart tests construct AutoRestartTrick([sys.executable, script]) with no patterns argument, so the handler falls back to the library default ["**"], which full-matches everything. watchmedo itself never produces that default — it always passes parse_patterns() output, whose default is "*". The gap sits exactly between the two defaults, so no existing test crosses it.
What I am not claiming
The engine change itself is intentional and changelog-documented; this issue is only about watchmedo (and its defaults/help text) not having been adapted to it. I also haven't tested the tricks-from-YAML path beyond reading that it feeds the same handler base.
Possible directions
- Translate bare relative patterns in
parse_patterns()(prepend**/when a pattern has no separator and no leading**), keeping the CLI's long-documented behavior across the engine change; or - change
watchmedo's default from"*"to"**"and document that CLI patterns now need**/prefixes, matching the library-level changelog entry.
Happy to put together a PR with tests for whichever direction you prefer — (1) keeps existing watchmedo invocations working and is my reading of least surprise, but it does add a translation layer you may not want.
Source: gorakhargosh/watchdog