_rust_notify.pyi 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from typing import Any, Literal, Protocol
  2. __all__ = 'RustNotify', 'WatchfilesRustInternalError'
  3. __version__: str
  4. """The package version as defined in `Cargo.toml`, modified to match python's versioning semantics."""
  5. class AbstractEvent(Protocol):
  6. def is_set(self) -> bool: ...
  7. class RustNotify:
  8. """
  9. Interface to the Rust [notify](https://crates.io/crates/notify) crate which does
  10. the heavy lifting of watching for file changes and grouping them into events.
  11. """
  12. def __init__(
  13. self,
  14. watch_paths: list[str],
  15. debug: bool,
  16. force_polling: bool,
  17. poll_delay_ms: int,
  18. recursive: bool,
  19. ignore_permission_denied: bool,
  20. ) -> None:
  21. """
  22. Create a new `RustNotify` instance and start a thread to watch for changes.
  23. `FileNotFoundError` is raised if any of the paths do not exist.
  24. Args:
  25. watch_paths: file system paths to watch for changes, can be directories or files
  26. debug: if true, print details about all events to stderr
  27. force_polling: if true, always use polling instead of file system notifications
  28. poll_delay_ms: delay between polling for changes, only used if `force_polling=True`
  29. recursive: if `True`, watch for changes in sub-directories recursively, otherwise watch only for changes in
  30. the top-level directory, default is `True`.
  31. ignore_permission_denied: if `True`, permission denied errors are ignored while watching changes.
  32. """
  33. def watch(
  34. self,
  35. debounce_ms: int,
  36. step_ms: int,
  37. timeout_ms: int,
  38. stop_event: AbstractEvent | None,
  39. ) -> set[tuple[int, str]] | Literal['signal', 'stop', 'timeout']:
  40. """
  41. Watch for changes.
  42. This method will wait `timeout_ms` milliseconds for changes, but once a change is detected,
  43. it will group changes and return in no more than `debounce_ms` milliseconds.
  44. The GIL is released during a `step_ms` sleep on each iteration to avoid
  45. blocking python.
  46. Args:
  47. debounce_ms: maximum time in milliseconds to group changes over before returning.
  48. step_ms: time to wait for new changes in milliseconds, if no changes are detected
  49. in this time, and at least one change has been detected, the changes are yielded.
  50. timeout_ms: maximum time in milliseconds to wait for changes before returning,
  51. `0` means wait indefinitely, `debounce_ms` takes precedence over `timeout_ms` once
  52. a change is detected.
  53. stop_event: event to check on every iteration to see if this function should return early.
  54. The event should be an object which has an `is_set()` method which returns a boolean.
  55. Returns:
  56. See below.
  57. Return values have the following meanings:
  58. * Change details as a `set` of `(event_type, path)` tuples, the event types are ints which match
  59. [`Change`][watchfiles.Change], `path` is a string representing the path of the file that changed
  60. * `'signal'` string, if a signal was received
  61. * `'stop'` string, if the `stop_event` was set
  62. * `'timeout'` string, if `timeout_ms` was exceeded
  63. """
  64. def __enter__(self) -> RustNotify:
  65. """
  66. Does nothing, but allows `RustNotify` to be used as a context manager.
  67. !!! note
  68. The watching thead is created when an instance is initiated, not on `__enter__`.
  69. """
  70. def __exit__(self, *args: Any) -> None:
  71. """
  72. Calls [`close`][watchfiles._rust_notify.RustNotify.close].
  73. """
  74. def close(self) -> None:
  75. """
  76. Stops the watching thread. After `close` is called, the `RustNotify` instance can no
  77. longer be used, calls to [`watch`][watchfiles._rust_notify.RustNotify.watch] will raise a `RuntimeError`.
  78. !!! note
  79. `close` is not required, just deleting the `RustNotify` instance will kill the thread
  80. implicitly.
  81. As per [#163](https://github.com/samuelcolvin/watchfiles/issues/163) `close()` is only required because
  82. in the event of an error, the traceback in `sys.exc_info` keeps a reference to `watchfiles.watch`'s
  83. frame, so you can't rely on the `RustNotify` object being deleted, and thereby stopping
  84. the watching thread.
  85. """
  86. class WatchfilesRustInternalError(RuntimeError):
  87. """
  88. Raised when RustNotify encounters an unknown error.
  89. If you get this a lot, please check [github](https://github.com/samuelcolvin/watchfiles/issues) issues
  90. and create a new issue if your problem is not discussed.
  91. """