Skip to content

Commit b1a5bd1

Browse files
authored
Add pylint -E and pytest to ci (#228)
* Remove EOL python 3.7 from the ci * Add pylint -E, fix some pylint errors * Add pytest step * Fix test_abs_values * Turned RuntimeError into the desired UInputError if the device is not a character device, caused by a re-raise outside an except block * Add test for S_ISCHR False
1 parent d182b7f commit b1a5bd1

File tree

8 files changed

+88
-21
lines changed

8 files changed

+88
-21
lines changed

.github/workflows/install.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
fail-fast: false
1212
matrix:
1313
os: [ubuntu-latest]
14-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
14+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
1515
include:
1616
- os: ubuntu-latest
17-
python-version: "3.7"
17+
python-version: "3.8"
1818

1919
steps:
2020
- uses: actions/checkout@v4

.github/workflows/lint.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Lint
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
jobs:
8+
pylint:
9+
runs-on: ${{ matrix.os }}
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
os: [ubuntu-latest]
14+
python-version: ["3.12"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python ${{ matrix.python-version }}
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
23+
- name: Check for pylint errors
24+
run: |
25+
python -m pip install pylint setuptools
26+
python setup.py build
27+
python -m pylint --disable=no-member --verbose -E build/lib*/evdev

.github/workflows/test.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Test
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
jobs:
8+
test:
9+
runs-on: ${{ matrix.os }}
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
os: [ubuntu-latest]
14+
python-version: ["3.12"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python ${{ matrix.python-version }}
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
23+
- name: Run pytest tests
24+
# pip install -e . builds _ecodes and such into the evdev directory
25+
# sudo required to write to uinputs
26+
run: |
27+
sudo python -m pip install pytest setuptools
28+
sudo python -m pip install -e .
29+
sudo python -m pytest tests

evdev/ecodes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# pylint: disable=undefined-variable
12
"""
23
This modules exposes the integer constants defined in ``linux/input.h`` and
34
``linux/input-event-codes.h``.

evdev/eventio.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def read(self):
7272
for event in events:
7373
yield InputEvent(*event)
7474

75+
# pylint: disable=no-self-argument
7576
def need_write(func):
7677
"""
7778
Decorator that raises :class:`EvdevError` if there is no write access to the
@@ -82,6 +83,7 @@ def need_write(func):
8283
def wrapper(*args):
8384
fd = args[0].fd
8485
if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR:
86+
# pylint: disable=not-callable
8587
return func(*args)
8688
msg = 'no write access to device "%s"' % args[0].path
8789
raise EvdevError(msg)

evdev/events.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ def timestamp(self):
6565
"""Return event timestamp as a float."""
6666
return self.sec + (self.usec / 1000000.0)
6767

68-
def __str__(s):
68+
def __str__(self):
6969
msg = "event at {:f}, code {:02d}, type {:02d}, val {:02d}"
70-
return msg.format(s.timestamp(), s.code, s.type, s.value)
70+
return msg.format(self.timestamp(), self.code, self.type, self.value)
7171

72-
def __repr__(s):
72+
def __repr__(self):
7373
msg = "{}({!r}, {!r}, {!r}, {!r}, {!r})"
74-
return msg.format(s.__class__.__name__, s.sec, s.usec, s.type, s.code, s.value)
74+
return msg.format(self.__class__.__name__, self.sec, self.usec, self.type, self.code, self.value)
7575

7676

7777
class KeyEvent:
@@ -119,8 +119,8 @@ def __str__(self):
119119
msg = "key event at {:f}, {} ({}), {}"
120120
return msg.format(self.event.timestamp(), self.scancode, self.keycode, ks)
121121

122-
def __repr__(s):
123-
return "{}({!r})".format(s.__class__.__name__, s.event)
122+
def __repr__(self):
123+
return "{}({!r})".format(self.__class__.__name__, self.event)
124124

125125

126126
class RelEvent:
@@ -136,8 +136,8 @@ def __str__(self):
136136
msg = "relative axis event at {:f}, {}"
137137
return msg.format(self.event.timestamp(), REL[self.event.code])
138138

139-
def __repr__(s):
140-
return "{}({!r})".format(s.__class__.__name__, s.event)
139+
def __repr__(self):
140+
return "{}({!r})".format(self.__class__.__name__, self.event)
141141

142142

143143
class AbsEvent:
@@ -153,8 +153,8 @@ def __str__(self):
153153
msg = "absolute axis event at {:f}, {}"
154154
return msg.format(self.event.timestamp(), ABS[self.event.code])
155155

156-
def __repr__(s):
157-
return "{}({!r})".format(s.__class__.__name__, s.event)
156+
def __repr__(self):
157+
return "{}({!r})".format(self.__class__.__name__, self.event)
158158

159159

160160
class SynEvent:
@@ -173,8 +173,8 @@ def __str__(self):
173173
msg = "synchronization event at {:f}, {}"
174174
return msg.format(self.event.timestamp(), SYN[self.event.code])
175175

176-
def __repr__(s):
177-
return "{}({!r})".format(s.__class__.__name__, s.event)
176+
def __repr__(self):
177+
return "{}({!r})".format(self.__class__.__name__, self.event)
178178

179179

180180
#: A mapping of event types to :class:`InputEvent` sub-classes. Used

evdev/uinput.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def _verify(self):
272272
try:
273273
m = os.stat(self.devnode)[stat.ST_MODE]
274274
if not stat.S_ISCHR(m):
275-
raise
275+
raise OSError
276276
except (IndexError, OSError):
277277
msg = '"{}" does not exist or is not a character device file ' "- verify that the uinput module is loaded"
278278
raise UInputError(msg.format(self.devnode))

tests/test_uinput.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# encoding: utf-8
2-
2+
import stat
33
from select import select
4-
from pytest import raises, fixture
4+
from unittest.mock import patch
55

6-
from evdev import uinput, ecodes, events, device, util
6+
import pytest
7+
from pytest import raises, fixture
78

9+
from evdev import uinput, ecodes, device, UInputError
810

911
# -----------------------------------------------------------------------------
1012
uinput_options = {
@@ -66,12 +68,12 @@ def test_enable_events(c):
6668

6769
def test_abs_values(c):
6870
e = ecodes
69-
c["events"] = {
71+
c = {
7072
e.EV_KEY: [e.KEY_A, e.KEY_B],
71-
e.EV_ABS: [(e.ABS_X, (0, 255, 0, 0)), (e.ABS_Y, device.AbsInfo(0, 255, 5, 10, 0, 0))],
73+
e.EV_ABS: [(e.ABS_X, (0, 0, 255, 0, 0)), (e.ABS_Y, device.AbsInfo(0, 0, 255, 5, 10, 0))],
7274
}
7375

74-
with uinput.UInput(**c) as ui:
76+
with uinput.UInput(events=c) as ui:
7577
c = ui.capabilities()
7678
abs = device.AbsInfo(value=0, min=0, max=255, fuzz=0, flat=0, resolution=0)
7779
assert c[e.EV_ABS][0] == (0, abs)
@@ -114,3 +116,9 @@ def test_write(c):
114116
assert evs[3].code == ecodes.KEY_A and evs[3].value == 2
115117
assert evs[4].code == ecodes.KEY_A and evs[4].value == 0
116118
break
119+
120+
121+
@patch.object(stat, 'S_ISCHR', return_value=False)
122+
def test_not_a_character_device(c):
123+
with pytest.raises(UInputError):
124+
uinput.UInput(**c)

0 commit comments

Comments
 (0)