Contributing¶
Contributions are welcome! Here's how to get started.
Development Setup¶
Or with uv:
Running Tests¶
# All unit tests
pytest tests/test_*.py
# With verbose output
pytest tests/test_*.py -v
# Specific test file
pytest tests/test_commands.py
# Specific test
pytest tests/test_commands.py::test_get_frequency_builds_correct_frame
Test Structure¶
tests/
├── conftest.py # Shared fixtures (FakeRadio, packet builders)
├── test_auth.py # Credential encoding, login/conninfo packets
├── test_commands.py # CI-V frame building and parsing
├── test_protocol.py # Header parsing/serialization
├── test_radio.py # IcomRadio high-level API (mocked transport)
├── test_transport.py # IcomTransport (mocked UDP)
└── integration/ # Real hardware tests (require a radio)
├── test_connect.py
└── test_get_freq.py
Unit tests use mocked transports — no radio required. Integration tests are in tests/integration/ and require actual hardware.
Code Style¶
- Type annotations on all public functions
- Docstrings on all public classes and methods (Google/NumPy style)
- Follow existing code patterns
- No external dependencies for the core library (stdlib only)
Commit Messages¶
We use Conventional Commits:
feat: add AGC level control
fix: handle timeout during conninfo exchange
docs: add IC-705 setup instructions
test: add VFO swap command test
chore: bump version to 0.3.0
Adding a New CI-V Command¶
-
Add the command builder in
commands.py: -
Add a response parser if needed (also in
commands.py) -
Add the high-level method in
radio.py: -
Add a CLI command in
cli.pyif user-facing -
Write tests in
tests/test_commands.pyandtests/test_radio.py -
Update documentation:
docs/guide/commands.md— user-facing command docsdocs/api/radio.md— API referencedocs/api/commands.md— low-level command reference
Adding a New Radio Model¶
- Look up the radio's default CI-V address
- Test basic operations (frequency, mode, meters)
- Document any model-specific behavior
- Add to the radios table in
docs/guide/radios.md - Add the CI-V address constant in
commands.pyif desired
Reporting Bugs¶
Open an issue with:
- Radio model and firmware version
- Python version and OS
- Steps to reproduce
- Debug log output (
logging.basicConfig(level=logging.DEBUG)) - Expected vs actual behavior
Pull Requests¶
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes with tests
- Ensure all tests pass:
pytest tests/test_*.py - Commit with conventional commit message
- Open a PR against
main