evdev 1.9.0__tar.gz → 1.9.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {evdev-1.9.0/src/evdev.egg-info → evdev-1.9.2}/PKG-INFO +3 -2
- {evdev-1.9.0 → evdev-1.9.2}/pyproject.toml +2 -2
- {evdev-1.9.0 → evdev-1.9.2}/setup.py +10 -3
- evdev-1.9.2/src/evdev/__init__.py +39 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/device.py +24 -16
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/ecodes_runtime.py +1 -1
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/eventio_async.py +47 -40
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/genecodes_c.py +11 -6
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/genecodes_py.py +2 -1
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/util.py +2 -2
- {evdev-1.9.0 → evdev-1.9.2/src/evdev.egg-info}/PKG-INFO +3 -2
- {evdev-1.9.0 → evdev-1.9.2}/tests/test_ecodes.py +13 -3
- evdev-1.9.0/src/evdev/__init__.py +0 -9
- {evdev-1.9.0 → evdev-1.9.2}/LICENSE +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/MANIFEST.in +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/README.md +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/setup.cfg +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/ecodes.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/eventio.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/events.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/evtest.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/ff.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/input.c +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/py.typed +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/uinput.c +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev/uinput.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev.egg-info/SOURCES.txt +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev.egg-info/dependency_links.txt +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/src/evdev.egg-info/top_level.txt +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/tests/test_events.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/tests/test_uinput.py +0 -0
- {evdev-1.9.0 → evdev-1.9.2}/tests/test_util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: evdev
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
4
4
|
Summary: Bindings to the Linux input handling subsystem
|
|
5
5
|
Author-email: Georgi Valkov <georgi.t.valkov@gmail.com>
|
|
6
6
|
Maintainer-email: Tobi <proxima@sezanzeb.de>
|
|
@@ -46,6 +46,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
46
46
|
Requires-Python: >=3.8
|
|
47
47
|
Description-Content-Type: text/markdown
|
|
48
48
|
License-File: LICENSE
|
|
49
|
+
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|
# evdev
|
|
51
52
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "evdev"
|
|
7
|
-
version = "1.9.
|
|
7
|
+
version = "1.9.2"
|
|
8
8
|
description = "Bindings to the Linux input handling subsystem"
|
|
9
9
|
keywords = ["evdev", "input", "uinput"]
|
|
10
10
|
readme = "README.md"
|
|
@@ -36,7 +36,7 @@ line-length = 120
|
|
|
36
36
|
ignore = ["E265", "E241", "F403", "F401", "E401", "E731"]
|
|
37
37
|
|
|
38
38
|
[tool.bumpversion]
|
|
39
|
-
current_version = "1.9.
|
|
39
|
+
current_version = "1.9.2"
|
|
40
40
|
commit = true
|
|
41
41
|
tag = true
|
|
42
42
|
allow_dirty = true
|
|
@@ -14,7 +14,7 @@ curdir = Path(__file__).resolve().parent
|
|
|
14
14
|
ecodes_c_path = curdir / "src/evdev/ecodes.c"
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def create_ecodes(headers=None):
|
|
17
|
+
def create_ecodes(headers=None, reproducible=False):
|
|
18
18
|
if not headers:
|
|
19
19
|
include_paths = set()
|
|
20
20
|
cpath = os.environ.get("CPATH", "").strip()
|
|
@@ -65,7 +65,10 @@ def create_ecodes(headers=None):
|
|
|
65
65
|
|
|
66
66
|
print("writing %s (using %s)" % (ecodes_c_path, " ".join(headers)))
|
|
67
67
|
with ecodes_c_path.open("w") as fh:
|
|
68
|
-
cmd = [sys.executable, "src/evdev/genecodes_c.py"
|
|
68
|
+
cmd = [sys.executable, "src/evdev/genecodes_c.py"]
|
|
69
|
+
if reproducible:
|
|
70
|
+
cmd.append("--reproducible")
|
|
71
|
+
cmd.extend(["--ecodes", *headers])
|
|
69
72
|
run(cmd, check=True, stdout=fh)
|
|
70
73
|
|
|
71
74
|
|
|
@@ -74,17 +77,21 @@ class build_ecodes(Command):
|
|
|
74
77
|
|
|
75
78
|
user_options = [
|
|
76
79
|
("evdev-headers=", None, "colon-separated paths to input subsystem headers"),
|
|
80
|
+
("reproducible", None, "hide host details (host/paths) to create a reproducible output"),
|
|
77
81
|
]
|
|
78
82
|
|
|
79
83
|
def initialize_options(self):
|
|
80
84
|
self.evdev_headers = None
|
|
85
|
+
self.reproducible = False
|
|
81
86
|
|
|
82
87
|
def finalize_options(self):
|
|
83
88
|
if self.evdev_headers:
|
|
84
89
|
self.evdev_headers = self.evdev_headers.split(":")
|
|
90
|
+
if self.reproducible is None:
|
|
91
|
+
self.reproducible = False
|
|
85
92
|
|
|
86
93
|
def run(self):
|
|
87
|
-
create_ecodes(self.evdev_headers)
|
|
94
|
+
create_ecodes(self.evdev_headers, reproducible=self.reproducible)
|
|
88
95
|
|
|
89
96
|
|
|
90
97
|
class build_ext(_build_ext.build_ext):
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# Gather everything into a single, convenient namespace.
|
|
3
|
+
# --------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
# The superfluous "import name as name" syntax is here to satisfy mypy's attrs-defined rule.
|
|
6
|
+
# Alternatively all exported objects can be listed in __all__.
|
|
7
|
+
|
|
8
|
+
from . import (
|
|
9
|
+
ecodes as ecodes,
|
|
10
|
+
ff as ff,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .device import (
|
|
14
|
+
AbsInfo as AbsInfo,
|
|
15
|
+
DeviceInfo as DeviceInfo,
|
|
16
|
+
EvdevError as EvdevError,
|
|
17
|
+
InputDevice as InputDevice,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .events import (
|
|
21
|
+
AbsEvent as AbsEvent,
|
|
22
|
+
InputEvent as InputEvent,
|
|
23
|
+
KeyEvent as KeyEvent,
|
|
24
|
+
RelEvent as RelEvent,
|
|
25
|
+
SynEvent as SynEvent,
|
|
26
|
+
event_factory as event_factory,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from .uinput import (
|
|
30
|
+
UInput as UInput,
|
|
31
|
+
UInputError as UInputError,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
from .util import (
|
|
35
|
+
categorize as categorize,
|
|
36
|
+
list_devices as list_devices,
|
|
37
|
+
resolve_ecodes as resolve_ecodes,
|
|
38
|
+
resolve_ecodes_dict as resolve_ecodes_dict,
|
|
39
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
import os
|
|
3
|
-
from typing import NamedTuple, Tuple, Union
|
|
3
|
+
from typing import Dict, Generic, Iterator, List, Literal, NamedTuple, Tuple, TypeVar, Union, overload
|
|
4
4
|
|
|
5
5
|
from . import _input, ecodes, util
|
|
6
6
|
|
|
@@ -9,6 +9,8 @@ try:
|
|
|
9
9
|
except ImportError:
|
|
10
10
|
from .eventio import EvdevError, EventIO
|
|
11
11
|
|
|
12
|
+
_AnyStr = TypeVar("_AnyStr", str, bytes)
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
class AbsInfo(NamedTuple):
|
|
14
16
|
"""Absolute axis information.
|
|
@@ -95,19 +97,19 @@ class DeviceInfo(NamedTuple):
|
|
|
95
97
|
product: int
|
|
96
98
|
version: int
|
|
97
99
|
|
|
98
|
-
def __str__(self):
|
|
100
|
+
def __str__(self) -> str:
|
|
99
101
|
msg = "bus: {:04x}, vendor {:04x}, product {:04x}, version {:04x}"
|
|
100
102
|
return msg.format(*self) # pylint: disable=not-an-iterable
|
|
101
103
|
|
|
102
104
|
|
|
103
|
-
class InputDevice(EventIO):
|
|
105
|
+
class InputDevice(EventIO, Generic[_AnyStr]):
|
|
104
106
|
"""
|
|
105
107
|
A linux input device from which input events can be read.
|
|
106
108
|
"""
|
|
107
109
|
|
|
108
110
|
__slots__ = ("path", "fd", "info", "name", "phys", "uniq", "_rawcapabilities", "version", "ff_effects_count")
|
|
109
111
|
|
|
110
|
-
def __init__(self, dev: Union[
|
|
112
|
+
def __init__(self, dev: Union[_AnyStr, "os.PathLike[_AnyStr]"]):
|
|
111
113
|
"""
|
|
112
114
|
Arguments
|
|
113
115
|
---------
|
|
@@ -116,7 +118,7 @@ class InputDevice(EventIO):
|
|
|
116
118
|
"""
|
|
117
119
|
|
|
118
120
|
#: Path to input device.
|
|
119
|
-
self.path = dev if not hasattr(dev, "__fspath__") else dev.__fspath__()
|
|
121
|
+
self.path: _AnyStr = dev if not hasattr(dev, "__fspath__") else dev.__fspath__()
|
|
120
122
|
|
|
121
123
|
# Certain operations are possible only when the device is opened in read-write mode.
|
|
122
124
|
try:
|
|
@@ -151,7 +153,7 @@ class InputDevice(EventIO):
|
|
|
151
153
|
#: The number of force feedback effects the device can keep in its memory.
|
|
152
154
|
self.ff_effects_count = _input.ioctl_EVIOCGEFFECTS(self.fd)
|
|
153
155
|
|
|
154
|
-
def __del__(self):
|
|
156
|
+
def __del__(self) -> None:
|
|
155
157
|
if hasattr(self, "fd") and self.fd is not None:
|
|
156
158
|
try:
|
|
157
159
|
self.close()
|
|
@@ -176,7 +178,13 @@ class InputDevice(EventIO):
|
|
|
176
178
|
|
|
177
179
|
return res
|
|
178
180
|
|
|
179
|
-
|
|
181
|
+
@overload
|
|
182
|
+
def capabilities(self, verbose: Literal[False] = ..., absinfo: bool = ...) -> Dict[int, List[int]]:
|
|
183
|
+
...
|
|
184
|
+
@overload
|
|
185
|
+
def capabilities(self, verbose: Literal[True], absinfo: bool = ...) -> Dict[Tuple[str, int], List[Tuple[str, int]]]:
|
|
186
|
+
...
|
|
187
|
+
def capabilities(self, verbose: bool = False, absinfo: bool = True) -> Union[Dict[int, List[int]], Dict[Tuple[str, int], List[Tuple[str, int]]]]:
|
|
180
188
|
"""
|
|
181
189
|
Return the event types that this device supports as a mapping of
|
|
182
190
|
supported event types to lists of handled event codes.
|
|
@@ -263,7 +271,7 @@ class InputDevice(EventIO):
|
|
|
263
271
|
|
|
264
272
|
return leds
|
|
265
273
|
|
|
266
|
-
def set_led(self, led_num: int, value: int):
|
|
274
|
+
def set_led(self, led_num: int, value: int) -> None:
|
|
267
275
|
"""
|
|
268
276
|
Set the state of the selected LED.
|
|
269
277
|
|
|
@@ -279,18 +287,18 @@ class InputDevice(EventIO):
|
|
|
279
287
|
"""
|
|
280
288
|
return isinstance(other, self.__class__) and self.info == other.info and self.path == other.path
|
|
281
289
|
|
|
282
|
-
def __str__(self):
|
|
290
|
+
def __str__(self) -> str:
|
|
283
291
|
msg = 'device {}, name "{}", phys "{}", uniq "{}"'
|
|
284
292
|
return msg.format(self.path, self.name, self.phys, self.uniq or "")
|
|
285
293
|
|
|
286
|
-
def __repr__(self):
|
|
294
|
+
def __repr__(self) -> str:
|
|
287
295
|
msg = (self.__class__.__name__, self.path)
|
|
288
296
|
return "{}({!r})".format(*msg)
|
|
289
297
|
|
|
290
298
|
def __fspath__(self):
|
|
291
299
|
return self.path
|
|
292
300
|
|
|
293
|
-
def close(self):
|
|
301
|
+
def close(self) -> None:
|
|
294
302
|
if self.fd > -1:
|
|
295
303
|
try:
|
|
296
304
|
super().close()
|
|
@@ -298,7 +306,7 @@ class InputDevice(EventIO):
|
|
|
298
306
|
finally:
|
|
299
307
|
self.fd = -1
|
|
300
308
|
|
|
301
|
-
def grab(self):
|
|
309
|
+
def grab(self) -> None:
|
|
302
310
|
"""
|
|
303
311
|
Grab input device using ``EVIOCGRAB`` - other applications will
|
|
304
312
|
be unable to receive events until the device is released. Only
|
|
@@ -311,7 +319,7 @@ class InputDevice(EventIO):
|
|
|
311
319
|
|
|
312
320
|
_input.ioctl_EVIOCGRAB(self.fd, 1)
|
|
313
321
|
|
|
314
|
-
def ungrab(self):
|
|
322
|
+
def ungrab(self) -> None:
|
|
315
323
|
"""
|
|
316
324
|
Release device if it has been already grabbed (uses `EVIOCGRAB`).
|
|
317
325
|
|
|
@@ -324,7 +332,7 @@ class InputDevice(EventIO):
|
|
|
324
332
|
_input.ioctl_EVIOCGRAB(self.fd, 0)
|
|
325
333
|
|
|
326
334
|
@contextlib.contextmanager
|
|
327
|
-
def grab_context(self):
|
|
335
|
+
def grab_context(self) -> Iterator[None]:
|
|
328
336
|
"""
|
|
329
337
|
A context manager for the duration of which only the current
|
|
330
338
|
process will be able to receive events from the device.
|
|
@@ -342,7 +350,7 @@ class InputDevice(EventIO):
|
|
|
342
350
|
ff_id = _input.upload_effect(self.fd, data)
|
|
343
351
|
return ff_id
|
|
344
352
|
|
|
345
|
-
def erase_effect(self, ff_id):
|
|
353
|
+
def erase_effect(self, ff_id) -> None:
|
|
346
354
|
"""
|
|
347
355
|
Erase a force effect from a force feedback device. This also
|
|
348
356
|
stops the effect.
|
|
@@ -402,7 +410,7 @@ class InputDevice(EventIO):
|
|
|
402
410
|
"""
|
|
403
411
|
return AbsInfo(*_input.ioctl_EVIOCGABS(self.fd, axis_num))
|
|
404
412
|
|
|
405
|
-
def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None):
|
|
413
|
+
def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None) -> None:
|
|
406
414
|
"""
|
|
407
415
|
Update :class:`AbsInfo` values. Only specified values will be overwritten.
|
|
408
416
|
|
|
@@ -46,7 +46,7 @@ from . import _ecodes
|
|
|
46
46
|
#: Mapping of names to values.
|
|
47
47
|
ecodes = {}
|
|
48
48
|
|
|
49
|
-
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP".split()
|
|
49
|
+
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP UI_FF".split()
|
|
50
50
|
prev_prefix = ""
|
|
51
51
|
g = globals()
|
|
52
52
|
|
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import select
|
|
3
|
+
import sys
|
|
3
4
|
|
|
4
5
|
from . import eventio
|
|
6
|
+
from .events import InputEvent
|
|
5
7
|
|
|
6
8
|
# needed for compatibility
|
|
7
9
|
from .eventio import EvdevError
|
|
8
10
|
|
|
11
|
+
if sys.version_info >= (3, 11):
|
|
12
|
+
from typing import Self
|
|
13
|
+
else:
|
|
14
|
+
from typing import Any as Self
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ReadIterator:
|
|
18
|
+
def __init__(self, device):
|
|
19
|
+
self.current_batch = iter(())
|
|
20
|
+
self.device = device
|
|
21
|
+
|
|
22
|
+
# Standard iterator protocol.
|
|
23
|
+
def __iter__(self) -> Self:
|
|
24
|
+
return self
|
|
25
|
+
|
|
26
|
+
def __next__(self) -> InputEvent:
|
|
27
|
+
try:
|
|
28
|
+
# Read from the previous batch of events.
|
|
29
|
+
return next(self.current_batch)
|
|
30
|
+
except StopIteration:
|
|
31
|
+
r, w, x = select.select([self.device.fd], [], [])
|
|
32
|
+
self.current_batch = self.device.read()
|
|
33
|
+
return next(self.current_batch)
|
|
34
|
+
|
|
35
|
+
def __aiter__(self) -> Self:
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
def __anext__(self) -> "asyncio.Future[InputEvent]":
|
|
39
|
+
future = asyncio.Future()
|
|
40
|
+
try:
|
|
41
|
+
# Read from the previous batch of events.
|
|
42
|
+
future.set_result(next(self.current_batch))
|
|
43
|
+
except StopIteration:
|
|
44
|
+
|
|
45
|
+
def next_batch_ready(batch):
|
|
46
|
+
try:
|
|
47
|
+
self.current_batch = batch.result()
|
|
48
|
+
future.set_result(next(self.current_batch))
|
|
49
|
+
except Exception as e:
|
|
50
|
+
future.set_exception(e)
|
|
51
|
+
|
|
52
|
+
self.device.async_read().add_done_callback(next_batch_ready)
|
|
53
|
+
return future
|
|
54
|
+
|
|
9
55
|
|
|
10
56
|
class EventIO(eventio.EventIO):
|
|
11
57
|
def _do_when_readable(self, callback):
|
|
@@ -42,7 +88,7 @@ class EventIO(eventio.EventIO):
|
|
|
42
88
|
self._do_when_readable(lambda: self._set_result(future, self.read))
|
|
43
89
|
return future
|
|
44
90
|
|
|
45
|
-
def async_read_loop(self):
|
|
91
|
+
def async_read_loop(self) -> ReadIterator:
|
|
46
92
|
"""
|
|
47
93
|
Return an iterator that yields input events. This iterator is
|
|
48
94
|
compatible with the ``async for`` syntax.
|
|
@@ -58,42 +104,3 @@ class EventIO(eventio.EventIO):
|
|
|
58
104
|
# no event loop present, so there is nothing to
|
|
59
105
|
# remove the reader from. Ignore
|
|
60
106
|
pass
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class ReadIterator:
|
|
64
|
-
def __init__(self, device):
|
|
65
|
-
self.current_batch = iter(())
|
|
66
|
-
self.device = device
|
|
67
|
-
|
|
68
|
-
# Standard iterator protocol.
|
|
69
|
-
def __iter__(self):
|
|
70
|
-
return self
|
|
71
|
-
|
|
72
|
-
def __next__(self):
|
|
73
|
-
try:
|
|
74
|
-
# Read from the previous batch of events.
|
|
75
|
-
return next(self.current_batch)
|
|
76
|
-
except StopIteration:
|
|
77
|
-
r, w, x = select.select([self.device.fd], [], [])
|
|
78
|
-
self.current_batch = self.device.read()
|
|
79
|
-
return next(self.current_batch)
|
|
80
|
-
|
|
81
|
-
def __aiter__(self):
|
|
82
|
-
return self
|
|
83
|
-
|
|
84
|
-
def __anext__(self):
|
|
85
|
-
future = asyncio.Future()
|
|
86
|
-
try:
|
|
87
|
-
# Read from the previous batch of events.
|
|
88
|
-
future.set_result(next(self.current_batch))
|
|
89
|
-
except StopIteration:
|
|
90
|
-
|
|
91
|
-
def next_batch_ready(batch):
|
|
92
|
-
try:
|
|
93
|
-
self.current_batch = batch.result()
|
|
94
|
-
future.set_result(next(self.current_batch))
|
|
95
|
-
except Exception as e:
|
|
96
|
-
future.set_exception(e)
|
|
97
|
-
|
|
98
|
-
self.device.async_read().add_done_callback(next_batch_ready)
|
|
99
|
-
return future
|
|
@@ -15,22 +15,27 @@ headers = [
|
|
|
15
15
|
"/usr/include/linux/uinput.h",
|
|
16
16
|
]
|
|
17
17
|
|
|
18
|
-
opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs"])
|
|
18
|
+
opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs", "reproducible"])
|
|
19
19
|
if not opts:
|
|
20
|
-
print("usage: genecodes.py [--ecodes|--stubs] <headers>")
|
|
20
|
+
print("usage: genecodes.py [--ecodes|--stubs] [--reproducible] <headers>")
|
|
21
21
|
exit(2)
|
|
22
22
|
|
|
23
23
|
if args:
|
|
24
24
|
headers = args
|
|
25
25
|
|
|
26
|
+
reproducible = ("--reproducible", "") in opts
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
# -----------------------------------------------------------------------------
|
|
28
30
|
macro_regex = r"#define\s+((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)"
|
|
29
31
|
macro_regex = re.compile(macro_regex)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
uname =
|
|
33
|
-
|
|
33
|
+
if reproducible:
|
|
34
|
+
uname = "hidden for reproducibility"
|
|
35
|
+
else:
|
|
36
|
+
# Uname without hostname.
|
|
37
|
+
uname = list(os.uname())
|
|
38
|
+
uname = " ".join((uname[0], *uname[2:]))
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
# -----------------------------------------------------------------------------
|
|
@@ -138,5 +143,5 @@ elif ("--stubs", "") in opts:
|
|
|
138
143
|
template = template_stubs
|
|
139
144
|
|
|
140
145
|
body = os.linesep.join(body)
|
|
141
|
-
text = template % (uname, headers, body)
|
|
146
|
+
text = template % (uname, headers if not reproducible else ["hidden for reproducibility"], body)
|
|
142
147
|
print(text.strip())
|
|
@@ -40,6 +40,7 @@ entries = [
|
|
|
40
40
|
("BUS", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
41
41
|
("SYN", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
42
42
|
("FF", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
43
|
+
("UI_FF", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
43
44
|
("FF_STATUS", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
44
45
|
("INPUT_PROP", "Dict[int, Union[str, Tuple[str]]]", None)
|
|
45
46
|
]
|
|
@@ -50,4 +51,4 @@ for key, annotation, doc in entries:
|
|
|
50
51
|
|
|
51
52
|
print(f"{key}: {annotation} = ", end="")
|
|
52
53
|
pprint(getattr(ecodes, key))
|
|
53
|
-
print()
|
|
54
|
+
print()
|
|
@@ -6,7 +6,7 @@ import stat
|
|
|
6
6
|
from typing import Union, List
|
|
7
7
|
|
|
8
8
|
from . import ecodes
|
|
9
|
-
from .events import event_factory
|
|
9
|
+
from .events import InputEvent, event_factory, KeyEvent, RelEvent, AbsEvent, SynEvent
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def list_devices(input_device_dir: Union[str, bytes, os.PathLike] = "/dev/input") -> List[str]:
|
|
@@ -32,7 +32,7 @@ def is_device(fn: Union[str, bytes, os.PathLike]) -> bool:
|
|
|
32
32
|
return True
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def categorize(event):
|
|
35
|
+
def categorize(event: InputEvent) -> Union[InputEvent, KeyEvent, RelEvent, AbsEvent, SynEvent]:
|
|
36
36
|
"""
|
|
37
37
|
Categorize an event according to its type.
|
|
38
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: evdev
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
4
4
|
Summary: Bindings to the Linux input handling subsystem
|
|
5
5
|
Author-email: Georgi Valkov <georgi.t.valkov@gmail.com>
|
|
6
6
|
Maintainer-email: Tobi <proxima@sezanzeb.de>
|
|
@@ -46,6 +46,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
46
46
|
Requires-Python: >=3.8
|
|
47
47
|
Description-Content-Type: text/markdown
|
|
48
48
|
License-File: LICENSE
|
|
49
|
+
Dynamic: license-file
|
|
49
50
|
|
|
50
51
|
# evdev
|
|
51
52
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
1
|
from evdev import ecodes
|
|
2
|
+
from evdev import ecodes_runtime
|
|
4
3
|
|
|
5
4
|
|
|
6
|
-
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF"
|
|
5
|
+
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF UI_FF"
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
def to_tuples(val):
|
|
@@ -29,3 +28,14 @@ def test_overlap():
|
|
|
29
28
|
vals_ff = set(to_tuples(ecodes.FF.values()))
|
|
30
29
|
vals_ff_status = set(to_tuples(ecodes.FF_STATUS.values()))
|
|
31
30
|
assert bool(vals_ff & vals_ff_status) is False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_generated():
|
|
34
|
+
e_run = vars(ecodes_runtime)
|
|
35
|
+
e_gen = vars(ecodes)
|
|
36
|
+
|
|
37
|
+
def keys(v):
|
|
38
|
+
res = {k for k in v.keys() if not k.startswith("_") and not k[1].islower()}
|
|
39
|
+
return res
|
|
40
|
+
|
|
41
|
+
assert keys(e_run) == keys(e_gen)
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# --------------------------------------------------------------------------
|
|
2
|
-
# Gather everything into a single, convenient namespace.
|
|
3
|
-
# --------------------------------------------------------------------------
|
|
4
|
-
|
|
5
|
-
from . import ecodes, ff
|
|
6
|
-
from .device import AbsInfo, DeviceInfo, EvdevError, InputDevice
|
|
7
|
-
from .events import AbsEvent, InputEvent, KeyEvent, RelEvent, SynEvent, event_factory
|
|
8
|
-
from .uinput import UInput, UInputError
|
|
9
|
-
from .util import categorize, list_devices, resolve_ecodes, resolve_ecodes_dict
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|