diff --git a/changelog.rst b/changelog.rst index 21b8e57b..776d8bf9 100644 --- a/changelog.rst +++ b/changelog.rst @@ -9,7 +9,8 @@ Changelog 2021-xx-x • `full history `__ - [watchmedo] Fix usage of ``os.setsid()`` and ``os.killpg()`` Unix-only functions. (`#809 `_) -- Thanks to our beloved contributors: @replabrobin, @BoboTiG +- [mac] Fix missing ``FileModifiedEvent`` on permission or ownership changes of a file. (`#809 `_) +- Thanks to our beloved contributors: @replabrobin, @BoboTiG, @SamSchott 2.1.3 ~~~~~ diff --git a/src/watchdog/observers/fsevents.py b/src/watchdog/observers/fsevents.py index 151f6229..21ba95c2 100644 --- a/src/watchdog/observers/fsevents.py +++ b/src/watchdog/observers/fsevents.py @@ -156,6 +156,11 @@ def _is_historic_created_event(self, event): return in_history or before_start + @staticmethod + def _is_meta_mod(event): + """Returns True if the event indicates a change in metadata.""" + return event.is_inode_meta_mod or event.is_xattr_mod or event.is_owner_change + def queue_events(self, timeout, events): if logger.getEffectiveLevel() <= logging.DEBUG: @@ -209,7 +214,7 @@ def queue_events(self, timeout, events): self._fs_view.add(event.inode) - if event.is_modified or event.is_inode_meta_mod or event.is_xattr_mod: + if event.is_modified or self._is_meta_mod(event): self._queue_modified_event(event, src_path, src_dirname) self._queue_deleted_event(event, src_path, src_dirname) @@ -222,7 +227,7 @@ def queue_events(self, timeout, events): self._fs_view.add(event.inode) - if event.is_modified or event.is_inode_meta_mod or event.is_xattr_mod: + if event.is_modified or self._is_meta_mod(event): self._queue_modified_event(event, src_path, src_dirname) if event.is_renamed: @@ -247,7 +252,7 @@ def queue_events(self, timeout, events): events.remove(dst_event) - if dst_event.is_modified or dst_event.is_inode_meta_mod or dst_event.is_xattr_mod: + if dst_event.is_modified or self._is_meta_mod(dst_event): self._queue_modified_event(dst_event, dst_path, dst_dirname) if dst_event.is_removed: diff --git a/tests/test_emitter.py b/tests/test_emitter.py index 708a0378..d7e19b36 100644 --- a/tests/test_emitter.py +++ b/tests/test_emitter.py @@ -15,6 +15,7 @@ # limitations under the License. import os +import stat import time import pytest import logging @@ -195,6 +196,21 @@ def test_modify(): assert isinstance(event, FileClosedEvent) +@pytest.mark.flaky(max_runs=5, min_passes=1, rerun_filter=rerun_filter) +def test_chmod(): + mkfile(p('a')) + start_watching() + + # Note: We use S_IREAD here because chmod on Windows only + # allows setting the read-only flag. + os.chmod(p('a'), stat.S_IREAD) + + expect_event(FileModifiedEvent(p('a'))) + + # Reset permissions to allow cleanup. + os.chmod(p('a'), stat.S_IWRITE) + + @pytest.mark.flaky(max_runs=5, min_passes=1, rerun_filter=rerun_filter) def test_move(): mkdir(p('dir1'))