Skip to content

Latest commit

 

History

History
446 lines (328 loc) · 12.5 KB

File metadata and controls

446 lines (328 loc) · 12.5 KB

Contributing to Course Constraint Scheduler

Thank you for your interest in contributing to the Course Constraint Scheduler! This document provides guidelines and instructions for developers who want to contribute to the project.

Table of Contents

Getting Started

Prerequisites

  • Python 3.12+: The project requires Python 3.12 or higher
  • Git: For version control
  • uv: Modern Python package manager (recommended)

Installing uv

We strongly recommend using uv for dependency management and virtual environments. It's faster and more reliable than traditional tools.

macOS and Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows:

powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

Alternative (pip):

pip install uv

Development Setup

1. Clone the repository

git clone https://github.com/mucsci/scheduler.git
cd scheduler

2. Set Up Virtual Environment with uv

Recommended approach using uv:

# Create and activate virtual environment
uv venv
source .venv/bin/activate  # On macOS/Linux
# OR
.venv\Scripts\activate     # On Windows

# Install dependencies and the package (dev group is included by default; see tool.uv in pyproject.toml)
uv sync

Alternative (if uv is not available):

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # On macOS/Linux
# OR
.venv\Scripts\activate     # On Windows

# Install the package (editable). There is no checked-in requirements.txt.
pip install -e .
# Dev tools (pytest, ruff, ty, …) are listed under [dependency-groups] dev in pyproject.toml;
# install the ones you need with pip, or prefer uv sync.

3. Install Development Dependencies

# Using uv (recommended): `uv sync` installs the dev group by default
uv sync

# If you disabled default-groups, install dev explicitly:
uv sync --group dev

# Using pip: there is no `[project.optional-dependencies]` dev extra; use uv, or install
# tools from the dev list in pyproject.toml manually after `pip install -e .`

Git hooks (prek)

After uv sync, install hooks so the same checks as CI run on each commit:

uv run prek install
# If you previously used pre-commit and need to replace its hook script:
uv run prek install -f

Configuration lives in .pre-commit-config.yaml (prek is compatible with this format).

4. Verify Installation

# Test the scheduler
uv run python -m scheduler.main --help

# Test the server
uv run python -m scheduler.server --help

# Run tests
uv run pytest

Project Structure

src/scheduler/
├── __init__.py             # Main package exports
├── config.py               # Configuration models and validation
├── json_types.py           # TypedDict definitions for JSON structures
├── main.py                 # Command-line interface
├── scheduler.py            # Core scheduling logic and Z3 integration
├── server.py               # FastAPI REST server
├── logging.py              # Logging configuration
├── models/                 # Data models
│   ├── __init__.py         # Model exports
│   ├── course.py           # Course and CourseInstance models
│   ├── day.py              # Day enumeration
│   └── time_slot.py        # Time-related models (TimeSlot, TimeInstance, etc.)
├── writers/                # Output formatters
│   ├── __init__.py         # Writer exports
│   ├── json_writer.py      # JSON output writer
│   └── csv_writer.py       # CSV output writer
└── time_slot_generator.py  # Time slot generation utilities

fern/                       # Fern documentation site (published to Fern Cloud)
├── docs.yml                # Site config, navigation, branding
├── generators.yml          # OpenAPI spec registration
├── openapi.json            # Generated from FastAPI (do not edit by hand)
├── fern.config.json        # Fern org + CLI version
└── docs/
    ├── pages/              # MDX guides (configuration, Python, dev, …)
    └── assets/             # Logos, favicon, combined-config.schema.json

docs/
└── configuration.md        # Redirect pointer to published docs

scripts/
├── export_openapi.py       # Refresh fern/openapi.json
├── export_config_schema.py # Refresh JSON Schema asset
└── gen_python_api_mdx.py   # Refresh Python API reference from docstrings

Development Workflow

1. Create a Feature Branch

# Ensure you're on main and up to date
git checkout main
git pull origin main

# Create and checkout a feature branch
git checkout -b feature/your-feature-name

2. Make Your Changes

  • Write your code following the Code Standards
  • Update documentation as needed
  • Ensure all tests pass

3. Test Your Changes

# Run tests
uv run pytest

# Run linting
uv run ruff check .

# Run type checking
uv run ty check . --ignore unresolved-import

# Or run the full hook suite (matches CI)
uv run prek run --all-files

4. Commit Your Changes

# Stage your changes
git add .

# Commit with a descriptive message
git commit -m "feat: add new optimization algorithm for room packing

- Implemented improved room packing algorithm
- Added configuration option for packing strategy
- Updated tests and documentation
- Performance improvement of 15% for large schedules"

5. Push and Create Pull Request

git push origin feature/your-feature-name

Then create a Pull Request on GitHub with:

  • Clear description of changes
  • Reference to any related issues
  • Screenshots for UI changes
  • Performance impact analysis if applicable

Code Standards

Python Style Guide

We follow PEP 8 with some modifications enforced by our linting tools.

Key Standards:

  • Use 4 spaces for indentation (no tabs)
  • Maximum line length: 120 characters (enforced by Ruff format; see [tool.ruff] in pyproject.toml)
  • Use descriptive variable and function names
  • Add type hints for all function parameters and return values
  • Use f-strings for string formatting (Python 3.6+)

Import Organization

# Standard library imports
import json
import logging
from typing import List, Optional

# Third-party imports
import z3
from pydantic import BaseModel

# Local imports
from .models import Course, CourseInstance
from .config import SchedulerConfig

Documentation Standards

Docstrings:

def generate_schedule(config: SchedulerConfig) -> List[CourseInstance]:
    """Generate a course schedule based on configuration.

    **Args:**
    - config: The scheduler configuration containing courses, faculty, and constraints.

    **Returns:**
    A list of course instances representing the generated schedule.

    **Raises:**
    - ValueError: If the configuration is invalid.
    - RuntimeError: If no valid schedule can be generated.

    **Example:**
        >>> from scheduler.config import CombinedConfig
        >>> config = load_config_from_file(CombinedConfig, "config.json")
        >>> schedule = generate_schedule(config, limit=5)
        >>> print(f"Generated {len(schedule)} courses")
    """
    pass

Inline Comments:

# Use comments to explain WHY, not WHAT
# Avoid obvious comments like "increment counter"
# Good: "Skip Fridays for labs as they're not available for scheduling"
if day == Day.FRI:
    continue

Error Handling

# Use specific exception types
try:
    result = z3_solver.check()
except z3.Z3Exception as e:
    logger.error(f"Z3 solver failed: {e}")
    raise RuntimeError(f"Schedule generation failed: {e}") from e

# Provide meaningful error messages
if not faculty_available:
    raise ValueError(
        f"Faculty member '{faculty_name}' has no available time slots "
        f"that match the course requirements"
    )

Documentation

Code Documentation

  • All public functions and classes must have docstrings
  • Use Google-style docstrings for consistency
  • Include examples for complex functions
  • Document exceptions and error conditions

API Documentation

  • Update REST API documentation for new endpoints
  • Include request/response examples
  • Document error codes and messages
  • Regenerate fern/openapi.json with uv run python scripts/export_openapi.py when server.py or shared models change
  • Regenerate fern/docs/pages/python/reference.mdx with uv run python scripts/gen_python_api_mdx.py when public docstrings change

User Documentation

  • Update Fern pages under fern/docs/pages/ (configuration, welcome, development)
  • Update README.md for new features
  • Regenerate fern/docs/assets/combined-config.schema.json with uv run python scripts/export_config_schema.py when CombinedConfig changes
  • Keep generated Fern artifacts committed when they are used by docs publishing (fern/openapi.json, fern/docs/assets/combined-config.schema.json, fern/docs/pages/python/reference.mdx)
  • Preview locally: npm install -g fern-api then fern docs dev (after the generate scripts above)

Submitting Changes

Pull Request Checklist

Before submitting a pull request, ensure:

  • Code passes linting (uv run ruff check .)
  • Type checking passes (uv run ty check . --ignore unresolved-import)
  • Tests pass (uv run pytest)
  • Documentation is updated
  • Breaking changes are documented
  • Commit messages follow conventional format

Commit Message Format

We use Conventional Commits format:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, etc.)
  • refactor: Code refactoring
  • test: Adding or updating tests
  • chore: Maintenance tasks

Examples:

feat: add new optimization algorithm for room packing

fix(scheduler): resolve memory leak in large schedule generation

docs: update configuration guide with new options

test: add performance benchmarks for optimization algorithms

Review Process

  1. Automated Checks: CI/CD pipeline runs tests and linting
  2. Code Review: At least one maintainer must approve
  3. Testing: Changes are tested in staging environment
  4. Merge: Changes are merged to main branch

Release Process

Version Management

We use Semantic Versioning:

  • MAJOR: Breaking changes
  • MINOR: New features (backward compatible)
  • PATCH: Bug fixes (backward compatible)

Release Steps

  1. Update Version: Update version in pyproject.toml
  2. Release Notes: Prepare release notes in the GitHub release description (or update CHANGELOG.md if your release includes one)
  3. Tag Release: Create git tag for the version
  4. Build Package: Build and test the package
  5. Publish: Publish to PyPI
  6. Documentation: Update documentation for new version

Release Commands

# Build package
uv run build

# Test package
uv run twine check dist/*

# Publish to PyPI
uv run twine upload dist/*

Getting Help

Communication Channels

  • GitHub Issues: Bug reports and feature requests
  • GitHub Discussions: General questions and discussions
  • Pull Requests: Code review and collaboration

Resources

Mentorship

New contributors are welcome! We're happy to:

  • Help you get started
  • Review your first pull request
  • Pair program on complex features
  • Provide guidance on best practices

Code of Conduct

We are committed to providing a welcoming and inclusive environment for all contributors. Please read our Code of Conduct for details.

License

By contributing to this project, you agree that your contributions will be licensed under the MIT License. See LICENSE for details.


Thank you for contributing to the Course Constraint Scheduler! Your contributions help make academic scheduling more efficient and accessible for everyone.