Skip to content

Commit

Permalink
Identify synthesized events
Browse files Browse the repository at this point in the history
Original patch by @skurfer in gorakhargosh#369.
  • Loading branch information
Rob McBroom authored and BoboTiG committed Feb 17, 2019
1 parent bb06797 commit b1cb0d0
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
1 change: 1 addition & 0 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ API changes
- ``WindowsApiEmitter`` made easier to subclass.
- Use separate ctypes DLL instances on Windows.
- Added ``--debug-force-polling`` arguments to watchmedo.
- Identify synthesized events with ``is_synthetic`` attribute.
- Refactored tests to use pytest.
- General code clean-up.

Expand Down
24 changes: 20 additions & 4 deletions src/watchdog/events.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ class FileSystemEvent(object):
is_directory = False
"""True if event was emitted for a directory; False otherwise."""

is_synthetic = False
"""
True if event was synthesized; False otherwise.
These are events that weren't actually broadcast by the OS, but
are presumed to have happened based on other, actual events.
"""

def __init__(self, src_path):
self._src_path = src_path

Expand Down Expand Up @@ -590,11 +598,15 @@ def generate_sub_moved_events(src_dir_path, dest_dir_path):
for directory in directories:
full_path = os.path.join(root, directory)
renamed_path = full_path.replace(dest_dir_path, src_dir_path) if src_dir_path else None
yield DirMovedEvent(renamed_path, full_path)
event = DirMovedEvent(renamed_path, full_path)
event.is_synthetic = True
yield event
for filename in filenames:
full_path = os.path.join(root, filename)
renamed_path = full_path.replace(dest_dir_path, src_dir_path) if src_dir_path else None
yield FileMovedEvent(renamed_path, full_path)
event = FileMovedEvent(renamed_path, full_path)
event.is_synthetic = True
yield event


def generate_sub_created_events(src_dir_path):
Expand All @@ -610,6 +622,10 @@ def generate_sub_created_events(src_dir_path):
"""
for root, directories, filenames in os.walk(src_dir_path):
for directory in directories:
yield DirCreatedEvent(os.path.join(root, directory))
event = DirCreatedEvent(os.path.join(root, directory))
event.is_synthetic = True
yield event
for filename in filenames:
yield FileCreatedEvent(os.path.join(root, filename))
event = FileCreatedEvent(os.path.join(root, filename))
event.is_synthetic = True
yield event
6 changes: 3 additions & 3 deletions src/watchdog/observers/inotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ def on_thread_stop(self):
self._inotify.close()

def queue_events(self, timeout, full_events=False):
#If "full_events" is true, then the method will report unmatched move events as seperate events
#This behavior is by default only called by a InotifyFullEmitter
# If "full_events" is true, then the method will report unmatched move events as seperate events
# This behavior is by default only called by a InotifyFullEmitter
with self._lock:
event = self._inotify.read_event()
if event is None:
Expand All @@ -146,7 +146,7 @@ def queue_events(self, timeout, full_events=False):

src_path = self._decode_path(event.src_path)
if event.is_moved_to:
if (full_events):
if full_events:
cls = DirMovedEvent if event.is_directory else FileMovedEvent
self.queue_event(cls(None, src_path))
else:
Expand Down
18 changes: 14 additions & 4 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,37 @@ def test_file_deleted_event():
assert path_1 == event.src_path
assert EVENT_TYPE_DELETED == event.event_type
assert not event.is_directory
assert not event.is_synthetic


def test_file_delete_event_is_directory():
# Inherited properties.
event1 = FileDeletedEvent(path_1)
assert not event1.is_directory
event = FileDeletedEvent(path_1)
assert not event.is_directory
assert not event.is_synthetic


def test_file_modified_event():
event = FileModifiedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_MODIFIED == event.event_type
assert not event.is_directory
assert not event.is_synthetic


def test_file_modified_event_is_directory():
# Inherited Properties
event1 = FileModifiedEvent(path_1)
assert not event1.is_directory
event = FileModifiedEvent(path_1)
assert not event.is_directory
assert not event.is_synthetic


def test_file_created_event():
event = FileCreatedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_CREATED == event.event_type
assert not event.is_directory
assert not event.is_synthetic


def test_file_moved_event():
Expand All @@ -75,27 +80,31 @@ def test_file_moved_event():
assert path_2 == event.dest_path
assert EVENT_TYPE_MOVED == event.event_type
assert not event.is_directory
assert not event.is_synthetic


def test_dir_deleted_event():
event = DirDeletedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_DELETED == event.event_type
assert event.is_directory
assert not event.is_synthetic


def test_dir_modified_event():
event = DirModifiedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_MODIFIED == event.event_type
assert event.is_directory
assert not event.is_synthetic


def test_dir_created_event():
event = DirCreatedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_CREATED == event.event_type
assert event.is_directory
assert not event.is_synthetic


def test_file_system_event_handler_dispatch():
Expand Down Expand Up @@ -139,4 +148,5 @@ def on_created(self, event):
handler = TestableEventHandler()

for event in all_events:
assert not event.is_synthetic
handler.dispatch(event)

0 comments on commit b1cb0d0

Please sign in to comment.