diff --git a/src/gevent/_ffi/watcher.py b/src/gevent/_ffi/watcher.py
index 013b2e59fcb64e3e47af2d61674cc25f4aa11567..e973830e10ac7a288b5ae4e92406871891fd001c 100644
--- a/src/gevent/_ffi/watcher.py
+++ b/src/gevent/_ffi/watcher.py
@@ -17,6 +17,20 @@ __all__ = [
 ]
 
 
+def events_to_str(event_field, all_events):
+    result = []
+    for (flag, string) in all_events:
+        c_flag = flag
+        if event_field & c_flag:
+            result.append(string)
+            event_field = event_field & (~c_flag)
+        if not event_field:
+            break
+    if event_field:
+        result.append(hex(event_field))
+    return '|'.join(result)
+
+
 def not_while_active(func):
     @functools.wraps(func)
     def nw(self, *args, **kwargs):
diff --git a/src/gevent/libev/corecffi.py b/src/gevent/libev/corecffi.py
index f83ba3641ec20557737a4378105a54446fa81929..7230687b7d61f4a4c1ff40bc31fca39293e1ea84 100644
--- a/src/gevent/libev/corecffi.py
+++ b/src/gevent/libev/corecffi.py
@@ -80,11 +80,8 @@ SIGNALFD = libev.EVFLAG_SIGNALFD
 NOSIGMASK = libev.EVFLAG_NOSIGMASK
 
 
-class _EVENTSType(object):
-    def __repr__(self):
-        return 'gevent.core.EVENTS'
-
-EVENTS = GEVENT_CORE_EVENTS = _EVENTSType()
+from gevent._ffi.loop import EVENTS
+GEVENT_CORE_EVENTS = EVENTS
 
 
 def get_version():
diff --git a/src/gevent/libev/watcher.py b/src/gevent/libev/watcher.py
index 4a27fed6a5f7de02ec139898924902c14790b9d7..0da51eec0011f207d109c7fb04ca5fbbcf7ecc98 100644
--- a/src/gevent/libev/watcher.py
+++ b/src/gevent/libev/watcher.py
@@ -46,21 +46,11 @@ _events = [(libev.EV_READ, 'READ'),
            (libev.EV_CUSTOM, 'CUSTOM'),
            (libev.EV_ERROR, 'ERROR')]
 
-def _events_to_str(events):
-    result = []
-    for (flag, string) in _events:
-        c_flag = flag
-        if events & c_flag:
-            result.append(string)
-            events = events & (~c_flag)
-        if not events:
-            break
-    if events:
-        result.append(hex(events))
-    return '|'.join(result)
+from gevent._ffi import watcher as _base
 
+def _events_to_str(events):
+    return _base.events_to_str(events, _events)
 
-from gevent._ffi import watcher as _base
 
 
 class watcher(_base.watcher):
diff --git a/src/gevent/libuv/_corecffi_cdef.c b/src/gevent/libuv/_corecffi_cdef.c
index bbcad15e2edad6cb1609438ed82d60e062b2dc74..156d33f45497424076e429339b871b874de081fd 100644
--- a/src/gevent/libuv/_corecffi_cdef.c
+++ b/src/gevent/libuv/_corecffi_cdef.c
@@ -5,6 +5,9 @@
 
 #define UV_EBUSY ...
 
+#define UV_VERSION_MAJOR ...
+#define UV_VERSION_MINOR ...
+#define UV_VERSION_PATCH ...
 
 typedef enum {
     UV_RUN_DEFAULT = 0,
@@ -52,6 +55,7 @@ enum uv_fs_event_flags {
 
 const char* uv_strerror(int);
 const char* uv_err_name(int);
+const char* uv_version_string(void);
 
 // handle structs and types
 struct uv_loop_s {
diff --git a/src/gevent/libuv/loop.py b/src/gevent/libuv/loop.py
index fc7d39083cd3f83ae083a6564d13117321fc2fda..4e62c20110640f5c52b3af8354dc878310da2c03 100644
--- a/src/gevent/libuv/loop.py
+++ b/src/gevent/libuv/loop.py
@@ -22,8 +22,29 @@ __all__ = [
 
 _callbacks = assign_standard_callbacks(ffi, libuv)
 
+from gevent._ffi.loop import EVENTS
+GEVENT_CORE_EVENTS = EVENTS # export
+
 from gevent.libuv import watcher as _watchers
 
+_events_to_str = _watchers._events_to_str # export
+
+READ = libuv.UV_READABLE
+WRITE = libuv.UV_WRITABLE
+
+def get_version():
+    uv_bytes = ffi.string(libuv.uv_version_string())
+    if not isinstance(uv_bytes, str):
+        # Py3
+        uv_str = uv_bytes.decode("ascii")
+    else:
+        uv_str = uv_bytes
+
+    return 'libuv-' + uv_str
+
+def get_header_version():
+    return 'libuv-%d.%d.%d' % (libuv.UV_VERSION_MAJOR, libuv.UV_VERSION_MINOR, libuv.UV_VERSION_PATCH)
+
 class loop(AbstractLoop):
 
     error_handler = None
diff --git a/src/gevent/libuv/watcher.py b/src/gevent/libuv/watcher.py
index cf26e0af2b47888c68fada6e380fe8121e457b55..ac217681eba93578e1ca04d68d8a641532c23206 100644
--- a/src/gevent/libuv/watcher.py
+++ b/src/gevent/libuv/watcher.py
@@ -21,6 +21,12 @@ def _uv_close_callback(handle):
 def _dbg(*args, **kwargs):
     pass
 
+_events = [(libuv.UV_READABLE, "READ"),
+           (libuv.UV_WRITABLE, "WRITE")]
+
+def _events_to_str(events): # export
+    return _base.events_to_str(events, _events)
+
 class watcher(_base.watcher):
     _FFI = ffi
     _LIB = libuv
diff --git a/src/greentest/test__core.py b/src/greentest/test__core.py
index d44067feb35c62bbaaa0dac0758208939749930a..d8e840a2f852709e34bcffb4b76742b41f651ac8 100644
--- a/src/greentest/test__core.py
+++ b/src/greentest/test__core.py
@@ -1,6 +1,7 @@
 import sys
 from greentest import TestCase, main
 from gevent import core
+import unittest
 
 
 class Test(TestCase):
@@ -16,6 +17,8 @@ class Test(TestCase):
         assert header_version, repr(header_version)
         self.assertEqual(version, header_version)
 
+    @unittest.skipIf(hasattr(core, 'libuv'),
+                     "flags are libev-only")
     def test_flags_conversion(self):
         if sys.platform != 'win32':
             self.assertEqual(core.loop(2, default=False).backend_int, 2)
@@ -41,7 +44,9 @@ class Test(TestCase):
             Error = ValueError
             win32 = False
         self.assertRaises(Error, core.loop().io, -1, 1)
-        self.assertRaises(ValueError, core.loop().io, 1, core.TIMER)
+        if hasattr(core, 'TIMER'):
+            # libev
+            self.assertRaises(ValueError, core.loop().io, 1, core.TIMER)
         # Test we can set events and io before it's started
         if not win32:
             # We can't do this with arbitrary FDs on windows;
@@ -50,7 +55,11 @@ class Test(TestCase):
             io.fd = 2
             self.assertEqual(io.fd, 2)
             io.events = core.WRITE
-            self.assertEqual(core._events_to_str(io.events), 'WRITE|_IOFDSET')
+            if not hasattr(core, 'libuv'):
+                # libev
+                self.assertEqual(core._events_to_str(io.events), 'WRITE|_IOFDSET')
+            else:
+                self.assertEqual(core._events_to_str(io.events), 'WRITE')
 
     def test_timer(self):
         self.assertRaises(ValueError, core.loop().timer, 1, -1)