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

refactor test setups towards fixtures and hinting #968

Merged
merged 17 commits into from
Mar 15, 2023
Merged
5 changes: 2 additions & 3 deletions src/watchdog/observers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@

import sys
import warnings
from typing import Type

from watchdog.utils import UnsupportedLibc

from .api import BaseObserver
from .api import BaseObserverSubclassCallable

Observer: Type[BaseObserver]
Observer: BaseObserverSubclassCallable


if sys.platform.startswith("linux"):
Expand Down
7 changes: 6 additions & 1 deletion src/watchdog/observers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import threading
from pathlib import Path

from watchdog.utils import BaseThread
from watchdog.utils import BaseThread, Protocol
from watchdog.utils.bricks import SkipRepeatsQueue

DEFAULT_EMITTER_TIMEOUT = 1 # in seconds.
Expand Down Expand Up @@ -379,3 +379,8 @@ def dispatch_events(self, event_queue):
if handler in self._handlers.get(watch, []):
handler.dispatch(event)
event_queue.task_done()


class BaseObserverSubclassCallable(Protocol):
def __call__(self, timeout: float = ...) -> BaseObserver:
...
12 changes: 12 additions & 0 deletions src/watchdog/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import sys
import threading
from typing import TYPE_CHECKING


class UnsupportedLibc(Exception):
Expand Down Expand Up @@ -136,3 +137,14 @@ def load_class(dotted_path):
raise AttributeError(
f"Module {module_name} does not have class attribute {klass_name}"
)


if TYPE_CHECKING or sys.version_info >= (3, 8):
# using `as` to explicitly re-export this since this is a compatibility layer
from typing import Protocol as Protocol
else:
# Provide a dummy Protocol class when not available from stdlib. Should be used
# only for hinting. This could be had from typing_protocol, but not worth adding
# the _first_ dependency just for this.
class Protocol:
...
29 changes: 29 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import annotations

import contextlib
import gc
import os
import threading
from functools import partial

import pytest

from .utils import ExpectEvent, Helper, P, StartWatching, TestEventQueue


@pytest.fixture()
def p(tmpdir, *args):
Expand Down Expand Up @@ -51,3 +54,29 @@ def no_warnings(recwarn):
warnings.append("{w.filename}:{w.lineno} {w.message}".format(w=warning))
print(warnings)
assert not warnings


@pytest.fixture(name="helper")
def helper_fixture(tmpdir):
with contextlib.closing(Helper(tmp=os.fspath(tmpdir))) as helper:
yield helper


@pytest.fixture(name="p")
def p_fixture(helper: Helper) -> P:
return helper.joinpath


@pytest.fixture(name="event_queue")
def event_queue_fixture(helper: Helper) -> TestEventQueue:
return helper.event_queue


@pytest.fixture(name="start_watching")
def start_watching_fixture(helper: Helper) -> StartWatching:
return helper.start_watching


@pytest.fixture(name="expect_event")
def expect_event_fixture(helper: Helper) -> ExpectEvent:
return helper.expect_event
Loading