Skip to main content

scietex.hal.spi

SPI transport backends shared by the scietex.hal.* device distributions.

A transport is the narrow seam between a device driver and the bus. Devices send whole frames through transfer() and release the bus with close(), so the same driver works over spidev, over gpiozero's hardware SPI, or over a scripted fake in tests. The package ships no device code and has no runtime dependencies: the optional backends are imported only when they are used.

The protocol

class SpiTransport(Protocol):
    def transfer(self, tx: Sequence[int]) -> list[int]: ...
    def close(self) -> None: ...
  • transfer(tx) sends one frame of words in 0..255 and returns the received words in the same order.
  • close() releases the bus handle; repeated calls have no effect. If the underlying close fails, the transport stays open and close() can be retried.
  • closed is True once close() has run. For a transport that wraps a caller-supplied handle, it reports that the transport itself is closed, not that the shared bus was closed.

Any object with callable transfer and close methods is accepted. Use is_spi_transport(obj) for the check: unlike isinstance(obj, SpiTransport), it rejects class objects. Use SpiTransport for typing only.

Failures raise TransportError, which subclasses OSError so callers that already handle spidev or gpiozero I/O errors keep working. A transaction attempted after close raises TransportClosed, a TransportError subclass.

Backends

Transport Install Notes
SpiDevTransport pip install 'scietex.hal.spi[spi]' Default. Opens /dev/spidev<bus>.<device> through spidev, Linux only.
GpiozeroSpiTransport pip install 'scietex.hal.spi[gpiozero]' Wraps a gpiozero hardware SPI object. Resolved lazily as scietex.hal.spi.GpiozeroSpiTransport.
FakeSpiTransport none In-memory backend with scripted responses, for tests without hardware.
from scietex.hal.spi import SpiDevTransport

transport = SpiDevTransport(bus=0, device=0, max_speed_hz=500_000)
transport.transfer([0x00, 43])
transport.close()

SpiDevTransport transfers with xfer2, which keeps chip select asserted for the whole frame; xfer would deassert it between 8-bit words.

GpiozeroSpiTransport builds a private shared gpiozero SPIDevice by default, or wraps one supplied with spi=. On a Raspberry Pi it also patches gpiozero so two hardware-SPI devices can share one port when they use different chip-select lines (fix_gpiozero_dual_cs_spi, also exported for callers that build their own gpiozero devices). Without the RPi pin backend the patch is a no-op.

A bare install ships no hardware backend; constructing one raises ImportError naming the extra to install.

Default selection

build_default_transport maps the legacy device keywords onto a backend:

Keyword SpiDevTransport GpiozeroSpiTransport
port bus port
device device device
clock_pin, mosi_pin, miso_pin, select_pin selects the gpiozero backend forwarded as-is
from scietex.hal.spi import build_default_transport

build_default_transport(port=0, device=1)  # SpiDevTransport(bus=0, device=1)
build_default_transport(clock_pin=11, mosi_pin=10)  # GpiozeroSpiTransport(...)

Any pin keyword selects the gpiozero backend and requires the gpiozero extra; without pin keywords the spidev backend is built with port or 0 and device or 0. port and device are accepted by both backends and are simply forwarded.

The selector takes backend keywords only. Conflict rejection — passing backend keywords together with transport= or spi= — is the responsibility of each device constructor, which owns that argument surface; the selector itself raises TypeError when given a transport= keyword.

Ownership

Create one transport per device; all channels of a device share it. The device's close() delegates to its transport.

  • SpiDevTransport always owns and closes its spidev handle.
  • GpiozeroSpiTransport closes only a handle it built. When it wraps a caller-supplied spi= object, close() marks the transport closed but leaves the shared bus open for its other users; the supplied handle's owner must outlive the wrapper and close it. Once that owner closes the handle, transfers through the wrapper raise TransportClosed.
  • FakeSpiTransport only flips its closed flag.

Linux permissions

SpiDevTransport needs the kernel SPI device node and permission to open it. Enable kernel SPI first, for example with dtparam=spi=on in /boot/firmware/config.txt on current Raspberry Pi OS (the older path is /boot/config.txt).

If the node exists but opening fails, add a udev rule. The development setup for these packages uses the gpio group; adjust the group to match your system::

SUBSYSTEM=="spidev", GROUP="gpio", MODE="0660"

Install the rule under /etc/udev/rules.d/, reload the rules, and reconnect the device. The user running the process must be a member of the group named in the rule; on Fedora setups that group is gpio, because no spi group exists.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Metadata

Release files for scietex.hal.spi 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scietex.hal.spi 0.1.0
File Size Uploaded Provenance Actions
scietex_hal_spi-0.1.0.tar.gz 24.4 kB With provenance Details for scietex_hal_spi-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for scietex.hal.spi 0.1.0
File Interpreter ABI Platform Actions
scietex_hal_spi-0.1.0-py3-none-any.whl Python 3 none any Details for scietex_hal_spi-0.1.0-py3-none-any.whl

Total release size: 40.4 kB

Release files / scietex_hal_spi-0.1.0.tar.gz

Download URL scietex_hal_spi-0.1.0.tar.gz
Size 24.4 kB
Tags Source
SHA-256 checksum
How to use checksums
f1aa28f22c1d68d46eeddf6105ec3ceb486100c90d6564a1fe4462d1f7920267
BLAKE2b-256 checksum
How to use checksums
41687d1ef80b233c8d46deaa27093d4aa30327a9bba125076985ec8901546632
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Release files / scietex_hal_spi-0.1.0-py3-none-any.whl

Download URL scietex_hal_spi-0.1.0-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0350840d53bb21c0b18554a64f19eb914df3442619cb55a38f019e6b5d4db032
BLAKE2b-256 checksum
How to use checksums
5c0d61f4d24de7ce82b175a51004e4450258a3bc1899b307bc5ec6ba9cdc4d8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Security for scietex.hal.spi 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for scietex_hal_spi-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page