From 50f038bff27b8e4ae25181d60ca841512d43e6c7 Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Sun, 19 Jan 2025 12:28:03 +0100 Subject: [PATCH 1/4] Refactor character device verification --- evdev/uinput.py | 22 ++++++++++++++-------- tests/test_uinput.py | 19 ++++++++++++++++--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/evdev/uinput.py b/evdev/uinput.py index 756f83c..d69bb30 100644 --- a/evdev/uinput.py +++ b/evdev/uinput.py @@ -268,14 +268,7 @@ def _verify(self): Verify that an uinput device exists and is readable and writable by the current process. """ - - try: - m = os.stat(self.devnode)[stat.ST_MODE] - if not stat.S_ISCHR(m): - raise OSError - except (IndexError, OSError): - msg = '"{}" does not exist or is not a character device file ' "- verify that the uinput module is loaded" - raise UInputError(msg.format(self.devnode)) + self._verify_character_device() if not os.access(self.devnode, os.W_OK): msg = '"{}" cannot be opened for writing' @@ -285,6 +278,19 @@ def _verify(self): msg = "uinput device name must not be longer than {} characters" raise UInputError(msg.format(_uinput.maxnamelen)) + def _verify_character_device(self): + try: + mode = os.stat(self.devnode)[stat.ST_MODE] + if stat.S_ISCHR(mode): + return + except (IndexError, OSError): + pass + + raise UInputError( + f'"{self.devnode}" does not exist or is not a character device file ' + "- verify that the uinput module is loaded" + ) + def _find_device(self, fd): """ Tries to find the device node. Will delegate this task to one of diff --git a/tests/test_uinput.py b/tests/test_uinput.py index dcd09e0..d2607ce 100644 --- a/tests/test_uinput.py +++ b/tests/test_uinput.py @@ -1,7 +1,8 @@ # encoding: utf-8 +import os import stat from select import select -from unittest.mock import patch +from unittest.mock import patch, MagicMock import pytest from pytest import raises, fixture @@ -119,6 +120,18 @@ def test_write(c): @patch.object(stat, 'S_ISCHR', return_value=False) -def test_not_a_character_device(c): - with pytest.raises(UInputError): +def test_not_a_character_device(ischr_mock, c): + with pytest.raises(UInputError, match='not a character device file'): + uinput.UInput(**c) + +@patch.object(stat, 'S_ISCHR', return_value=True) +@patch.object(os, 'stat', side_effect=OSError()) +def test_not_a_character_device_2(stat_mock, ischr_mock, c): + with pytest.raises(UInputError, match='not a character device file'): + uinput.UInput(**c) + +@patch.object(stat, 'S_ISCHR', return_value=True) +@patch.object(os, 'stat', return_value=[]) +def test_not_a_character_device_3(stat_mock, ischr_mock, c): + with pytest.raises(UInputError, match='not a character device file'): uinput.UInput(**c) From 3256cb49c9fc5b6e351b035e5ecdc36ec2c5ea1b Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Sun, 19 Jan 2025 12:34:04 +0100 Subject: [PATCH 2/4] unused import --- tests/test_uinput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_uinput.py b/tests/test_uinput.py index d2607ce..666361f 100644 --- a/tests/test_uinput.py +++ b/tests/test_uinput.py @@ -2,7 +2,7 @@ import os import stat from select import select -from unittest.mock import patch, MagicMock +from unittest.mock import patch import pytest from pytest import raises, fixture From 6d3b590fc8fa64dfe1e91ca6b4d1d8e6677a3869 Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Sun, 19 Jan 2025 12:39:27 +0100 Subject: [PATCH 3/4] assert instead --- evdev/uinput.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/evdev/uinput.py b/evdev/uinput.py index d69bb30..26648c0 100644 --- a/evdev/uinput.py +++ b/evdev/uinput.py @@ -268,7 +268,12 @@ def _verify(self): Verify that an uinput device exists and is readable and writable by the current process. """ - self._verify_character_device() + try: + m = os.stat(self.devnode)[stat.ST_MODE] + assert stat.S_ISCHR(m) + except (IndexError, OSError, AssertionError): + msg = '"{}" does not exist or is not a character device file ' "- verify that the uinput module is loaded" + raise UInputError(msg.format(self.devnode)) if not os.access(self.devnode, os.W_OK): msg = '"{}" cannot be opened for writing' @@ -278,19 +283,6 @@ def _verify(self): msg = "uinput device name must not be longer than {} characters" raise UInputError(msg.format(_uinput.maxnamelen)) - def _verify_character_device(self): - try: - mode = os.stat(self.devnode)[stat.ST_MODE] - if stat.S_ISCHR(mode): - return - except (IndexError, OSError): - pass - - raise UInputError( - f'"{self.devnode}" does not exist or is not a character device file ' - "- verify that the uinput module is loaded" - ) - def _find_device(self, fd): """ Tries to find the device node. Will delegate this task to one of From d56ddd4ba88d15cf63330d0e1da27cb775cc58e3 Mon Sep 17 00:00:00 2001 From: sezanzeb <28510156+sezanzeb@users.noreply.github.com> Date: Sun, 19 Jan 2025 12:43:50 +0100 Subject: [PATCH 4/4] string stuff --- evdev/uinput.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evdev/uinput.py b/evdev/uinput.py index 26648c0..2c6b980 100644 --- a/evdev/uinput.py +++ b/evdev/uinput.py @@ -272,7 +272,7 @@ def _verify(self): m = os.stat(self.devnode)[stat.ST_MODE] assert stat.S_ISCHR(m) except (IndexError, OSError, AssertionError): - msg = '"{}" does not exist or is not a character device file ' "- verify that the uinput module is loaded" + msg = '"{}" does not exist or is not a character device file - verify that the uinput module is loaded' raise UInputError(msg.format(self.devnode)) if not os.access(self.devnode, os.W_OK):