Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-evdev for openSUSE:Factory checked in at 2025-01-30 14:52:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-evdev (Old) and /work/SRC/openSUSE:Factory/.python-evdev.new.2316 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-evdev" Thu Jan 30 14:52:15 2025 rev:16 rq:1241259 version:1.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-evdev/python-evdev.changes 2024-05-10 12:06:32.748557642 +0200 +++ /work/SRC/openSUSE:Factory/.python-evdev.new.2316/python-evdev.changes 2025-01-30 14:52:22.156328810 +0100 @@ -1,0 +2,18 @@ +Wed Jan 29 19:36:45 UTC 2025 - Matthias Bach <ma...@marix.org> - 1.8.0 + +- Update to 1.8.0 + * The evdev.ecodes module is now generated at install time and + contains only constants. This allows type checking and + introspection of the evdev.ecodes module, without having to + execute it first. The old module is available as + evdev.ecodes_runtime. + * Reverse mappings in evdev.ecodes that point to more than one + value are now tuples instead of lists. + * Fix keyboard delay and repeat being swapped. + * Move the syn() convenience method from InputDevice to EventIO. +- Add fix-tests.patch to pull in test fixes that upstream only + included after tagging their release. +- Switch source download during packaging from disabledrun to + manualrun. + +------------------------------------------------------------------- Old: ---- python-evdev-1.7.1.tar.gz New: ---- fix-tests.patch python-evdev-1.8.0.tar.gz BETA DEBUG BEGIN: New: * Move the syn() convenience method from InputDevice to EventIO. - Add fix-tests.patch to pull in test fixes that upstream only included after tagging their release. BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-evdev.spec ++++++ --- /var/tmp/diff_new_pack.TwN701/_old 2025-01-30 14:52:23.120368575 +0100 +++ /var/tmp/diff_new_pack.TwN701/_new 2025-01-30 14:52:23.124368740 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-evdev # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define modname evdev %{?sle15_python_module_pythons} Name: python-evdev -Version: 1.7.1 +Version: 1.8.0 Release: 0 Summary: Python bindings to the Linux input handling subsystem License: BSD-3-Clause @@ -27,6 +27,7 @@ URL: https://github.com/gvalkov/python-evdev # Source needs to be pulled form Github as the source distribution on PyPI lacks the test directory Source: https://github.com/gvalkov/python-evdev/archive/refs/tags/v%{version}.tar.gz#/python-evdev-%{version}.tar.gz +Patch0: fix-tests.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} ++++++ _service ++++++ --- /var/tmp/diff_new_pack.TwN701/_old 2025-01-30 14:52:23.152369895 +0100 +++ /var/tmp/diff_new_pack.TwN701/_new 2025-01-30 14:52:23.156370060 +0100 @@ -1,4 +1,4 @@ <services> - <service name="download_files" mode="disabled" /> + <service name="download_files" mode="manual" /> </services> ++++++ fix-tests.patch ++++++ From: Georgi Valkov <georgi.t.val...@gmail.com> Date: Sat, 25 Jan 2025 18:04:39 +0100 Subject: [PATCH] Fix tests Upstream: merged This is pulled from upstream main branch where it was committed right after the release. --- tests/test_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_util.py b/tests/test_util.py index 5a979df..7112927 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -6,7 +6,7 @@ def test_match_ecodes_a(): assert res == {1: [372, 418, 419, 420]} assert dict(util.resolve_ecodes_dict(res)) == { ("EV_KEY", 1): [ - (["KEY_FULL_SCREEN", "KEY_ZOOM"], 372), + (("KEY_FULL_SCREEN", "KEY_ZOOM"), 372), ("KEY_ZOOMIN", 418), ("KEY_ZOOMOUT", 419), ("KEY_ZOOMRESET", 420), ++++++ python-evdev-1.7.1.tar.gz -> python-evdev-1.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/.github/workflows/install.yaml new/python-evdev-1.8.0/.github/workflows/install.yaml --- old/python-evdev-1.7.1/.github/workflows/install.yaml 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/.github/workflows/install.yaml 2025-01-25 17:37:33.000000000 +0100 @@ -11,10 +11,10 @@ fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] include: - os: ubuntu-latest - python-version: "3.7" + python-version: "3.8" steps: - uses: actions/checkout@v4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/.github/workflows/lint.yml new/python-evdev-1.8.0/.github/workflows/lint.yml --- old/python-evdev-1.7.1/.github/workflows/lint.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/.github/workflows/lint.yml 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,27 @@ +name: Lint + +on: + - push + - pull_request + +jobs: + pylint: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + python-version: ["3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Check for pylint errors + run: | + python -m pip install pylint setuptools + python setup.py build + python -m pylint --verbose -E build/lib*/evdev diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/.github/workflows/test.yml new/python-evdev-1.8.0/.github/workflows/test.yml --- old/python-evdev-1.7.1/.github/workflows/test.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/.github/workflows/test.yml 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,29 @@ +name: Test + +on: + - push + - pull_request + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + python-version: ["3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Run pytest tests + # pip install -e . builds _ecodes and such into the evdev directory + # sudo required to write to uinputs + run: | + sudo python -m pip install pytest setuptools + sudo python -m pip install -e . + sudo python -m pytest tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/.gitignore new/python-evdev-1.8.0/.gitignore --- old/python-evdev-1.7.1/.gitignore 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/.gitignore 2025-01-25 17:37:33.000000000 +0100 @@ -5,20 +5,22 @@ develop-eggs/ dist/ build/ +wheelhouse/ dropin.cache pip-log.txt .installed.cfg .coverage tags TAGS -evdev/*.so -evdev/ecodes.c -evdev/iprops.c -docs/_build .#* __pycache__ .pytest_cache +.ruff_cache +evdev/*.so +evdev/ecodes.c +evdev/ecodes.pyi +docs/_build evdev/_ecodes.py evdev/_input.py evdev/_uinput.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/LICENSE new/python-evdev-1.8.0/LICENSE --- old/python-evdev-1.7.1/LICENSE 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/LICENSE 2025-01-25 17:37:33.000000000 +0100 @@ -1,4 +1,4 @@ -Copyright (c) 2012-2023 Georgi Valkov. All rights reserved. +Copyright (c) 2012-2025 Georgi Valkov. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/MANIFEST.in new/python-evdev-1.8.0/MANIFEST.in --- old/python-evdev-1.7.1/MANIFEST.in 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/MANIFEST.in 2025-01-25 17:37:33.000000000 +0100 @@ -2,3 +2,4 @@ # evdev headers of the running kernel. Refer to the 'build_ecodes' distutils # command in setup.py. exclude evdev/ecodes.c +include evdev/ecodes.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/README.md new/python-evdev-1.8.0/README.md --- old/python-evdev-1.7.1/README.md 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/README.md 2025-01-25 17:37:33.000000000 +0100 @@ -3,6 +3,7 @@ <p> <a href="https://pypi.python.org/pypi/evdev"><img alt="pypi version" src="https://img.shields.io/pypi/v/evdev.svg"></a> <a href="https://github.com/gvalkov/python-evdev/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/evdev"></a> + <a href="https://repology.org/project/python:evdev/versions"><img alt="Packaging status" src="https://repology.org/badge/tiny-repos/python:evdev.svg"></a> </p> This package provides bindings to the generic input event interface in Linux. Binary files old/python-evdev-1.7.1/docs/_static/evdev-logo-small.png and new/python-evdev-1.8.0/docs/_static/evdev-logo-small.png differ Binary files old/python-evdev-1.7.1/docs/_static/evdev-logo.png and new/python-evdev-1.8.0/docs/_static/evdev-logo.png differ Binary files old/python-evdev-1.7.1/docs/_static/github-logo.png and new/python-evdev-1.8.0/docs/_static/github-logo.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-archlinux.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-archlinux.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-debian.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-debian.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-fedora.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-fedora.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-linux-mint.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-linux-mint.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-opensuse.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-opensuse.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-raspbian.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-raspbian.png differ Binary files old/python-evdev-1.7.1/docs/_static/pacifica-icon-set/distributor-logo-ubuntu.png and new/python-evdev-1.8.0/docs/_static/pacifica-icon-set/distributor-logo-ubuntu.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/docs/changelog.rst new/python-evdev-1.8.0/docs/changelog.rst --- old/python-evdev-1.7.1/docs/changelog.rst 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/docs/changelog.rst 2025-01-25 17:37:33.000000000 +0100 @@ -1,6 +1,29 @@ Changelog --------- +1.8.0 (Jan 25, 2025) +================== + +- Binary wheels are now provided by the `evdev-binary http://pypi.python.org/pypi/evdev-binary`_ package. + The package is compiled on manylinux_2_28 against kernel 4.18. + +- The ``evdev.ecodes`` module is now generated at install time and contains only constants. This allows type + checking and introspection of the ``evdev.ecodes`` module, without having to execute it first. The old + module is available as ``evdev.ecodes_runtime``. In case generation of the static ``ecodes.py`` fails, the + install process falls back to using ``ecodes_runtime.py`` as ``ecodes.py``. + +- Reverse mappings in ``evdev.ecodes`` that point to more than one value are now tuples and not lists. For example:: + + >>> ecodes.KEY[153] + 153: ('KEY_DIRECTION', 'KEY_ROTATE_DISPLAY'), + +- Minimum Python version raised to Python 3.8. + +- Fix keyboard delay and repeat being swapped. + +- Move `syn()` convenience method from `InputDevice` to `EventIO`. + + 1.7.1 (May 8, 2024) ==================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/docs/conf.py new/python-evdev-1.8.0/docs/conf.py --- old/python-evdev-1.7.1/docs/conf.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/docs/conf.py 2025-01-25 17:37:33.000000000 +0100 @@ -67,7 +67,7 @@ # built documents. # # The full version, including alpha/beta/rc tags. -release = "1.7.1" +release = "1.8.0" # The short X.Y version. version = release @@ -130,7 +130,7 @@ # The name of an image file (relative to this directory) to place at the top # of the sidebar. -# html_logo = '_static/evdev-logo-small.png' +# html_logo = '' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/docs/install.rst new/python-evdev-1.8.0/docs/install.rst --- old/python-evdev-1.7.1/docs/install.rst 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/docs/install.rst 2025-01-25 17:37:33.000000000 +0100 @@ -1,31 +1,13 @@ -From a binary package -===================== - -Python-evdev has been packaged for the following GNU/Linux distributions: +From an OS package +================== +Python-evdev has been packaged for the following distributions: .. raw:: html - <div style="margin:1em;"> - <a href="https://www.archlinux.org/packages/extra/x86_64/python-evdev/"> - <img height="30px" src="_static/pacifica-icon-set/distributor-logo-archlinux.png"> - </a> - <a href="https://packages.debian.org/search?searchon=names&keywords=python-evdev"> - <img height="30px" src="_static/pacifica-icon-set/distributor-logo-debian.png"> + <a href="https://repology.org/project/python:evdev/versions"> + <img src="https://repology.org/badge/vertical-allrepos/python:evdev.svg?exclude_sources=modules,site&exclude_unsupported=1" alt="Packaging status"> </a> - <a href="https://packages.ubuntu.com/search?suite=default§ion=all&arch=any&keywords=python-evdev&searchon=names"> - <img height="30px" src="_static/pacifica-icon-set/distributor-logo-ubuntu.png"> - </a> - <a href="https://packages.fedoraproject.org/pkgs/python-evdev/python3-evdev/"> - <img height="30px" src="_static/pacifica-icon-set/distributor-logo-fedora.png"> - </a> - <!-- - <a href=""><img height="40px" src="_static/pacifica-icon-set/distributor-logo-raspbian.png"></a> - <a href=""><img height="40px" src="_static/pacifica-icon-set/distributor-logo-debian.png"></a> - <a href=""><img height="40px" src="_static/pacifica-icon-set/distributor-logo-linux-mint.png"></a> - <a href=""><img height="40px" src="_static/pacifica-icon-set/distributor-logo-opensuse.png"></a> - --!> - </div> Consult the documentation of your OS package manager for installation instructions. @@ -36,7 +18,7 @@ The latest stable version of *python-evdev* can be installed from pypi_, provided that you have a compiler, pip_ and the Python and Linux development headers installed on your system. Installing these is distribution specific and -typically falls in one of the following: +typically falls into one of the following: On a Debian compatible OS: @@ -58,22 +40,31 @@ $ pacman -S core/linux-api-headers python-pip gcc -Once all dependencies are available, you may install *python-evdev* using pip_: +Once all OS dependencies are available, you may install *python-evdev* using +pip_, preferably in a [virtualenv]_: .. code-block:: bash - $ sudo pip install evdev # available globally - $ pip install --user evdev # available to the current user + # Install globally (not recommended). + $ sudo python3 -m pip install evdev + + # Install for the current user. + $ python3 -m pip install --user evdev + + # Install in a virtual environment. + $ python3 -m venv abc + $ source abc/bin/activate + $ python3 -m pip install evdev Specifying header locations -=========================== +--------------------------- By default, the setup script will look for the ``input.h`` and ``input-event-codes.h`` [#f1]_ header files ``/usr/include/linux``. You may use the ``--evdev-headers`` option to the ``build_ext`` setuptools -command to the location of these header files. It accepts one or more +command to the location of these header files. It accepts one or more colon-separated paths. For example: .. code-block:: bash @@ -83,11 +74,27 @@ --include-dirs buildroot/ \ install # or any other command (e.g. develop, bdist, bdist_wheel) -.. [#f1] ``input-event-codes.h`` is found only in more recent kernel versions. + +From a binary package +===================== + +You may choose to install a precompiled version of *python-evdev* from pypi. The +`evdev-binary`_ package provides binary wheels that have been compiled on EL8 +against the 4.18.0 kernel headers. + +.. code-block:: bash + + $ python3 -m pip install evdev-binary + +While the evdev interface is stable, the precompiled version may not be fully +compatible or expose all the features of your running kernel. For best results, +it is recommended to use an OS package or to install from source. +.. [#f1] ``input-event-codes.h`` is found only in recent kernel versions. .. _pypi: http://pypi.python.org/pypi/evdev +.. _evdev-binary: http://pypi.python.org/pypi/evdev-binary .. _github: https://github.com/gvalkov/python-evdev .. _pip: http://pip.readthedocs.org/en/latest/installing.html .. _example: https://github.com/gvalkov/python-evdev/tree/master/examples -.. _`async/await`: https://docs.python.org/3/library/asyncio-task.html +.. _virtualenv: https://docs.python.org/3/library/venv.html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/docs/tutorial.rst new/python-evdev-1.8.0/docs/tutorial.rst --- old/python-evdev-1.7.1/docs/tutorial.rst 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/docs/tutorial.rst 2025-01-25 17:37:33.000000000 +0100 @@ -451,9 +451,10 @@ repeat_count = 1 effect_id = dev.upload_effect(effect) dev.write(ecodes.EV_FF, effect_id, repeat_count) - time.sleep(duration_ms) + time.sleep(duration_ms / 1000) dev.erase_effect(effect_id) + Forwarding force-feedback from uinput to a real device ====================================================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/__init__.py new/python-evdev-1.8.0/evdev/__init__.py --- old/python-evdev-1.7.1/evdev/__init__.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/__init__.py 2025-01-25 17:37:33.000000000 +0100 @@ -2,9 +2,8 @@ # Gather everything into a single, convenient namespace. # -------------------------------------------------------------------------- -from evdev.device import DeviceInfo, InputDevice, AbsInfo, EvdevError -from evdev.events import InputEvent, KeyEvent, RelEvent, SynEvent, AbsEvent, event_factory -from evdev.uinput import UInput, UInputError -from evdev.util import list_devices, categorize, resolve_ecodes, resolve_ecodes_dict -from evdev import ecodes -from evdev import ff +from . import ecodes, ff +from .device import AbsInfo, DeviceInfo, EvdevError, InputDevice +from .events import AbsEvent, InputEvent, KeyEvent, RelEvent, SynEvent, event_factory +from .uinput import UInput, UInputError +from .util import categorize, list_devices, resolve_ecodes, resolve_ecodes_dict diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/device.py new/python-evdev-1.8.0/evdev/device.py --- old/python-evdev-1.7.1/evdev/device.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/device.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,23 +1,22 @@ # encoding: utf-8 +import collections +import contextlib import os import warnings -import contextlib -import collections -from evdev import _input, ecodes, util -from evdev.events import InputEvent +from . import _input, ecodes, util try: - from evdev.eventio_async import EventIO, EvdevError + from .eventio_async import EvdevError, EventIO except ImportError: - from evdev.eventio import EventIO, EvdevError + from .eventio import EvdevError, EventIO # -------------------------------------------------------------------------- _AbsInfo = collections.namedtuple("AbsInfo", ["value", "min", "max", "fuzz", "flat", "resolution"]) -_KbdInfo = collections.namedtuple("KbdInfo", ["repeat", "delay"]) +_KbdInfo = collections.namedtuple("KbdInfo", ["delay", "repeat"]) _DeviceInfo = collections.namedtuple("DeviceInfo", ["bustype", "vendor", "product", "version"]) @@ -70,16 +69,16 @@ Attributes ---------- - repeat - Keyboard repeat rate in characters per second. - delay Amount of time that a key must be depressed before it will start to repeat (in milliseconds). + + repeat + Keyboard repeat rate in characters per second. """ def __str__(self): - return "repeat {}, delay {}".format(*self) + return "delay {}, repeat {}".format(*self) class DeviceInfo(_DeviceInfo): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/ecodes.py new/python-evdev-1.8.0/evdev/ecodes.py --- old/python-evdev-1.7.1/evdev/ecodes.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/ecodes.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,101 +1,5 @@ -""" -This modules exposes the integer constants defined in ``linux/input.h`` and -``linux/input-event-codes.h``. +# When installed, this module is replaced by an ecodes.py generated at +# build time by genecodes_py.py (see build_ext in setup.py). -Exposed constants:: - - KEY, ABS, REL, SW, MSC, LED, BTN, REP, SND, ID, EV, - BUS, SYN, FF, FF_STATUS, INPUT_PROP - -This module also provides reverse and forward mappings of the names and values -of the above mentioned constants:: - - >>> evdev.ecodes.KEY_A - 30 - - >>> evdev.ecodes.ecodes['KEY_A'] - 30 - - >>> evdev.ecodes.KEY[30] - 'KEY_A' - - >>> evdev.ecodes.REL[0] - 'REL_X' - - >>> evdev.ecodes.EV[evdev.ecodes.EV_KEY] - 'EV_KEY' - - >>> evdev.ecodes.bytype[evdev.ecodes.EV_REL][0] - 'REL_X' - -Keep in mind that values in reverse mappings may point to one or more event -codes. For example:: - - >>> evdev.ecodes.FF[80] - ['FF_EFFECT_MIN', 'FF_RUMBLE'] - - >>> evdev.ecodes.FF[81] - 'FF_PERIODIC' -""" - -from inspect import getmembers -from evdev import _ecodes - - -#: Mapping of names to values. -ecodes = {} - -prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP" -prev_prefix = "" -g = globals() - -# eg. code: 'REL_Z', val: 2 -for code, val in getmembers(_ecodes): - for prefix in prefixes.split(): # eg. 'REL' - if code.startswith(prefix): - ecodes[code] = val - # FF_STATUS codes should not appear in the FF reverse mapping - if not code.startswith(prev_prefix): - d = g.setdefault(prefix, {}) - # codes that share the same value will be added to a list. eg: - # >>> ecodes.FF_STATUS - # {0: 'FF_STATUS_STOPPED', 1: ['FF_STATUS_MAX', 'FF_STATUS_PLAYING']} - if val in d: - if isinstance(d[val], list): - d[val].append(code) - else: - d[val] = [d[val], code] - else: - d[val] = code - - prev_prefix = prefix - -#: Keys are a combination of all BTN and KEY codes. -keys = {} -keys.update(BTN) -keys.update(KEY) - -# make keys safe to use for the default list of uinput device -# capabilities -del keys[_ecodes.KEY_MAX] -del keys[_ecodes.KEY_CNT] - -#: Mapping of event types to other value/name mappings. -bytype = { - _ecodes.EV_KEY: keys, - _ecodes.EV_ABS: ABS, - _ecodes.EV_REL: REL, - _ecodes.EV_SW: SW, - _ecodes.EV_MSC: MSC, - _ecodes.EV_LED: LED, - _ecodes.EV_REP: REP, - _ecodes.EV_SND: SND, - _ecodes.EV_SYN: SYN, - _ecodes.EV_FF: FF, - _ecodes.EV_FF_STATUS: FF_STATUS, -} - -from evdev._ecodes import * - -# cheaper than whitelisting in an __all__ -del code, val, prefix, getmembers, g, d, prefixes, prev_prefix +# This stub exists to make development of evdev itself more convenient. +from . ecodes_runtime import * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/ecodes_runtime.py new/python-evdev-1.8.0/evdev/ecodes_runtime.py --- old/python-evdev-1.7.1/evdev/ecodes_runtime.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/evdev/ecodes_runtime.py 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,111 @@ +# pylint: disable=undefined-variable +""" +This modules exposes the integer constants defined in ``linux/input.h`` and +``linux/input-event-codes.h``. + +Exposed constants:: + + KEY, ABS, REL, SW, MSC, LED, BTN, REP, SND, ID, EV, + BUS, SYN, FF, FF_STATUS, INPUT_PROP + +This module also provides reverse and forward mappings of the names and values +of the above mentioned constants:: + + >>> evdev.ecodes.KEY_A + 30 + + >>> evdev.ecodes.ecodes['KEY_A'] + 30 + + >>> evdev.ecodes.KEY[30] + 'KEY_A' + + >>> evdev.ecodes.REL[0] + 'REL_X' + + >>> evdev.ecodes.EV[evdev.ecodes.EV_KEY] + 'EV_KEY' + + >>> evdev.ecodes.bytype[evdev.ecodes.EV_REL][0] + 'REL_X' + +Keep in mind that values in reverse mappings may point to one or more event +codes. For example:: + + >>> evdev.ecodes.FF[80] + ('FF_EFFECT_MIN', 'FF_RUMBLE') + + >>> evdev.ecodes.FF[81] + 'FF_PERIODIC' +""" + +from inspect import getmembers + +from . import _ecodes + +#: Mapping of names to values. +ecodes = {} + +prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP".split() +prev_prefix = "" +g = globals() + +# eg. code: 'REL_Z', val: 2 +for code, val in getmembers(_ecodes): + for prefix in prefixes: # eg. 'REL' + if code.startswith(prefix): + ecodes[code] = val + # FF_STATUS codes should not appear in the FF reverse mapping + if not code.startswith(prev_prefix): + d = g.setdefault(prefix, {}) + # codes that share the same value will be added to a list. eg: + # >>> ecodes.FF_STATUS + # {0: 'FF_STATUS_STOPPED', 1: ['FF_STATUS_MAX', 'FF_STATUS_PLAYING']} + if val in d: + if isinstance(d[val], list): + d[val].append(code) + else: + d[val] = [d[val], code] + else: + d[val] = code + + prev_prefix = prefix + + +# Convert lists to tuples. +k, v = None, None +for prefix in prefixes: + for k, v in g[prefix].items(): + if isinstance(v, list): + g[prefix][k] = tuple(v) + + +#: Keys are a combination of all BTN and KEY codes. +keys = {} +keys.update(BTN) +keys.update(KEY) + +# make keys safe to use for the default list of uinput device +# capabilities +del keys[_ecodes.KEY_MAX] +del keys[_ecodes.KEY_CNT] + +#: Mapping of event types to other value/name mappings. +bytype = { + _ecodes.EV_KEY: keys, + _ecodes.EV_ABS: ABS, + _ecodes.EV_REL: REL, + _ecodes.EV_SW: SW, + _ecodes.EV_MSC: MSC, + _ecodes.EV_LED: LED, + _ecodes.EV_REP: REP, + _ecodes.EV_SND: SND, + _ecodes.EV_SYN: SYN, + _ecodes.EV_FF: FF, + _ecodes.EV_FF_STATUS: FF_STATUS, +} + +from evdev._ecodes import * + +# cheaper than whitelisting in an __all__ +del code, val, prefix, getmembers, g, d, k, v, prefixes, prev_prefix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/eventio.py new/python-evdev-1.8.0/evdev/eventio.py --- old/python-evdev-1.7.1/evdev/eventio.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/eventio.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,10 +1,10 @@ -import os import fcntl -import select import functools +import os +import select -from evdev import _input, _uinput, ecodes, util -from evdev.events import InputEvent +from . import _input, _uinput, ecodes +from .events import InputEvent # -------------------------------------------------------------------------- @@ -72,6 +72,7 @@ for event in events: yield InputEvent(*event) + # pylint: disable=no-self-argument def need_write(func): """ Decorator that raises :class:`EvdevError` if there is no write access to the @@ -82,6 +83,7 @@ def wrapper(*args): fd = args[0].fd if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR: + # pylint: disable=not-callable return func(*args) msg = 'no write access to device "%s"' % args[0].path raise EvdevError(msg) @@ -136,5 +138,14 @@ _uinput.write(self.fd, etype, code, value) + def syn(self): + """ + Inject a ``SYN_REPORT`` event into the input subsystem. Events + queued by :func:`write()` will be fired. If possible, events + will be merged into an 'atomic' event. + """ + + self.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0) + def close(self): pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/eventio_async.py new/python-evdev-1.8.0/evdev/eventio_async.py --- old/python-evdev-1.7.1/evdev/eventio_async.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/eventio_async.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,10 +1,10 @@ import asyncio import select -from evdev import eventio +from . import eventio # needed for compatibility -from evdev.eventio import EvdevError +from .eventio import EvdevError class EventIO(eventio.EventIO): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/events.py new/python-evdev-1.8.0/evdev/events.py --- old/python-evdev-1.7.1/evdev/events.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/events.py 2025-01-25 17:37:33.000000000 +0100 @@ -37,7 +37,8 @@ # event type descriptions have been taken mot-a-mot from: # http://www.kernel.org/doc/Documentation/input/event-codes.txt -from evdev.ecodes import keys, KEY, SYN, REL, ABS, EV_KEY, EV_REL, EV_ABS, EV_SYN +# pylint: disable=no-name-in-module +from .ecodes import ABS, EV_ABS, EV_KEY, EV_REL, EV_SYN, KEY, REL, SYN, keys class InputEvent: @@ -65,13 +66,13 @@ """Return event timestamp as a float.""" return self.sec + (self.usec / 1000000.0) - def __str__(s): + def __str__(self): msg = "event at {:f}, code {:02d}, type {:02d}, val {:02d}" - return msg.format(s.timestamp(), s.code, s.type, s.value) + return msg.format(self.timestamp(), self.code, self.type, self.value) - def __repr__(s): + def __repr__(self): msg = "{}({!r}, {!r}, {!r}, {!r}, {!r})" - return msg.format(s.__class__.__name__, s.sec, s.usec, s.type, s.code, s.value) + return msg.format(self.__class__.__name__, self.sec, self.usec, self.type, self.code, self.value) class KeyEvent: @@ -119,8 +120,8 @@ msg = "key event at {:f}, {} ({}), {}" return msg.format(self.event.timestamp(), self.scancode, self.keycode, ks) - def __repr__(s): - return "{}({!r})".format(s.__class__.__name__, s.event) + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) class RelEvent: @@ -136,8 +137,8 @@ msg = "relative axis event at {:f}, {}" return msg.format(self.event.timestamp(), REL[self.event.code]) - def __repr__(s): - return "{}({!r})".format(s.__class__.__name__, s.event) + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) class AbsEvent: @@ -153,8 +154,8 @@ msg = "absolute axis event at {:f}, {}" return msg.format(self.event.timestamp(), ABS[self.event.code]) - def __repr__(s): - return "{}({!r})".format(s.__class__.__name__, s.event) + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) class SynEvent: @@ -173,8 +174,8 @@ msg = "synchronization event at {:f}, {}" return msg.format(self.event.timestamp(), SYN[self.event.code]) - def __repr__(s): - return "{}({!r})".format(s.__class__.__name__, s.event) + def __repr__(self): + return "{}({!r})".format(self.__class__.__name__, self.event) #: A mapping of event types to :class:`InputEvent` sub-classes. Used diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/evtest.py new/python-evdev-1.8.0/evdev/evtest.py --- old/python-evdev-1.7.1/evdev/evtest.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/evtest.py 2025-01-25 17:37:33.000000000 +0100 @@ -16,21 +16,15 @@ evtest /dev/input/event0 /dev/input/event1 """ -from __future__ import print_function +import atexit +import optparse import re -import sys import select -import atexit +import sys import termios -import optparse - -try: - input = raw_input -except NameError: - pass -from evdev import ecodes, list_devices, AbsInfo, InputDevice +from . import AbsInfo, InputDevice, ecodes, list_devices def parseopt(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/ff.py new/python-evdev-1.8.0/evdev/ff.py --- old/python-evdev-1.7.1/evdev/ff.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/ff.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,6 +1,6 @@ import ctypes -from evdev import ecodes +from . import ecodes _u8 = ctypes.c_uint8 _u16 = ctypes.c_uint16 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/genecodes.py new/python-evdev-1.8.0/evdev/genecodes.py --- old/python-evdev-1.7.1/evdev/genecodes.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/genecodes.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -""" -Generate a Python extension module with the constants defined in linux/input.h. -""" - -from __future__ import print_function -import os, sys, re - - -# ----------------------------------------------------------------------------- -# The default header file locations to try. -headers = [ - "/usr/include/linux/input.h", - "/usr/include/linux/input-event-codes.h", - "/usr/include/linux/uinput.h", -] - -if sys.argv[1:]: - headers = sys.argv[1:] - - -# ----------------------------------------------------------------------------- -macro_regex = r"#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)" -macro_regex = re.compile(macro_regex) - -uname = list(os.uname()) -del uname[1] -uname = " ".join(uname) - - -# ----------------------------------------------------------------------------- -template = r""" -#include <Python.h> -#ifdef __FreeBSD__ -#include <dev/evdev/input.h> -#else -#include <linux/input.h> -#include <linux/uinput.h> -#endif - -/* Automatically generated by evdev.genecodes */ -/* Generated on %s */ - -#define MODULE_NAME "_ecodes" -#define MODULE_HELP "linux/input.h macros" - -static PyMethodDef MethodTable[] = { - { NULL, NULL, 0, NULL} -}; - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - MODULE_NAME, - MODULE_HELP, - -1, /* m_size */ - MethodTable, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; - -PyMODINIT_FUNC -PyInit__ecodes(void) -{ - PyObject* m = PyModule_Create(&moduledef); - if (m == NULL) return NULL; - -%s - - return m; -} -""" - - -def parse_header(header): - for line in open(header): - macro = macro_regex.search(line) - if macro: - yield " PyModule_AddIntMacro(m, %s);" % macro.group(1) - - -all_macros = [] -for header in headers: - try: - fh = open(header) - except (IOError, OSError): - continue - all_macros += parse_header(header) - -if not all_macros: - print("no input macros found in: %s" % " ".join(headers), file=sys.stderr) - sys.exit(1) - - -macros = os.linesep.join(all_macros) -print(template % (uname, macros)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/genecodes_c.py new/python-evdev-1.8.0/evdev/genecodes_c.py --- old/python-evdev-1.7.1/evdev/genecodes_c.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/evdev/genecodes_c.py 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,138 @@ +""" +Generate a Python extension module with the constants defined in linux/input.h. +""" + +import getopt +import os +import re +import sys + +# ----------------------------------------------------------------------------- +# The default header file locations to try. +headers = [ + "/usr/include/linux/input.h", + "/usr/include/linux/input-event-codes.h", + "/usr/include/linux/uinput.h", +] + +opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs"]) +if not opts: + print("usage: genecodes.py [--ecodes|--stubs] <headers>") + exit(2) + + +# ----------------------------------------------------------------------------- +macro_regex = r"#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)" +macro_regex = re.compile(macro_regex) + +# Uname without hostname. +uname = list(os.uname()) +uname = " ".join((uname[0], *uname[2:])) + + +# ----------------------------------------------------------------------------- +template_ecodes = r""" +#include <Python.h> +#ifdef __FreeBSD__ +#include <dev/evdev/input.h> +#else +#include <linux/input.h> +#include <linux/uinput.h> +#endif + +/* Automatically generated by evdev.genecodes */ +/* Generated on %s */ +/* Generated from %s */ + +#define MODULE_NAME "_ecodes" +#define MODULE_HELP "linux/input.h macros" + +static PyMethodDef MethodTable[] = { + { NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + MODULE_NAME, + MODULE_HELP, + -1, /* m_size */ + MethodTable, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC +PyInit__ecodes(void) +{ + PyObject* m = PyModule_Create(&moduledef); + if (m == NULL) return NULL; + +%s + + return m; +} +""" + + +template_stubs = r""" +# Automatically generated by evdev.genecodes +# Generated on %s +# Generated from %s + +# pylint: skip-file + +ecodes: dict[str, int] +keys: dict[int, str|list[str]] +bytype: dict[int, dict[int, str|list[str]]] + +KEY: dict[int, str|list[str]] +ABS: dict[int, str|list[str]] +REL: dict[int, str|list[str]] +SW: dict[int, str|list[str]] +MSC: dict[int, str|list[str]] +LED: dict[int, str|list[str]] +BTN: dict[int, str|list[str]] +REP: dict[int, str|list[str]] +SND: dict[int, str|list[str]] +ID: dict[int, str|list[str]] +EV: dict[int, str|list[str]] +BUS: dict[int, str|list[str]] +SYN: dict[int, str|list[str]] +FF_STATUS: dict[int, str|list[str]] +FF_INPUT_PROP: dict[int, str|list[str]] + +%s +""" + + +def parse_headers(headers=headers): + for header in headers: + try: + fh = open(header) + except (IOError, OSError): + continue + + for line in fh: + macro = macro_regex.search(line) + if macro: + yield macro.group(1) + + +all_macros = list(parse_headers()) +if not all_macros: + print("no input macros found in: %s" % " ".join(headers), file=sys.stderr) + sys.exit(1) + +# pylint: disable=possibly-used-before-assignment, used-before-assignment +if ("--ecodes", "") in opts: + body = (" PyModule_AddIntMacro(m, %s);" % macro for macro in all_macros) + template = template_ecodes +elif ("--stubs", "") in opts: + body = ("%s: int" % macro for macro in all_macros) + template = template_stubs + +body = os.linesep.join(body) +text = template % (uname, headers, body) +print(text.strip()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/genecodes_py.py new/python-evdev-1.8.0/evdev/genecodes_py.py --- old/python-evdev-1.7.1/evdev/genecodes_py.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/evdev/genecodes_py.py 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,53 @@ +import sys +from unittest import mock +from pprint import PrettyPrinter + +sys.modules["evdev.ecodes"] = mock.Mock() +from evdev import ecodes_runtime as ecodes + +pprint = PrettyPrinter(indent=2, sort_dicts=True, width=120).pprint + + +print("# Automatically generated by evdev.genecodes_py") +print() +print('"""') +print(ecodes.__doc__.strip()) +print('"""') + +print() +print("from typing import Final, Dict, Tuple, Union") +print() + +for name, value in ecodes.ecodes.items(): + print(f"{name}: Final[int] = {value}") +print() + +entries = [ + ("ecodes", "Dict[str, int]", "#: Mapping of names to values."), + ("bytype", "Dict[int, Dict[int, Union[str, Tuple[str]]]]", "#: Mapping of event types to other value/name mappings."), + ("keys", "Dict[int, Union[str, Tuple[str]]]", "#: Keys are a combination of all BTN and KEY codes."), + ("KEY", "Dict[int, Union[str, Tuple[str]]]", None), + ("ABS", "Dict[int, Union[str, Tuple[str]]]", None), + ("REL", "Dict[int, Union[str, Tuple[str]]]", None), + ("SW", "Dict[int, Union[str, Tuple[str]]]", None), + ("MSC", "Dict[int, Union[str, Tuple[str]]]", None), + ("LED", "Dict[int, Union[str, Tuple[str]]]", None), + ("BTN", "Dict[int, Union[str, Tuple[str]]]", None), + ("REP", "Dict[int, Union[str, Tuple[str]]]", None), + ("SND", "Dict[int, Union[str, Tuple[str]]]", None), + ("ID", "Dict[int, Union[str, Tuple[str]]]", None), + ("EV", "Dict[int, Union[str, Tuple[str]]]", None), + ("BUS", "Dict[int, Union[str, Tuple[str]]]", None), + ("SYN", "Dict[int, Union[str, Tuple[str]]]", None), + ("FF", "Dict[int, Union[str, Tuple[str]]]", None), + ("FF_STATUS", "Dict[int, Union[str, Tuple[str]]]", None), + ("INPUT_PROP", "Dict[int, Union[str, Tuple[str]]]", None) +] + +for key, annotation, doc in entries: + if doc: + print(doc) + + print(f"{key}: {annotation} = ", end="") + pprint(getattr(ecodes, key)) + print() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/uinput.py new/python-evdev-1.8.0/evdev/uinput.py --- old/python-evdev-1.7.1/evdev/uinput.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/uinput.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,3 +1,4 @@ +import ctypes import os import platform import re @@ -5,11 +6,8 @@ import time from collections import defaultdict -from evdev import _uinput -from evdev import ecodes, util, device -from evdev.events import InputEvent -import evdev.ff as ff -import ctypes +from . import _uinput, device, ecodes, ff, util +from .events import InputEvent try: from evdev.eventio_async import EventIO @@ -227,15 +225,6 @@ _uinput.close(self.fd) self.fd = -1 - def syn(self): - """ - Inject a ``SYN_REPORT`` event into the input subsystem. Events - queued by :func:`write()` will be fired. If possible, events - will be merged into an 'atomic' event. - """ - - _uinput.write(self.fd, ecodes.EV_SYN, ecodes.SYN_REPORT, 0) - def capabilities(self, verbose=False, absinfo=True): """See :func:`capabilities <evdev.device.InputDevice.capabilities>`.""" if self.device is None: @@ -277,13 +266,11 @@ 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 - except (IndexError, OSError): - msg = '"{}" does not exist or is not a character device file ' "- verify that the uinput module is loaded" + 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): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/evdev/util.py new/python-evdev-1.8.0/evdev/util.py --- old/python-evdev-1.7.1/evdev/util.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/evdev/util.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,11 +1,11 @@ -import re +import collections +import glob import os +import re import stat -import glob -import collections -from evdev import ecodes -from evdev.events import event_factory +from . import ecodes +from .events import event_factory def list_devices(input_device_dir="/dev/input"): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/pyproject.toml new/python-evdev-1.8.0/pyproject.toml --- old/python-evdev-1.7.1/pyproject.toml 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/pyproject.toml 2025-01-25 17:37:33.000000000 +0100 @@ -4,12 +4,12 @@ [project] name = "evdev" -version = "1.7.1" +version = "1.8.0" description = "Bindings to the Linux input handling subsystem" keywords = ["evdev", "input", "uinput"] readme = "README.md" license = {file = "LICENSE"} -requires-python = ">=3.6" +requires-python = ">=3.8" authors = [ { name="Georgi Valkov", email="georgi.t.val...@gmail.com" }, ] @@ -39,7 +39,7 @@ ignore = ["E265", "E241", "F403", "F401", "E401", "E731"] [tool.bumpversion] -current_version = "1.7.1" +current_version = "1.8.0" commit = true tag = true allow_dirty = true @@ -49,3 +49,12 @@ [[tool.bumpversion.files]] filename = "docs/conf.py" + +[tool.pylint.'MESSAGES CONTROL'] +disable = """ + no-member, +""" + +[tool.pylint.typecheck] +generated-members = ["evdev.ecodes.*"] +ignored-modules= ["evdev._*"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/requirements-dev.txt new/python-evdev-1.8.0/requirements-dev.txt --- old/python-evdev-1.7.1/requirements-dev.txt 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/requirements-dev.txt 2025-01-25 17:37:33.000000000 +0100 @@ -6,3 +6,4 @@ bump-my-version ~= 0.17.4 build twine +cibuildwheel diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/scripts/build-binary.sh new/python-evdev-1.8.0/scripts/build-binary.sh --- old/python-evdev-1.7.1/scripts/build-binary.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/scripts/build-binary.sh 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -o allexport +set -o nounset + +CIBW_MANYLINUX_X86_64_IMAGE="manylinux_2_28" +CIBW_MANYLINUX_I686_IMAGE="manylinux_2_28" +CIBW_CONTAINER_ENGINE="podman" +CIBW_SKIP="cp36-*" +CIBW_ARCHS_LINUX="auto64" +CIBW_BEFORE_ALL_LINUX=./scripts/cibw-before.sh +CIBW_TEST_COMMAND="python -c 'import evdev; print(evdev)'" +CIBW_ENVIRONMENT="PACKAGE_NAME=evdev-binary" + +exec cibuildwheel \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/scripts/cibw-before.sh new/python-evdev-1.8.0/scripts/cibw-before.sh --- old/python-evdev-1.7.1/scripts/cibw-before.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/python-evdev-1.8.0/scripts/cibw-before.sh 2025-01-25 17:37:33.000000000 +0100 @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + + +if [ -n "$PACKAGE_NAME" ]; then + sed -i -re 's,^(name = ")evdev("),\1'${PACKAGE_NAME}'\2,' pyproject.toml +fi \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/setup.py new/python-evdev-1.8.0/setup.py --- old/python-evdev-1.7.1/setup.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/setup.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,14 +1,16 @@ import os import sys +import shutil import textwrap from pathlib import Path +from subprocess import run from setuptools import setup, Extension, Command from setuptools.command import build_ext as _build_ext curdir = Path(__file__).resolve().parent -ecodes_path = curdir / "evdev/ecodes.c" +ecodes_c_path = curdir / "evdev/ecodes.c" def create_ecodes(headers=None): @@ -47,16 +49,18 @@ build_ecodes --evdev-headers path/input.h:path/input-event-codes.h \\ build_ext --include-dirs path/ \\ install + + If you want to avoid building this package from source, then please consider + installing the `evdev-binary` package instead. Keep in mind that it may not be + fully compatible with, or support all the features of your current kernel. """ sys.stderr.write(textwrap.dedent(msg)) sys.exit(1) - from subprocess import run - - print("writing %s (using %s)" % (ecodes_path, " ".join(headers))) - with ecodes_path.open("w") as fh: - cmd = [sys.executable, "evdev/genecodes.py", *headers] + print("writing %s (using %s)" % (ecodes_c_path, " ".join(headers))) + with ecodes_c_path.open("w") as fh: + cmd = [sys.executable, "evdev/genecodes_c.py", "--ecodes", *headers] run(cmd, check=True, stdout=fh) @@ -80,14 +84,27 @@ class build_ext(_build_ext.build_ext): def has_ecodes(self): - if ecodes_path.exists(): + if ecodes_c_path.exists(): print("ecodes.c already exists ... skipping build_ecodes") - return not ecodes_path.exists() + return False + return True + + def generate_ecodes_py(self): + ecodes_py = Path(self.build_lib) / "evdev/ecodes.py" + print(f"writing {ecodes_py}") + with ecodes_py.open("w") as fh: + cmd = [sys.executable, "-B", "evdev/genecodes_py.py"] + res = run(cmd, env={"PYTHONPATH": self.build_lib}, stdout=fh) + + if res.returncode != 0: + print(f"failed to generate static {ecodes_py} - will use ecodes_runtime.py") + shutil.copy("evdev/ecodes_runtime.py", ecodes_py) def run(self): for cmd_name in self.get_sub_commands(): self.run_command(cmd_name) _build_ext.build_ext.run(self) + self.generate_ecodes_py() sub_commands = [("build_ecodes", has_ecodes)] + _build_ext.build_ext.sub_commands diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-evdev-1.7.1/tests/test_uinput.py new/python-evdev-1.8.0/tests/test_uinput.py --- old/python-evdev-1.7.1/tests/test_uinput.py 2024-05-08 01:01:20.000000000 +0200 +++ new/python-evdev-1.8.0/tests/test_uinput.py 2025-01-25 17:37:33.000000000 +0100 @@ -1,10 +1,13 @@ # encoding: utf-8 - +import os +import stat from select import select -from pytest import raises, fixture +from unittest.mock import patch -from evdev import uinput, ecodes, events, device, util +import pytest +from pytest import raises, fixture +from evdev import uinput, ecodes, device, UInputError # ----------------------------------------------------------------------------- uinput_options = { @@ -66,12 +69,12 @@ def test_abs_values(c): e = ecodes - c["events"] = { + c = { e.EV_KEY: [e.KEY_A, e.KEY_B], - e.EV_ABS: [(e.ABS_X, (0, 255, 0, 0)), (e.ABS_Y, device.AbsInfo(0, 255, 5, 10, 0, 0))], + e.EV_ABS: [(e.ABS_X, (0, 0, 255, 0, 0)), (e.ABS_Y, device.AbsInfo(0, 0, 255, 5, 10, 0))], } - with uinput.UInput(**c) as ui: + with uinput.UInput(events=c) as ui: c = ui.capabilities() abs = device.AbsInfo(value=0, min=0, max=255, fuzz=0, flat=0, resolution=0) assert c[e.EV_ABS][0] == (0, abs) @@ -114,3 +117,21 @@ assert evs[3].code == ecodes.KEY_A and evs[3].value == 2 assert evs[4].code == ecodes.KEY_A and evs[4].value == 0 break + + +@patch.object(stat, 'S_ISCHR', return_value=False) +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)