fix: watch files that do not exist yet - #408
Conversation
FileWatcher dispatched file-vs-directory mode with os.path.isfile(), so a path that doesn't exist yet fell into directory mode: watchdog was asked to schedule an observer on the nonexistent path (which fails) and the handler ran unfiltered. Callers watching a config file that is created later (eg. ovos-config watching mycroft.conf before it exists) never got the 'created' event. Dispatch on os.path.isdir() instead: an existing directory keeps directory mode unchanged; anything else (an existing file, or a path that doesn't exist yet) is file mode, watching the parent directory and filtering to that single path - safe because of the per-file filtering added in #406. If the parent directory also doesn't exist, watchdog can't schedule an observer on it either; skip that entry with a LOG.warning instead of letting an opaque watchdog exception propagate.
|
Warning Review limit reached
Next review available in: 12 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Processing sequence 0x4F564F53 complete! 🦾I've aggregated the results of the automated checks for this PR below. 📋 Repo HealthA detailed health report for the project. 📝 ✅ All required files present. Latest Version: ✅ 🏷️ Release PreviewI've checked the release assets for completeness. 💾 Current:
✅ PR title follows conventional commit format. 🚀 Release Channel Compatibility Predicted next version:
⚖️ License CheckVerifying that everything is above board legally. ⚓ ✅ No license violations found. Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed. 🔍 LintI've finished the digital walk-through of your PR. 🚶♂️ ❌ ruff: issues found — see job log 🔒 Security (pip-audit)I've audited the packages. Safety first! 🦺 ✅ No known vulnerabilities found (47 packages scanned). 📊 CoverageMapping out the 'known' vs 'unknown' in your code. 🗺️ ✅ 85.2% total coverage Files below 80% coverage (5 files)
Full report: download the 🔨 Build TestsThe build pipeline has finished its work. 🏁 ✅ All versions pass
The silent guardian of the dev branch. 🦇 |
Summary
FileWatcher.__init__chose file-mode vs directory-mode withos.path.isfile(file_path). A path that does not exist yet is not a file, so it fell through to directory mode:watch_dirbecame the nonexistent path (whichwatchdogcannot schedule an observer on) and the handler ran unfiltered instead of being scoped to that single path.Practical effect:
FileWatcher(["/some/dir/config.json"], cb)could not detect the file being created later, even with the defaultignore_creation=Falsewhose whole point is to reportcreatedevents. Callers were forced to either pre-create the file or watch the entire containing directory.This is exactly what
ovos-configPR #194 hit: it switched to watching specific config files, and a test that registers the watcher before writingmycroft.confstopped firing, because the not-yet-existing file was silently dropped into directory mode.Fix
Dispatch on
os.path.isdir()instead ofos.path.isfile():If the parent directory also doesn't exist,
watchdogcan't schedule an observer on it either. Rather than let an opaquewatchdogtraceback propagate, that entry is skipped withLOG.warning.Consumers re-checked
ovos-workshopskill_launcher.py:FileWatcher([self.skill_directory], ...)— existing directory, still lands in directory mode. Unaffected.ovos-microphone-plugin-files:FileWatcher([self.files_folder], ...)— same, unaffected.This unblocks downstream consumers (e.g.
ovos-config) that need to watch specific config files which may not exist yet at startup.Test plan
createdevent for it fires the callback, while a different file created in the same directory does notLOG.warning, no exception raisedtest_log_parser.py::TestOvosLogsCLINoStrayFiles