mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-25 12:39:18 +03:00
Previously, the external module relied on gpiod attributes being present within `globals()` to construct return values back to the caller. This assumption required callers of the external module to have imported the attributes to populate `globals()` for the interface to work. Having this implicit contract is opaque and prone to causing issues if imports within gpiod modules ever get reworked. Now, the external module explicitly imports attributes from gpiod in order to return values back to the caller. There should be no concern about circular imports as the external module should be completely imported by the time callers call into it. Since Py_gpiod_GetGlobalType is no longer used, it has been replaced with Py_gpiod_GetModuleAttrString which returns a new PyObject* reference for the named module and attribute that must be decremented when no longer in use. Closes: https://github.com/brgl/libgpiod/issues/101 Signed-off-by: Vincent Fazio <vfazio@xes-inc.com> Link: https://lore.kernel.org/r/20241008175139.1198980-1-vfazio@xes-inc.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
97 lines
1.7 KiB
C
97 lines
1.7 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
// SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
|
|
|
#include "internal.h"
|
|
|
|
/* Generic dealloc callback for all gpiod objects. */
|
|
void Py_gpiod_dealloc(PyObject *self)
|
|
{
|
|
int ret;
|
|
|
|
ret = PyObject_CallFinalizerFromDealloc(self);
|
|
if (ret < 0)
|
|
return;
|
|
|
|
PyObject_Del(self);
|
|
}
|
|
|
|
PyObject *Py_gpiod_SetErrFromErrno(void)
|
|
{
|
|
PyObject *exc;
|
|
|
|
if (errno == ENOMEM)
|
|
return PyErr_NoMemory();
|
|
|
|
switch (errno) {
|
|
case EINVAL:
|
|
exc = PyExc_ValueError;
|
|
break;
|
|
case EOPNOTSUPP:
|
|
exc = PyExc_NotImplementedError;
|
|
break;
|
|
case EPIPE:
|
|
exc = PyExc_BrokenPipeError;
|
|
break;
|
|
case ECHILD:
|
|
exc = PyExc_ChildProcessError;
|
|
break;
|
|
case EINTR:
|
|
exc = PyExc_InterruptedError;
|
|
break;
|
|
case EEXIST:
|
|
exc = PyExc_FileExistsError;
|
|
break;
|
|
case ENOENT:
|
|
exc = PyExc_FileNotFoundError;
|
|
break;
|
|
case EISDIR:
|
|
exc = PyExc_IsADirectoryError;
|
|
break;
|
|
case ENOTDIR:
|
|
exc = PyExc_NotADirectoryError;
|
|
break;
|
|
case EPERM:
|
|
exc = PyExc_PermissionError;
|
|
break;
|
|
case ETIMEDOUT:
|
|
exc = PyExc_TimeoutError;
|
|
break;
|
|
default:
|
|
exc = PyExc_OSError;
|
|
break;
|
|
}
|
|
|
|
return PyErr_SetFromErrno(exc);
|
|
}
|
|
|
|
PyObject *Py_gpiod_GetModuleAttrString(const char *modname,
|
|
const char *attrname)
|
|
{
|
|
PyObject *module, *attribute;
|
|
|
|
module = PyImport_ImportModule(modname);
|
|
if (!module)
|
|
return NULL;
|
|
|
|
attribute = PyObject_GetAttrString(module, attrname);
|
|
Py_DECREF(module);
|
|
|
|
return attribute;
|
|
}
|
|
|
|
unsigned int Py_gpiod_PyLongAsUnsignedInt(PyObject *pylong)
|
|
{
|
|
unsigned long tmp;
|
|
|
|
tmp = PyLong_AsUnsignedLong(pylong);
|
|
if (PyErr_Occurred())
|
|
return 0;
|
|
|
|
if (tmp > UINT_MAX) {
|
|
PyErr_SetString(PyExc_ValueError, "value exceeding UINT_MAX");
|
|
return 0;
|
|
}
|
|
|
|
return tmp;
|
|
}
|