Skip to content

Allow scheduling watches without an initial event handler (fixes #1039)#1169

Open
Prosperibe12 wants to merge 2 commits into
gorakhargosh:masterfrom
Prosperibe12:issue-1039-allow-adding-observedwatch-without-handlers
Open

Allow scheduling watches without an initial event handler (fixes #1039)#1169
Prosperibe12 wants to merge 2 commits into
gorakhargosh:masterfrom
Prosperibe12:issue-1039-allow-adding-observedwatch-without-handlers

Conversation

@Prosperibe12

Copy link
Copy Markdown
Contributor

🚀 Description

Implements handler-less watches: Observer.schedule(None, path, …) (or schedule(noop_event_handler, path, …)) registers the watch without an initial handler; handlers are added later with add_handler_for_watch. Fixes unschedule when no handlers exist.

💁 Why is this change needed?

Several call sites need one shared watch on a path while attaching handlers from different subroutines. Previously schedule always registered an initial handler, and passing None stored None in the handler set, which could break dispatch. This implements the approach discussed on the issue: optional None / no-op handler at schedule time, then add_handler_for_watch for real handlers.

📎 Issue (#1039)

Type of change

  • New feature (non-breaking change which adds functionality)

📋 New feature implementation

  • BaseObserver.schedule: skip _add_handler_for_watch when event_handler is None; @overload for FileSystemEventHandler vs None.
  • watchdog.events: NoOpEventHandler, noop_event_handler.
  • BaseObserver.unschedule: use _handlers.pop(watch, None).
  • FSEventsObserver.schedule: same overloads / FileSystemEventHandler | None as the base class.
from watchdog.events import FileSystemEventHandler, FileModifiedEvent
from watchdog.observers import Observer


class Handler0(FileSystemEventHandler):
    def on_modified(self, event: FileModifiedEvent) -> None:
        print("handler0", event.src_path)


class Handler1(FileSystemEventHandler):
    def on_modified(self, event: FileModifiedEvent) -> None:
        print("handler1", event.src_path)


def do_something0(observer, watch):
    observer.add_handler_for_watch(Handler0(), watch)


def do_something1(observer, watch):
    observer.add_handler_for_watch(Handler1(), watch)


observer = Observer()
watch = observer.schedule(None, "/path/to/dir", recursive=True)
# Typing-friendly alternative:
# from watchdog.events import noop_event_handler
# watch = observer.schedule(noop_event_handler, "/path/to/dir", recursive=True)

do_something0(observer, watch)
do_something1(observer, watch)
observer.start()

…khargosh#1039)

Prior to this commit, Observer.schedule always registered the given
event_handler; passing None stored None in the handler set, which could
raise if events were dispatched, and there was no supported way to attach
only add_handler_for_watch after creating the watch.

This commit treats None as no initial handler (skip registration), adds
NoOpEventHandler and noop_event_handler for typing-friendly call sites,
mirrors overloads on FSEventsObserver.schedule, fixes unschedule when no handlers are registered
@Prosperibe12 Prosperibe12 force-pushed the issue-1039-allow-adding-observedwatch-without-handlers branch from 6b29489 to ba58e8d Compare April 19, 2026 14:20
@Prosperibe12

Copy link
Copy Markdown
Contributor Author

@BoboTiG I will appreaciate a review on this pr

@Prosperibe12

Copy link
Copy Markdown
Contributor Author

@BoboTiG commenting again, maybe you have missed the previous message

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant