11# Contributing to ` mkl_fft `
22
3- This document covers the development
4- workflow: how to get a working build, how to run the checks, and how the code is
5- laid out so a change lands in the right layer.
3+ This document covers the development workflow: how to get a working build, how
4+ to run the checks, and what to include in a pull request.
65
7- For end-user installation and API usage, see [ README.md] ( README.md ) . Security
6+ For end-user installation and API usage, see [ README.md] ( README.md ) . For a map
7+ of the source tree, see [ ` AGENTS.md ` ] ( AGENTS.md ) , which links to the local
8+ ` AGENTS.md ` files in directories that have their own rules. Security
89vulnerabilities go through the process in [ SECURITY.md] ( SECURITY.md ) .
910
1011---
@@ -17,22 +18,31 @@ NumPy. A conda environment is the least surprising way to get them:
1718``` sh
1819# add python=X.Y to target a specific interpreter
1920conda create -n mkl_fft-dev -c conda-forge python pip mkl-devel numpy \
20- meson-python ninja cmake cython pytest scipy mkl-service
21+ meson-python ninja cmake cython pytest
2122conda activate mkl_fft-dev
2223```
2324
2425Then build in place, which reuses the environment's MKL and NumPy:
2526
2627``` sh
27- pip install -e " .[test] " --no-build-isolation --verbose
28+ pip install -e . --no-build-isolation --verbose
2829```
2930
3031` pyproject.toml ` defines the supported Python range, and
3132` .github/workflows/build_pip.yml ` is canonical for the versions CI covers.
3233
33- The ` [test] ` extra pulls in ` pytest ` , ` scipy ` , and ` mkl-service ` . Other extras
34- are declared in ` pyproject.toml ` : ` scipy_interface ` for the SciPy adapter at
35- runtime and ` benchmark ` for the ASV suite.
34+ SciPy and ` mkl-service ` are optional. They are needed only for the
35+ ` mkl_fft.interfaces.scipy_fft ` adapter, and the tests that exercise it are
36+ skipped without them. To use or test the SciPy interface, add both to the
37+ environment:
38+
39+ ``` sh
40+ conda install -c conda-forge scipy mkl-service
41+ ```
42+
43+ The matching pip extras are declared in ` pyproject.toml ` : ` scipy_interface ` for
44+ the SciPy adapter, ` test ` for ` pytest ` plus both packages, and ` benchmark ` for
45+ the ASV suite.
3646
3747` README.md ` documents the non-editable install paths, including the isolated
3848build that resolves its own ` mkl ` and ` numpy ` .
@@ -53,78 +63,19 @@ pre-commit run --all-files # lint and format hooks
5363```
5464
5565Install the hooks once with ` pre-commit install ` and they run on each commit.
56- ` .pre-commit-config.yaml ` is the source of truth for the tooling; today it
57- covers ` black ` , ` isort ` , ` flake8 ` , ` pylint ` (errors only), ` cython-lint ` ,
58- ` clang-format ` , ` codespell ` , ` shellcheck ` , ` gitleaks ` , and ` actionlint ` . Line
59- length is 80 for Python, Cython, and TOML.
60-
61- ### What CI runs
62-
63- ` .github/workflows/*.yml ` is canonical for platform and Python matrices. In
64- outline:
66+ ` .pre-commit-config.yaml ` is the source of truth for the tooling.
6567
66- | Workflow | Purpose |
67- | --- | --- |
68- | ` conda-package.yml ` | conda build and test against the Intel channel |
69- | ` conda-package-cf.yml ` | conda build and test against conda-forge only |
70- | ` build_pip.yml ` | editable pip build, including pre-release NumPy |
71- | ` build-with-clang.yml ` | build with the IntelLLVM ` icx ` compiler |
72- | ` build-with-standard-clang.yml ` | build with upstream clang |
73- | ` pre-commit.yml ` | lint and format |
74- | ` coverity.yml ` | static analysis (see ` coverity/README.md ` ) |
75- | ` openssf-scorecard.yml ` , ` zizmor.yml ` | supply-chain and workflow security |
68+ Opening a pull request also runs CI, which builds and tests the package across
69+ platforms and Python versions and runs various lint and static-analysis checks.
7670
77- To reproduce a conda packaging failure locally, build the recipe the same way CI
78- does — ` conda build --python <ver> --numpy <ver> -c <channels> --override-channels conda-recipe `
79- (or ` conda-recipe-cf ` for the conda-forge variant). The recipe directories are
80- canonical for packaging intent and dependency pins.
71+ ## Code style
8172
82- ## How the code fits together
83-
84- Build configuration lives in ` pyproject.toml ` (with ` meson-python ` as the build
85- backend) and ` meson.build ` . The version is read from ` mkl_fft/_version.py ` by
86- ` meson.build ` , so that file is the single place a version is set.
87-
88- A transform call flows down through these layers:
89-
90- ```
91- mkl_fft.interfaces.numpy_fft / scipy_fft drop-in NumPy/SciPy adapters
92- mkl_fft (__init__.py) public FFT API
93- mkl_fft/_mkl_fft.py, _fft_utils.py argument handling, normalization, dispatch
94- mkl_fft/_pydfti.pyx Cython bindings
95- mkl_fft/src/mklfft.c.src -> mklfft.c C backend, generated at build time
96- oneMKL DFTI
97- ```
73+ Style is loose, and the pre-commit hooks enforce most of it:
9874
99- Directories:
100-
101- - ** ` mkl_fft/ ` ** — the package. ` __init__.py ` is the public API surface;
102- ` _mkl_fft.py ` and ` _fft_utils.py ` hold the Python-level FFT logic;
103- ` _pydfti.pyx ` is the Cython binding layer.
104- - ** ` mkl_fft/src/ ` ** — the C backend, written as ` *.c.src ` templates. At build
105- time ` _vendored/process_src_template.py ` expands ` mklfft.c.src ` into
106- ` mklfft.c ` , which is compiled into the ` _pydfti ` extension. The generated
107- ` .c ` is regenerated on every build, so only template edits survive.
108- - ** ` mkl_fft/interfaces/ ` ** — adapters presenting ` numpy.fft ` - and
109- ` scipy.fft ` -shaped APIs. ` numpy_fft.py ` and ` scipy_fft.py ` are the public
110- modules; the ` _ ` -prefixed siblings are implementation. Upstream signatures and
111- semantics are the contract here.
112- - ** ` mkl_fft/ ` ** patching layer — ` patch.py ` , ` with_patch.py ` , ` _patch_numpy.py ` ,
113- ` _patch_startup.py ` , and the ` __main__.py ` CLI implement the monkey-patching
114- entry points documented in the README. The contract is that patching stays
115- reversible and observable: anything installed can be uninstalled, and
116- ` is_patched() ` reports the truth.
117- - ** ` mkl_fft/tests/ ` ** — the suite. ` helper.py ` holds shared utilities and
118- ` third_party/ ` carries tests adapted from upstream projects.
119- - ** ` _vendored/ ` ** — build-time code-generation helpers vendored from NumPy.
120- They are excluded from ` black ` and ` isort ` in ` pyproject.toml ` .
121- - ** ` conda-recipe/ ` ** , ** ` conda-recipe-cf/ ` ** — Intel-channel and conda-forge
122- packaging.
123- - ** ` benchmarks/ ` ** — ASV benchmarks, run with the ` benchmark ` extra.
124-
125- Each of these directories has an ` AGENTS.md ` stating the same boundaries for
126- coding agents; [ ` AGENTS.md ` ] ( AGENTS.md ) at the root indexes them and is a useful
127- orientation map for humans too.
75+ - Python and Cython are formatted with ` black ` and ` isort ` , with a line length
76+ of 80.
77+ - C sources follow the repository's ` .clang-format ` .
78+ - Otherwise, match the surrounding code.
12879
12980## Dos and don'ts
13081
@@ -137,8 +88,10 @@ orientation map for humans too.
13788- Add tests in ` mkl_fft/tests/ ` alongside behavior changes, and a regression
13889 test with every bug fix.
13990- Keep tests deterministic.
140- - Edit the ` *.c.src ` templates for C backend changes.
141- - Keep patching reversible and observable.
91+ - Edit the ` *.c.src ` templates in ` mkl_fft/src/ ` for C backend changes. The
92+ ` .c ` files are generated from them on every build.
93+ - Keep patching reversible and observable: anything installed can be
94+ uninstalled, and ` is_patched() ` reports the truth.
14295- Cite the source-of-truth file for mutable details: ` pyproject.toml ` ,
14396 ` meson.build ` , ` conda-recipe*/meta.yaml ` , ` .github/workflows/ ` .
14497- Give benchmark numbers reproducible context — hardware, versions, and the
0 commit comments