Contributing¶
Contributions to Python code, C++ code, tests, examples, and documentation are welcome. For a large API or algorithm change, open an issue first so numerical requirements and backend parity can be agreed before implementation.
Development setup¶
Install uv, then clone and synchronize the locked environment:
git clone https://github.com/GiorgioMedico/InterpolatePy.git
cd InterpolatePy
uv sync
uv run pre-commit install
The default dependency groups are dev, test, and examples. Add the docs
group for documentation work:
Before submitting a change¶
Run checks in proportion to the affected area. The complete Python-side set is:
For documentation changes:
INTERPOLATEPY_NO_CPP=1 MPLBACKEND=Agg uv run python -m scripts.check_doc_snippets
uv run mkdocs build --clean --strict
For changes to examples, run the affected scripts. A headless smoke check uses:
Repository map¶
interpolatepy/ Python package
_api.py backend routing
_backend.py native extension detection
_adapters/ C++-backed Python API adapters
tests/ pytest suite
examples/ executable Python demonstrations
cpp/
include/interpolatecpp/ public C++ headers
src/ C++ implementation
bindings/ pybind11 bindings
tests/ Catch2 tests
examples/ C++ programs
docs/ MkDocs source
Python changes¶
Use modern type annotations supported by Python 3.11. Public functions and classes should have NumPy-style docstrings describing shapes, units, valid ranges, return semantics, and errors. Keep implementation details private when they are not part of the compatibility contract.
When adding or changing an algorithm:
- validate lengths, finite values, and monotonicity at the boundary;
- test endpoints, interior waypoints, vectorized input where supported, reverse motion, degenerate cases, and invalid input;
- test derivative continuity or bounds numerically;
- update a runnable example and the relevant tutorial;
- update both backend routes if a native implementation exists.
Use the package-root API in end-user examples. Direct implementation imports are appropriate only for backend-specific tests or diagnostics.
Backend parity¶
A native algorithm is not complete when only the C++ class exists. Update:
- a public header under
cpp/include/interpolatecpp/; - a source file and
INTERPOLATECPP_SOURCESincpp/CMakeLists.txt; - Catch2 tests and, when useful, a C++ example;
- a pybind11 binding under
cpp/bindings/; - the matching adapter in
interpolatepy/_adapters/; - both branches of
interpolatepy/_api.py; - package exports and public-API tests.
Adapters should normalize container types, return types, vectorized behavior, and public parameter names. Tests should call the package-root name so the same assertions exercise whichever backend is active.
C++ build and tests¶
From the repository root:
cmake -S cpp -B build/cpp-tests \
-DINTERPOLATECPP_BUILD_TESTS=ON \
-DINTERPOLATECPP_BUILD_BINDINGS=OFF
cmake --build build/cpp-tests --parallel
ctest --test-dir build/cpp-tests --output-on-failure
To build the extension for parity tests:
cmake -S cpp -B build/cpp-bindings \
-DINTERPOLATECPP_BUILD_TESTS=OFF \
-DINTERPOLATECPP_BUILD_BINDINGS=ON
cmake --build build/cpp-bindings --parallel
cp build/cpp-bindings/bindings/interpolatecpp_py*.so interpolatepy/
python -c "import interpolatepy as ip; assert ip.HAS_CPP"
uv run pytest
The copy command shown is for Linux/macOS. See Installation for Windows and ABI details.
Tests¶
Prefer focused tests with explicit numerical tolerances. A useful algorithm test usually checks:
- exact or near-exact endpoint values;
- interpolation at all required waypoints;
- continuity from both sides of an interior knot;
- derivative limits over a dense sample, when limits are promised;
- scalar and array return shape, where vectorization is supported;
- the active public API rather than private coefficients.
Run a focused file while iterating:
Then run the full suite before opening a pull request.
Documentation¶
The site uses MkDocs Material and mkdocstrings. API pages render NumPy-style
docstrings from the installed source tree. Every code block presented as a
complete example should be executable as written; fragments should be clearly
identified. scripts.check_doc_snippets executes every standalone Python block
that imports InterpolatePy.
Keep these sources synchronized:
README.mdfor installation and the shortest introduction;ALGORITHMS.mdfor the repository-level selection guide;docs/for the published site;- public Python docstrings and C++ header comments;
docs/changelog.mdfor released behavior.
Do not publish unmeasured performance numbers, unsupported platform claims, or continuity/bound guarantees that tests do not verify.
Preview locally with:
The documentation workflow uses mkdocs build --clean --strict, so broken
links and mkdocstrings warnings fail CI.
Example programs¶
New Python examples should:
- have deterministic inputs;
- place execution under
if __name__ == "__main__"; - complete under
MPLBACKEND=Agg; - use public imports unless backend internals are the topic;
- avoid requiring an interactive prompt;
- document units and the distinction between time and curve parameters.
Add the script to Example programs. C++ examples must be added to
cpp/examples/CMakeLists.txt.
Pull requests¶
Keep a pull request focused and describe:
- the problem and numerical behavior being changed;
- compatibility or backend implications;
- tests performed;
- documentation and example updates;
- any intentionally unsupported edge case.
Do not commit generated site/, local native extension binaries, build trees,
coverage output, or virtual environments.
InterpolatePy follows semantic versioning. Breaking public API changes require a major release; backward-compatible features use a minor release; compatible fixes use a patch release.