Developer Guide

The document provides resources for current/prospective pooltool developers.

Development environment setup

For complete installation instructions, please refer to the Installation Guide. Follow the “From source” section.

After installation, make sure to install the pre-commit hooks, which ensure your code adheres to the project’s style guidelines:

pre-commit install

This will automatically check and format your code when you make commits.

Development workflow

Common Make commands

The project includes a Makefile with common commands to streamline development:

Documentation:

make docs                 # Build and view documentation
make live                 # Live preview of docs with auto-refresh
make notebooks            # Execute and update notebooks in docs
make docs-with-notebooks  # Build docs including notebook execution

Code quality:

make format               # Auto-format and fix lint issues
make lint                 # Check formatting and lint (read-only)
make typecheck            # Run type checking

Testing:

make test                 # Run all tests
make test-coverage        # Run tests with coverage report

Building and publishing:

make clean                # Clean build artifacts
make build                # Build package distribution

Pre-commit hooks

Pre-commit hooks ensure that code formatting and linting are checked before each commit. These hooks run automatically when you commit code if you’ve installed them with pre-commit install.

The pre-commit configuration in pooltool includes:

  • Code formatting (using Ruff)

  • Linting checks (using Ruff)

  • Type checking (using Pyright)

  • Running tests (using Pytest)

If a hook fails, the commit will be aborted. You can fix the issues and try committing again. Sometimes the hooks will automatically fix issues (like formatting), in which case you’ll need to stage those changes before committing again.

Code style and formatting

Python code style

  • Linting and formatting is handled by Ruff.

  • Type hints are highly appreciated for all functions and methods

Docstring conventions

Pooltool uses Google-style docstrings. Here’s an example of the expected format:

def function_name(arg1: str, arg2: int) -> list[str]:
    """Brief description of the function.
    
    More detailed description that can span multiple lines.
    
    Args:
        arg1: Description of arg1
        arg2: Description of arg2
            
    Returns:
        list[str]:
            Description of the return value
        
    Raises:
        ExceptionType: Description of when this exception is raised
        
    Notes:
        Additional information about implementation details
        
    Example:
        >>> code_example
        expected_output
        
    See Also:
        - related_function: Description of how it's related
    """

Type checking

The project uses pyright for static type checking. Type annotations should be used for all function parameters, return values, and class attributes. The type checking configuration is in pyrightconfig.ci.json.

Testing

Pooltool uses pytest for testing. Tests should be written for all new features and bug fixes.

Writing tests

  • Tests are located in the tests/ directory

  • Test files should be named test_*.py

  • Test functions should be named test_*

Running tests

# Run all tests
make test

# Run a specific test file
pytest tests/path/to/test_file.py

# Run a specific test
pytest -k test_function_name

Documentation

  • Documentation is written in Markdown and built using Sphinx with MyST parser. The documentation is hosted on Read the Docs.

  • The API reference is automatically generated from docstrings.

  • Examples are provided as Jupyter notebooks in the docs/examples/ directory.

Commands for building documentation:

# Build documentation
make docs

# Live preview with auto-reload (recommended for development)
make docs-live

# Execute notebooks, then build docs
make docs-with-notebooks

Cross-referencing examples

The following shows examples and information for cross-referencing from source → target.

Markdown → Python

To add an inlaid dropdown signature:

Markdown → Markdown/Jupyter

To cross-reference other pages use relative paths. This takes you to the 30 Degree Rule example. Technically, the extension can be ommitted, but since cross-referencing in Jupyter notebooks requires the extension (see below), for consistency please keep the extension.

Docstrings → Python

When referencing objects in the same module, simply provide their name:

:class:`LinearCushionSegment`
:attr:`contains`
:func:`continuize`

When referencing from a different module, use the object reference with the lowest level API. As an example, consider Ball and its various references:

pooltool.Ball
pooltool.objects.Ball
pooltool.objects.ball.datatypes.Ball

Ball is defined as pooltool.objects.ball.datatypes.Ball, but pooltool.objects.ball.datatypes isn’t part of the API. pooltool.Ball is in the API but it’s also referenced as pooltool.objects.Ball. Since that has a lower reference, it is the preferred reference. To see which subpackages are part of the API, see what’s imported in pooltool/__init__.py.

Docstrings → Markdown/Jupyter

You can cross-reference document pages with the :doc: directive. For example,

:doc:`Table Specification </resources/table_specs>`

Jupyter → Python

It’s a bit tricky. The working formula is:

[Text](../autoapi/{MODULE_PATH}/index.rst#{FULL_OBJECT_DESCRIPTOR})

For example, to link to the Table object,

[Table](../autoapi/pooltool/objects/index.rst#pooltool.objects.table)

Jupyter → Markdown/Jupyter

To cross-reference other pages use relative paths:

[Straight shot example](./straight_shot.ipynb)

Providing the file extension is required.