Developer's Overview
Quick Start for Contributors
- Fork the repository on GitHub and clone your fork.
- Create a new branch for your changes.
- Set up your development environment.
- Make your changes, add/update tests and documentation as needed.
- Run tox to check your changes.
- Push your branch and open a pull request.
Contributing
Welcome! Thank you for your interest in python-can. Whether you want to fix a bug, add a feature, improve documentation, write examples, help solve issues, or simply report a problem, your contribution is valued. Contributions are made via the python-can GitHub repository. If you have questions, feel free to open an issue or start a discussion on GitHub.
If you're new to the codebase, see the next section for an overview of the code structure.
For more about the internals, see :ref:`internalapi` and information on extending the can.io module.
Code Structure
The modules in python-can are:
| Module | Description |
|---|---|
| :doc:`interfaces <interfaces>` | Contains interface dependent code. |
| :doc:`bus <bus>` | Contains the interface independent Bus object. |
| :doc:`message <message>` | Contains the interface independent Message object. |
| :doc:`io <file_io>` | Contains a range of file readers and writers. |
| :doc:`broadcastmanager <bcm>` | Contains interface independent broadcast manager code. |
Step-by-Step Contribution Guide
Fork and Clone the Repository
Fork the python-can repository on GitHub to your own account.
Clone your fork:
git clone https://github.com/<your-username>/python-can.git cd python-can
Create a new branch for your work:
git checkout -b my-feature-branch
Ensure your branch is up to date with the latest changes from the main repository. First, add the main repository as a remote (commonly named upstream) if you haven't already:
git remote add upstream https://github.com/hardbyte/python-can.git
Then, regularly fetch and rebase from the main branch:
git fetch upstream git rebase upstream/main
Set Up Your Development Environment
We recommend using uv to install development tools and run CLI utilities. uv is a modern Python packaging tool that can quickly create virtual environments and manage dependencies, including downloading required Python versions automatically. The uvx command allows you to run CLI tools in isolated environments, separate from your global Python installation. This is useful for installing and running Python applications (such as tox) without affecting your project's dependencies or environment.
Install tox (if not already available):
uv tool install tox --with tox-uv
Quickly running your local python-can code
To run a local script (e.g., snippet.py) using your current python-can code, you can use either the traditional virtualenv and pip workflow or the modern uv tool.
Traditional method (virtualenv + pip):
Create a virtual environment and install the package in editable mode. This allows changes to your local code to be reflected immediately, without reinstalling.
# Create a new virtual environment python -m venv .venv # Activate the environment .venv\Scripts\activate # On Windows source .venv/bin/activate # On Unix/macOS # Upgrade pip and install python-can in editable mode with development dependencies python -m pip install --upgrade pip pip install -e .[dev] # Run your script python snippet.py
Modern method (uv):
With uv, you can run your script directly:
When
uv run ...is called inside a project, uv automatically sets up the environment and symlinks local packages. No editable install is needed—changes to your code are reflected immediately.Make Your Changes
- Edit code, documentation, or tests as needed.
- If you fix a bug or add a feature, add or update tests in the
test/directory. - If your change affects users, update documentation in
doc/and relevant docstrings.
Test Your Changes
This project uses tox to automate all checks (tests, lint, type, docs). Tox will set up isolated environments and run the right tools for you.
To run all checks:
To run a specific check, use:
tox -e lint # Run code style and lint checks (black, ruff, pylint) tox -e type # Run type checks (mypy) tox -e docs # Build and test documentation (sphinx) tox -e py # Run tests (pytest)
To run all checks in parallel (where supported), you can use:
Some environments require specific Python versions. If you use uv, it will automatically download and manage these for you.
Add a News Fragment for the Changelog
This project uses towncrier to manage the changelog in
CHANGELOG.md. For every user-facing change (new feature, bugfix, deprecation, etc.), you must add a news fragment:News fragments are short files describing your change, stored in
doc/changelog.d.Name each fragment
<issue-or-description>.<type>.md, where<type>is one of:added,changed,deprecated,removed,fixed, orsecurity.Example (for a feature added in PR #1234):
echo "Added support for CAN FD." > doc/changelog.d/1234.added.md
Or use the towncrier CLI:
uvx towncrier create --dir doc/changelog.d -c "Added support for CAN FD." 1234.added.mdFor changes not tied to an issue/PR, the fragment name must start with a plus symbol (e.g.,
+mychange.added.md). Towncrier calls these "orphan fragments".
Note
You do not need to manually update
CHANGELOG.md—maintainers will build the changelog at release time.(Optional) Build Source Distribution and Wheels
If you want to manually build the source distribution (sdist) and wheels for python-can, you can use uvx to run the build and twine tools:
uv build uvx twine check --strict dist/*Push and Submit Your Contribution
Push your branch:
git push origin my-feature-branch
Open a pull request from your branch to the
mainbranch of the main python-can repository on GitHub.
Please be patient — maintainers review contributions as time allows.
Creating a new interface/backend
Attention!
Please note: Pull requests that attempt to add new hardware interfaces directly to the python-can codebase will not be accepted. Instead, we encourage contributors to create plugins by publishing a Python package containing your :class:`can.BusABC` subclass and using it within the python-can API. We will mention your package in this documentation and add it as an optional dependency. For current best practices, please refer to :ref:`plugin interface`.
The following guideline is retained for informational purposes only and is not valid for new contributions.
These steps are a guideline on how to add a new backend to python-can.
- Create a module (either a
*.pyor an entire subdirectory depending on the complexity) insidecan.interfaces. Seecan/interfaces/socketcanfor a reference implementation. - Implement the central part of the backend: the bus class that extends :class:`can.BusABC`. See :ref:`businternals` for more info on this one!
- Register your backend bus class in
BACKENDSin the filecan.interfaces.__init__.py. - Add docs where appropriate. At a minimum add to
doc/interfaces.rstand add a new interface specific document indoc/interface/*. It should document the supported platforms and also the hardware/software it requires. A small snippet of how to install the dependencies would also be useful to get people started without much friction. - Also, don't forget to document your classes, methods and function with docstrings.
- Add tests in
test/*where appropriate. For example, seetest/back2back_test.pyand add a test case likeBasicTestSocketCanfor your new interface.
Creating a new Release
Releases are automated via GitHub Actions. To create a new release:
Build the changelog with towncrier:
Collect all news fragments and update
CHANGELOG.mdby running:uvx towncrier build --yes --version vX.Y.Z
(Replace
vX.Y.Zwith the new version number. The version must exactly match the tag you will create for the release.) This will add all news fragments to the changelog and remove the fragments by default.Note
You can generate the changelog for prereleases, but keep the news fragments so they are included in the final release. To do this, replace
--yeswith--keep. This will updateCHANGELOG.mdbut leave the fragments in place for future builds.Review
CHANGELOG.mdfor accuracy and completeness.
Ensure all tests pass and documentation is up-to-date.
Update
CONTRIBUTORS.txtwith any new contributors.For larger changes, update
doc/history.rst.Create a new tag and GitHub release (e.g.,
vX.Y.Z) targeting themainbranch. Add release notes and publish.The CI workflow will automatically build, check, and upload the release to PyPI and other platforms.
You can monitor the release status on: PyPi, Read the Docs and GitHub Releases.