Contributing Guide¶
Thank you for your interest in contributing to OctoPrint-TempETA!
This guide expands on the main CONTRIBUTING.md with developer-specific details.
Quick Links¶
Before You Start¶
- One issue per PR: Keep pull requests focused
- Check existing issues: Someone might be working on it
- Discuss major changes: Open an issue first for large features
- Test your changes: Include tests and verify manually
- Follow conventions: Match existing code style
Development Setup¶
See Getting Started for detailed setup instructions.
Quick version:
# Clone
git clone https://github.com/Ajimaru/OctoPrint-TempETA.git
cd OctoPrint-TempETA
# Setup environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install
pip install -e ".[develop]"
pre-commit install
Workflow¶
1. Create a Branch¶
# Feature branch
git checkout -b feature/your-feature-name
# Bug fix branch
git checkout -b fix/issue-123-description
Branch naming:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringtest/- Test additions/fixes
2. Make Changes¶
Follow coding standards:
- 4 spaces indentation (no tabs)
- English only
- Docstrings for public methods
- Type hints where applicable
- Comments explain WHY, not WHAT
Example:
def calculate_eta(self, history: Deque, target: float) -> Optional[float]:
"""
Calculate estimated time to target temperature.
Uses linear extrapolation of recent temperature history.
Args:
history: Temperature history deque
target: Target temperature in °C
Returns:
ETA in seconds, or None if insufficient data
"""
if len(history) < 2:
return None
# ... implementation
3. Write Tests¶
Add tests for new functionality:
# tests/test_calculator.py
def test_linear_heating():
"""Test linear algorithm with constant heating rate."""
calculator = ETACalculator(algorithm="linear")
history = deque()
# Simulate heating at 2°C/s
for i in range(10):
history.append((i, 25 + i * 2, 200))
eta = calculator.calculate_eta(history, 200)
# Rate = 2°C/s, remaining = 175°C
# Expected ETA = 87.5s
assert abs(eta - 87.5) < 0.1
4. Run Tests¶
# All tests
pytest
# Specific test
pytest tests/test_calculator.py::test_linear_heating
# With coverage
pytest --cov=octoprint_temp_eta --cov-report=html
# View coverage
open htmlcov/index.html
5. Run Pre-commit Checks¶
# Run all checks
pre-commit run --all-files
# Format code
black octoprint_temp_eta tests
isort octoprint_temp_eta tests
# Lint
flake8 octoprint_temp_eta tests
6. Update Documentation¶
If your changes affect:
- User behavior: Update README.md
- Settings: Update settings documentation
- API: Update API docs
- Architecture: Update architecture docs
Generate updated docs:
./scripts/generate-jsdocs.sh
mkdocs build
7. Commit Changes¶
Write clear commit messages:
# Good commit message
git commit -m "Add exponential ETA algorithm
Implements exponential model for more accurate ETA near target.
Uses scipy for curve fitting. Falls back to linear if fitting fails.
Closes #123"
# Bad commit message
git commit -m "fix stuff"
Commit message format:
<type>: <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Formattingrefactor: Code restructuringtest: Add/fix testschore: Maintenance
8. Push and Create PR¶
# Push branch
git push origin feature/your-feature-name
# Create PR on GitHub
# Fill in the PR template
Pull Request Guidelines¶
PR Title¶
Use the same format as commit messages:
feat: Add exponential ETA algorithm
fix: Correct ETA calculation for cooling
docs: Update installation instructions
PR Description¶
Include:
- What: What does this PR do?
- Why: Why is this change needed?
- How: How did you implement it?
- Testing: How did you test it?
- Screenshots: For UI changes
- Breaking changes: List any breaking changes
Template:
## Description
Adds exponential ETA algorithm for more accurate predictions near target temperature.
## Motivation
Linear algorithm is inaccurate in final approach to target due to thermal lag.
## Changes
- Added `exponential_eta()` method to calculator
- Added scipy dependency
- Updated settings to allow algorithm selection
- Added tests for exponential algorithm
## Testing
- [x] Unit tests pass
- [x] Manual testing with real printer
- [x] Tested with Python 3.11, 3.12, 3.13
## Screenshots
N/A - backend only change
## Breaking Changes
None
Review Process¶
- Automated checks must pass (CI, pre-commit)
- Code review by maintainer
- Address review comments
- Squash commits if requested
- Merge when approved
Bug Reports¶
Before Reporting¶
- Check existing issues
- Try latest version
- Verify it's not a user error
Report Template¶
**OctoPrint Version**: 1.10.2
**Plugin Version**: 0.7.1
**Python Version**: 3.11.5
**OS**: Raspberry Pi OS (Debian 12)
**Description**
ETA shows incorrect value when heating bed.
**Steps to Reproduce**
1. Set bed target to 80°C
2. Observe ETA display
3. ETA shows "00:00" immediately
**Expected Behavior**
ETA should show realistic time estimate.
**Actual Behavior**
ETA shows zero immediately.
**Logs**
**Screenshots**
[Screenshot showing issue]
Feature Requests¶
Before Requesting¶
- Check existing issues
- Search discussions
- Consider scope and feasibility
Request Template¶
**Problem**
Current ETA display is hard to read in bright light.
**Proposed Solution**
Add theme option for high-contrast display.
**Alternatives**
- Use user's system theme
- Add custom color picker
**Additional Context**
Common in outdoor 3D printing environments.
Code Style¶
Python¶
Follow PEP 8 and OctoPrint conventions:
# Good
def calculate_eta(self, history, target):
"""Calculate ETA using linear extrapolation."""
if len(history) < 2:
return None
rate = self._calculate_rate(history)
remaining = target - history[-1][1]
return remaining / rate if rate > 0 else None
# Bad
def calcETA(self,h,t):
if len(h)<2:return None
r=self._calcRate(h);rem=t-h[-1][1]
return rem/r if r>0 else None
JavaScript¶
Follow OctoPrint's JavaScript style:
// Good
self.updateETA = function(heater, data) {
var obs = self.heaters[heater];
if (obs) {
obs.eta(data.eta_seconds);
obs.rate(data.rate);
}
};
// Bad
self.updateETA=function(h,d){
var o=self.heaters[h];
if(o){o.eta(d.eta_seconds);o.rate(d.rate);}
};
LESS/CSS¶
Use semantic naming:
// Good
.temp-eta-sidebar {
.heater-name {
font-weight: bold;
}
.eta-value {
color: @brand-primary;
}
}
// Bad
.sidebar-1 {
.text1 {
font-weight: bold;
}
.text2 {
color: blue;
}
}
Translation Contributions¶
See Internationalization Guide for details.
To contribute translations:
# Initialize new language
pybabel init -i translations/messages.pot -d translations -l fr
# Edit translations/fr/LC_MESSAGES/messages.po
# Compile
pybabel compile -d translations
# Test in OctoPrint with French locale
# Submit PR with translation files
Documentation Contributions¶
Documentation improvements are always welcome!
Building Docs¶
# Install dependencies
pip install -r requirements-docs.txt
npm install
# Generate JS docs
./scripts/generate-jsdocs.sh
# Serve locally
mkdocs serve
# Build
mkdocs build
Documentation Style¶
- Use clear, concise language
- Include code examples
- Add diagrams where helpful
- Link to related pages
- Test all code examples
Community¶
- Be respectful and constructive
- Help others in discussions
- Share your use cases
- Report issues promptly
- Celebrate successes
Getting Help¶
- Questions: Use GitHub Discussions
- Bugs: Open an issue
- Security: See SECURITY.md
License¶
By contributing, you agree that your contributions will be licensed under the AGPLv3 license.
Recognition¶
Contributors are listed in AUTHORS.md.
Thank you for contributing! 🎉
Next Steps¶
- Testing Guide - Writing and running tests
- Release Process - How releases are made
- Architecture Overview - Understanding the codebase