Contributing to py2max¶
Thank you for your interest in contributing to py2max! This document provides guidelines and instructions for contributing to the project.
Code of Conduct¶
- Be respectful and inclusive in all interactions
- Focus on constructive feedback
- Help create a welcoming environment for all contributors
Getting Started¶
Development Setup¶
- Clone the repository:
- Install uv (if not already installed):
- Set up development environment:
- Verify installation:
Development Workflow¶
Before You Start¶
- Check existing issues to see if your feature/bug is already being worked on
- Open an issue to discuss major changes before implementing them
- Fork the repository and create a feature branch
Making Changes¶
- Create a feature branch:
-
Make your changes following our coding standards (see below)
-
Run quality checks:
- Run tests:
- Commit your changes:
Coding Standards¶
Code Style¶
- Linter: We use
rufffor linting - Auto-fix: Run
make lintto automatically fix issues - Line length: Maximum 100 characters (configured in
pyproject.toml)
Type Hints¶
- Required: All function signatures must have type hints
- Type checker: We use
mypyfor static type checking - Run:
make typecheckormypy py2max
Testing¶
- Coverage requirement: Maintain > 80% test coverage (current: 82%)
- Test framework: pytest
- Test location:
tests/directory - Naming: Test files must start with
test_
Writing Tests¶
"""tests/test_my_feature.py"""
from py2max import Patcher
def test_my_feature():
"""Test description."""
p = Patcher('test.maxpat')
# ... test code ...
assert expected == actual
Running Tests¶
# Run all tests
make test
# Run specific test file
uv run pytest tests/test_my_feature.py
# Run with verbose output
uv run pytest -v
# Generate coverage report
make coverage
Documentation¶
- Docstrings: All public classes, methods, and functions must have docstrings
- Format: Google-style docstrings
- Examples: Include usage examples in docstrings
Docstring Example¶
def add_textbox(self, text: str, maxclass: Optional[str] = None) -> Box:
"""Add a text-based Max object to the patch.
Creates a Max object from a text specification (e.g., 'cycle~ 440').
Args:
text: Max object specification (e.g., 'cycle~ 440', 'gain~').
maxclass: Override the automatically determined maxclass.
Returns:
The created Box object.
Example:
>>> p = Patcher('patch.maxpat')
>>> osc = p.add_textbox('cycle~ 440')
>>> gain = p.add_textbox('gain~')
>>> p.add_line(osc, gain)
"""
# ... implementation ...
Pull Request Process¶
Checklist¶
Before submitting a pull request, ensure:
- [ ] Code follows project style guidelines
- [ ] All tests pass (
make test) - [ ] Type checking passes (
make typecheck) - [ ] Linting passes (
make lint) - [ ] Test coverage remains > 80% (
make coverage) - [ ] Documentation is updated (if applicable)
- [ ] CHANGELOG.md is updated (for user-facing changes)
- [ ] Commit messages are clear and descriptive
Submitting¶
- Push your branch:
- Create a pull request on GitHub with:
- Clear title describing the change
- Description explaining:
- What changed
- Why it changed
- How to test it
-
Link to related issues
-
Respond to feedback from reviewers
-
Ensure CI passes - All GitHub Actions checks must pass
Commit Message Guidelines¶
Format¶
Types¶
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, no logic change)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
Examples¶
feat: add find_by_text method for searching boxes
Adds case-insensitive text search across all boxes in a patcher.
Includes comprehensive test coverage.
Closes #123
fix: resolve type error in db.py
Fixed incompatible types in db_path assignment by adding Union type.
Project Structure¶
py2max/
├── py2max/ # Main package
│ ├── __init__.py # Public API exports
│ ├── cli.py # Command-line interface
│ ├── exceptions.py # Exception hierarchy
│ ├── log.py # Logging utilities
│ ├── utils.py # Utility functions
│ ├── transformers.py # Patch transformers
│ │
│ ├── core/ # Core patcher functionality
│ │ ├── patcher.py # Patcher class
│ │ ├── box.py # Box class
│ │ ├── patchline.py # Patchline class
│ │ ├── abstract.py # Abstract base classes
│ │ └── common.py # Rect class
│ │
│ ├── maxref/ # Max object reference system
│ │ ├── parser.py # XML parsing
│ │ ├── db.py # SQLite database
│ │ ├── category.py # Object categorization
│ │ └── legacy.py # MAXCLASS_DEFAULTS
│ │
│ ├── layout/ # Layout managers
│ │ ├── base.py # LayoutManager base class
│ │ ├── grid.py # GridLayoutManager
│ │ ├── flow.py # FlowLayoutManager
│ │ └── matrix.py # MatrixLayoutManager
│ │
│ ├── server/ # Interactive server & REPL
│ │ ├── websocket.py # WebSocket server
│ │ ├── repl.py # REPL core
│ │ ├── client.py # REPL client
│ │ ├── inline.py # Inline REPL
│ │ └── rpc.py # RPC server
│ │
│ └── export/ # Export functionality
│ ├── svg.py # SVG export
│ └── converters.py # Format converters
│
├── tests/ # Test suite
├── docs/ # Documentation
├── .github/workflows/ # CI/CD configuration
├── Makefile # Development commands
└── pyproject.toml # Project configuration
Common Tasks¶
Running Quality Checks¶
# Run all quality checks
make qa
# Individual checks
make lint # Code linting with auto-fix
make typecheck # Type checking
Building Documentation¶
# Build the MkDocs documentation
make docs
# Serve documentation locally with live reload
make docs-serve
# Deploy to GitHub Pages
make docs-deploy
Building Package¶
Getting Help¶
- Issues: Open an issue on GitHub for bugs or feature requests
- Discussions: Use GitHub Discussions for questions
- Documentation: Check the docs directory
License¶
By contributing to py2max, you agree that your contributions will be licensed under the MIT License.
Recognition¶
Contributors will be recognized in:
- CHANGELOG.md (for significant contributions)
- GitHub contributors page
- Project documentation (for major features)
Questions?¶
If you have questions about contributing, please:
- Check existing issues and documentation
- Open a GitHub Discussion
- Reach out to maintainers
Thank you for contributing to py2max!