Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Automotive for Python

An asyncio library for CAN, ISO-TP, and UDS, powered by the automotive Rust crate. The distribution and import name are both automotive. Rust handles adapter I/O, protocol framing, validation, and timing; Python provides reusable configuration objects, typed values, context managers, and documented services.

Requires CPython 3.11+ and builds locally with maturin. This directory contains the Python package, its Rust extension, examples, and Scapy ECU regression tests.

Installation and development

To test the alpha release from PyPI in another uv project:

uv add --prerelease allow automotive

To test the library in another uv project, with Rust and the adapter build dependencies available:

uv add "automotive @ git+https://github.com/I-CAN-hack/automotive.git#subdirectory=python"

From the repository root, with Rust and the adapter build dependencies available, use the latest uv.

With Nix, first run nix develop from the repository root. The flake provides the required uv version and native build dependencies, taking precedence over an older uv on your normal PATH.

cd python
uv sync
uv run python examples/uds.py
uv check
uv format

uv check runs ty; uv format runs Ruff with default settings and a 120-character line length. uv sync installs the project and development tools; the lockfile records their versions. Use uv run maturin develop after changing Rust code when working directly in the installed development environment. For Rust formatting, run cargo fmt --all.

The Python extension always includes every adapter supported on its platform: SocketCAN on Linux, panda and PEAK USB adapters, and Vector and J2534 on Windows. Vendor drivers/DLLs and USB permissions remain necessary. The Rust crate retains feature flags for Rust applications.

Basic usage

Minimal setup retains the Rust defaults. Use Adapter() for automatic discovery, PeakAdapter() for default PEAK settings, or SocketCanAdapter("can0") to select a SocketCAN interface directly. Adapters open when entering async with; await adapter.open() supports explicit lifecycle management:

import asyncio

from automotive.adapters import Adapter
from automotive.protocols.uds import DataIdentifier, UDSClient
from automotive.transports.isotp import IsoTPAdapter


async def main():
    async with (
        Adapter() as adapter,
        IsoTPAdapter.from_id(adapter, 0x7A1) as transport,
    ):
        uds = UDSClient(transport)
        response = await uds.read_data_by_identifier(DataIdentifier.VIN)
        print(response)


asyncio.run(main())

Configuration

Reusable configs expose advanced settings without Rust-style builders:

import asyncio

from automotive.adapters import PeakAdapter, PeakConfig
from automotive.can import Identifier
from automotive.can.bitrate import BitrateSettings
from automotive.protocols.uds import DataIdentifier, UDSClient, UDSConfig
from automotive.transports.isotp import IsoTPAdapter, IsoTPConfig

adapter_config = PeakConfig(
    bitrate=BitrateSettings(
        bitrate=500_000, sample_point=0.8,
        data_bitrate=2_000_000, data_sample_point=0.8,
    ),
    tx_timeout=1.0,
)
transport_config = IsoTPConfig(
    tx_id=Identifier.extended(0x18DA10F1),
    fd=True, max_dlen=32, block_size=8,
    receive_separation_time_min=0.0003,
)
uds_config = UDSConfig(request_timeout=10.0, strict=True)


async def main():
    async with (
        PeakAdapter(adapter_config) as adapter,
        IsoTPAdapter(adapter, transport_config) as transport,
    ):
        uds = UDSClient(transport, uds_config)
        print(await uds.read_data_by_identifier(DataIdentifier.VIN))


asyncio.run(main())

All Python durations are seconds. Omitting settings retains Rust defaults; explicit bitrate settings start without presets, so a nominal bitrate alone selects Classic CAN. Vector retains shared access and existing timing when no bitrate settings are supplied. resolved_bitrate reports the calculated timing; SocketCAN selects an existing OS-configured interface.

Payload inputs accept bytes, bytearray, and contiguous byte-oriented memoryview objects; payload results are bytes. Named codes are Python IntEnum members, raw numbers are accepted, and unknown received codes are preserved. Invalid arguments use Python's ValueError/TypeError/OverflowError; deadlines use TimeoutError; disconnects use ConnectionError. Protocol exceptions retain NRCs or full response bytes. See automotive.errors.

Receive subscriptions are created by recv() immediately: create one before sending, then use async for, anext(), and aclose(). Hardware, transports, and receivers support async with. Close raw ISO-TP receivers before using UDS on the same transport; raw CAN monitoring can run alongside UDS. UDS exchanges on a transport are serialized. A cancelled queued call does not transmit; an active cancelled exchange drains under the lock before the next call starts. Closing the parent interrupts dependent operations. Set request_timeout when an overall bound is needed, including repeated NRC 0x78.

Use an ordinary context manager to suppress positive responses. Suppression supports nested scopes, restores its previous setting on exit, and is local to the current async task. Tasks created inside the scope inherit its context; already-running tasks are unaffected. Negative responses still raise errors.

with uds.suppress_positive_responses():
    await uds.tester_present()
await uds.tester_present()  # Requires a positive response again.

Examples and API documentation

The Python examples mirror every Rust example, including transmit timeout recovery, advanced bitrate configuration, concurrent firmware queries, and native J2534 device reuse. Read installed API documentation using uv run python -m pydoc automotive.protocols.uds, or Python's help().

End-to-end regression tests

On Linux, prepare the kernel modules and vcan0 from the repository root:

scripts/build_can_isotp.sh
scripts/set_up_vcan.sh

These scripts require sudo. Then run:

cd python
uv run pytest --run-vcan -q

The regression suite starts the existing Scapy ECU scripts, verifies readiness, and closes/reaps them after each scenario. It exercises all 14 implemented UDS service IDs, transfer round trips, suppression and pending responses, strict validation, cancellation, and ISO-TP Classic/FD framing and flow control. Tests run serially on vcan0; do not run the Rust and Python virtual-CAN suites concurrently. Without --run-vcan, the hardware-dependent tests are skipped; explicit runs fail if prerequisites are unavailable.

Publishing to PyPI

Set the Python release version in pyproject.toml. Both build.sh and deploy.sh read it automatically: build.sh builds the artifacts, and deploy.sh uploads them with uv publish. No CI publishing is configured. Release wheels use CPython's stable ABI starting at 3.11, so each platform needs one wheel for regular CPython 3.11 and newer. Free-threaded Python builds need separate wheels and are not included here.

The supported release targets are:

Build target Rust target Platform
linux-x86_64 x86_64-unknown-linux-gnu 64-bit Linux x86
linux-aarch64 aarch64-unknown-linux-gnu 64-bit Linux ARM
linux-armv7 armv7-unknown-linux-gnueabihf 32-bit Raspberry Pi 2+
macos-arm64 aarch64-apple-darwin Apple Silicon, macOS 11+
windows-x64 x86_64-pc-windows-msvc 64-bit Windows x86

On Nix, run the following from the repository root to build all five targets:

nix develop
cd python
./build.sh

The development shell supplies a pinned Rust toolchain with all five target standard libraries, LLVM/Clang and its cross-linkers, uv, and an Apple SDK fetched using nixpkgs' pinned Apple URLs and checksum. It sets SDKROOT automatically, so no rustup installation or manual SDK extraction is needed. The lockfile's release dependency group supplies Maturin, Zig, and Linux wheel repair tooling.

Select individual targets with --target linux-aarch64, or several with --target linux-x86_64 linux-armv7 windows-x64. Add --dry-run to preview commands.

Outside Nix, install Rust with the target standard libraries, LLVM/Clang (including libclang and llvm-dlltool), and uv. For a rustup toolchain:

rustup target add x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu \
    armv7-unknown-linux-gnueabihf aarch64-apple-darwin x86_64-pc-windows-msvc

Maturin uses Zig for Linux cross builds and xwin for Windows MSVC builds. xwin downloads the Windows SDK/CRT and is subject to the Microsoft license described in its documentation. Linux wheels enforce manylinux_2_17 (glibc 2.17+). The build uses bundled libusb and avoids host pkg-config libraries, retaining all platform-supported adapters. Driver/DLL and USB permission requirements still apply at runtime.

Outside the Nix shell, macOS ARM64 can be built on an Apple Silicon Mac or cross-compiled from Linux with an extracted Apple SDK. For the latter, set SDKROOT:

SDKROOT=/path/to/MacOSX.sdk ./build.sh --target macos-arm64

Use alpha releases to test imports and hardware behavior on the target platforms before a stable release. See Maturin's cross-compilation guide and cargo-zigbuild.

Builds collect wheels and a source distribution in python/dist/<version>/. The source distribution allows installation on other supported systems with Rust and native build prerequisites. Inspect the files and validate an upload:

./deploy.sh --dry-run

Create a PyPI account with 2FA and a verified email, then create an API token. The first upload creates the project; use an account-scoped token initially, then a project-scoped token for later releases. Provide the token through UV_PUBLISH_TOKEN in your shell or secret manager, and run:

./deploy.sh

To rehearse against TestPyPI, use its separate account/token and upload endpoint:

./deploy.sh --publish-url https://test.pypi.org/legacy/ \
    --check-url https://test.pypi.org/simple/

deploy.sh selects only the current version's directory and forwards its arguments to uv publish. If you build with --dist-dir PATH, publish that directory directly with uv publish 'PATH/*'. See the uv publishing guide.

Metadata

Release files for automotive 0.5.0a1

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

Source distribution (sdist)

Source distribution for automotive 0.5.0a1
File Size Uploaded Provenance
automotive-0.5.0a1.tar.gz 240.9 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for automotive 0.5.0a1
File
automotive-0.5.0a1-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
automotive-0.5.0a1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
automotive-0.5.0a1-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl CPython 3.11 abi3 Linux glibc 2.17+ ARMv7l Details
automotive-0.5.0a1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
automotive-0.5.0a1-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details

Total release size: 5.8 MB

Release files / automotive-0.5.0a1.tar.gz

Download URL automotive-0.5.0a1.tar.gz
Size 240.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3c064526b9fe91f505dd9a1e9430e5996c8754745aa460a0ad2ece75d092feee
BLAKE2b-256 checksum
How to use checksums
2bb4bdbeaaa070b7d54d2c61167b541faaac8a25141dea4f84ac6b38ff21cda3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a1-cp311-abi3-win_amd64.whl

Download URL automotive-0.5.0a1-cp311-abi3-win_amd64.whl
Size 1.0 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
bedda361c18bb6219fecf1e19cdb1fc72f362fc958c5b1655e433211ac2c288b
BLAKE2b-256 checksum
How to use checksums
8835a7049bcafc873fb3a4a77e96e52fb928185eb30300b6a40d75133bbd26a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL automotive-0.5.0a1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 961.3 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
9bde912c535f977db17630569a1ab0e8ae31f0e0a6b3fb283867347dc56ef3f6
BLAKE2b-256 checksum
How to use checksums
258396b51734b93944258f4a2e2cacb3d7ba1ab6f041ed9253609eeee0a30a52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a1-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl

Download URL automotive-0.5.0a1-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Size 890.8 kB
Tags CPython 3.11 Linux glibc 2.17+ ARMv7l abi3
SHA-256 checksum
How to use checksums
e3c3cde87bf52c1f79f454918ccdcbcd767499d675c1d0fa1c49269eedb31f9e
BLAKE2b-256 checksum
How to use checksums
33a1c43d5a49c74016d498cc2dbc8e8239289f4181eca3fbbdb05576c7447324
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL automotive-0.5.0a1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 937.6 kB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
394fd1aef486560f7e65979634a5f3cbeceea8dcb1bd77248f5d2db9c6c8b7fc
BLAKE2b-256 checksum
How to use checksums
f91cce4261a2532b2ca440d3a3679365287ddc327fa74624ea9317ce37c8d6e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a1-cp311-abi3-macosx_11_0_arm64.whl

Download URL automotive-0.5.0a1-cp311-abi3-macosx_11_0_arm64.whl
Size 1.7 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a2f6858798bd3a5b79ad9c12ab3b05107a227a6fd631c8ed002eb42b78d57d85
BLAKE2b-256 checksum
How to use checksums
006c8622e95dd286e7487441d8a12c389d683df3f7a4a24230afe7afc7ca816a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for automotive 0.5.0a1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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.

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