Development Guide
Guide for contributing to and extending the pyCRUMBS library.
Development Setup
Editable Installation
git clone https://github.com/FEASTorg/pyCRUMBS.git
cd pyCRUMBS
pip install -e . --config-settings editable_mode=compat
Development Tools
pip install pytest black flake8 mypy sphinx sphinx-rtd-theme
Project Structure
pyCRUMBS/
├── src/pyCRUMBS/ # Main package
│ ├── __init__.py # Package exports
│ ├── CRUMBS.py # Main communication class
│ └── CRUMBSMessage.py # Message dataclass
├── examples/ # Usage examples
├── docs/ # Documentation
├── tests/ # Unit tests (to be added)
└── pyproject.toml # Package configuration
Code Standards
Style Guidelines
# Format code
black src/ examples/
# Check style
flake8 src/ examples/
# Type checking
mypy src/
Code Quality
- Follow PEP 8 standards
- Use type hints for all functions
- Document all public APIs with docstrings
- Write unit tests for new functionality
- Maintain backward compatibility
Testing
Unit Tests
# Run tests
pytest tests/
# With coverage
pytest --cov=pyCRUMBS tests/
Hardware Testing
Test with actual Raspberry Pi hardware:
- Raspberry Pi with I2C enabled
- Arduino or compatible I2C device
- Level shifters for voltage conversion
- Proper pull-up resistors
Mock Testing
from unittest.mock import Mock, patch
from pyCRUMBS import CRUMBS
def test_send_message():
with patch('smbus2.SMBus') as mock_bus:
crumbs = CRUMBS()
crumbs.begin()
mock_bus.return_value.i2c_rdwr.return_value = None
result = crumbs.send_message(message, 0x08)
assert result == True
mock_bus.return_value.i2c_rdwr.assert_called_once()
Architecture
Core Design
CRUMBS Class:
- Manages SMBus connection lifecycle
- Handles message encoding/decoding
- Provides error handling and logging
- One instance per I2C bus
CRUMBSMessage Class:
- Immutable data structure for messages
- Automatic binary encoding/decoding
- Built-in validation
Design Patterns
- Resource management: Explicit begin()/close() lifecycle
- Error propagation: Return values and exceptions
- Immutable messages: Treat as read-only after creation
- Type safety: Comprehensive type hints
Adding Features
New Message Types
- Define constants in CRUMBSMessage.py
- Add validation logic
- Update documentation
- Add usage examples
# Example: Add message type constant
SENSOR_MESSAGE_TYPE = 1
MOTOR_MESSAGE_TYPE = 2
CONFIG_MESSAGE_TYPE = 3
New Communication Patterns
- Extend CRUMBS class with new methods
- Maintain backward compatibility
- Add comprehensive error handling
- Document usage patterns
def bulk_send(self, messages, addresses):
"""Send multiple messages to multiple devices"""
results = []
for msg, addr in zip(messages, addresses):
results.append(self.send_message(msg, addr))
return results
Custom Message Classes
class SensorMessage(CRUMBSMessage):
"""Specialized sensor message"""
def __init__(self, temp=0.0, humidity=0.0):
super().__init__(
typeID=1, commandType=0,
data=[temp, humidity, 0, 0, 0, 0]
)
@property
def temperature(self):
return self.data[0]
@property
def humidity(self):
return self.data[1]
Contributing
Development Workflow
- Fork: Fork the repository on GitHub
- Branch: Create feature branch from main
- Develop: Make changes with tests
- Test: Run full test suite
- Document: Update documentation
- PR: Submit pull request
Pull Request Guidelines
- Clear description of changes
- Tests for new functionality
- Documentation updates
- Code style compliance
- Backward compatibility maintained
Commit Messages
Use conventional commits format:
feat: add bulk message sending capability
fix: handle I2C timeout errors gracefully
docs: update API reference examples
test: add unit tests for message validation
Release Process
Version Management
- Update version in
pyproject.toml - Update
CHANGELOG.md - Create git tag:
git tag v0.2.0 - Build package:
python -m build - Upload to PyPI:
twine upload dist/*
Documentation
- Update all documentation files
- Test code examples
- Verify links and references
- Generate API documentation
Documentation
Writing Guidelines
- Use clear, concise language
- Include practical examples
- Test all code snippets
- Keep documentation current with code
Building Docs
# Install dependencies
pip install sphinx sphinx-rtd-theme
# Build documentation
cd docs
make html
Performance Considerations
Optimization Areas
- Message reuse: Avoid unnecessary object creation
- Connection pooling: Reuse CRUMBS instances
- Batch operations: Group I2C transactions
- Error handling: Minimize exception overhead
Profiling
import cProfile
import pstats
def profile_communication():
# Your code here
pass
if __name__ == "__main__":
cProfile.run('profile_communication()', 'profile_stats')
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative').print_stats(10)
Debugging
Logging Configuration
import logging
# Enable detailed logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Enable specific loggers
logging.getLogger("pyCRUMBS").setLevel(logging.DEBUG)
Common Issues
- Thread safety: CRUMBS is not thread-safe
- Resource cleanup: Always call close()
- Address validation: Check 0x08-0x77 range
- Message size: Always 27 bytes
See Also
- API Reference - Complete API documentation
- Examples - Usage patterns and examples
- Getting Started - Basic setup guide