Contributing¶
We welcome contributions to pycsp3-scheduling! This guide will help you get started.
Getting Started¶
Fork the repository on GitHub
Clone your fork:
git clone https://github.com/YOUR_USERNAME/pycsp3-scheduling.git cd pycsp3-scheduling
Set up development environment:
pip install -e ".[dev]"
Create a feature branch:
git checkout -b feature/your-feature-name
Development Workflow¶
Running Tests¶
# Run all tests
pytest
# Run with coverage
pytest --cov=pycsp3_scheduling
# Run specific test file
pytest tests/test_interval.py
# Run with verbose output
pytest -v
Code Quality¶
We use several tools to maintain code quality:
# Linting
ruff check .
# Auto-format code
ruff format .
# Type checking
mypy pycsp3_scheduling
Pre-commit Checks¶
Before committing, ensure:
All tests pass
Code is formatted with
ruff formatNo linting errors from
ruff checkType hints are correct (
mypy)
Coding Standards¶
Code Style¶
Follow PEP 8 guidelines
Use type hints for all public functions
Maximum line length: 100 characters
Use
from __future__ import annotationsfor forward references
Docstrings¶
Use Google-style docstrings:
def function_name(param1: int, param2: str) -> bool:
"""Short description of the function.
Longer description if needed, explaining the function's
behavior in more detail.
Args:
param1: Description of first parameter.
param2: Description of second parameter.
Returns:
Description of return value.
Raises:
TypeError: When input types are invalid.
ValueError: When values are out of range.
Example:
>>> result = function_name(1, "test")
>>> print(result)
True
"""
...
Naming Conventions¶
Classes:
PascalCase(e.g.,IntervalVar,SequenceVar)Functions:
snake_case(e.g.,end_before_start,interval_value)Constants:
UPPER_SNAKE_CASE(e.g.,INTERVAL_MIN,INTERVAL_MAX)Private functions:
_leading_underscore
Project Structure¶
pycsp3_scheduling/
├── __init__.py # Public API exports
├── interop.py # pycsp3 bridge functions
├── variables/ # Variable types
│ ├── interval.py # IntervalVar
│ └── sequence.py # SequenceVar
├── expressions/ # Expression functions
│ └── interval_expr.py # start_of, end_of, etc.
├── constraints/ # Constraint functions
│ ├── precedence.py # Precedence constraints
│ ├── grouping.py # span, alternative, synchronize
│ └── sequence.py # SeqNoOverlap, first, last, etc.
└── functions/ # Cumulative and state functions
├── cumul_functions.py
└── state_functions.py
Adding New Features¶
Adding a New Constraint¶
Choose the appropriate module (or create a new one)
Implement the constraint function:
Validate input types
Build pycsp3 Node expression
Return the constraint
Add to exports in
__init__.pyWrite tests in
tests/test_constraints.pyDocument in the API reference
Example pattern:
def new_constraint(a: IntervalVar, b: IntervalVar, param: int = 0):
"""
Description of the constraint.
Args:
a: First interval.
b: Second interval.
param: Optional parameter.
Returns:
A pycsp3 Node representing the constraint.
"""
if not isinstance(a, IntervalVar) or not isinstance(b, IntervalVar):
raise TypeError("new_constraint expects IntervalVar inputs")
Node, TypeNode = _get_node_builders()
# Build constraint...
return Node.build(TypeNode.XXX, ...)
Adding a New Variable Type¶
Create module in
variables/Implement class with
@dataclassdecoratorInclude validation in
__post_init__Add registry for model compilation
Export from
variables/__init__.pyand main__init__.pyWrite comprehensive tests
Testing Guidelines¶
Test Organization¶
Use class-based test organization
One test class per major feature
Use fixtures for setup/teardown
import pytest
from pycsp3_scheduling import IntervalVar
class TestIntervalVar:
@pytest.fixture(autouse=True)
def reset_registry(self):
"""Reset registry before each test."""
from pycsp3_scheduling.variables.interval import clear_interval_registry
clear_interval_registry()
def test_creation_with_fixed_size(self):
task = IntervalVar(size=10, name="task")
assert task.size_min == 10
assert task.size_max == 10
def test_creation_with_variable_size(self):
task = IntervalVar(size=(5, 15), name="task")
assert task.size_min == 5
assert task.size_max == 15
Test Coverage¶
Aim for >90% code coverage
Test edge cases (empty inputs, boundary values)
Test error handling (invalid inputs)
Submitting Changes¶
Ensure all checks pass:
pytest ruff check . mypy pycsp3_scheduling
Write clear commit messages:
Add end_before_start constraint with delay parameter - Implement end_before_start(a, b, delay=0) - Add validation for IntervalVar inputs - Include docstring with examples - Add unit tests for all cases
Push to your fork:
git push origin feature/your-feature-name
Open a Pull Request with:
Clear description of changes
Reference to any related issues
Test results
Questions?¶
Open an issue for bugs or feature requests
Check existing issues before creating new ones
Join discussions in pull requests
Thank you for contributing!