1
0
mirror of https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git synced 2026-10-24 00:48:53 +03:00
Commit Graph

498 Commits

Author SHA1 Message Date
Bartosz Golaszewski
3076847a6c bindings: python: gpiod v2.5.0
Changelog:
- add support for free-threaded (no-GIL) CPython
- generate wheels for CPython 3.14t (free-threaded)
- drop support for Python 3.9
- migrate the C extension and test modules to multi-phase module
  initialization
- release the GIL in chip_get_info()
- fix heap-buffer overflow bugs when setting/getting line values
- check for errors after PyIter_Next() when setting output values
- check for errors after PyIter_Next() when reading request values
- fix reference count imbalances (missing Py_None and line-name
  increments, erroneous decref on PyList_SetItem() failure)
- allow closing a Chip multiple times without raising an error
- allow releasing a LineRequest multiple times without raising an error
- remove a duplicated edge-detection setting
- add a CHANGELOG.md to track changes between releases
- copy the license file into source and binary distributions
- require setuptools v77 or newer
- remove wheel from the build dependencies
- add multi-threaded tests
- add a dedicated lint dependency group and update linter configuration
- apply linter recommendations and add type annotations across examples,
  setup and helper scripts
- modernize the C extension using upgrade_pythoncapi.py suggestions
- minor internal cleanups and performance improvements

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-17 09:20:20 +02:00
Bartosz Golaszewski
31e184a41e bindings: python: use the correct libgpiod API version define in setup.py
Since commit a62c732936 ("core: change the behavior of
gpiod_api_version()"), the libgpiod build expects the
GPIOD_API_VERSION_STR external define to contain the API version string.
The setup.py script in python bindings was not updated so it fails to
build the library sources into the generated wheel. Use the correct
define.

Fixes: a62c732936 ("core: change the behavior of gpiod_api_version()")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-17 09:13:19 +02:00
Bartosz Golaszewski
d7d6ae8dd4 bindings: python: release the GIL in chip_get_info()
Other methods that call into the C library (chip_get_line_info,
chip_watch_line_info, etc.) properly release the GIL with
Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS, but chip_get_info() was
missed. Add the missing GIL release for consistency and to avoid
blocking other Python threads during the ioctl.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Assisted-by: Claude Opus 4.6
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-14-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
e6fb6554e9 bindings: python: check for errors after PyIter_Next() in set_output_values
PyIter_Next() returns NULL both at end-of-iteration and when an exception
is raised. The code breaks out of the loop without checking
PyErr_Occurred(), potentially swallowing Python exceptions and continuing
with a partially filled buffer.

Add the missing error check.

Fixes: 27a69b0bfd ("bindings: python: add the output_values argument to Chip.request_lines()")
Assisted-by: Claude Opus 4.6
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-13-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
3c04ff9949 bindings: python: check for errors after PyIter_Next() in request_get_values
PyIter_Next() returns NULL both at end-of-iteration and when an exception
is raised. The code breaks out of the loop without checking
PyErr_Occurred(), potentially swallowing Python exceptions and continuing
with a partially filled buffer.

Add the missing error check.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Assisted-by: Claude Opus 4.6
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-12-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
62283cc98c bindings: rust: use repr(transparent) on edge Event and simplify casts
The Event struct wraps a single *mut gpiod_edge_event pointer and is cast
from raw pointers in event_buffer.rs. Without #[repr(transparent)], the
layout compatibility is not guaranteed by the language specification.

Add #[repr(transparent)] to make the pointer cast sound, and replace
try_into().unwrap() with a simple 'as' cast for the sequence number
getters since c_ulong and usize are the same width on Linux.

Fixes: 91f9373c65 ("bindings: rust: Add libgpiod crate")
Assisted-by: Claude Opus 4.6
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-11-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
33a92137f1 bindings: rust: implement Eq and Ord for chip::Info
chip::Info already implements PartialEq and PartialOrd (both based on
comparing chip names as UTF-8 strings), but not their total-order
counterparts Eq and Ord. The omission is inconsistent: types with a
total order should implement Ord so callers can use the ergonomic sort()
/ min() / max() APIs.

Add the missing impls. Ord::cmp() delegates to partial_cmp() and falls
back to Ordering::Equal for the unreachable case where a chip name is
not valid UTF-8. Update gpiochip_devices() to use cmp() directly now
that Ord is available.

Assisted-by: Claude Sonnet 4.6
Acked-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-10-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
b94f9591e6 bindings: rust: avoid potential panic in gpiochip_devices()
chip::Info::partial_cmp() returns None when either chip name cannot be
decoded as UTF-8. Passing that None straight to unwrap() in
gpiochip_devices() would panic at runtime. Use unwrap_or(Ordering::Equal)
so that chips with undecodable names are treated as equal rather than
causing a panic.

Fixes: 91f9373c65 ("bindings: rust: Add libgpiod crate")
Assisted-by: Claude Sonnet 4.6
Acked-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-9-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
b5225b6d76 bindings: cxx: use get_mapped_value() for all enum mappings in line_info
The direction() method correctly uses get_mapped_value() which converts
std::out_of_range to the project's bad_mapping exception, but bias(),
drive(), edge_detection(), and event_clock() call .at() directly. This
causes them to throw std::out_of_range instead of the expected
bad_mapping exception on unexpected values.

Use get_mapped_value() consistently for all enum mapping lookups.

Fixes: 78020eae9d ("bindings: cxx: remove duplicate mapping helper")
Assisted-by: Claude Opus 4.6
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-8-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
e773070e6e bindings: cxx: drop redundant class qualifier in line_request::set_value
The definition of set_value() carried a duplicate class name prefix
(line_request::line_request::set_value) which compiles correctly but
is misleading and inconsistent with every other method definition in
the same file.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Assisted-by: Claude Sonnet 4.6
Acked-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-7-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
f4ee1f36f9 bindings: cxx: fix consumer string in line_info stream operator
The consumer field in operator<< for line_info was using info.name()
instead of info.consumer() when building the quoted consumer string.
As a result any non-empty consumer would be printed as the line name,
not the actual consumer string.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Assisted-by: Claude Sonnet 4.6
Acked-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260604-pre-2-3-fixes-v2-6-781bcaf47475@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-08 10:01:21 +02:00
Bartosz Golaszewski
7950002228 build: display the summary of build options after meson setup
It's useful to know which options ended up really being selected by
meson (for instance for --auto-features) so use the dedicated meson
function to display the summary.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-06-02 14:51:32 +02:00
Vincent Fazio
c0650edd44 bindings: python: add a changelog
Add a changelog to summarize changes to the bindings between releases.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260527215922.18678-4-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-28 11:01:02 +02:00
Vincent Fazio
c9378d6c63 bindings: python: support free-threaded CPython
PEP 703 [0] discusses making the GIL optional in certain builds of the
CPython interpreter.

This build option was available experiementally in Python 3.13 but has
since been stabilized in Python 3.14 per PEP 779 [1].

According to the porting guide [2], there is no strict requirement that
C extensions must be thread-safe.

Experiments have shown that no logic changes are required if callers
use sychronization mechanisms provided by the Python standard library.

The documentation has been updated to call this out specifically using
terminology from the porting guide [3].

[0]: https://peps.python.org/pep-0703/
[1]: https://peps.python.org/pep-0779/
[2]: https://py-free-threading.github.io/porting/#define-and-document-thread-safety-guarantees
[3]: https://py-free-threading.github.io/documentation-principles/#free-threading-terminology

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260527215922.18678-3-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-28 10:59:30 +02:00
Vincent Fazio
9d8940f38f bindings: python: tests: add multi-threaded tests
Add new multi-threaded test cases to ensure the bindings operate as
expected and do not lead to crashes or data corruption.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260527215922.18678-2-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-28 10:59:12 +02:00
Bartosz Golaszewski
a7b443f2c7 bindings: python: don't decref objects on PyList_SetItem() failure
PyList_SetItem() steals the reference to the object we want to add
regardless of whether it succeeds or fails. Don't decrease the reference
count of the object we failed to add in error path.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Closes: https://github.com/brgl/libgpiod/issues/187
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260511111538.60844-1-bartosz.golaszewski@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-12 09:29:54 +02:00
Bartosz Golaszewski
b2b1267d1c docs: fix build with meson
Migration to meson broke the sphinx build for docs. Wire the gi-docgen
generation into the meson build and fix docs/conf.py to use the new
build system.

Fixes: 97bab4cc87 ("build: replace autotools with meson & ninja")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-04 12:32:04 +02:00
Bartosz Golaszewski
a7f3feb1a6 build: put the project URL in one place
Define and ue the project_url variable instead of repeating the URL in
several places.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-04 12:30:02 +02:00
Bartosz Golaszewski
78bfc44f0d bindings: rust: remove leftover autotools bits
Remove leftover mentions of Makefiles from Cargo.toml files in rust
bindings. They are no longer needed after the migration to meson.

Fixes: 97bab4cc87 ("build: replace autotools with meson & ninja")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-04 11:40:01 +02:00
Bartosz Golaszewski
1dc5b7eccf build: remove leftover autotools .pc.in templates
The meson build already generates all pkg-config files via
pkgconfig.generate() in the respective meson.build files. The .pc.in
templates were not cleaned up during the autotools-to-meson migration
and are dead code. Drop them.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-04 11:04:20 +02:00
Bartosz Golaszewski
97bab4cc87 build: replace autotools with meson & ninja
Port the project from autotools to meson. All build options are
preserved with the same semantics.

The goal of this change is to produce the same set of files as the
current autotools approach: libraries with correct SONAME/version,
headers, pkg-config files, GObject introspection data, Python extension
modules, D-Bus interface and configuration files. This is done to enable
a one-liner test command running all available test suites.

The only thing we drop is the `make docs` target as it's rarely used and
docs can be generated easily with sphinx directly. They are also not
required for testing.

The Rust workspace is built via a custom target that invokes cargo and
uses SYSTEM_DEPS_* environment variables to point the libgpiod-sys and
gpiosim-sys crates at the locally built C libraries.

In addition to porting the build files to meson, update the docs, remove
unneded items from .gitignore files (or remove them entirely if they're
no longer needed) and update the shunit2 test scripts to no longer care
about source directories.

Tested-by: Erik Wierich <erik@riscstar.com>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260428-meson-build-v3-1-8da6976fb0a2@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-05-04 09:51:03 +02:00
Vincent Fazio
7acbbcf778 bindings: python: tests: migrate the gpiosim module to multi-phase init
Single-phase initialization has been classified as legacy within CPython
documentation [0] with multi-phase being its successor [1].

As such, switch to the new methodology.

Switching requires converting `gpiosim.Chip` to be a heap-type [2] in
order to access the module's state [3].

[0]: https://docs.python.org/3/c-api/extension-modules.html#legacy-single-phase-initialization
[1]: https://docs.python.org/3/c-api/extension-modules.html#multi-phase-initialization
[2]: https://docs.python.org/3/c-api/typeobj.html#heap-types
[3]: https://docs.python.org/3/howto/isolating-extensions.html#heap-types

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-9-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 11:08:11 +02:00
Vincent Fazio
bf4211f3e1 bindings: python: tests: migrate the system module to multi-phase init
Single-phase initialization has been classified as legacy within CPython
documentation [0] with multi-phase being its successor [1].

As such, switch to the new methodology.

[0]: https://docs.python.org/3/c-api/extension-modules.html#legacy-single-phase-initialization
[1]: https://docs.python.org/3/c-api/extension-modules.html#multi-phase-initialization

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-8-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 11:07:35 +02:00
Vincent Fazio
89ffee8349 bindings: python: migrate the gpiod._ext module to multi-phase init
Single-phase initialization has been classified as legacy within CPython
documentation [0] with multi-phase being its successor [1].

As such, switch to the new methodology.

[0]: https://docs.python.org/3/c-api/extension-modules.html#legacy-single-phase-initialization
[1]: https://docs.python.org/3/c-api/extension-modules.html#multi-phase-initialization

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-7-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 11:01:34 +02:00
Vincent Fazio
9106b6c190 bindings: python: use PyImport_ImportModuleAttrString() when available
Commit 035ad74fdd introduced Py_gpiod_GetModuleAttrString() as a way to
get a module's attribute and was inspired by CPython's internal function
_PyImport_GetModuleAttrString().

CPython 3.14 added PyImport_ImportModuleAttrString() to the public
API [0] which allows us to use the standard function when available.

[0]: https://github.com/python/cpython/pull/128912

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-6-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 10:49:51 +02:00
Vincent Fazio
63d4fd7ad7 bindings: python: use suggestions from upgrade_pythoncapi.py
The upgrade_pythoncapi.py script performs transforms on C extension
sources to use new syntax [0]. It's generally used with a shim header
for compatibility, but the header is not necessary for these changes.

The suggested changes are:

  * Use the `Py_IsNone` function introduced in CPython 3.10 [1] over
    direct comparison to `Py_None`

  * Use `PyObject_Free` instead of `PyObject_Del` since `PyObject_Del`
    has been aliased to `PyObject_Free` for nearly 24 years [2] and has
    been announced as deprecated [3]

  * Use the `Py_NewRef` function introduced in CPython 3.10 [4] to
    increment and return a new reference.

[0]: https://pythoncapi-compat.readthedocs.io/en/latest/index.html
[1]: 09bbebea16
[2]: 3e7b893899
[3]: https://docs.python.org/3/c-api/allocation.html#deprecated-aliases
[4]: 53a03aafd5

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-5-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 10:47:55 +02:00
Vincent Fazio
55ce0cf681 bindings: python: simplify disallowing _ext.Request from being created
Previously, tp_new and tp_init functions were defined for Request with
the tp_init function raising a NotImplementedError to prevent the object
from being initialized (__init__, the stage after __new__).

Similar results can be achieved by removing the tp_new and tp_init
functions which raise a slightly different error:

  TypeError: cannot create 'gpiod._ext.Request' instances

As this is an internal only detail, there should be impact to users.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-4-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 10:47:38 +02:00
Vincent Fazio
e5b6f6ecb9 bindings: python: avoid PyObject_CallMethod() during request_finalize()
The PyObject_CallMethod() function jumps through hoops to find the method
to call and to build a stack (if necessary) to call a given method.

In the case of finalizing the request object, that overhead can be
avoided by simply sharing a function with `request_release()` to close the
underlying gpiod_line_request object.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-3-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 10:47:07 +02:00
Vincent Fazio
53be72baca bindings: python: avoid PyObject_CallMethod() during chip_finalize()
The PyObject_CallMethod() function jumps through hoops to find the method
to call and to build a stack (if necessary) to call a given method.

In the case of finalizing the chip object, that overhead can be avoided
by simply sharing a function with `chip_close()` to close the underlying
gpiod_chip object.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260423222125.29097-2-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-24 10:45:30 +02:00
Bartosz Golaszewski
a2c92c9ece bindings: python: remove duplicated edge detection setting
In line_settings_init() we call gpiod_line_settings_set_edge_detection()
twice unnecessarily. Remove the second call.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Reported-by: 4fqr <4fqr@proton.me>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260407-treewide-fixes-v1-2-66c9744a56a3@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-09 09:32:37 +02:00
Bartosz Golaszewski
c6a76be56c bindings: python: fix heap-buffer overflow bugs on setting/getting values
The C extension methods request_set_values() and request_get_values()
iterate over a caller-supplied sequence and write offsets/values into
pre-allocated buffers self->offsets and self->values, without checking
the write index.

If the user tries to read values for more lines than they previously
requested, we overflow the buffers.

Add appropriate bounds checks and implement test cases for this issue.

Fixes: b7ba732e6a ("treewide: libgpiod v2 implementation")
Reported-by: 4fqr <4fqr@proton.me>
Tested-by: Vincent Fazio <vfazio@xes-inc.com>
Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260407-treewide-fixes-v1-1-66c9744a56a3@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-09 09:32:37 +02:00
Vincent Fazio
bfffd6506c bindings: python: allow releasing a LineRequest multiple times
In Python, it is common for objects to allow their `close` method to be
executed multiple times out of convenience. An example of this is the
`IOBase` class [0] which is the base class of most file-like classes.

Update `LineRequest.release` to follow this example as it performs the
same function as `close`.

[0]: https://docs.python.org/release/3.10.0/library/io.html#io.IOBase.close

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260403154629.3944942-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-07 14:52:59 +02:00
Vincent Fazio
711a05b254 bindings: python: allow closing a Chip multiple times
In Python, it is common for objects to allow their `close` method to be
executed multiple times out of convenience. An example of this is the
`IOBase` class [0] which is the base class of most file-like classes.

Update `Chip.close` to follow this example.

[0]: https://docs.python.org/release/3.10.0/library/io.html#io.IOBase.close

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260403154604.3944747-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-07 14:52:19 +02:00
Vincent Fazio
530fa7823b bindings: python: update linter configuration
Simplify linter configuration to check all files in the bindings
directory while excluding files in .gitignore.

With a minimum mypy version of 1.18.1, the `strict_equality` knob can
be removed as it was a work around a known issue [0] that is now fixed.

With a minimum ruff version of 15.x, rename the TCH check to TC since
it was renamed in v0.8.0 [1].

[0]: https://github.com/python/mypy/issues/10910
[1]: https://github.com/astral-sh/ruff/releases/tag/0.8.0

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-9-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
5efa9e8144 bindings: python: add a lint dependency group
Specify useful dependencies for linting the bindings and related code.

The group can be installed with `pip install --group lint`.

As part of this group, specify version ranges for mypy and ruff to keep
linting consistent until new minimal versions of Python are targeted or
until the new annual style introduced by ruff is chosen.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-8-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
485b81cd4b bindings: python: examples: apply linter recommendations
* Sort imports
* Use f-strings where possible
* Remove usage of `tuple` for config key values

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-7-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
d130ec7666 bindings: python: examples: add type annotations
Add type annotations to help with lint checks.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-6-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
0c466480e7 bindings: python: setup: use logging module
Use the `logging` module to conform to setuptools' recommendations [0].

[0]: https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html#prefer-setuptools

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-5-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
49843b8c70 bindings: python: setup: apply linter recommendations
* Drop unneeded mode parameters
* Cast toml parsing result to dict[str, str] for expected license value
* Disambiguate the `line` variable type for parsing the .asc file

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-4-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
0bb990a59e bindings: python: setup: add type annotations
Add type annotations to help with lint checks.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-3-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
ddca805d92 bindings: python: build_tests: simplify the Distribution
The version, package, and platform information is not necessary to
compile and stage the extensions, so drop that information.

If we need to add it back, we can use `dist.parse_config_files()` to
parse information from the pyproject.toml.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-2-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Vincent Fazio
f53d6c8825 bindings: python: build_tests: do not fallback to distutils
Make the assumption that the build host has setuptools>=60.2.0 which
exposes the logging module and remove references to distutils.

This conforms to setuptools' logging recommendation [0].

[0]: https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html#prefer-setuptools

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260401001459.19159-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-04-03 11:00:36 +02:00
Bartosz Golaszewski
2e47ad76bc Revert "bindings: python: replace PyModule_AddObjectRef() with PyModule_AddObject()"
This reverts commit b436d05809.

Commit 950ff3d1b3 ("bindings: python: drop python 3.9 support")
removed support for python v3.9 and with v3.10 now being the minimum
required version, we're now free to use PyModule_AddObjectRef().

Reviewed-by: Vincent Fazio <vfazio@xes-inc.com>
Link: https://patch.msgid.link/20260330125023.109789-1-bartosz.golaszewski@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-03-31 14:58:26 +02:00
Vincent Fazio
950ff3d1b3 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>
2026-03-30 10:57:47 +02:00
Vincent Fazio
42fcd4c084 bindings: python: remove wheel from build dependencies
The `wheel` package is not actually a build dependency for the project
since it is not imported during setup.

The `setuptools` documentation [0] says it was documented as required at
one point and that most packages have cargo culted the inclusion.

[0]: https://setuptools.pypa.io/en/latest/userguide/quickstart.html#basic-use

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260328153830.57177-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-03-30 10:32:08 +02:00
Vincent Fazio
ccc3f91f37 bindings: python: update .gitignore
Update gitignore to ignore common cache directories used by linters as
well as common virtual environment patterns.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260328153819.57025-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-03-30 10:31:39 +02:00
Vincent Fazio
ca20f1c3aa bindings: python: remove egg-info during clean
The egg-info directory gets generated when a distribution is built so
should be removed when `make clean` is run.

Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260228185213.31442-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-03-02 12:14:27 +01:00
Vincent Fazio
21d1687b88 bindings: python: copy the license into distributions
Previously, the bindings called out the SPDX license identifier in the
pyproject.toml but did not include a copy of the license in either the
source or binary distributions.

This can be problematic for tools that rely on extracting license
information, such as Buildroot or other license auditing mechanisms.

Now, when distributions are built, the license is copied out of the
libgpiod source tarball and into the target distribution.

Closes: https://github.com/brgl/libgpiod/issues/162
Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260228184158.25003-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-03-02 12:13:12 +01:00
Vincent Fazio
ff267fb439 bindings: python: require newer setuptools
When commit d9b156ecc2 updated pyproject.toml to conform to PEP 639
we failed to make sure the build dependencies were updated to support
the new structure.

Support for PEP 639 was added to setuptools in v77.0.0 [0] so minimally
require that version in `build-system.requires` to avoid failures.

Link: https://setuptools.pypa.io/en/latest/history.html#v77-0-0 # [0]
Fixes: d9b156ecc2 ("bindings: python: make licensing information conform with PEP 639")
Signed-off-by: Vincent Fazio <vfazio@gmail.com>
Link: https://patch.msgid.link/20260217005314.31016-1-vfazio@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-02-18 09:25:30 +01:00
Bartosz Golaszewski
fbc0a44712 bindings: python: add missing Py_None reference increment
For lines with no name, chip_get_line_name() returns Py_None but does
not increment its reference count. Do it enough times and the following
error will occur with cpython before v3.12:

  Fatal Python error: none_dealloc: deallocating None: bug likely caused by a refcount error in a C extension

Add the missing Py_INCREF(). It's safe to do even on python >= v3.12 as
Py_INCREF() has no effect on immortal objects in more recent versions.

Fixes: 0c0993569c ("bindings: python: ext: add ability to query line name")
Reported-by: Pierre Gramme <pgramme@gmail.com>
Closes: https://github.com/brgl/libgpiod/issues/166
Link: https://lore.kernel.org/r/20260113092852.42573-1-bartosz.golaszewski@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-01-13 16:11:52 +01:00