mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-24 00:48:53 +03:00
bindings: python: drop python 3.9 support
* Update pyproject.toml to require Python 3.10+ for runtime * Update mypy's target version to 3.10 syntax * Drop ruff's target version as it's inferred by the project's requires-python value * Remove the linter settings that ignored UP007 & UP0045 * Update type annotations to conform to active linter rules Closes: https://github.com/brgl/libgpiod/issues/151 Signed-off-by: Vincent Fazio <vfazio@gmail.com> Link: https://patch.msgid.link/20260329182832.39824-1-vfazio@gmail.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
This commit is contained in:
committed by
Bartosz Golaszewski
parent
42fcd4c084
commit
950ff3d1b3
@@ -8,7 +8,6 @@ This module wraps the native C API of libgpiod in a set of python classes.
|
||||
"""
|
||||
|
||||
from collections.abc import Iterable
|
||||
from typing import Optional, Union
|
||||
|
||||
from . import (
|
||||
_ext,
|
||||
@@ -87,10 +86,10 @@ def is_gpiochip_device(path: str) -> bool:
|
||||
|
||||
def request_lines(
|
||||
path: str,
|
||||
config: dict[Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]],
|
||||
consumer: Optional[str] = None,
|
||||
event_buffer_size: Optional[int] = None,
|
||||
output_values: Optional[dict[Union[int, str], line.Value]] = None,
|
||||
config: dict[Iterable[int | str] | int | str, LineSettings | None],
|
||||
consumer: str | None = None,
|
||||
event_buffer_size: int | None = None,
|
||||
output_values: dict[int | str, line.Value] | None = None,
|
||||
) -> LineRequest:
|
||||
"""
|
||||
Open a GPIO chip pointed to by 'path', request lines according to the
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# SPDX-FileCopyrightText: 2024 Vincent Fazio <vfazio@gmail.com>
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from .chip_info import ChipInfo
|
||||
from .edge_event import EdgeEvent
|
||||
from .info_event import InfoEvent
|
||||
@@ -32,7 +30,7 @@ class Request:
|
||||
def get_values(self, offsets: list[int], values: list[Value]) -> None: ...
|
||||
def set_values(self, values: dict[int, Value]) -> None: ...
|
||||
def reconfigure_lines(self, line_cfg: LineConfig) -> None: ...
|
||||
def read_edge_events(self, max_events: Optional[int]) -> list[EdgeEvent]: ...
|
||||
def read_edge_events(self, max_events: int | None) -> list[EdgeEvent]: ...
|
||||
@property
|
||||
def chip_name(self) -> str: ...
|
||||
@property
|
||||
@@ -47,12 +45,12 @@ class Chip:
|
||||
def get_info(self) -> ChipInfo: ...
|
||||
def line_offset_from_id(self, id: str) -> int: ...
|
||||
def get_line_info(self, offset: int, watch: bool) -> LineInfo: ...
|
||||
def get_line_name(self, offset: int) -> Optional[str]: ...
|
||||
def get_line_name(self, offset: int) -> str | None: ...
|
||||
def request_lines(
|
||||
self,
|
||||
line_cfg: LineConfig,
|
||||
consumer: Optional[str],
|
||||
event_buffer_size: Optional[int],
|
||||
consumer: str | None,
|
||||
event_buffer_size: int | None,
|
||||
) -> Request: ...
|
||||
def read_info_event(self) -> InfoEvent: ...
|
||||
def close(self) -> None: ...
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from select import select
|
||||
from typing import TYPE_CHECKING, Optional, Union
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator, Iterable
|
||||
@@ -15,8 +15,8 @@ if TYPE_CHECKING:
|
||||
__all__ = ["poll_fd", "config_iter"]
|
||||
|
||||
|
||||
def poll_fd(fd: int, timeout: Optional[Union[timedelta, float]] = None) -> bool:
|
||||
sec: Union[float, None]
|
||||
def poll_fd(fd: int, timeout: timedelta | float | None = None) -> bool:
|
||||
sec: float | None
|
||||
if isinstance(timeout, timedelta):
|
||||
sec = timeout.total_seconds()
|
||||
else:
|
||||
@@ -27,8 +27,8 @@ def poll_fd(fd: int, timeout: Optional[Union[timedelta, float]] = None) -> bool:
|
||||
|
||||
|
||||
def config_iter(
|
||||
config: dict[Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]],
|
||||
) -> Generator[tuple[Union[int, str], Optional[LineSettings]]]:
|
||||
config: dict[Iterable[int | str] | int | str, LineSettings | None],
|
||||
) -> Generator[tuple[int | str, LineSettings | None]]:
|
||||
for key, settings in config.items():
|
||||
if isinstance(key, int) or isinstance(key, str):
|
||||
yield key, settings
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from errno import ENOENT
|
||||
from typing import TYPE_CHECKING, Optional, Union, cast
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from . import _ext
|
||||
from ._internal import config_iter, poll_fd
|
||||
@@ -60,8 +60,8 @@ class Chip:
|
||||
path:
|
||||
Path to the GPIO character device file.
|
||||
"""
|
||||
self._chip: Union[_ext.Chip, None] = _ext.Chip(path)
|
||||
self._info: Union[ChipInfo, None] = None
|
||||
self._chip: _ext.Chip | None = _ext.Chip(path)
|
||||
self._info: ChipInfo | None = None
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
"""
|
||||
@@ -81,9 +81,9 @@ class Chip:
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: Optional[type[BaseException]],
|
||||
exc_value: Optional[BaseException],
|
||||
traceback: Optional[TracebackType],
|
||||
exc_type: type[BaseException] | None,
|
||||
exc_value: BaseException | None,
|
||||
traceback: TracebackType | None,
|
||||
) -> None:
|
||||
"""
|
||||
Controlled execution exit callback.
|
||||
@@ -117,7 +117,7 @@ class Chip:
|
||||
|
||||
return self._info
|
||||
|
||||
def line_offset_from_id(self, id: Union[str, int]) -> int:
|
||||
def line_offset_from_id(self, id: str | int) -> int:
|
||||
"""
|
||||
Map a line's identifier to its offset within the chip.
|
||||
|
||||
@@ -155,13 +155,13 @@ class Chip:
|
||||
|
||||
return offset
|
||||
|
||||
def _get_line_info(self, line: Union[int, str], watch: bool) -> LineInfo:
|
||||
def _get_line_info(self, line: int | str, watch: bool) -> LineInfo:
|
||||
self._check_closed()
|
||||
return cast("_ext.Chip", self._chip).get_line_info(
|
||||
self.line_offset_from_id(line), watch
|
||||
)
|
||||
|
||||
def get_line_info(self, line: Union[int, str]) -> LineInfo:
|
||||
def get_line_info(self, line: int | str) -> LineInfo:
|
||||
"""
|
||||
Get the snapshot of information about the line at given offset.
|
||||
|
||||
@@ -174,7 +174,7 @@ class Chip:
|
||||
"""
|
||||
return self._get_line_info(line, watch=False)
|
||||
|
||||
def watch_line_info(self, line: Union[int, str]) -> LineInfo:
|
||||
def watch_line_info(self, line: int | str) -> LineInfo:
|
||||
"""
|
||||
Get the snapshot of information about the line at given offset and
|
||||
start watching it for future changes.
|
||||
@@ -188,7 +188,7 @@ class Chip:
|
||||
"""
|
||||
return self._get_line_info(line, watch=True)
|
||||
|
||||
def unwatch_line_info(self, line: Union[int, str]) -> None:
|
||||
def unwatch_line_info(self, line: int | str) -> None:
|
||||
"""
|
||||
Stop watching a line for status changes.
|
||||
|
||||
@@ -201,9 +201,7 @@ class Chip:
|
||||
self.line_offset_from_id(line)
|
||||
)
|
||||
|
||||
def wait_info_event(
|
||||
self, timeout: Optional[Union[timedelta, float]] = None
|
||||
) -> bool:
|
||||
def wait_info_event(self, timeout: timedelta | float | None = None) -> bool:
|
||||
"""
|
||||
Wait for line status change events on any of the watched lines on the
|
||||
chip.
|
||||
@@ -237,12 +235,10 @@ class Chip:
|
||||
|
||||
def request_lines(
|
||||
self,
|
||||
config: dict[
|
||||
Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]
|
||||
],
|
||||
consumer: Optional[str] = None,
|
||||
event_buffer_size: Optional[int] = None,
|
||||
output_values: Optional[dict[Union[int, str], Value]] = None,
|
||||
config: dict[Iterable[int | str] | int | str, LineSettings | None],
|
||||
consumer: str | None = None,
|
||||
event_buffer_size: int | None = None,
|
||||
output_values: dict[int | str, Value] | None = None,
|
||||
) -> LineRequest:
|
||||
"""
|
||||
Request a set of lines for exclusive usage.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import warnings
|
||||
from typing import TYPE_CHECKING, Optional, Union, cast
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from . import _ext
|
||||
from ._internal import config_iter, poll_fd
|
||||
@@ -33,11 +33,11 @@ class LineRequest:
|
||||
Note: LineRequest objects can only be instantiated by a Chip parent.
|
||||
LineRequest.__init__() is not part of stable API.
|
||||
"""
|
||||
self._req: Union[_ext.Request, None] = req
|
||||
self._req: _ext.Request | None = req
|
||||
self._chip_name: str
|
||||
self._offsets: list[int]
|
||||
self._name_map: dict[str, int]
|
||||
self._lines: list[Union[int, str]]
|
||||
self._lines: list[int | str]
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
"""
|
||||
@@ -57,9 +57,9 @@ class LineRequest:
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: Optional[type[BaseException]],
|
||||
exc_value: Optional[BaseException],
|
||||
traceback: Optional[TracebackType],
|
||||
exc_type: type[BaseException] | None,
|
||||
exc_value: BaseException | None,
|
||||
traceback: TracebackType | None,
|
||||
) -> None:
|
||||
"""
|
||||
Controlled execution exit callback.
|
||||
@@ -79,7 +79,7 @@ class LineRequest:
|
||||
cast("_ext.Request", self._req).release()
|
||||
self._req = None
|
||||
|
||||
def get_value(self, line: Union[int, str]) -> Value:
|
||||
def get_value(self, line: int | str) -> Value:
|
||||
"""
|
||||
Get a single GPIO line value.
|
||||
|
||||
@@ -92,16 +92,14 @@ class LineRequest:
|
||||
"""
|
||||
return self.get_values([line])[0]
|
||||
|
||||
def _line_to_offset(self, line: Union[int, str]) -> int:
|
||||
def _line_to_offset(self, line: int | str) -> int:
|
||||
if isinstance(line, int):
|
||||
return line
|
||||
if (_line := self._name_map.get(line)) is None:
|
||||
raise ValueError(f"unknown line name: {line}")
|
||||
return _line
|
||||
|
||||
def get_values(
|
||||
self, lines: Optional[Iterable[Union[int, str]]] = None
|
||||
) -> list[Value]:
|
||||
def get_values(self, lines: Iterable[int | str] | None = None) -> list[Value]:
|
||||
"""
|
||||
Get values of a set of GPIO lines.
|
||||
|
||||
@@ -124,7 +122,7 @@ class LineRequest:
|
||||
cast("_ext.Request", self._req).get_values(offsets, buf)
|
||||
return buf
|
||||
|
||||
def set_value(self, line: Union[int, str], value: Value) -> None:
|
||||
def set_value(self, line: int | str, value: Value) -> None:
|
||||
"""
|
||||
Set the value of a single GPIO line.
|
||||
|
||||
@@ -136,7 +134,7 @@ class LineRequest:
|
||||
"""
|
||||
self.set_values({line: value})
|
||||
|
||||
def set_values(self, values: dict[Union[int, str], Value]) -> None:
|
||||
def set_values(self, values: dict[int | str, Value]) -> None:
|
||||
"""
|
||||
Set the values of a subset of GPIO lines.
|
||||
|
||||
@@ -152,9 +150,7 @@ class LineRequest:
|
||||
|
||||
def reconfigure_lines(
|
||||
self,
|
||||
config: dict[
|
||||
Union[Iterable[Union[int, str]], int, str], Optional[LineSettings]
|
||||
],
|
||||
config: dict[Iterable[int | str] | int | str, LineSettings | None],
|
||||
) -> None:
|
||||
"""
|
||||
Reconfigure requested lines.
|
||||
@@ -196,9 +192,7 @@ class LineRequest:
|
||||
|
||||
cast("_ext.Request", self._req).reconfigure_lines(line_cfg)
|
||||
|
||||
def wait_edge_events(
|
||||
self, timeout: Optional[Union[timedelta, float]] = None
|
||||
) -> bool:
|
||||
def wait_edge_events(self, timeout: timedelta | float | None = None) -> bool:
|
||||
"""
|
||||
Wait for edge events on any of the requested lines.
|
||||
|
||||
@@ -215,7 +209,7 @@ class LineRequest:
|
||||
|
||||
return poll_fd(self.fd, timeout)
|
||||
|
||||
def read_edge_events(self, max_events: Optional[int] = None) -> list[EdgeEvent]:
|
||||
def read_edge_events(self, max_events: int | None = None) -> list[EdgeEvent]:
|
||||
"""
|
||||
Read a number of edge events from a line request.
|
||||
|
||||
@@ -271,7 +265,7 @@ class LineRequest:
|
||||
return self._offsets
|
||||
|
||||
@property
|
||||
def lines(self) -> list[Union[int, str]]:
|
||||
def lines(self) -> list[int | str]:
|
||||
"""
|
||||
List of requested lines. Lines requested by name are listed as such.
|
||||
"""
|
||||
|
||||
@@ -11,7 +11,7 @@ dynamic = ["version"]
|
||||
description = "Python bindings for libgpiod"
|
||||
readme = "README.md"
|
||||
license = "LGPL-2.1-or-later"
|
||||
requires-python = ">=3.9.0"
|
||||
requires-python = ">=3.10"
|
||||
authors = [
|
||||
{name = "Bartosz Golaszewski", email = "brgl@bgdev.pl"},
|
||||
]
|
||||
@@ -22,7 +22,6 @@ classifiers = [
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
@@ -46,7 +45,7 @@ include = ["gpiod"]
|
||||
namespaces = false
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.9"
|
||||
python_version = "3.10"
|
||||
files = [
|
||||
"gpiod/",
|
||||
"tests/",
|
||||
@@ -57,7 +56,7 @@ module = "gpiod.line.*"
|
||||
strict_equality = false # Ignore Enum comparison-overlap: https://github.com/python/mypy/issues/17317
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py39"
|
||||
target-version = "py310"
|
||||
include = [
|
||||
"gpiod/**/*.py",
|
||||
"gpiod/**/*.pyi",
|
||||
@@ -72,9 +71,6 @@ ignore=[
|
||||
"B904",
|
||||
# Never enforce line length violations. Let the formatter handle it: https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
||||
"E501",
|
||||
# Ignore new Union (|) syntax until we require 3.10+
|
||||
"UP007",
|
||||
"UP045",
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from . import _ext
|
||||
|
||||
@@ -27,10 +26,10 @@ class Chip:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
label: Optional[str] = None,
|
||||
num_lines: Optional[int] = None,
|
||||
line_names: Optional[dict[int, str]] = None,
|
||||
hogs: Optional[dict[int, tuple[str, Direction]]] = None,
|
||||
label: str | None = None,
|
||||
num_lines: int | None = None,
|
||||
line_names: dict[int, str] | None = None,
|
||||
hogs: dict[int, tuple[str, Direction]] | None = None,
|
||||
):
|
||||
self._chip = _ext.Chip()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from types import TracebackType
|
||||
@@ -20,8 +20,8 @@ class LinkGuard:
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
type: Optional[type[BaseException]],
|
||||
val: Optional[BaseException],
|
||||
tb: Optional[TracebackType],
|
||||
type: type[BaseException] | None,
|
||||
val: BaseException | None,
|
||||
tb: TracebackType | None,
|
||||
) -> None:
|
||||
os.unlink(self.dst)
|
||||
|
||||
@@ -6,7 +6,6 @@ from datetime import timedelta
|
||||
from functools import partial
|
||||
from select import select
|
||||
from threading import Thread
|
||||
from typing import Optional
|
||||
from unittest import TestCase
|
||||
|
||||
import gpiod
|
||||
@@ -56,7 +55,7 @@ class EdgeEventInvalidConfig(TestCase):
|
||||
class WaitingForEdgeEvents(TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.sim = gpiosim.Chip(num_lines=8)
|
||||
self.thread: Optional[Thread] = None
|
||||
self.thread: Thread | None = None
|
||||
|
||||
def tearDown(self) -> None:
|
||||
if self.thread:
|
||||
@@ -208,7 +207,7 @@ class PollLineRequestObject(TestCase):
|
||||
self.request = gpiod.request_lines(
|
||||
self.sim.dev_path, {2: gpiod.LineSettings(edge_detection=Edge.BOTH)}
|
||||
)
|
||||
self.thread: Optional[Thread] = None
|
||||
self.thread: Thread | None = None
|
||||
|
||||
def tearDown(self) -> None:
|
||||
if self.thread:
|
||||
|
||||
@@ -8,7 +8,6 @@ import time
|
||||
from dataclasses import FrozenInstanceError
|
||||
from functools import partial
|
||||
from select import select
|
||||
from typing import Optional
|
||||
from unittest import TestCase
|
||||
|
||||
import gpiod
|
||||
@@ -53,7 +52,7 @@ class WatchingInfoEventWorks(TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.sim = gpiosim.Chip(num_lines=8, line_names={4: "foobar"})
|
||||
self.chip = gpiod.Chip(self.sim.dev_path)
|
||||
self.thread: Optional[threading.Thread] = None
|
||||
self.thread: threading.Thread | None = None
|
||||
|
||||
def tearDown(self) -> None:
|
||||
if self.thread:
|
||||
|
||||
@@ -234,7 +234,7 @@ AM_CONDITIONAL([WITH_BINDINGS_PYTHON], [test "x$with_bindings_python" = xtrue])
|
||||
|
||||
if test "x$with_bindings_python" = xtrue
|
||||
then
|
||||
AM_PATH_PYTHON([3.9], [],
|
||||
AM_PATH_PYTHON([3.10], [],
|
||||
[AC_MSG_ERROR([python3 not found - needed for python bindings])])
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user