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/directoryTest files should be named
test_*.pyTest 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¶
pooltool.objects.Cue.set_state()(text = hyperlink)
To add an inlaid dropdown signature:
Admonition Title (e.g. “Physics Engine”)
Add optional text here
- class SimulationEngine(is_3d: bool = False, resolver: Resolver = Resolver.default)[source]
A bundle of physics strategies used by the simulator.
Holds the resolver (pluggable per-event-type collision strategies) and the detector. The simulator is handed an instance and routes work to its components.
Attributes:
- is_3d : bool
Whether the simulation supports the airborne motion state and ball-table events. Validated at construction against the dimensionality capability (
dim) of every bundled strategy inresolver.
- resolver : Resolver
Pluggable bundle of event-resolution strategies. Each strategy declares a
Dimcapability (exceptball_table).
- detector : pooltool.evolution.event_based.detect.detector.EventDetector
Canonical event detector. Not constructor-passable — built from
is_3dautomatically.
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.
Examples gallery¶
The Examples gallery is a key part of the documentation, consisting of Jupyter notebooks that demonstrate various aspects of pooltool. These notebooks are located in the docs/examples/ directory.
To add a new example to the gallery:
Create a new Jupyter notebook in the
docs/examples/directoryFollow the naming convention of existing examples (descriptive, with underscores)
Include a clear title and description at the top of the notebook
Add assets (images, etc.) to the
docs/examples/assets/your_example_name/directory if neededUpdate the
docs/examples/index.mdfile to include your new exampleRun
make docs-with-notebooksto build the documentation with your new example