Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ classifiers = [
"Topic :: System :: Hardware :: Hardware Drivers",
]
keywords = ["SPI", "Linux", "SPI device"]
requires-python = ">=3.8"
requires-python = ">=3.10"

[build-system]
requires = ["setuptools>=80.0"]
Expand All @@ -32,10 +32,10 @@ Repository = "http://github.com/doceme/py-spidev"
Issues = "https://github.com/doceme/py-spidev/issues"
Changelog = "https://github.com/doceme/py-spidev/blob/master/CHANGELOG.md"

[tool.setuptools.dynamic]
readme = {file = ["README.md"], content-type = "text/markdown" }

[tool.setuptools]
ext-modules = [
{name = "spidev", sources = ["spidev_module.c"]}
{name = "spidev._spidev", sources = ["spidev/_spidev.c"]}
]

[tool.setuptools.dynamic]
readme = {file = ["README.md"], content-type = "text/markdown" }
8 changes: 3 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#!/usr/bin/env python

from setuptools import setup

version = "0.0"

lines = [x for x in open("spidev_module.c").read().split("\n") if "#define" in x and "_VERSION_" in x and "\"" in x]
lines = [x for x in open("spidev/_spidev.c").read().split("\n") if "#define" in x and "_VERSION_" in x and "\"" in x]

if len(lines) > 0:
version = lines[0].split("\"")[1]
else:
raise Exception("Unable to find _VERSION_ in spidev_module.c")
raise Exception("Unable to find _VERSION_ in spidev/_spidev.c")

setup(
version = version,
)
)
4 changes: 4 additions & 0 deletions spidev/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from spidev._spi import SpiDev
from spidev._spidev import __version__

__all__ = ("SpiDev",)
171 changes: 171 additions & 0 deletions spidev/_spi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
from typing import TYPE_CHECKING
from contextlib import suppress

from spidev._spidev import _SpiDev

from collections.abc import Sequence
from os import PathLike
from types import TracebackType


class SpiDev:

def __init__(self, bus: int | None = None, device: int | None = None) -> None:
if bus is not None:
self._bus = int(bus)
if device is not None:
self._device = int(device)

self._cmod = _SpiDev(self._bus, self._device)

@property
def bus(self) -> int:
return self._bus

@property
def device(self) -> int:
return self._device

@property
def mode(self) -> int:
return self._cmod.mode

@mode.setter
def mode(self, value: int, /) -> None:
self._cmod.mode = int(value)

@property
def cshigh(self) -> bool:
return self._cmod.cshigh

@cshigh.setter
def cshigh(self, value: bool, /) -> None:
self._cmod.cshigh = bool(value)

@property
def threewire(self) -> bool:
return self._cmod.threewire

@threewire.setter
def threewire(self, value: bool, /) -> None:
self._cmod.threewire = bool(value)

@property
def lsbfirst(self) -> bool:
return self._cmod.lsbfirst

@lsbfirst.setter
def lsbfirst(self, value: bool, /) -> None:
self._cmod.lsbfirst = bool(value)

@property
def loop(self) -> bool:
return self._cmod.loop

@loop.setter
def loop(self, value: bool, /) -> None:
self._cmod.loop = bool(value)

@property
def no_cs(self) -> bool:
return self._cmod.no_cs

@no_cs.setter
def no_cs(self, value: bool, /) -> None:
self._cmod.no_cs = bool(value)

@property
def bits_per_word(self) -> int:
return self._cmod.bits_per_word

@bits_per_word.setter
def bits_per_word(self, value: int, /) -> None:
self._cmod.bits_per_word = int(value)

@property
def max_speed_hz(self) -> int:
return self._cmod.max_speed_hz

@max_speed_hz.setter
def max_speed_hz(self, value: int, /) -> None:
self._cmod.max_speed_hz = int(value)

@property
def read0(self) -> bool:
return self._cmod.read0

@read0.setter
def read0(self, value: bool, /) -> None:
self._cmod.read0 = bool(value)

@property
def mosi_idle_low(self) -> bool:
return self._cmod.mosi_idle_low

@mosi_idle_low.setter
def mosi_idle_low(self, value: bool, /) -> None:
self._cmod.mosi_idle_low = bool(value)

def close(self) -> None:
self._cmod.close()

def open(self, bus: int, device: int) -> None:
self._cmod.open(bus, device)

def open_path(self, path: str) -> None:
self._cmod.open_path(path)

def fileno(self) -> int:
return self._cmod.fileno()

def readbytes(self, length: int) -> list[int]:
return self._cmod.readbytes(length)

def writebytes(self, values: Sequence[int]) -> None:
self._cmod.writebytes(values)

# TODO: also accepts collections.abc.Buffer type, but that's 3.12+...
def writebytes2(self, values: Sequence[int]) -> None:
self._cmod.writebytes2(values)

def xfer(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> list[int]:
return self._cmod.xfer(values, speed_hz, delay_usecs, bits_per_word)

def xfer2(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> list[int]:
return self._cmod.xfer2(values, speed_hz, delay_usecs, bits_per_word)

def xfer3(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> tuple[int, ...]:
return self._cmod.xfer3(values, speed_hz, delay_usecs, bits_per_word)

def __del__(self) -> None:
with suppress(AttributeError):
del self._cmod

def __enter__(self) -> "SpiDev":
return self

def __exit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
self._cmod.__exit__(exc_type, exc_value, exc_tb)
19 changes: 10 additions & 9 deletions spidev_module.c → spidev/_spidev.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* spidev_module.c - Python bindings for Linux SPI access through spidev
* _spidev.c - Python bindings for Linux SPI access through spidev
*
* MIT License
*
Expand Down Expand Up @@ -102,7 +102,8 @@ PyDoc_STRVAR(SpiDev_module_doc,
"modules.\n"
"\n"
"Because the SPI device interface is opened R/W, users of this\n"
"module usually must have root permissions.\n");
"module usually must have root permissions.\n"
"This is a low-level C extension module. Use spidev.SpiDev instead.\n");

typedef struct {
PyObject_HEAD
Expand Down Expand Up @@ -1480,7 +1481,7 @@ SpiDev_init(SpiDevObject *self, PyObject *args, PyObject *kwds)


PyDoc_STRVAR(SpiDevObjectType_doc,
"SpiDev([bus],[client]) -> SPI\n\n"
"_SpiDev([bus],[client]) -> SPI\n\n"
"Return a new SPI object that is (optionally) connected to the\n"
"specified SPI device interface.\n");

Expand Down Expand Up @@ -1545,7 +1546,7 @@ static PyTypeObject SpiDevObjectType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
#endif
"SpiDev", /* tp_name */
"_spidev._SpiDev", /* tp_name */
sizeof(SpiDevObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)SpiDev_dealloc, /* tp_dealloc */
Expand Down Expand Up @@ -1591,7 +1592,7 @@ static PyMethodDef SpiDev_module_methods[] = {
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"spidev",
"_spidev",
SpiDev_module_doc,
-1,
SpiDev_module_methods,
Expand All @@ -1608,9 +1609,9 @@ static struct PyModuleDef moduledef = {

#if PY_MAJOR_VERSION >= 3
PyMODINIT_FUNC
PyInit_spidev(void)
PyInit__spidev(void)
#else
void initspidev(void)
void init_spidev(void)
#endif
{
PyObject* m;
Expand All @@ -1626,7 +1627,7 @@ void initspidev(void)
m = PyModule_Create(&moduledef);
PyObject *version = PyUnicode_FromString(_VERSION_);
#else
m = Py_InitModule3("spidev", SpiDev_module_methods, SpiDev_module_doc);
m = Py_InitModule3("_spidev", SpiDev_module_methods, SpiDev_module_doc);
PyObject *version = PyString_FromString(_VERSION_);
#endif

Expand All @@ -1635,7 +1636,7 @@ void initspidev(void)
Py_DECREF(version);

Py_INCREF(&SpiDevObjectType);
PyModule_AddObject(m, "SpiDev", (PyObject *)&SpiDevObjectType);
PyModule_AddObject(m, "_SpiDev", (PyObject *)&SpiDevObjectType);

#if PY_MAJOR_VERSION >= 3
return m;
Expand Down
79 changes: 79 additions & 0 deletions spidev/_spidev.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Type stubs for _spidev C extension module."""

from typing import Sequence
from typing_extensions import Buffer

__version__: str

class _SpiDev:
def __init__(self, bus: int = -1, client: int = -1) -> None: ...
def open(self, bus: int, device: int) -> None: ...
def open_path(self, path: str) -> None: ...
def close(self) -> None: ...
def fileno(self) -> int: ...
def readbytes(self, length: int) -> list[int]: ...
def writebytes(self, values: Sequence[int]) -> None: ...
def writebytes2(self, values: Sequence[int] | Buffer) -> None: ...
def xfer(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> list[int]: ...
def xfer2(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> list[int]: ...
def xfer3(
self,
values: Sequence[int],
speed_hz: int = 0,
delay_usecs: int = 0,
bits_per_word: int = 0,
) -> tuple[int, ...]: ...
def __enter__(self) -> _SpiDev: ...
def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> bool: ...
@property
def mode(self) -> int: ...
@mode.setter
def mode(self, value: int) -> None: ...
@property
def cshigh(self) -> bool: ...
@cshigh.setter
def cshigh(self, value: bool) -> None: ...
@property
def threewire(self) -> bool: ...
@threewire.setter
def threewire(self, value: bool) -> None: ...
@property
def lsbfirst(self) -> bool: ...
@lsbfirst.setter
def lsbfirst(self, value: bool) -> None: ...
@property
def loop(self) -> bool: ...
@loop.setter
def loop(self, value: bool) -> None: ...
@property
def no_cs(self) -> bool: ...
@no_cs.setter
def no_cs(self, value: bool) -> None: ...
@property
def bits_per_word(self) -> int: ...
@bits_per_word.setter
def bits_per_word(self, value: int) -> None: ...
@property
def max_speed_hz(self) -> int: ...
@max_speed_hz.setter
def max_speed_hz(self, value: int) -> None: ...
@property
def read0(self) -> bool: ...
@read0.setter
def read0(self, value: bool) -> None: ...
@property
def mosi_idle_low(self) -> bool: ...
@mosi_idle_low.setter
def mosi_idle_low(self, value: bool) -> None: ...
Empty file added spidev/py.typed
Empty file.