[PATCH evemu 4/4] py: Add and use wrapper for libevemu calls

Daniel Martin consume.noise at gmail.com
Fri Jan 10 00:30:37 PST 2014


Introduce a class LibEvemu in base.py, which wraps API calls to
libevemu, and replace _call()s by using it.
As this obsoletes the class EvEmuBase, it's removed as well.

v2: Removed tests if functions can be found in the loaded library and
    added tests that the loaded library is static in the class.

Signed-off-by: Daniel Martin <consume.noise at gmail.com>
---
 python/evemu/__init__.py        |  93 ++++++---------
 python/evemu/base.py            | 254 +++++++++++++++++++++++++++++++++++++---
 python/evemu/const.py           |  33 ------
 python/evemu/tests/test_base.py |  29 ++++-
 4 files changed, 292 insertions(+), 117 deletions(-)

diff --git a/python/evemu/__init__.py b/python/evemu/__init__.py
index f474036..8e725c7 100644
--- a/python/evemu/__init__.py
+++ b/python/evemu/__init__.py
@@ -53,36 +53,28 @@ class Device(object):
             raise TypeError("expected file or file name")
 
         self._is_propfile = self._check_is_propfile(self._file)
-        self._evemu = evemu.base.EvEmuBase()
         self._libc = evemu.base.LibC()
+        self._libevemu = evemu.base.LibEvemu()
         self._uinput = None
 
-        libevemu_new = self._evemu.get_lib().evemu_new
-        libevemu_new.restype = ctypes.c_void_p
-        self._evemu_device = libevemu_new("")
+        self._evemu_device = self._libevemu.evemu_new(b"")
 
         if self._is_propfile:
             fs = self._libc.fdopen(self._file.fileno(), b"r")
-            self._evemu._call(self._evemu.get_lib().evemu_read,
-                              self._evemu_device,
-                              fs)
+            self._libevemu.evemu_read(self._evemu_device, fs)
             self._uinput = os.open(evemu.const.UINPUT_NODE, os.O_WRONLY)
             self._file = self._create_devnode()
         else:
-            self._evemu._call(self._evemu.get_lib().evemu_extract,
-                             self._evemu_device,
-                             self._file.fileno())
+            self._libevemu.evemu_extract(self._evemu_device,
+                                         self._file.fileno())
 
     def __del__(self):
         if hasattr(self, "_is_propfile") and self._is_propfile:
             self._file.close()
-            self._evemu._call(self._evemu.get_lib().evemu_destroy,
-                              self._evemu_device, self._uinput)
+            self._libevemu.evemu_destroy(self._evemu_device, self._uinput)
 
     def _create_devnode(self):
-        self._evemu._call(self._evemu.get_lib().evemu_create,
-                          self._evemu_device,
-                          self._uinput)
+        self._libevemu.evemu_create(self._evemu_device, self._uinput)
         return open(self._find_newest_devnode(self.name), 'r+b', buffering=0)
 
     def _find_newest_devnode(self, target_name):
@@ -129,9 +121,7 @@ class Device(object):
             raise TypeError("expected file")
 
         fs = self._libc.fdopen(prop_file.fileno(), b"w")
-        self._evemu._call(self._evemu.get_lib().evemu_write,
-                          self._evemu_device,
-                          fs)
+        self._libevemu.evemu_write(self._evemu_device, fs)
         self._libc.fflush(fs)
 
     def play(self, events_file):
@@ -146,9 +136,7 @@ class Device(object):
             raise TypeError("expected file")
 
         fs = self._libc.fdopen(events_file.fileno(), b"r")
-        self._evemu._call(self._evemu.get_lib().evemu_play,
-                          fs,
-                          self._file.fileno())
+        self._libevemu.evemu_play(fs, self._file.fileno())
 
     def record(self, events_file, timeout=10000):
         """
@@ -163,10 +151,7 @@ class Device(object):
             raise TypeError("expected file")
 
         fs = self._libc.fdopen(events_file.fileno(), b"w")
-        self._evemu._call(self._evemu.get_lib().evemu_record,
-                          fs,
-                          self._file.fileno(),
-                          timeout)
+        self._libevemu.evemu_record(fs, self._file.fileno(), timeout)
         self._libc.fflush(fs)
 
     @property
@@ -174,8 +159,7 @@ class Device(object):
         """
         Gets the version of the evemu library used to create the Device.
         """
-        return self._evemu._call(self._evemu.get_lib().evemu_get_version,
-                                 self._evemu_device)
+        return self._libevemu.evemu_get_version(self._evemu_device)
 
     @property
     def devnode(self):
@@ -189,71 +173,60 @@ class Device(object):
         """
         Gets the name of the input device (as reported by the device).
         """
-        func = self._evemu.get_lib().evemu_get_name
-        func.restype = ctypes.c_char_p
-        return self._evemu._call(func, self._evemu_device)
+        result = self._libevemu.evemu_get_name(self._evemu_device)
+        return result.decode(evemu.const.ENCODING)
 
     @property
     def id_bustype(self):
         """
         Identifies the kernel device bustype.
         """
-        return self._evemu._call(self._evemu.get_lib().evemu_get_id_bustype,
-                                 self._evemu_device)
+        return self._libevemu.evemu_get_id_bustype(self._evemu_device)
 
     @property
     def id_vendor(self):
         """
         Identifies the kernel device vendor.
         """
-        return self._evemu._call(self._evemu.get_lib().evemu_get_id_vendor,
-                                 self._evemu_device)
+        return self._libevemu.evemu_get_id_vendor(self._evemu_device)
 
     @property
     def id_product(self):
         """
         Identifies the kernel device product.
         """
-        return self._evemu._call(self._evemu.get_lib().evemu_get_id_product,
-                                 self._evemu_device)
+        return self._libevemu.evemu_get_id_product(self._evemu_device)
 
     @property
     def id_version(self):
         """
         Identifies the kernel device version.
         """
-        return self._evemu._call(self._evemu.get_lib().evemu_get_id_version,
-                                 self._evemu_device)
+        return self._libevemu.evemu_get_id_version(self._evemu_device)
 
     def get_abs_minimum(self, event_code):
-        return self._evemu._call(self._evemu.get_lib().evemu_get_abs_minimum,
-                                 self._evemu_device,
-                                 int(event_code))
+        return self._libevemu.evemu_get_abs_minimum(self._evemu_device,
+                                                    event_code)
 
     def get_abs_maximum(self, event_code):
-        return self._evemu._call(self._evemu.get_lib().evemu_get_abs_maximum,
-                                 self._evemu_device,
-                                 event_code)
+        return self._libevemu.evemu_get_abs_maximum(self._evemu_device,
+                                                    event_code)
 
     def get_abs_fuzz(self, event_code):
-        return self._evemu._call(self._evemu.get_lib().evemu_get_abs_fuzz,
-                                 self._evemu_device,
-                                 event_code)
+        return self._libevemu.evemu_get_abs_fuzz(self._evemu_device,
+                                                 event_code)
 
     def get_abs_flat(self, event_code):
-        return self._evemu._call(self._evemu.get_lib().evemu_get_abs_flat,
-                                 self._evemu_device,
-                                 event_code)
+        return self._libevemu.evemu_get_abs_flat(self._evemu_device,
+                                                 event_code)
 
     def get_abs_resolution(self, event_code):
-        return self._evemu._call(self._evemu.get_lib().evemu_get_abs_resolution,
-                                 self._evemu_device,
-                                 event_code)
+        return self._libevemu.evemu_get_abs_resolution(self._evemu_device,
+                                                       event_code)
 
     def has_prop(self, event_code):
-        return bool(self._evemu._call(self._evemu.get_lib().evemu_has_prop,
-                                      self._evemu_device,
-                                      event_code))
+        result = self._libevemu.evemu_has_prop(self._evemu_device, event_code)
+        return bool(result)
 
     def has_event(self, event_type, event_code):
         """
@@ -267,8 +240,8 @@ class Device(object):
         used to simulate gestures for a higher number of touches than are
         possible with just 2-touch hardware.
         """
-        return bool(self._evemu._call(self._evemu.get_lib().evemu_has_event,
-                                      self._evemu_device,
-                                      event_type,
-                                      event_code))
+        result = self._libevemu.evemu_has_event(self._evemu_device,
+                                                event_type,
+                                                event_code)
+        return bool(result)
 
diff --git a/python/evemu/base.py b/python/evemu/base.py
index 884c861..b366e2f 100644
--- a/python/evemu/base.py
+++ b/python/evemu/base.py
@@ -160,25 +160,243 @@ class LibC(LibraryWrapper):
         }
 
 
-class EvEmuBase(object):
+class LibEvemu(LibraryWrapper):
     """
-    A base wrapper class for the evemu functions, accessed via ctypes.
+    Wrapper for API calls to the evemu library.
     """
-    def __init__(self):
-        self._lib = ctypes.CDLL(evemu.const.LIB, use_errno=True)
-
-    def _call(self, api_call, *parameters):
-        result = api_call(*parameters)
-        if result < 0 and self.get_c_errno() != 0:
-            raise evemu.exception.ExecutionError("%s: %s" % (
-                api_call.__name__, self.get_c_error()))
-        return result
-
-    def get_c_errno(self):
-        return ctypes.get_errno()
 
-    def get_c_error(self):
-        return os.strerror(ctypes.get_errno())
+    @staticmethod
+    def _cdll():
+        return ctypes.CDLL(evemu.const.LIB, use_errno=True)
 
-    def get_lib(self):
-        return self._lib
+    _api_prototypes = {
+        #struct evemu_device *evemu_new(const char *name);
+        "evemu_new": {
+            "argtypes": (c_char_p,),
+            "restype": c_void_p,
+            "errcheck": expect_not_none
+            },
+        #void evemu_delete(struct evemu_device *dev);
+        "evemu_delete": {
+            "argtypes": (c_void_p,),
+            "restype": None
+            },
+        #unsigned int evemu_get_version(const struct evemu_device *dev);
+        "evemu_get_version": {
+            "argtypes": (c_void_p,),
+            "restype": c_uint,
+            },
+        #const char *evemu_get_name(const struct evemu_device *dev);
+        "evemu_get_name": {
+            "argtypes": (c_void_p,),
+            "restype": c_char_p,
+            "errcheck": expect_not_none
+            },
+        #void evemu_set_name(struct evemu_device *dev, const char *name);
+        "evemu_set_name": {
+            "argtypes": (c_void_p, c_char_p),
+            "restype": None
+            },
+        #unsigned int evemu_get_id_bustype(const struct evemu_device *dev);
+        "evemu_get_id_bustype": {
+            "argtypes": (c_void_p,),
+            "restype": c_uint
+            },
+        #void evemu_set_id_bustype(struct evemu_device *dev,
+        #                          unsigned int bustype);
+        "evemu_set_id_bustype": {
+            "argtypes": (c_void_p, c_uint),
+            "restype": None
+            },
+        #unsigned int evemu_get_id_vendor(const struct evemu_device *dev);
+        "evemu_get_id_vendor": {
+            "argtypes": (c_void_p,),
+            "restype": c_uint
+            },
+        #void evemu_set_id_vendor(struct evemu_device *dev,
+        #                         unsigned int vendor);
+        "evemu_set_id_vendor": {
+            "argtypes": (c_void_p, c_uint),
+            "restype": None
+            },
+        #unsigned int evemu_get_id_product(const struct evemu_device *dev);
+        "evemu_get_id_product": {
+            "argtypes": (c_void_p,),
+            "restype": c_uint
+            },
+        #void evemu_set_id_product(struct evemu_device *dev,
+        #                          unsigned int product);
+        "evemu_set_id_product": {
+            "argtypes": (c_void_p, c_uint),
+            "restype": None
+            },
+        #unsigned int evemu_get_id_version(const struct evemu_device *dev);
+        "evemu_get_id_version": {
+            "argtypes": (c_void_p,),
+            "restype": c_uint
+            },
+        #void evemu_set_id_version(struct evemu_device *dev,
+        #                          unsigned int version);
+        "evemu_set_id_version": {
+            "argtypes": (c_void_p, c_uint),
+            "restype": None
+            },
+        #int evemu_get_abs_current_value(const struct evemu_device *dev,
+        #                                int code);
+        "evemu_get_abs_current_value": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #int evemu_get_abs_minimum(const struct evemu_device *dev, int code);
+        "evemu_get_abs_minimum": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #void evemu_set_abs_minimum(struct evemu_device *dev, int code,
+        #                           int min);
+        "evemu_set_abs_minimum": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": None
+            },
+        #int evemu_get_abs_maximum(const struct evemu_device *dev, int code);
+        "evemu_get_abs_maximum": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #void evemu_set_abs_maximum(struct evemu_device *dev, int code,
+        #                           int max);
+        "evemu_set_abs_maximum": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": None
+            },
+        #int evemu_get_abs_fuzz(const struct evemu_device *dev, int code);
+        "evemu_get_abs_fuzz": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #void evemu_set_abs_fuzz(struct evemu_device *dev, int code, int fuzz);
+        "evemu_set_abs_fuzz": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": None,
+            },
+        #int evemu_get_abs_flat(const struct evemu_device *dev, int code);
+        "evemu_get_abs_flat": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #void evemu_set_abs_flat(struct evemu_device *dev, int code, int flat);
+        "evemu_set_abs_flat": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": None
+            },
+        #int evemu_get_abs_resolution(const struct evemu_device *dev,
+        #                             int code);
+        "evemu_get_abs_resolution": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #void evemu_set_abs_resolution(struct evemu_device *dev, int code,
+        #                              int res);
+        "evemu_set_abs_resolution": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": None
+            },
+        #int evemu_has_prop(const struct evemu_device *dev, int code);
+        "evemu_has_prop": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #int evemu_has_event(const struct evemu_device *dev, int type,
+        #                    int code);
+        "evemu_has_event": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #int evemu_has_bit(const struct evemu_device *dev, int type);
+        "evemu_has_bit": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_ge_zero
+            },
+        #int evemu_extract(struct evemu_device *dev, int fd);
+        "evemu_extract": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_write(const struct evemu_device *dev, FILE *fp);
+        "evemu_write": {
+            "argtypes": (c_void_p, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_read(struct evemu_device *dev, FILE *fp);
+        "evemu_read": {
+            "argtypes": (c_void_p, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_gt_zero
+            },
+        #int evemu_write_event(FILE *fp, const struct input_event *ev);
+        "evemu_write_event": {
+            "argtypes": (c_void_p, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_gt_zero
+            },
+        #int evemu_create_event(struct input_event *ev, int type, int code,
+        #                       int value);
+        "evemu_create_event": {
+            "argtypes": (c_void_p, c_int, c_int, c_int),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_read_event(FILE *fp, struct input_event *ev);
+        "evemu_read_event": {
+            "argtypes": (c_void_p, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_gt_zero
+            },
+        #int evemu_read_event_realtime(FILE *fp, struct input_event *ev,
+        #			      struct timeval *evtime);
+        "evemu_read_event_realtime": {
+            "argtypes": (c_void_p, c_void_p, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_gt_zero
+            },
+        #int evemu_record(FILE *fp, int fd, int ms);
+        "evemu_record": {
+            "argtypes": (c_void_p, c_int, c_int),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_play_one(int fd, const struct input_event *ev);
+        "evemu_play_one": {
+            "argtypes": (c_int, c_void_p),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_play(FILE *fp, int fd);
+        "evemu_play": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #int evemu_create(struct evemu_device *dev, int fd);
+        "evemu_create": {
+            "argtypes": (c_void_p, c_int),
+            "restype": c_int,
+            "errcheck": expect_eq_zero
+            },
+        #void evemu_destroy(struct evemu_device *dev);
+        "evemu_destroy": {
+            "argtypes": (c_void_p,),
+            "restype": None
+            },
+        }
diff --git a/python/evemu/const.py b/python/evemu/const.py
index 35f1878..19c507a 100644
--- a/python/evemu/const.py
+++ b/python/evemu/const.py
@@ -2,39 +2,6 @@ LIB = "libevemu.so"
 ENCODING="iso8859-1"
 UINPUT_NODE = "/dev/uinput"
 
-# The following should be examined every release of evemu
-API = [
-    "evemu_new",
-    "evemu_delete",
-    "evemu_extract",
-    "evemu_write",
-    "evemu_read",
-    "evemu_write_event",
-    "evemu_record",
-    "evemu_read_event",
-    "evemu_play",
-    "evemu_create",
-    "evemu_destroy",
-    # Device settrs
-    "evemu_set_name",
-    # Device gettrs
-    "evemu_get_version",
-    "evemu_get_name",
-    "evemu_get_id_bustype",
-    "evemu_get_id_vendor",
-    "evemu_get_id_product",
-    "evemu_get_id_version",
-    "evemu_get_abs_minimum",
-    "evemu_get_abs_maximum",
-    "evemu_get_abs_fuzz",
-    "evemu_get_abs_flat",
-    "evemu_get_abs_resolution",
-    # Device hasers
-    "evemu_has_prop",
-    "evemu_has_event",
-    "evemu_has_bit",
-    ]
-
 event_types = {
     "EV_SYN": 0x00,
     "EV_KEY": 0x01,
diff --git a/python/evemu/tests/test_base.py b/python/evemu/tests/test_base.py
index 29bdb15..bc35c73 100644
--- a/python/evemu/tests/test_base.py
+++ b/python/evemu/tests/test_base.py
@@ -7,12 +7,6 @@ import evemu.testing.testcase
 
 class EvEmuBaseTestCase(evemu.testing.testcase.BaseTestCase):
 
-    def test_so_library_found(self):
-        wrapper = evemu.base.EvEmuBase()
-        # Make sure that the library loads
-        self.assertNotEqual(
-            wrapper._lib._name.find("libevemu"), -1)
-
     def test_libc_found(self):
         lib = evemu.base.LibC._load()
         self.assertNotEqual(lib, None)
@@ -36,5 +30,28 @@ class EvEmuBaseTestCase(evemu.testing.testcase.BaseTestCase):
 
         self.assertEqual(first._loaded_lib, second._loaded_lib)
 
+    def test_libevemu_found(self):
+        lib = evemu.base.LibEvemu._load()
+        self.assertNotEqual(lib, None)
+        self.assertTrue(lib._name.startswith("libevemu"))
+
+    def test_libevemu_static_from_load(self):
+        first = evemu.base.LibEvemu._load()
+        self.assertNotEqual(first, None)
+
+        second = evemu.base.LibEvemu._load()
+        self.assertNotEqual(second, None)
+
+        self.assertEqual(first, second)
+
+    def test_libevemu_static_in_object(self):
+        first = evemu.base.LibEvemu()
+        self.assertNotEqual(first, None)
+
+        second = evemu.base.LibEvemu()
+        self.assertNotEqual(second, None)
+
+        self.assertEqual(first._loaded_lib, second._loaded_lib)
+
 if __name__ == "__main__":
     unittest.main()
-- 
1.8.5.2



More information about the Input-tools mailing list