Navigation Menu

Skip to content

Commit

Permalink
Remove emitters which failed to start
Browse files Browse the repository at this point in the history
  • Loading branch information
BoboTiG committed Mar 20, 2019
1 parent 6ba82ac commit 8b94506
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 12 deletions.
1 change: 1 addition & 0 deletions changelog.rst
Expand Up @@ -18,6 +18,7 @@ API changes
- Fixed a race condition crash when a directory is swapped for a file.
- Fixed the way we re-raise ``OSError``.
- Fixed the path separator used in watchmedo.
- Remove emitters which failed to start.
- We now generate sub created events only if ``recursive=True``.
- Security fix in watchmedo: use ``yaml.safe_load()`` instead of ``yaml.load()``
- Use ``scandir`` to save memory.
Expand Down
8 changes: 6 additions & 2 deletions src/watchdog/observers/api.py
Expand Up @@ -248,8 +248,12 @@ def emitters(self):
return self._emitters

def start(self):
for emitter in self._emitters:
emitter.start()
for emitter in self._emitters.copy():
try:
emitter.start()
except Exception:
self._remove_emitter(emitter)
raise
super(BaseObserver, self).start()

def schedule(self, event_handler, path, recursive=False):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_emitter.py
Expand Up @@ -41,7 +41,7 @@
InotifyFullEmitter,
)
elif platform.is_darwin():
pytestmark = pytest.mark.skip("FIXME: It is a matter of bad comparisons between bytes and str.")
pytestmark = pytest.mark.skip("FIXME: issue #546.")
from watchdog.observers.fsevents2 import FSEventsEmitter as Emitter
elif platform.is_windows():
from watchdog.observers.read_directory_changes import (
Expand Down
27 changes: 27 additions & 0 deletions tests/test_observer.py
Expand Up @@ -115,3 +115,30 @@ def test_2_observers_on_the_same_path(observer, observer2):

observer2.schedule(None, '')
assert len(observer2.emitters) == 1


def test_start_failure_should_not_prevent_further_try(monkeypatch, observer):
observer.schedule(None, '')
emitters = observer.emitters
assert len(emitters) == 1

# Make the emitter to fail on start()

def mocked_start():
raise OSError()

emitter = next(iter(emitters))
monkeypatch.setattr(emitter, "start", mocked_start)
with pytest.raises(OSError):
observer.start()
# The emitter should be removed from the list
assert len(observer.emitters) == 0

# Restoring the original behavior should work like there never be emitters
monkeypatch.undo()
observer.start()
assert len(observer.emitters) == 0

# Re-schduling the watch should work
observer.schedule(None, '')
assert len(observer.emitters) == 1
7 changes: 4 additions & 3 deletions tests/test_observers_polling.py
Expand Up @@ -65,12 +65,14 @@ def event_queue():
@pytest.fixture
def emitter(event_queue):
watch = ObservedWatch(temp_dir, True)
yield Emitter(event_queue, watch, timeout=0.2)
em = Emitter(event_queue, watch, timeout=0.2)
em.start()
yield em
em.stop()


def test___init__(event_queue, emitter):
SLEEP_TIME = 0.4
emitter.start()

sleep(SLEEP_TIME)
mkdir(p('project'))
Expand Down Expand Up @@ -165,7 +167,6 @@ def test___init__(event_queue, emitter):
def test_delete_watched_dir(event_queue, emitter):
SLEEP_TIME = 0.4

emitter.start()
rm(p(''), recursive=True)

sleep(SLEEP_TIME)
Expand Down
12 changes: 6 additions & 6 deletions tests/test_observers_winapi.py
Expand Up @@ -59,14 +59,14 @@ def event_queue():
@pytest.fixture
def emitter(event_queue):
watch = ObservedWatch(temp_dir, True)
yield WindowsApiEmitter(event_queue, watch, timeout=0.2)
em = WindowsApiEmitter(event_queue, watch, timeout=0.2)
yield em
em.stop()


def test___init__():
def test___init__(event_queue, emitter):
SLEEP_TIME = 2

emitter.start()

sleep(SLEEP_TIME)
mkdir(p('fromdir'))

Expand All @@ -81,10 +81,10 @@ def test___init__():
# * unordered
# * non-unique
# A multiset! Python's collections.Counter class seems appropriate.
expected = {[
expected = {
DirCreatedEvent(p('fromdir')),
DirMovedEvent(p('fromdir'), p('todir')),
]}
}

got = set()

Expand Down

0 comments on commit 8b94506

Please sign in to comment.