Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement inotify file close events #690

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Changelog

- Add logger parameter for the LoggingEventHandler (`#676 <https://github.com/gorakhargosh/watchdog/pull/676>`_)
- Replace mutable default arguments with ``if None`` implementation (`#677 <https://github.com/gorakhargosh/watchdog/pull/677>`_)
- Thanks to our beloved contributors: @Sraw
- [inotify] Add events for IN_WRITE_CLOSE and IN_NOWRITE_CLOSE (`#690 <https://github.com/gorakhargosh/watchdog/pull/690>`)
- Thanks to our beloved contributors: @Sraw, @lukassup


0.10.3
Expand Down
18 changes: 18 additions & 0 deletions src/watchdog/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
:members:
:show-inheritance:

.. autoclass:: FileClosedEvent
:members:
:show-inheritance:

.. autoclass:: DirCreatedEvent
:members:
:show-inheritance:
Expand Down Expand Up @@ -97,6 +101,7 @@
EVENT_TYPE_DELETED = 'deleted'
EVENT_TYPE_CREATED = 'created'
EVENT_TYPE_MODIFIED = 'modified'
EVENT_TYPE_CLOSED = 'closed'


class FileSystemEvent(object):
Expand Down Expand Up @@ -248,6 +253,19 @@ def __repr__(self):
dest_path=self.dest_path))


class FileClosedEvent(FileSystemEvent):
"""File system event representing file close on the file system."""

event_type = EVENT_TYPE_CLOSED

def __init__(self, src_path):
super(FileClosedEvent, self).__init__(src_path)

def __repr__(self):
return ("<%(class_name)s: src_path=%(src_path)r>"
) % (dict(class_name=self.__class__.__name__,
src_path=self.src_path))

# Directory events.


Expand Down
8 changes: 8 additions & 0 deletions src/watchdog/observers/inotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
FileModifiedEvent,
FileMovedEvent,
FileCreatedEvent,
FileClosedEvent,
generate_sub_moved_events,
generate_sub_created_events,
)
Expand Down Expand Up @@ -174,6 +175,13 @@ def queue_events(self, timeout, full_events=False):
cls = DirCreatedEvent if event.is_directory else FileCreatedEvent
self.queue_event(cls(src_path))
self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
elif event.is_close_write and not event.is_directory:
cls = FileClosedEvent
self.queue_event(cls(src_path))
self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
elif event.is_close_nowrite and not event.is_directory:
cls = FileClosedEvent
self.queue_event(cls(src_path))

def _decode_path(self, path):
""" Decode path only if unicode string was passed to this emitter. """
Expand Down
13 changes: 13 additions & 0 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
FileDeletedEvent,
FileModifiedEvent,
FileCreatedEvent,
FileClosedEvent,
DirDeletedEvent,
DirModifiedEvent,
DirCreatedEvent,
Expand All @@ -30,6 +31,7 @@
EVENT_TYPE_CREATED,
EVENT_TYPE_DELETED,
EVENT_TYPE_MOVED,
EVENT_TYPE_CLOSED,
)

path_1 = '/path/xyz'
Expand Down Expand Up @@ -82,6 +84,12 @@ def test_file_moved_event():
assert not event.is_directory
assert not event.is_synthetic

def test_file_closed_event():
event = FileClosedEvent(path_1)
assert path_1 == event.src_path
assert EVENT_TYPE_CLOSED == event.event_type
assert not event.is_directory
assert not event.is_synthetic

def test_dir_deleted_event():
event = DirDeletedEvent(path_1)
Expand Down Expand Up @@ -112,6 +120,7 @@ def test_file_system_event_handler_dispatch():
file_del_event = FileDeletedEvent('/path/blah.txt')
dir_cre_event = DirCreatedEvent('/path/blah.py')
file_cre_event = FileCreatedEvent('/path/blah.txt')
file_cls_event = FileClosedEvent('/path/blah.txt')
dir_mod_event = DirModifiedEvent('/path/blah.py')
file_mod_event = FileModifiedEvent('/path/blah.txt')
dir_mov_event = DirMovedEvent('/path/blah.py', '/path/blah')
Expand All @@ -126,6 +135,7 @@ def test_file_system_event_handler_dispatch():
file_del_event,
file_cre_event,
file_mov_event,
file_cls_event,
]

class TestableEventHandler(FileSystemEventHandler):
Expand All @@ -145,6 +155,9 @@ def on_moved(self, event):
def on_created(self, event):
assert event.event_type == EVENT_TYPE_CREATED

def on_closed(self, event):
assert event.event_type == EVENT_TYPE_CLOSED

handler = TestableEventHandler()

for event in all_events:
Expand Down