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

Fix a TypeError when deleting the watched folder on Windows #601

Merged
merged 1 commit into from
Dec 11, 2019
Merged
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
2 changes: 1 addition & 1 deletion src/watchdog/observers/winapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def _is_observed_path_deleted(handle, path):
def _generate_observed_path_deleted_event():
# Create synthetic event for notify that observed directory is deleted
path = ctypes.create_unicode_buffer('.')
event = FILE_NOTIFY_INFORMATION(0, FILE_ACTION_DELETED_SELF, len(path), path.value)
event = FILE_NOTIFY_INFORMATION(0, FILE_ACTION_DELETED_SELF, len(path), path.value.encode("utf-8"))
event_size = ctypes.sizeof(event)
buff = ctypes.create_string_buffer(BUFFER_SIZE)
ctypes.memmove(buff, ctypes.addressof(event), event_size)
Expand Down
55 changes: 51 additions & 4 deletions tests/test_observers_winapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
if not platform.is_windows(): # noqa
pytest.skip("Windows only.", allow_module_level=True)

import os
import os.path
from time import sleep

Expand All @@ -36,11 +37,16 @@
from .shell import (
mkdir,
mkdtemp,
mv
mv,
rm
)


temp_dir = mkdtemp()
SLEEP_TIME = 2

# Path with non-ASCII
temp_dir = os.path.join(mkdtemp(), u"Strange \N{SNOWMAN}")
os.makedirs(temp_dir)


def p(*args):
Expand All @@ -65,8 +71,6 @@ def emitter(event_queue):


def test___init__(event_queue, emitter):
SLEEP_TIME = 2

emitter.start()
sleep(SLEEP_TIME)
mkdir(p('fromdir'))
Expand Down Expand Up @@ -98,3 +102,46 @@ def test___init__(event_queue, emitter):
got.add(event)

assert expected == got


def test_root_deleted(event_queue, emitter):
r"""Test the event got when removing the watched folder.
The regression to prevent is:

Exception in thread Thread-1:
Traceback (most recent call last):
File "watchdog\observers\winapi.py", line 333, in read_directory_changes
ctypes.byref(nbytes), None, None)
File "watchdog\observers\winapi.py", line 105, in _errcheck_bool
raise ctypes.WinError()
PermissionError: [WinError 5] Access refused.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Python37-32\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "watchdog\observers\api.py", line 145, in run
self.queue_events(self.timeout)
File "watchdog\observers\read_directory_changes.py", line 76, in queue_events
winapi_events = self._read_events()
File "watchdog\observers\read_directory_changes.py", line 73, in _read_events
return read_events(self._handle, self.watch.path, self.watch.is_recursive)
File "watchdog\observers\winapi.py", line 387, in read_events
buf, nbytes = read_directory_changes(handle, path, recursive)
File "watchdog\observers\winapi.py", line 340, in read_directory_changes
return _generate_observed_path_deleted_event()
File "watchdog\observers\winapi.py", line 298, in _generate_observed_path_deleted_event
event = FILE_NOTIFY_INFORMATION(0, FILE_ACTION_DELETED_SELF, len(path), path.value)
TypeError: expected bytes, str found
"""

emitter.start()
sleep(SLEEP_TIME)

# This should not fail
rm(p(), recursive=True)
sleep(SLEEP_TIME)

# The emitter is automatically stopped, with no error
assert not emitter.should_keep_running()