evdev 1.8.0__tar.gz → 1.9.0__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.
Files changed (32) hide show
  1. {evdev-1.8.0 → evdev-1.9.0}/MANIFEST.in +2 -2
  2. {evdev-1.8.0/evdev.egg-info → evdev-1.9.0}/PKG-INFO +2 -2
  3. {evdev-1.8.0 → evdev-1.9.0}/pyproject.toml +2 -5
  4. {evdev-1.8.0 → evdev-1.9.0}/setup.py +13 -8
  5. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/device.py +40 -43
  6. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/ecodes.py +3 -3
  7. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/eventio.py +6 -5
  8. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/events.py +19 -18
  9. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/evtest.py +5 -4
  10. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/genecodes_c.py +5 -1
  11. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/input.c +22 -51
  12. evdev-1.9.0/src/evdev/py.typed +0 -0
  13. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/uinput.c +2 -23
  14. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/uinput.py +36 -29
  15. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/util.py +4 -5
  16. {evdev-1.8.0 → evdev-1.9.0/src/evdev.egg-info}/PKG-INFO +2 -2
  17. evdev-1.9.0/src/evdev.egg-info/SOURCES.txt +29 -0
  18. {evdev-1.8.0 → evdev-1.9.0}/tests/test_util.py +1 -1
  19. evdev-1.8.0/evdev.egg-info/SOURCES.txt +0 -28
  20. {evdev-1.8.0 → evdev-1.9.0}/LICENSE +0 -0
  21. {evdev-1.8.0 → evdev-1.9.0}/README.md +0 -0
  22. {evdev-1.8.0 → evdev-1.9.0}/setup.cfg +0 -0
  23. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/__init__.py +0 -0
  24. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/ecodes_runtime.py +0 -0
  25. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/eventio_async.py +0 -0
  26. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/ff.py +0 -0
  27. {evdev-1.8.0 → evdev-1.9.0/src}/evdev/genecodes_py.py +0 -0
  28. {evdev-1.8.0 → evdev-1.9.0/src}/evdev.egg-info/dependency_links.txt +0 -0
  29. {evdev-1.8.0 → evdev-1.9.0/src}/evdev.egg-info/top_level.txt +0 -0
  30. {evdev-1.8.0 → evdev-1.9.0}/tests/test_ecodes.py +0 -0
  31. {evdev-1.8.0 → evdev-1.9.0}/tests/test_events.py +0 -0
  32. {evdev-1.8.0 → evdev-1.9.0}/tests/test_uinput.py +0 -0
@@ -1,5 +1,5 @@
1
1
  # The _ecodes extension module source file needs to be generated against the
2
2
  # evdev headers of the running kernel. Refer to the 'build_ecodes' distutils
3
3
  # command in setup.py.
4
- exclude evdev/ecodes.c
5
- include evdev/ecodes.py
4
+ exclude src/evdev/ecodes.c
5
+ include src/evdev/ecodes.py
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.1
2
2
  Name: evdev
3
- Version: 1.8.0
3
+ Version: 1.9.0
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>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evdev"
7
- version = "1.8.0"
7
+ version = "1.9.0"
8
8
  description = "Bindings to the Linux input handling subsystem"
9
9
  keywords = ["evdev", "input", "uinput"]
10
10
  readme = "README.md"
@@ -29,9 +29,6 @@ classifiers = [
29
29
  [project.urls]
30
30
  "Homepage" = "https://github.com/gvalkov/python-evdev"
31
31
 
32
- [tool.setuptools]
33
- packages = ["evdev"]
34
-
35
32
  [tool.ruff]
36
33
  line-length = 120
37
34
 
@@ -39,7 +36,7 @@ line-length = 120
39
36
  ignore = ["E265", "E241", "F403", "F401", "E401", "E731"]
40
37
 
41
38
  [tool.bumpversion]
42
- current_version = "1.8.0"
39
+ current_version = "1.9.0"
43
40
  commit = true
44
41
  tag = true
45
42
  allow_dirty = true
@@ -2,6 +2,7 @@ import os
2
2
  import sys
3
3
  import shutil
4
4
  import textwrap
5
+ import platform
5
6
  from pathlib import Path
6
7
  from subprocess import run
7
8
 
@@ -10,7 +11,7 @@ from setuptools.command import build_ext as _build_ext
10
11
 
11
12
 
12
13
  curdir = Path(__file__).resolve().parent
13
- ecodes_c_path = curdir / "evdev/ecodes.c"
14
+ ecodes_c_path = curdir / "src/evdev/ecodes.c"
14
15
 
15
16
 
16
17
  def create_ecodes(headers=None):
@@ -25,7 +26,11 @@ def create_ecodes(headers=None):
25
26
  include_paths.update(c_inc_path.split(":"))
26
27
 
27
28
  include_paths.add("/usr/include")
28
- files = ["linux/input.h", "linux/input-event-codes.h", "linux/uinput.h"]
29
+ if platform.system().lower() == "freebsd":
30
+ files = ["dev/evdev/input.h", "dev/evdev/input-event-codes.h", "dev/evdev/uinput.h"]
31
+ else:
32
+ files = ["linux/input.h", "linux/input-event-codes.h", "linux/uinput.h"]
33
+
29
34
  headers = [os.path.join(path, file) for path in include_paths for file in files]
30
35
 
31
36
  headers = [header for header in headers if os.path.isfile(header)]
@@ -60,7 +65,7 @@ def create_ecodes(headers=None):
60
65
 
61
66
  print("writing %s (using %s)" % (ecodes_c_path, " ".join(headers)))
62
67
  with ecodes_c_path.open("w") as fh:
63
- cmd = [sys.executable, "evdev/genecodes_c.py", "--ecodes", *headers]
68
+ cmd = [sys.executable, "src/evdev/genecodes_c.py", "--ecodes", *headers]
64
69
  run(cmd, check=True, stdout=fh)
65
70
 
66
71
 
@@ -93,12 +98,12 @@ class build_ext(_build_ext.build_ext):
93
98
  ecodes_py = Path(self.build_lib) / "evdev/ecodes.py"
94
99
  print(f"writing {ecodes_py}")
95
100
  with ecodes_py.open("w") as fh:
96
- cmd = [sys.executable, "-B", "evdev/genecodes_py.py"]
101
+ cmd = [sys.executable, "-B", "src/evdev/genecodes_py.py"]
97
102
  res = run(cmd, env={"PYTHONPATH": self.build_lib}, stdout=fh)
98
103
 
99
104
  if res.returncode != 0:
100
105
  print(f"failed to generate static {ecodes_py} - will use ecodes_runtime.py")
101
- shutil.copy("evdev/ecodes_runtime.py", ecodes_py)
106
+ shutil.copy("src/evdev/ecodes_runtime.py", ecodes_py)
102
107
 
103
108
  def run(self):
104
109
  for cmd_name in self.get_sub_commands():
@@ -112,9 +117,9 @@ class build_ext(_build_ext.build_ext):
112
117
  cflags = ["-std=c99", "-Wno-error=declaration-after-statement"]
113
118
  setup(
114
119
  ext_modules=[
115
- Extension("evdev._input", sources=["evdev/input.c"], extra_compile_args=cflags),
116
- Extension("evdev._uinput", sources=["evdev/uinput.c"], extra_compile_args=cflags),
117
- Extension("evdev._ecodes", sources=["evdev/ecodes.c"], extra_compile_args=cflags),
120
+ Extension("evdev._input", sources=["src/evdev/input.c"], extra_compile_args=cflags),
121
+ Extension("evdev._uinput", sources=["src/evdev/uinput.c"], extra_compile_args=cflags),
122
+ Extension("evdev._ecodes", sources=["src/evdev/ecodes.c"], extra_compile_args=cflags),
118
123
  ],
119
124
  cmdclass={
120
125
  "build_ext": build_ext,
@@ -1,9 +1,6 @@
1
- # encoding: utf-8
2
-
3
- import collections
4
1
  import contextlib
5
2
  import os
6
- import warnings
3
+ from typing import NamedTuple, Tuple, Union
7
4
 
8
5
  from . import _input, ecodes, util
9
6
 
@@ -13,18 +10,10 @@ except ImportError:
13
10
  from .eventio import EvdevError, EventIO
14
11
 
15
12
 
16
- # --------------------------------------------------------------------------
17
- _AbsInfo = collections.namedtuple("AbsInfo", ["value", "min", "max", "fuzz", "flat", "resolution"])
18
-
19
- _KbdInfo = collections.namedtuple("KbdInfo", ["delay", "repeat"])
20
-
21
- _DeviceInfo = collections.namedtuple("DeviceInfo", ["bustype", "vendor", "product", "version"])
22
-
23
-
24
- class AbsInfo(_AbsInfo):
13
+ class AbsInfo(NamedTuple):
25
14
  """Absolute axis information.
26
15
 
27
- A ``namedtuple`` used for storing absolute axis information -
16
+ A ``namedtuple`` with absolute axis information -
28
17
  corresponds to the ``input_absinfo`` struct:
29
18
 
30
19
  Attributes
@@ -60,11 +49,18 @@ class AbsInfo(_AbsInfo):
60
49
 
61
50
  """
62
51
 
52
+ value: int
53
+ min: int
54
+ max: int
55
+ fuzz: int
56
+ flat: int
57
+ resolution: int
58
+
63
59
  def __str__(self):
64
- return "val {}, min {}, max {}, fuzz {}, flat {}, res {}".format(*self)
60
+ return "value {}, min {}, max {}, fuzz {}, flat {}, res {}".format(*self) # pylint: disable=not-an-iterable
65
61
 
66
62
 
67
- class KbdInfo(_KbdInfo):
63
+ class KbdInfo(NamedTuple):
68
64
  """Keyboard repeat rate.
69
65
 
70
66
  Attributes
@@ -77,11 +73,14 @@ class KbdInfo(_KbdInfo):
77
73
  Keyboard repeat rate in characters per second.
78
74
  """
79
75
 
76
+ delay: int
77
+ repeat: int
78
+
80
79
  def __str__(self):
81
- return "delay {}, repeat {}".format(*self)
80
+ return "delay {}, repeat {}".format(self.delay, self.repeat)
82
81
 
83
82
 
84
- class DeviceInfo(_DeviceInfo):
83
+ class DeviceInfo(NamedTuple):
85
84
  """
86
85
  Attributes
87
86
  ----------
@@ -91,9 +90,14 @@ class DeviceInfo(_DeviceInfo):
91
90
  version
92
91
  """
93
92
 
93
+ bustype: int
94
+ vendor: int
95
+ product: int
96
+ version: int
97
+
94
98
  def __str__(self):
95
99
  msg = "bus: {:04x}, vendor {:04x}, product {:04x}, version {:04x}"
96
- return msg.format(*self)
100
+ return msg.format(*self) # pylint: disable=not-an-iterable
97
101
 
98
102
 
99
103
  class InputDevice(EventIO):
@@ -103,7 +107,7 @@ class InputDevice(EventIO):
103
107
 
104
108
  __slots__ = ("path", "fd", "info", "name", "phys", "uniq", "_rawcapabilities", "version", "ff_effects_count")
105
109
 
106
- def __init__(self, dev):
110
+ def __init__(self, dev: Union[str, bytes, os.PathLike]):
107
111
  """
108
112
  Arguments
109
113
  ---------
@@ -114,15 +118,14 @@ class InputDevice(EventIO):
114
118
  #: Path to input device.
115
119
  self.path = dev if not hasattr(dev, "__fspath__") else dev.__fspath__()
116
120
 
117
- # Certain operations are possible only when the device is opened in
118
- # read-write mode.
121
+ # Certain operations are possible only when the device is opened in read-write mode.
119
122
  try:
120
123
  fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
121
124
  except OSError:
122
125
  fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
123
126
 
124
127
  #: A non-blocking file descriptor to the device file.
125
- self.fd = fd
128
+ self.fd: int = fd
126
129
 
127
130
  # Returns (bustype, vendor, product, version, name, phys, capabilities).
128
131
  info_res = _input.ioctl_devinfo(self.fd)
@@ -131,16 +134,16 @@ class InputDevice(EventIO):
131
134
  self.info = DeviceInfo(*info_res[:4])
132
135
 
133
136
  #: The name of the event device.
134
- self.name = info_res[4]
137
+ self.name: str = info_res[4]
135
138
 
136
139
  #: The physical topology of the device.
137
- self.phys = info_res[5]
140
+ self.phys: str = info_res[5]
138
141
 
139
142
  #: The unique identifier of the device.
140
- self.uniq = info_res[6]
143
+ self.uniq: str = info_res[6]
141
144
 
142
145
  #: The evdev protocol version.
143
- self.version = _input.ioctl_EVIOCGVERSION(self.fd)
146
+ self.version: int = _input.ioctl_EVIOCGVERSION(self.fd)
144
147
 
145
148
  #: The raw dictionary of device capabilities - see `:func:capabilities()`.
146
149
  self._rawcapabilities = _input.ioctl_capabilities(self.fd)
@@ -155,7 +158,7 @@ class InputDevice(EventIO):
155
158
  except (OSError, ImportError, AttributeError):
156
159
  pass
157
160
 
158
- def _capabilities(self, absinfo=True):
161
+ def _capabilities(self, absinfo: bool = True):
159
162
  res = {}
160
163
 
161
164
  for etype, _ecodes in self._rawcapabilities.items():
@@ -173,7 +176,7 @@ class InputDevice(EventIO):
173
176
 
174
177
  return res
175
178
 
176
- def capabilities(self, verbose=False, absinfo=True):
179
+ def capabilities(self, verbose: bool = False, absinfo: bool = True):
177
180
  """
178
181
  Return the event types that this device supports as a mapping of
179
182
  supported event types to lists of handled event codes.
@@ -218,7 +221,7 @@ class InputDevice(EventIO):
218
221
  else:
219
222
  return self._capabilities(absinfo)
220
223
 
221
- def input_props(self, verbose=False):
224
+ def input_props(self, verbose: bool = False):
222
225
  """
223
226
  Get device properties and quirks.
224
227
 
@@ -239,7 +242,7 @@ class InputDevice(EventIO):
239
242
 
240
243
  return props
241
244
 
242
- def leds(self, verbose=False):
245
+ def leds(self, verbose: bool = False):
243
246
  """
244
247
  Return currently set LED keys.
245
248
 
@@ -260,7 +263,7 @@ class InputDevice(EventIO):
260
263
 
261
264
  return leds
262
265
 
263
- def set_led(self, led_num, value):
266
+ def set_led(self, led_num: int, value: int):
264
267
  """
265
268
  Set the state of the selected LED.
266
269
 
@@ -330,7 +333,7 @@ class InputDevice(EventIO):
330
333
  yield
331
334
  self.ungrab()
332
335
 
333
- def upload_effect(self, effect):
336
+ def upload_effect(self, effect: "ff.Effect"):
334
337
  """
335
338
  Upload a force feedback effect to a force feedback device.
336
339
  """
@@ -357,10 +360,10 @@ class InputDevice(EventIO):
357
360
  return KbdInfo(*_input.ioctl_EVIOCGREP(self.fd))
358
361
 
359
362
  @repeat.setter
360
- def repeat(self, value):
363
+ def repeat(self, value: Tuple[int, int]):
361
364
  return _input.ioctl_EVIOCSREP(self.fd, *value)
362
365
 
363
- def active_keys(self, verbose=False):
366
+ def active_keys(self, verbose: bool = False):
364
367
  """
365
368
  Return currently active keys.
366
369
 
@@ -383,13 +386,7 @@ class InputDevice(EventIO):
383
386
 
384
387
  return active_keys
385
388
 
386
- @property
387
- def fn(self):
388
- msg = "Please use {0}.path instead of {0}.fn".format(self.__class__.__name__)
389
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
390
- return self.path
391
-
392
- def absinfo(self, axis_num):
389
+ def absinfo(self, axis_num: int):
393
390
  """
394
391
  Return current :class:`AbsInfo` for input device axis
395
392
 
@@ -405,7 +402,7 @@ class InputDevice(EventIO):
405
402
  """
406
403
  return AbsInfo(*_input.ioctl_EVIOCGABS(self.fd, axis_num))
407
404
 
408
- def set_absinfo(self, axis_num, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None):
405
+ def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None):
409
406
  """
410
407
  Update :class:`AbsInfo` values. Only specified values will be overwritten.
411
408
 
@@ -1,5 +1,5 @@
1
- # When installed, this module is replaced by an ecodes.py generated at
1
+ # When installed, this module is replaced by an ecodes.py generated at
2
2
  # build time by genecodes_py.py (see build_ext in setup.py).
3
3
 
4
- # This stub exists to make development of evdev itself more convenient.
5
- from . ecodes_runtime import *
4
+ # This stub exists to make development of evdev itself more convenient.
5
+ from .ecodes_runtime import *
@@ -2,6 +2,7 @@ import fcntl
2
2
  import functools
3
3
  import os
4
4
  import select
5
+ from typing import Iterator, Union
5
6
 
6
7
  from . import _input, _uinput, ecodes
7
8
  from .events import InputEvent
@@ -35,7 +36,7 @@ class EventIO:
35
36
  """
36
37
  return self.fd
37
38
 
38
- def read_loop(self):
39
+ def read_loop(self) -> Iterator[InputEvent]:
39
40
  """
40
41
  Enter an endless :func:`select.select()` loop that yields input events.
41
42
  """
@@ -45,7 +46,7 @@ class EventIO:
45
46
  for event in self.read():
46
47
  yield event
47
48
 
48
- def read_one(self):
49
+ def read_one(self) -> Union[InputEvent, None]:
49
50
  """
50
51
  Read and return a single input event as an instance of
51
52
  :class:`InputEvent <evdev.events.InputEvent>`.
@@ -59,14 +60,14 @@ class EventIO:
59
60
  if event:
60
61
  return InputEvent(*event)
61
62
 
62
- def read(self):
63
+ def read(self) -> Iterator[InputEvent]:
63
64
  """
64
65
  Read multiple input events from device. Return a generator object that
65
66
  yields :class:`InputEvent <evdev.events.InputEvent>` instances. Raises
66
67
  `BlockingIOError` if there are no available events at the moment.
67
68
  """
68
69
 
69
- # events -> [(sec, usec, type, code, val), ...]
70
+ # events -> ((sec, usec, type, code, val), ...)
70
71
  events = _input.device_read_many(self.fd)
71
72
 
72
73
  for event in events:
@@ -114,7 +115,7 @@ class EventIO:
114
115
  self.write(event.type, event.code, event.value)
115
116
 
116
117
  @need_write
117
- def write(self, etype, code, value):
118
+ def write(self, etype: int, code: int, value: int):
118
119
  """
119
120
  Inject an input event into the input subsystem. Events are
120
121
  queued until a synchronization event is received.
@@ -38,6 +38,7 @@ methods::
38
38
  # http://www.kernel.org/doc/Documentation/input/event-codes.txt
39
39
 
40
40
  # pylint: disable=no-name-in-module
41
+ from typing import Final
41
42
  from .ecodes import ABS, EV_ABS, EV_KEY, EV_REL, EV_SYN, KEY, REL, SYN, keys
42
43
 
43
44
 
@@ -48,21 +49,21 @@ class InputEvent:
48
49
 
49
50
  def __init__(self, sec, usec, type, code, value):
50
51
  #: Time in seconds since epoch at which event occurred.
51
- self.sec = sec
52
+ self.sec: int = sec
52
53
 
53
54
  #: Microsecond portion of the timestamp.
54
- self.usec = usec
55
+ self.usec: int = usec
55
56
 
56
57
  #: Event type - one of ``ecodes.EV_*``.
57
- self.type = type
58
+ self.type: int = type
58
59
 
59
60
  #: Event code related to the event type.
60
- self.code = code
61
+ self.code: int = code
61
62
 
62
63
  #: Event value related to the event type.
63
- self.value = value
64
+ self.value: int = value
64
65
 
65
- def timestamp(self):
66
+ def timestamp(self) -> float:
66
67
  """Return event timestamp as a float."""
67
68
  return self.sec + (self.usec / 1000000.0)
68
69
 
@@ -78,20 +79,20 @@ class InputEvent:
78
79
  class KeyEvent:
79
80
  """An event generated by a keyboard, button or other key-like devices."""
80
81
 
81
- key_up = 0x0
82
- key_down = 0x1
83
- key_hold = 0x2
82
+ key_up: Final[int] = 0x0
83
+ key_down: Final[int] = 0x1
84
+ key_hold: Final[int] = 0x2
84
85
 
85
86
  __slots__ = "scancode", "keycode", "keystate", "event"
86
87
 
87
- def __init__(self, event, allow_unknown=False):
88
+ def __init__(self, event: InputEvent, allow_unknown: bool = False):
88
89
  """
89
90
  The ``allow_unknown`` argument determines what to do in the event of an event code
90
91
  for which a key code cannot be found. If ``False`` a ``KeyError`` will be raised.
91
92
  If ``True`` the keycode will be set to the hex value of the event code.
92
93
  """
93
94
 
94
- self.scancode = event.code
95
+ self.scancode: int = event.code
95
96
 
96
97
  if event.value == 0:
97
98
  self.keystate = KeyEvent.key_up
@@ -109,7 +110,7 @@ class KeyEvent:
109
110
  raise
110
111
 
111
112
  #: Reference to an :class:`InputEvent` instance.
112
- self.event = event
113
+ self.event: InputEvent = event
113
114
 
114
115
  def __str__(self):
115
116
  try:
@@ -129,9 +130,9 @@ class RelEvent:
129
130
 
130
131
  __slots__ = "event"
131
132
 
132
- def __init__(self, event):
133
+ def __init__(self, event: InputEvent):
133
134
  #: Reference to an :class:`InputEvent` instance.
134
- self.event = event
135
+ self.event: InputEvent = event
135
136
 
136
137
  def __str__(self):
137
138
  msg = "relative axis event at {:f}, {}"
@@ -146,9 +147,9 @@ class AbsEvent:
146
147
 
147
148
  __slots__ = "event"
148
149
 
149
- def __init__(self, event):
150
+ def __init__(self, event: InputEvent):
150
151
  #: Reference to an :class:`InputEvent` instance.
151
- self.event = event
152
+ self.event: InputEvent = event
152
153
 
153
154
  def __str__(self):
154
155
  msg = "absolute axis event at {:f}, {}"
@@ -166,9 +167,9 @@ class SynEvent:
166
167
 
167
168
  __slots__ = "event"
168
169
 
169
- def __init__(self, event):
170
+ def __init__(self, event: InputEvent):
170
171
  #: Reference to an :class:`InputEvent` instance.
171
- self.event = event
172
+ self.event: InputEvent = event
172
173
 
173
174
  def __str__(self):
174
175
  msg = "synchronization event at {:f}, {}"
@@ -16,7 +16,6 @@ Examples:
16
16
  evtest /dev/input/event0 /dev/input/event1
17
17
  """
18
18
 
19
-
20
19
  import atexit
21
20
  import optparse
22
21
  import re
@@ -149,9 +148,11 @@ def print_capabilities(device):
149
148
  def print_event(e):
150
149
  if e.type == ecodes.EV_SYN:
151
150
  if e.code == ecodes.SYN_MT_REPORT:
152
- msg = "time {:<16} +++++++++ {} ++++++++"
151
+ msg = "time {:<17} +++++++++++++ {} +++++++++++++"
152
+ elif e.code == ecodes.SYN_DROPPED:
153
+ msg = "time {:<17} !!!!!!!!!!!!! {} !!!!!!!!!!!!!"
153
154
  else:
154
- msg = "time {:<16} --------- {} --------"
155
+ msg = "time {:<17} ------------- {} -------------"
155
156
  print(msg.format(e.timestamp(), ecodes.SYN[e.code]))
156
157
  else:
157
158
  if e.type in ecodes.bytype:
@@ -159,7 +160,7 @@ def print_event(e):
159
160
  else:
160
161
  codename = "?"
161
162
 
162
- evfmt = "time {:<16} type {} ({}), code {:<4} ({}), value {}"
163
+ evfmt = "time {:<17} type {} ({}), code {:<4} ({}), value {}"
163
164
  print(evfmt.format(e.timestamp(), e.type, ecodes.EV[e.type], e.code, codename, e.value))
164
165
 
165
166
 
@@ -20,9 +20,12 @@ if not opts:
20
20
  print("usage: genecodes.py [--ecodes|--stubs] <headers>")
21
21
  exit(2)
22
22
 
23
+ if args:
24
+ headers = args
25
+
23
26
 
24
27
  # -----------------------------------------------------------------------------
25
- macro_regex = r"#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)"
28
+ macro_regex = r"#define\s+((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)"
26
29
  macro_regex = re.compile(macro_regex)
27
30
 
28
31
  # Uname without hostname.
@@ -35,6 +38,7 @@ template_ecodes = r"""
35
38
  #include <Python.h>
36
39
  #ifdef __FreeBSD__
37
40
  #include <dev/evdev/input.h>
41
+ #include <dev/evdev/uinput.h>
38
42
  #else
39
43
  #include <linux/input.h>
40
44
  #include <linux/uinput.h>
@@ -46,12 +46,10 @@ int test_bit(const char* bitmask, int bit) {
46
46
  static PyObject *
47
47
  device_read(PyObject *self, PyObject *args)
48
48
  {
49
- int fd;
50
49
  struct input_event event;
51
50
 
52
51
  // get device file descriptor (O_RDONLY|O_NONBLOCK)
53
- if (PyArg_ParseTuple(args, "i", &fd) < 0)
54
- return NULL;
52
+ int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
55
53
 
56
54
  int n = read(fd, &event, sizeof(event));
57
55
 
@@ -68,12 +66,9 @@ device_read(PyObject *self, PyObject *args)
68
66
  PyObject* sec = PyLong_FromLong(event.input_event_sec);
69
67
  PyObject* usec = PyLong_FromLong(event.input_event_usec);
70
68
  PyObject* val = PyLong_FromLong(event.value);
71
- PyObject* py_input_event = NULL;
72
-
73
- py_input_event = Py_BuildValue("OOhhO", sec, usec, event.type, event.code, val);
74
- Py_DECREF(sec);
75
- Py_DECREF(usec);
76
- Py_DECREF(val);
69
+ PyObject* type = PyLong_FromLong(event.type);
70
+ PyObject* code = PyLong_FromLong(event.code);
71
+ PyObject* py_input_event = PyTuple_Pack(5, sec, usec, type, code, val);
77
72
 
78
73
  return py_input_event;
79
74
  }
@@ -83,17 +78,16 @@ device_read(PyObject *self, PyObject *args)
83
78
  static PyObject *
84
79
  device_read_many(PyObject *self, PyObject *args)
85
80
  {
86
- int fd;
87
-
88
81
  // get device file descriptor (O_RDONLY|O_NONBLOCK)
89
- int ret = PyArg_ParseTuple(args, "i", &fd);
90
- if (!ret) return NULL;
82
+ int fd = (int)PyLong_AsLong(PyTuple_GET_ITEM(args, 0));
91
83
 
92
- PyObject* event_list = PyList_New(0);
93
84
  PyObject* py_input_event = NULL;
85
+ PyObject* events = NULL;
94
86
  PyObject* sec = NULL;
95
87
  PyObject* usec = NULL;
96
88
  PyObject* val = NULL;
89
+ PyObject* type = NULL;
90
+ PyObject* code = NULL;
97
91
 
98
92
  struct input_event event[64];
99
93
 
@@ -102,26 +96,24 @@ device_read_many(PyObject *self, PyObject *args)
102
96
 
103
97
  if (nread < 0) {
104
98
  PyErr_SetFromErrno(PyExc_OSError);
105
- Py_DECREF(event_list);
106
99
  return NULL;
107
100
  }
108
101
 
109
- // Construct a list of event tuples, which we'll make sense of in Python
110
- for (unsigned i = 0 ; i < nread/event_size ; i++) {
102
+ // Construct a tuple of event tuples. Each tuple is the arguments to InputEvent.
103
+ size_t num_events = nread / event_size;
104
+ events = PyTuple_New(num_events);
105
+ for (size_t i = 0 ; i < num_events; i++) {
111
106
  sec = PyLong_FromLong(event[i].input_event_sec);
112
107
  usec = PyLong_FromLong(event[i].input_event_usec);
113
108
  val = PyLong_FromLong(event[i].value);
109
+ type = PyLong_FromLong(event[i].type);
110
+ code = PyLong_FromLong(event[i].code);
114
111
 
115
- py_input_event = Py_BuildValue("OOhhO", sec, usec, event[i].type, event[i].code, val);
116
- PyList_Append(event_list, py_input_event);
117
-
118
- Py_DECREF(py_input_event);
119
- Py_DECREF(sec);
120
- Py_DECREF(usec);
121
- Py_DECREF(val);
112
+ py_input_event = PyTuple_Pack(5, sec, usec, type, code, val);
113
+ PyTuple_SET_ITEM(events, i, py_input_event);
122
114
  }
123
115
 
124
- return event_list;
116
+ return events;
125
117
  }
126
118
 
127
119
 
@@ -309,7 +301,7 @@ static PyObject *
309
301
  ioctl_EVIOCGREP(PyObject *self, PyObject *args)
310
302
  {
311
303
  int fd, ret;
312
- unsigned int rep[2] = {0};
304
+ unsigned int rep[REP_CNT] = {0};
313
305
  ret = PyArg_ParseTuple(args, "i", &fd);
314
306
  if (!ret) return NULL;
315
307
 
@@ -317,7 +309,7 @@ ioctl_EVIOCGREP(PyObject *self, PyObject *args)
317
309
  if (ret == -1)
318
310
  return NULL;
319
311
 
320
- return Py_BuildValue("(ii)", rep[0], rep[1]);
312
+ return Py_BuildValue("(ii)", rep[REP_DELAY], rep[REP_PERIOD]);
321
313
  }
322
314
 
323
315
 
@@ -325,7 +317,7 @@ static PyObject *
325
317
  ioctl_EVIOCSREP(PyObject *self, PyObject *args)
326
318
  {
327
319
  int fd, ret;
328
- unsigned int rep[2] = {0};
320
+ unsigned int rep[REP_CNT] = {0};
329
321
 
330
322
  ret = PyArg_ParseTuple(args, "iii", &fd, &rep[0], &rep[1]);
331
323
  if (!ret) return NULL;
@@ -539,7 +531,6 @@ ioctl_EVIOCGPROP(PyObject *self, PyObject *args)
539
531
  }
540
532
 
541
533
 
542
-
543
534
  static PyMethodDef MethodTable[] = {
544
535
  { "ioctl_devinfo", ioctl_devinfo, METH_VARARGS, "fetch input device info" },
545
536
  { "ioctl_capabilities", ioctl_capabilities, METH_VARARGS, "fetch input device capabilities" },
@@ -561,14 +552,10 @@ static PyMethodDef MethodTable[] = {
561
552
  };
562
553
 
563
554
 
564
- #define MODULE_NAME "_input"
565
- #define MODULE_HELP "Python bindings to certain linux input subsystem functions"
566
-
567
- #if PY_MAJOR_VERSION >= 3
568
555
  static struct PyModuleDef moduledef = {
569
556
  PyModuleDef_HEAD_INIT,
570
- MODULE_NAME,
571
- MODULE_HELP,
557
+ "_input",
558
+ "Python bindings to certain linux input subsystem functions",
572
559
  -1, /* m_size */
573
560
  MethodTable, /* m_methods */
574
561
  NULL, /* m_reload */
@@ -590,19 +577,3 @@ PyInit__input(void)
590
577
  {
591
578
  return moduleinit();
592
579
  }
593
-
594
- #else
595
- static PyObject *
596
- moduleinit(void)
597
- {
598
- PyObject* m = Py_InitModule3(MODULE_NAME, MethodTable, MODULE_HELP);
599
- if (m == NULL) return NULL;
600
- return m;
601
- }
602
-
603
- PyMODINIT_FUNC
604
- init_input(void)
605
- {
606
- moduleinit();
607
- }
608
- #endif
File without changes
@@ -356,8 +356,6 @@ int _uinput_end_erase(int fd, struct uinput_ff_erase *upload)
356
356
  return ioctl(fd, UI_END_FF_ERASE, upload);
357
357
  }
358
358
 
359
- #define MODULE_NAME "_uinput"
360
- #define MODULE_HELP "Python bindings for parts of linux/uinput.c"
361
359
 
362
360
  static PyMethodDef MethodTable[] = {
363
361
  { "open", uinput_open, METH_VARARGS,
@@ -390,11 +388,10 @@ static PyMethodDef MethodTable[] = {
390
388
  { NULL, NULL, 0, NULL}
391
389
  };
392
390
 
393
- #if PY_MAJOR_VERSION >= 3
394
391
  static struct PyModuleDef moduledef = {
395
392
  PyModuleDef_HEAD_INIT,
396
- MODULE_NAME,
397
- MODULE_HELP,
393
+ "_uinput",
394
+ "Python bindings for parts of linux/uinput.c",
398
395
  -1, /* m_size */
399
396
  MethodTable, /* m_methods */
400
397
  NULL, /* m_reload */
@@ -418,21 +415,3 @@ PyInit__uinput(void)
418
415
  {
419
416
  return moduleinit();
420
417
  }
421
-
422
- #else
423
- static PyObject *
424
- moduleinit(void)
425
- {
426
- PyObject* m = Py_InitModule3(MODULE_NAME, MethodTable, MODULE_HELP);
427
- if (m == NULL) return NULL;
428
-
429
- PyModule_AddIntConstant(m, "maxnamelen", UINPUT_MAX_NAME_SIZE);
430
- return m;
431
- }
432
-
433
- PyMODINIT_FUNC
434
- init_uinput(void)
435
- {
436
- moduleinit();
437
- }
438
- #endif
@@ -5,8 +5,10 @@ import re
5
5
  import stat
6
6
  import time
7
7
  from collections import defaultdict
8
+ from typing import Union, Tuple, Dict, Sequence, Optional
8
9
 
9
- from . import _uinput, device, ecodes, ff, util
10
+ from . import _uinput, ecodes, ff, util
11
+ from .device import InputDevice, AbsInfo
10
12
  from .events import InputEvent
11
13
 
12
14
  try:
@@ -38,7 +40,12 @@ class UInput(EventIO):
38
40
  )
39
41
 
40
42
  @classmethod
41
- def from_device(cls, *devices, filtered_types=(ecodes.EV_SYN, ecodes.EV_FF), **kwargs):
43
+ def from_device(
44
+ cls,
45
+ *devices: Union[InputDevice, Union[str, bytes, os.PathLike]],
46
+ filtered_types: Tuple[int] = (ecodes.EV_SYN, ecodes.EV_FF),
47
+ **kwargs,
48
+ ):
42
49
  """
43
50
  Create an UInput device with the capabilities of one or more input
44
51
  devices.
@@ -57,8 +64,8 @@ class UInput(EventIO):
57
64
 
58
65
  device_instances = []
59
66
  for dev in devices:
60
- if not isinstance(dev, device.InputDevice):
61
- dev = device.InputDevice(str(dev))
67
+ if not isinstance(dev, InputDevice):
68
+ dev = InputDevice(str(dev))
62
69
  device_instances.append(dev)
63
70
 
64
71
  all_capabilities = defaultdict(set)
@@ -79,14 +86,14 @@ class UInput(EventIO):
79
86
 
80
87
  def __init__(
81
88
  self,
82
- events=None,
83
- name="py-evdev-uinput",
84
- vendor=0x1,
85
- product=0x1,
86
- version=0x1,
87
- bustype=0x3,
88
- devnode="/dev/uinput",
89
- phys="py-evdev-uinput",
89
+ events: Optional[Dict[int, Sequence[int]]] = None,
90
+ name: str = "py-evdev-uinput",
91
+ vendor: int = 0x1,
92
+ product: int = 0x1,
93
+ version: int = 0x1,
94
+ bustype: int = 0x3,
95
+ devnode: str = "/dev/uinput",
96
+ phys: str = "py-evdev-uinput",
90
97
  input_props=None,
91
98
  # CentOS 7 has sufficiently old headers that FF_MAX_EFFECTS is not defined there,
92
99
  # which causes the whole module to fail loading. Fallback on a hardcoded value of
@@ -131,13 +138,13 @@ class UInput(EventIO):
131
138
  to inject only ``KEY_*`` and ``BTN_*`` event codes.
132
139
  """
133
140
 
134
- self.name = name #: Uinput device name.
135
- self.vendor = vendor #: Device vendor identifier.
136
- self.product = product #: Device product identifier.
137
- self.version = version #: Device version identifier.
138
- self.bustype = bustype #: Device bustype - e.g. ``BUS_USB``.
139
- self.phys = phys #: Uinput device physical path.
140
- self.devnode = devnode #: Uinput device node - e.g. ``/dev/uinput/``.
141
+ self.name: str = name #: Uinput device name.
142
+ self.vendor: int = vendor #: Device vendor identifier.
143
+ self.product: int = product #: Device product identifier.
144
+ self.version: int = version #: Device version identifier.
145
+ self.bustype: int = bustype #: Device bustype - e.g. ``BUS_USB``.
146
+ self.phys: str = phys #: Uinput device physical path.
147
+ self.devnode: str = devnode #: Uinput device node - e.g. ``/dev/uinput/``.
141
148
 
142
149
  if not events:
143
150
  events = {ecodes.EV_KEY: ecodes.keys.keys()}
@@ -173,7 +180,7 @@ class UInput(EventIO):
173
180
  #: An :class:`InputDevice <evdev.device.InputDevice>` instance
174
181
  #: for the fake input device. ``None`` if the device cannot be
175
182
  #: opened for reading and writing.
176
- self.device = self._find_device(self.fd)
183
+ self.device: InputDevice = self._find_device(self.fd)
177
184
 
178
185
  def _prepare_events(self, events):
179
186
  """Prepare events for passing to _uinput.enable and _uinput.setup"""
@@ -181,7 +188,7 @@ class UInput(EventIO):
181
188
  for etype, codes in events.items():
182
189
  for code in codes:
183
190
  # Handle max, min, fuzz, flat.
184
- if isinstance(code, (tuple, list, device.AbsInfo)):
191
+ if isinstance(code, (tuple, list, AbsInfo)):
185
192
  # Flatten (ABS_Y, (0, 255, 0, 0, 0, 0)) to (ABS_Y, 0, 255, 0, 0, 0, 0).
186
193
  f = [code[0]]
187
194
  f.extend(code[1])
@@ -206,7 +213,7 @@ class UInput(EventIO):
206
213
  return "{}({})".format(self.__class__.__name__, ", ".join(v))
207
214
 
208
215
  def __str__(self):
209
- msg = 'name "{}", bus "{}", vendor "{:04x}", product "{:04x}", version "{:04x}", phys "{}"\n' "event types: {}"
216
+ msg = 'name "{}", bus "{}", vendor "{:04x}", product "{:04x}", version "{:04x}", phys "{}"\nevent types: {}'
210
217
 
211
218
  evtypes = [i[0] for i in self.capabilities(True).keys()]
212
219
  msg = msg.format(
@@ -225,7 +232,7 @@ class UInput(EventIO):
225
232
  _uinput.close(self.fd)
226
233
  self.fd = -1
227
234
 
228
- def capabilities(self, verbose=False, absinfo=True):
235
+ def capabilities(self, verbose: bool = False, absinfo: bool = True):
229
236
  """See :func:`capabilities <evdev.device.InputDevice.capabilities>`."""
230
237
  if self.device is None:
231
238
  raise UInputError("input device not opened - cannot read capabilities")
@@ -281,7 +288,7 @@ class UInput(EventIO):
281
288
  msg = "uinput device name must not be longer than {} characters"
282
289
  raise UInputError(msg.format(_uinput.maxnamelen))
283
290
 
284
- def _find_device(self, fd):
291
+ def _find_device(self, fd: int) -> InputDevice:
285
292
  """
286
293
  Tries to find the device node. Will delegate this task to one of
287
294
  several platform-specific functions.
@@ -299,7 +306,7 @@ class UInput(EventIO):
299
306
  # use the generic fallback method.
300
307
  return self._find_device_fallback()
301
308
 
302
- def _find_device_linux(self, sysname):
309
+ def _find_device_linux(self, sysname: str) -> InputDevice:
303
310
  """
304
311
  Tries to find the device node when running on Linux.
305
312
  """
@@ -327,15 +334,15 @@ class UInput(EventIO):
327
334
  # device to show up or the permissions to be set.
328
335
  for attempt in range(19):
329
336
  try:
330
- return device.InputDevice(device_path)
337
+ return InputDevice(device_path)
331
338
  except (FileNotFoundError, PermissionError):
332
339
  time.sleep(0.1)
333
340
 
334
341
  # Last attempt. If this fails, whatever exception the last attempt raises
335
342
  # shall be the exception that this function raises.
336
- return device.InputDevice(device_path)
343
+ return InputDevice(device_path)
337
344
 
338
- def _find_device_fallback(self):
345
+ def _find_device_fallback(self) -> Union[InputDevice, None]:
339
346
  """
340
347
  Tries to find the device node when UI_GET_SYSNAME is not available or
341
348
  we're running on a system sufficiently exotic that we do not know how
@@ -363,6 +370,6 @@ class UInput(EventIO):
363
370
  path_number_pairs.sort(key=lambda pair: pair[1], reverse=True)
364
371
 
365
372
  for path, _ in path_number_pairs:
366
- d = device.InputDevice(path)
373
+ d = InputDevice(path)
367
374
  if d.name == self.name:
368
375
  return d
@@ -3,21 +3,20 @@ import glob
3
3
  import os
4
4
  import re
5
5
  import stat
6
+ from typing import Union, List
6
7
 
7
8
  from . import ecodes
8
9
  from .events import event_factory
9
10
 
10
11
 
11
- def list_devices(input_device_dir="/dev/input"):
12
+ def list_devices(input_device_dir: Union[str, bytes, os.PathLike] = "/dev/input") -> List[str]:
12
13
  """List readable character devices in ``input_device_dir``."""
13
14
 
14
15
  fns = glob.glob("{}/event*".format(input_device_dir))
15
- fns = list(filter(is_device, fns))
16
+ return list(filter(is_device, fns))
16
17
 
17
- return fns
18
18
 
19
-
20
- def is_device(fn):
19
+ def is_device(fn: Union[str, bytes, os.PathLike]) -> bool:
21
20
  """Check if ``fn`` is a readable and writable character device."""
22
21
 
23
22
  if not os.path.exists(fn):
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.1
2
2
  Name: evdev
3
- Version: 1.8.0
3
+ Version: 1.9.0
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>
@@ -0,0 +1,29 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ src/evdev/__init__.py
7
+ src/evdev/device.py
8
+ src/evdev/ecodes.py
9
+ src/evdev/ecodes_runtime.py
10
+ src/evdev/eventio.py
11
+ src/evdev/eventio_async.py
12
+ src/evdev/events.py
13
+ src/evdev/evtest.py
14
+ src/evdev/ff.py
15
+ src/evdev/genecodes_c.py
16
+ src/evdev/genecodes_py.py
17
+ src/evdev/input.c
18
+ src/evdev/py.typed
19
+ src/evdev/uinput.c
20
+ src/evdev/uinput.py
21
+ src/evdev/util.py
22
+ src/evdev.egg-info/PKG-INFO
23
+ src/evdev.egg-info/SOURCES.txt
24
+ src/evdev.egg-info/dependency_links.txt
25
+ src/evdev.egg-info/top_level.txt
26
+ tests/test_ecodes.py
27
+ tests/test_events.py
28
+ tests/test_uinput.py
29
+ tests/test_util.py
@@ -6,7 +6,7 @@ def test_match_ecodes_a():
6
6
  assert res == {1: [372, 418, 419, 420]}
7
7
  assert dict(util.resolve_ecodes_dict(res)) == {
8
8
  ("EV_KEY", 1): [
9
- (["KEY_FULL_SCREEN", "KEY_ZOOM"], 372),
9
+ (("KEY_FULL_SCREEN", "KEY_ZOOM"), 372),
10
10
  ("KEY_ZOOMIN", 418),
11
11
  ("KEY_ZOOMOUT", 419),
12
12
  ("KEY_ZOOMRESET", 420),
@@ -1,28 +0,0 @@
1
- LICENSE
2
- MANIFEST.in
3
- README.md
4
- pyproject.toml
5
- setup.py
6
- evdev/__init__.py
7
- evdev/device.py
8
- evdev/ecodes.py
9
- evdev/ecodes_runtime.py
10
- evdev/eventio.py
11
- evdev/eventio_async.py
12
- evdev/events.py
13
- evdev/evtest.py
14
- evdev/ff.py
15
- evdev/genecodes_c.py
16
- evdev/genecodes_py.py
17
- evdev/input.c
18
- evdev/uinput.c
19
- evdev/uinput.py
20
- evdev/util.py
21
- evdev.egg-info/PKG-INFO
22
- evdev.egg-info/SOURCES.txt
23
- evdev.egg-info/dependency_links.txt
24
- evdev.egg-info/top_level.txt
25
- tests/test_ecodes.py
26
- tests/test_events.py
27
- tests/test_uinput.py
28
- tests/test_util.py
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