[PATCH evemu 16/19] py: Add and use wrapper for libc calls

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 6 15:53:57 PST 2014


On Mon, Jan 06, 2014 at 06:38:16PM +0100, Daniel Martin wrote:
> Introduce a class LibC in base.py, which wraps fdopen and fflush, and
> replace _call0()s to fdopen and fflush in __init__.py.
> 
> Signed-off-by: Daniel Martin <consume.noise at gmail.com>
> ---
>  python/evemu/__init__.py        | 21 +++++++--------------
>  python/evemu/base.py            | 34 +++++++++++++++++++++++-----------
>  python/evemu/tests/test_base.py | 16 ++++++++++------
>  3 files changed, 40 insertions(+), 31 deletions(-)
> 
> diff --git a/python/evemu/__init__.py b/python/evemu/__init__.py
> index f07a8ca..521652b 100644
> --- a/python/evemu/__init__.py
> +++ b/python/evemu/__init__.py
> @@ -54,6 +54,7 @@ class Device(object):
>  
>          self._is_propfile = self._check_is_propfile(self._file)
>          self._evemu = evemu.base.EvEmuBase()
> +        self._libc = evemu.base.LibC()
>          self._uinput = None
>  
>          libevemu_new = self._evemu.get_lib().evemu_new
> @@ -61,9 +62,7 @@ class Device(object):
>          self._evemu_device = libevemu_new("")
>  
>          if self._is_propfile:
> -            fs = self._evemu._call0(self._evemu.get_c_lib().fdopen,
> -                                    self._file.fileno(),
> -                                    'r')
> +            fs = self._libc.fdopen(self._file.fileno(), b"r")
>              self._evemu._call(self._evemu.get_lib().evemu_read,
>                                self._evemu_device,
>                                fs)
> @@ -129,13 +128,11 @@ class Device(object):
>          if not hasattr(prop_file, "read"):
>              raise TypeError("expected file")
>  
> -        fs = self._evemu._call0(self._evemu.get_c_lib().fdopen,
> -                                prop_file.fileno(),
> -                                "w")
> +        fs = self._libc.fdopen(prop_file.fileno(), b"w")
>          self._evemu._call(self._evemu.get_lib().evemu_write,
>                            self._evemu_device,
>                            fs)
> -        self._evemu.get_c_lib().fflush(fs)
> +        self._libc.fflush(fs)
>  
>      def play(self, events_file):
>          """
> @@ -148,9 +145,7 @@ class Device(object):
>          if not hasattr(events_file, "read"):
>              raise TypeError("expected file")
>  
> -        fs = self._evemu._call0(self._evemu.get_c_lib().fdopen,
> -                                events_file.fileno(),
> -                                "r")
> +        fs = self._libc.fdopen(events_file.fileno(), b"r")
>          self._evemu._call(self._evemu.get_lib().evemu_play,
>                            fs,
>                            self._file.fileno())
> @@ -167,14 +162,12 @@ class Device(object):
>          if not hasattr(events_file, "read"):
>              raise TypeError("expected file")
>  
> -        fs = self._evemu._call0(self._evemu.get_c_lib().fdopen,
> -                                events_file.fileno(),
> -                                "w")
> +        fs = self._libc.fdopen(events_file.fileno(), b"w")
>          self._evemu._call(self._evemu.get_lib().evemu_record,
>                            fs,
>                            self._file.fileno(),
>                            timeout)
> -        self._evemu.get_c_lib().fflush(fs)
> +        self._libc.fflush(fs)
>  
>      @property
>      def version(self):
> diff --git a/python/evemu/base.py b/python/evemu/base.py
> index 3a9de8d..5f514f3 100644
> --- a/python/evemu/base.py
> +++ b/python/evemu/base.py
> @@ -134,20 +134,35 @@ class LibraryWrapper(object):
>          raise NotImplementedError
>  
>  
> +class LibC(LibraryWrapper):
> +    """
> +    Wrapper for API calls to the C library.
> +    """
> +
> +    @staticmethod
> +    def _cdll():
> +        return ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
> +
> +    _api_prototypes = {
> +        "fdopen": {
> +            "argtypes": (c_int, c_char_p),
> +            "restype": c_void_p,
> +            "errcheck": expect_not_none
> +            },
> +        "fflush": {
> +            "argtypes": (c_void_p,),
> +            "restype": c_int,
> +            "errcheck": expect_eq_zero
> +            },
> +        }
> +
> +
>  class EvEmuBase(object):
>      """
>      A base wrapper class for the evemu functions, accessed via ctypes.
>      """
>      def __init__(self):
>          self._lib = ctypes.CDLL(evemu.const.LIB, use_errno=True)
> -        self._libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
> -
> -    def _call0(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 _call(self, api_call, *parameters):
>          result = api_call(*parameters)
> @@ -169,8 +184,5 @@ class EvEmuBase(object):
>      def get_c_error(self):
>          return os.strerror(ctypes.get_errno())
>  
> -    def get_c_lib(self):
> -        return self._libc
> -
>      def get_lib(self):
>          return self._lib
> diff --git a/python/evemu/tests/test_base.py b/python/evemu/tests/test_base.py
> index 60a05f9..9064d42 100644
> --- a/python/evemu/tests/test_base.py
> +++ b/python/evemu/tests/test_base.py
> @@ -13,13 +13,17 @@ class EvEmuBaseTestCase(evemu.testing.testcase.BaseTestCase):
>          self.assertNotEqual(
>              wrapper._lib._name.find("libevemu"), -1)
>  
> -    def test_c_symbols_found(self):
> -        # Make sure that the expected functions are present
> -        wrapper = evemu.base.EvEmuBase()
> -        for function_name in evemu.const.API:
> -            function = getattr(wrapper._lib, function_name)
> -            self.assertTrue(function is not None)
> +    def test_libc_found(self):
> +        lib = evemu.base.LibC._load()
> +        self.assertNotEqual(lib, None)
> +        self.assertTrue(lib._name.startswith("libc"))
>  
> +    def test_libc_symbols_found(self):
> +        lib = evemu.base.LibC._load()
> +        for func_name in evemu.base.LibC._api_prototypes.keys():
> +            func = getattr(lib, func_name)
> +            self.assertNotEqual(func, None)
> +            self.assertEqual(func.__name__, func_name)

these two look like they can be integrated into the LibraryWrapper so that we
fail if we can't find the required symbols. it may already do that anyway, I
suspect getattr() will fail on the library for undefined functions so you
can probably drop this bit.

Cheers,
   Peter

>  
>  if __name__ == "__main__":
>      unittest.main()
> -- 
> 1.8.5.2
> 
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list