mirror of
https://github.com/powerline/powerline.git
synced 2025-07-15 09:54:54 +02:00
Merge pull request #1053 from ZyX-I/fix-uv-watcher
Some fixes for libuv-based watcher
This commit is contained in:
commit
77d311bdc8
@ -45,6 +45,7 @@ Common configuration is a subdictionary that is a value of ``common`` key in
|
|||||||
auto Selects most performant watcher.
|
auto Selects most performant watcher.
|
||||||
inotify Select inotify watcher. Linux only.
|
inotify Select inotify watcher. Linux only.
|
||||||
stat Select stat-based polling watcher.
|
stat Select stat-based polling watcher.
|
||||||
|
uv Select libuv-based watcher.
|
||||||
======= ===================================
|
======= ===================================
|
||||||
|
|
||||||
Default is ``auto``.
|
Default is ``auto``.
|
||||||
|
@ -19,6 +19,8 @@ Generic requirements
|
|||||||
repositories.
|
repositories.
|
||||||
* ``bzr`` python package (note: *not* standalone executable). Required to work
|
* ``bzr`` python package (note: *not* standalone executable). Required to work
|
||||||
with bazaar repositories.
|
with bazaar repositories.
|
||||||
|
* ``pyuv`` python package. Required for :ref:`libuv-based watcher
|
||||||
|
<config-common-watcher>` to work.
|
||||||
* ``i3-py``, `available on github <https://github.com/ziberna/i3-py>`_. Required
|
* ``i3-py``, `available on github <https://github.com/ziberna/i3-py>`_. Required
|
||||||
for i3wm bindings and segments.
|
for i3wm bindings and segments.
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ def get_branch_name(directory, config_file, get_func, create_watcher):
|
|||||||
with branch_lock:
|
with branch_lock:
|
||||||
# Check if the repo directory was moved/deleted
|
# Check if the repo directory was moved/deleted
|
||||||
fw = branch_watcher(create_watcher)
|
fw = branch_watcher(create_watcher)
|
||||||
is_watched = fw.is_watched(directory)
|
is_watched = fw.is_watching(directory)
|
||||||
try:
|
try:
|
||||||
changed = fw(directory)
|
changed = fw(directory)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
|
@ -18,16 +18,17 @@ def create_file_watcher(pl, watcher_type='auto', expire_time=10):
|
|||||||
|
|
||||||
Use ``.unwatch()`` method of the returned object to stop watching the file.
|
Use ``.unwatch()`` method of the returned object to stop watching the file.
|
||||||
|
|
||||||
Uses inotify if available, otherwise tracks mtimes. expire_time is the
|
Uses inotify if available, then pyuv, otherwise tracks mtimes. expire_time
|
||||||
number of minutes after the last query for a given path for the inotify
|
is the number of minutes after the last query for a given path for the
|
||||||
watch for that path to be automatically removed. This conserves kernel
|
inotify watch for that path to be automatically removed. This conserves
|
||||||
resources.
|
kernel resources.
|
||||||
|
|
||||||
:param PowerlineLogger pl:
|
:param PowerlineLogger pl:
|
||||||
Logger.
|
Logger.
|
||||||
:param str watcher_type:
|
:param str watcher_type
|
||||||
One of ``inotify`` (linux only), ``stat``, ``auto``. Determines what
|
One of ``inotify`` (linux only), ``uv``, ``stat``, ``auto``. Determines
|
||||||
watcher will be used. ``auto`` will use ``inotify`` if available.
|
what watcher will be used. ``auto`` will use ``inotify`` if available,
|
||||||
|
then ``libuv`` and then fall back to ``stat``.
|
||||||
:param int expire_time:
|
:param int expire_time:
|
||||||
Number of minutes since last ``.__call__()`` before inotify watcher will
|
Number of minutes since last ``.__call__()`` before inotify watcher will
|
||||||
stop watching given file.
|
stop watching given file.
|
||||||
@ -67,7 +68,7 @@ def create_tree_watcher(pl, watcher_type='auto', expire_time=10):
|
|||||||
Logger.
|
Logger.
|
||||||
:param str watcher_type:
|
:param str watcher_type:
|
||||||
Watcher type. Currently the only supported types are ``inotify`` (linux
|
Watcher type. Currently the only supported types are ``inotify`` (linux
|
||||||
only), ``dummy`` and ``auto``.
|
only), ``uv``, ``dummy`` and ``auto``.
|
||||||
:param int expire_time:
|
:param int expire_time:
|
||||||
Number of minutes since last ``.__call__()`` before inotify watcher will
|
Number of minutes since last ``.__call__()`` before inotify watcher will
|
||||||
stop watching given file.
|
stop watching given file.
|
||||||
|
@ -101,7 +101,7 @@ class INotifyFileWatcher(INotify):
|
|||||||
self.watches[path] = wd
|
self.watches[path] = wd
|
||||||
self.modified[path] = False
|
self.modified[path] = False
|
||||||
|
|
||||||
def is_watched(self, path):
|
def is_watching(self, path):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
return realpath(path) in self.watches
|
return realpath(path) in self.watches
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class StatFileWatcher(object):
|
|||||||
with self.lock:
|
with self.lock:
|
||||||
self.watches.pop(path, None)
|
self.watches.pop(path, None)
|
||||||
|
|
||||||
def is_watched(self, path):
|
def is_watching(self, path):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
return realpath(path) in self.watches
|
return realpath(path) in self.watches
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ class UvWatcher(object):
|
|||||||
self.loop = start_uv_thread()
|
self.loop = start_uv_thread()
|
||||||
|
|
||||||
def watch(self, path):
|
def watch(self, path):
|
||||||
|
path = realpath(path)
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if path not in self.watches:
|
if path not in self.watches:
|
||||||
try:
|
try:
|
||||||
@ -80,6 +81,7 @@ class UvWatcher(object):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def unwatch(self, path):
|
def unwatch(self, path):
|
||||||
|
path = realpath(path)
|
||||||
with self.lock:
|
with self.lock:
|
||||||
try:
|
try:
|
||||||
watch = self.watches.pop(path)
|
watch = self.watches.pop(path)
|
||||||
@ -87,6 +89,10 @@ class UvWatcher(object):
|
|||||||
return
|
return
|
||||||
watch.close(partial(self._stopped_watching, path))
|
watch.close(partial(self._stopped_watching, path))
|
||||||
|
|
||||||
|
def is_watching(self, path):
|
||||||
|
with self.lock:
|
||||||
|
return realpath(path) in self.watches
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
try:
|
||||||
lock = self.lock
|
lock = self.lock
|
||||||
@ -115,6 +121,7 @@ class UvFileWatcher(UvWatcher):
|
|||||||
self.events.pop(path, None)
|
self.events.pop(path, None)
|
||||||
|
|
||||||
def __call__(self, path):
|
def __call__(self, path):
|
||||||
|
path = realpath(path)
|
||||||
with self.lock:
|
with self.lock:
|
||||||
events = self.events.pop(path, None)
|
events = self.events.pop(path, None)
|
||||||
if events:
|
if events:
|
||||||
@ -122,6 +129,7 @@ class UvFileWatcher(UvWatcher):
|
|||||||
if path not in self.watches:
|
if path not in self.watches:
|
||||||
self.watch(path)
|
self.watch(path)
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class UvTreeWatcher(UvWatcher):
|
class UvTreeWatcher(UvWatcher):
|
||||||
@ -135,7 +143,7 @@ class UvTreeWatcher(UvWatcher):
|
|||||||
self.watch_directory(self.basedir)
|
self.watch_directory(self.basedir)
|
||||||
|
|
||||||
def watch_directory(self, path):
|
def watch_directory(self, path):
|
||||||
os.path.walk(path, self.watch_one_directory, None)
|
os.path.walk(realpath(path), self.watch_one_directory, None)
|
||||||
|
|
||||||
def watch_one_directory(self, arg, dirname, fnames):
|
def watch_one_directory(self, arg, dirname, fnames):
|
||||||
try:
|
try:
|
||||||
|
@ -141,6 +141,40 @@ class TestFilesystemWatchers(TestCase):
|
|||||||
tw = create_tree_watcher(get_fallback_logger(), 'uv')
|
tw = create_tree_watcher(get_fallback_logger(), 'uv')
|
||||||
return self.do_test_tree_watcher(tw)
|
return self.do_test_tree_watcher(tw)
|
||||||
|
|
||||||
|
def test_inotify_file_watcher_is_watching(self):
|
||||||
|
try:
|
||||||
|
w = create_file_watcher(pl=get_fallback_logger(), watcher_type='inotify')
|
||||||
|
except INotifyError:
|
||||||
|
raise SkipTest('INotify is not available')
|
||||||
|
return self.do_test_file_watcher_is_watching(w)
|
||||||
|
|
||||||
|
def test_stat_file_watcher_is_watching(self):
|
||||||
|
w = create_file_watcher(pl=get_fallback_logger(), watcher_type='stat')
|
||||||
|
return self.do_test_file_watcher_is_watching(w)
|
||||||
|
|
||||||
|
def test_uv_file_watcher_is_watching(self):
|
||||||
|
try:
|
||||||
|
w = create_file_watcher(pl=get_fallback_logger(), watcher_type='uv')
|
||||||
|
except UvNotFound:
|
||||||
|
raise SkipTest('Pyuv is not available')
|
||||||
|
return self.do_test_file_watcher_is_watching(w)
|
||||||
|
|
||||||
|
def do_test_file_watcher_is_watching(self, w):
|
||||||
|
try:
|
||||||
|
f1, f2, f3 = map(lambda x: os.path.join(INOTIFY_DIR, 'file%d' % x), (1, 2, 3))
|
||||||
|
with open(f1, 'wb'):
|
||||||
|
with open(f2, 'wb'):
|
||||||
|
with open(f3, 'wb'):
|
||||||
|
pass
|
||||||
|
ne = os.path.join(INOTIFY_DIR, 'notexists')
|
||||||
|
self.assertRaises(OSError, w, ne)
|
||||||
|
self.assertTrue(w(f1))
|
||||||
|
self.assertFalse(w.is_watching(ne))
|
||||||
|
self.assertTrue(w.is_watching(f1))
|
||||||
|
self.assertFalse(w.is_watching(f2))
|
||||||
|
finally:
|
||||||
|
clear_dir(INOTIFY_DIR)
|
||||||
|
|
||||||
|
|
||||||
old_cwd = None
|
old_cwd = None
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user