Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ _Put your message here_
- [ ] Make sure all CI workflows are green
- [ ] When adding a public feature/fix: Update the `Unreleased` section of `CHANGELOG.md` (no date)
- [ ] Self-Review: Review "Files Changed" tab and fix any problems you find
- API Docs (only if there are changes in docstrings, rst files or samples):
- API Docs (only if there are changes in docstrings, markdown files or samples):
- [ ] Check the docs build **without** warning: see the log of the API Docs workflow
- [ ] Check that your changes render well in HTML: download the API Docs artifact and open `index.html`
- If there are any problems it is faster to iterate by [building locally the API Docs](../blob/main/doc/README.md#build-the-documentation)
- If there are any problems it is faster to iterate by [building locally the API Docs](doc/README.md#build-the-documentation)
4 changes: 2 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ supervised models (classifiers, regressors, encoders) and unsupervised models
- **`khiops.extras`** — Optional integrations such as the Docker runner
- **`khiops.tools`** — Miscellaneous utility tools and CLI entry points
- **`khiops.samples`** — Sample scripts, also used to generate parts of the
documentation via `doc/convert-samples-hook`
documentation via `doc/util/convert-samples-hook`

Keep changes inside these layer boundaries.

Expand All @@ -64,7 +64,7 @@ Keep changes inside these layer boundaries.
- Do not add new external dependencies without discussion. Minimize external
package dependencies to reduce installation problems.
- Development and documentation generation dependencies (e.g., `black`,
`isort`, `sphinx`, `wrapt`, `furo`) can be more permissive, but still avoid
`isort`, `zensical`, `wrapt`) can be more permissive, but still avoid
unnecessary additions.
- Test dependencies are listed in `test-requirements.txt` (`coverage`, `wrapt`).
Package dependencies are extracted from `pyproject.toml` at CI time via
Expand Down
25 changes: 14 additions & 11 deletions .github/instructions/ci-workflows.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ guidance.

## Workflow Overview

This repository has six GitHub Actions workflows in `.github/workflows/`. Most
workflows use concurrency groups to cancel in-progress runs when superseded,
except `api-docs.yml` (which uses a `pages` concurrency group that does not
cancel in-progress runs).
This repository has six GitHub Actions workflows in `.github/workflows/`. All
workflows except `api-docs.yml` use concurrency groups to cancel in-progress
runs when superseded.

### `quick-checks.yml`

Expand All @@ -22,7 +21,7 @@ hooks (configured in
`.pre-commit-config.yaml`) are: Black, pylint, isort (with special no-sections
config for sample files), yamlfix, shellcheck, GitHub workflow/action schema
validation (`check-github-workflows`, `check-github-actions`), and a local
`samples-generation` hook that regenerates reST samples when
`samples-generation` hook that regenerates Markdown samples when
`khiops/samples/samples.py` or `khiops/samples/samples_sklearn.py` change.

### `tests.yml`
Expand Down Expand Up @@ -71,16 +70,20 @@ corresponding GitHub environment (`testpypi` or `pypi`). Only runs for the

### `api-docs.yml`

Builds Sphinx documentation inside a dev Docker container. Triggers on:
Builds Zensical documentation inside a dev Docker container for validation.
Triggers on:

- Tag pushes — builds docs and uploads a zip archive to GitHub Releases
- PRs touching `doc/**/*.rst`, `doc/create-doc`, `doc/clean-doc`, `doc/*.py`,
`khiops/**/*.py`, or the workflow file
- PRs touching `doc/site/**/*.md`, `doc/util/create-doc`, `doc/util/clean-doc`, `doc/util/*.py`,
`zensical.toml`, `khiops/**/*.py`, or the workflow file
- `workflow_dispatch` with optional tutorial and samples revision inputs

Uses the `khiopspydev-ubuntu22.04` Docker image and runs
`./create-doc -t -d -g <revision>`. Uses a `pages` concurrency group that does
**not** cancel in-progress runs (to avoid interrupting production deployments).
`doc/util/create-doc -t -d -g <revision>`. The built HTML is uploaded as a
`api-docs` artifact for review.

Note: the production API docs are built by the
[khiops-doc](https://github.com/KhiopsML/khiops-doc) CI, which clones this
repository and builds the docs using mkdocstrings.

### `dev-docker.yml`

Expand Down
179 changes: 86 additions & 93 deletions .github/instructions/doc-changes.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,112 +12,110 @@ guidance.

```
doc/
├── conf.py # Sphinx configuration
├── index.rst # Top-level doc page
├── create-doc # Full build script (tutorials + Sphinx)
├── clean-doc # Clean script (supports --clean-tutorial)
├── convert-samples-hook # Pre-commit hook: regenerates sample reST + notebooks
├── convert_samples.py # Converts samples.py / samples_sklearn.py to reST or .ipynb
├── convert_tutorials.py # Converts tutorial Jupyter notebooks to reST
├── requirements.txt # Python doc-build dependencies
├── multi_table_primer.rst # Multi-table learning guide
├── notes.rst # API notes (common params, input types, sampling)
├── core/index.rst # khiops.core API reference (autosummary)
├── sklearn/index.rst # khiops.sklearn API reference (autosummary)
├── internal/index.rst # Internal modules reference
├── tools/index.rst # khiops.tools reference
├── samples/ # Generated reST sample pages (via convert-samples-hook)
├── tutorials/ # Generated reST tutorials (via create-doc -t)
├── _static/ # CSS and images (branding, logo)
└── _templates/autosummary/ # Custom autosummary templates (class, function, method, module)
├── README.md # Documentation guide
├── util/ # Build tooling (outside Zensical's docs_dir)
│ ├── create-doc # Full build script (tutorials + Zensical)
│ ├── clean-doc # Clean script (supports --clean-tutorial)
│ ├── convert-samples-hook # Pre-commit hook: regenerates sample Markdown + notebooks
│ ├── convert_samples.py # Converts samples.py / samples_sklearn.py to Markdown or .ipynb
│ ├── convert_tutorials.py # Converts tutorial Jupyter notebooks to Markdown
│ └── requirements.txt # Python doc-build dependencies
├── site/ # docs_dir (Zensical content only)
│ ├── index.md # Top-level doc page
│ ├── multi_table_primer.md # Multi-table learning guide
│ ├── notes.md # API notes (common params, input types, sampling)
│ ├── core/index.md # khiops.core API reference (mkdocstrings)
│ ├── sklearn/index.md # khiops.sklearn API reference (mkdocstrings)
│ ├── internal/index.md # Internal modules reference
│ ├── tools/index.md # khiops.tools reference
│ ├── samples/ # Generated Markdown sample pages (via convert-samples-hook)
│ ├── tutorials/ # Generated Markdown tutorials (via create-doc -t)
│ ├── _static/ # CSS and images (branding, logo)
│ └── _templates/ # mkdocstrings Jinja templates
└── build/ # Zensical output (site_dir)
└── html/
```

The Zensical configuration file `zensical.toml` is at the repository root.

## Build and Validation

```bash
cd doc

# Install doc dependencies (do NOT create a virtualenv inside doc/ — Sphinx will process its .rst files)
pip install -U -r requirements.txt
# Install doc dependencies (do NOT create a virtualenv inside doc/util — Zensical will process its .md files).
uv pip install -U -r doc/util/requirements.txt

# Also requires:
# - A system-wide pandoc installation (used by nbconvert for notebook→reST conversion)
# - The 'black' Python package (used by convert_samples.py to format code snippets)

# Regenerate reST samples and notebooks from samples.py / samples_sklearn.py.
# Regenerate Markdown samples and notebooks from samples.py / samples_sklearn.py.
# This hook also runs automatically via pre-commit when those files are modified.
./convert-samples-hook
doc/util/convert-samples-hook

# Full build: download tutorials, convert notebooks to Markdown, run Zensical
doc/util/create-doc -d -t

# Full build: download tutorials, convert notebooks to reST, run Sphinx
./create-doc -d -t
# Incremental build (Zensical only, after Markdown files are already generated):
zensical build

# Incremental build (Sphinx only, after reST files are already generated):
sphinx-build -M html . _build/
# Serve locally for development:
zensical serve

# Clean generated docs (add --clean-tutorial to also remove tutorials/ and khiops-python-tutorial/)
./clean-doc
doc/util/clean-doc
```

The `create-doc` script requires `tar`, `python`, `make`, `zip`, and `git` (if
downloading tutorials). Output goes to `doc/_build/html/`.
The `create-doc` script requires `python`, `uv` and `git` (if
downloading tutorials). Output goes to `doc/build/html/`.

The `create-doc` script accepts the following options:

- `-d` — Download the khiops-python-tutorial repository (implies `-t`)
- `-t` — Transform tutorial Jupyter notebooks into reST
- `-t` — Transform tutorial Jupyter notebooks into Markdown
- `-r REPO_URL` — Set the tutorial repository URL
- `-g GIT_REF` — Set the tutorial repository Git reference (branch or tag)
- `-l DIR` — Set the local directory of the tutorial repository
- `-p` — Prepare only: download tutorials, convert notebooks, create ZIPs,
and copy samples, but skip the final Zensical build. Used by the
[khiops-doc](https://github.com/KhiopsML/khiops-doc) CI.

## CI Workflow

The **API Docs** workflow (`.github/workflows/api-docs.yml`) triggers on:
The **API Docs** workflow (`.github/workflows/api-docs.yml`) validates
documentation builds. It triggers on:

- **Tag pushes** — builds docs and uploads a zip archive to GitHub Releases as
a prerelease (with `allowUpdates: true`)
- **PRs** touching `doc/**.rst`, `doc/create-doc`, `doc/clean-doc`, `doc/*.py`,
`khiops/**.py`, or the workflow file itself
- **PRs** touching `doc/site/**.md`, `doc/util/create-doc`, `doc/util/clean-doc`, `doc/util/*.py`,
`zensical.toml`, `khiops/**.py`, or the workflow file itself
- **`workflow_dispatch`** with optional inputs:
- `khiops-revision` (default `11.0.1`)
- `khiops-python-tutorial-revision` (default: `11.0.0.0`)
- `khiops-samples-revision` (default: `11.0.0`)
- `image-tag` (default: `latest`) — the dev Docker image tag

The workflow uses a concurrency group (`pages`) so only one deployment runs at a
time — queued runs are skipped but in-progress runs are never cancelled.
**Build job**

**Build job** — runs inside the
`ghcr.io/khiopsml/khiops-python/khiopspydev-ubuntu22.04:<image-tag>` Docker
image:

1. Installs the khiops-python package itself (`pip install .`)
1. Installs the khiops-core package (`uv pip install khiops-core`) and
khiops-python package itself (`uv pip install .`)
2. Downloads sample datasets via `kh-download-datasets`
3. Installs doc Python requirements from `doc/requirements.txt`
4. Runs `./create-doc -t -d -g <tutorial-revision>`
3. Installs doc Python requirements from `doc/util/requirements.txt`
4. Runs `doc/util/create-doc -t -d -g <tutorial-revision>`
5. Uploads the built HTML as a `api-docs` artifact

**Release job** (tag pushes only) — downloads the artifact, zips it, and
uploads the zip to GitHub Releases.

## Sphinx Setup

- **Engine**: Sphinx with the [Furo](https://pradyunsg.me/furo/) theme
(Orange-branded colors and Helvetica Neue font)
- **Docstring format**: [NumPy style](https://numpydoc.readthedocs.io/en/latest/format.html) parsed by the `numpydoc` extension
(`numpydoc_show_class_members = False`)
- **Extensions**: `autodoc`, `autosummary`, `intersphinx`, `numpydoc`,
`sphinx_copybutton`
- **Intersphinx targets**: Python, pandas, scikit-learn, NumPy, SciPy
- **Custom templates**: `_templates/autosummary/` provides templates for
`class.rst`, `function.rst`, `method.rst`, `module.rst`
- **Strict mode**: `nitpicky = True` — broken references are errors
- **Default role**: `obj` (configured as `default_role = "obj"` in `conf.py`) —
allows cross-referencing without explicit `:class:`/`:func:` qualifiers in
most cases
- **Warning suppression**: `conf.py` defines a `suppress_sklearn_warnings`
callback that silences known false-positive missing-reference warnings for
sklearn variables (`X`, `y`) and tutorial literals
- Sphinx warnings **should not be ignored** — they almost always indicate
rendering errors
Note: the production API docs are built by the
[khiops-doc](https://github.com/KhiopsML/khiops-doc) CI, which clones this
repository at the version tag and builds the docs natively using mkdocstrings.

## Zensical Setup

- **Engine**: Zensical with the [Material](https://squidfunk.github.io/mkdocs-material/)
theme (Orange-branded colors and Helvetica Neue font)
- **Docstring format**: [NumPy style](https://numpydoc.readthedocs.io/en/latest/format.html)
parsed by the `mkdocstrings[python]` plugin
- **Plugins**: `mkdocstrings[python]`, `autorefs`, `search`
- **Intersphinx-equivalent**: mkdocstrings `import` option loads inventory files
from Python, pandas, scikit-learn, NumPy, SciPy
- **Cross-references**: Use `[display text][fully.qualified.name]` or
`[fully.qualified.name][]` syntax for linking to documented objects
- **Custom CSS**: `doc/site/_static/css/custom.css` provides Orange branding via CSS
custom properties (Material theme variables)

## Docstring Conventions

Expand Down Expand Up @@ -166,18 +164,18 @@ Keep concise — use `list of <type>` for simple cases. For complex containers,

### Type Referencing

Use type referencing (backtick cross-references) only for complex types and
Exceptions. Do not use it for built-in types like `str` or `int`.
Use cross-references only for complex types and Exceptions. Do not use them for
built-in types like `str` or `int`.

```
# No — str and int link to the Python docs unnecessarily:
some_string : `str`
some_int : `int`
# No — str and int do not need cross-references:
some_string : str
some_int : int

# Yes — Khiops internal class:
dictionary : `.Dictionary`
dictionary : `Dictionary`

# Yes — Pandas project class (via intersphinx):
# Yes — Pandas project class (via intersphinx inventory):
df : `pandas.DataFrame`

# Yes — Exception:
Expand All @@ -187,22 +185,17 @@ Raises
When something wrong happens.
```

### Cross-References
### Cross-References in Markdown

```rst
`~khiops.core.api.train_predictor` # shows "train_predictor" (short form)
`khiops.core.api.train_predictor` # shows full path
`.train_predictor` # wildcard — works if unambiguous
`train_predictor` # within the same module
```markdown
[train_predictor][khiops.core.api.train_predictor] # shows "train_predictor"
[khiops.core.api.train_predictor][] # shows full path
```

Use explicit `:func:`, `:class:` domains only for complex types and Exceptions.
The `default_role = "obj"` setting handles most cases.

## reStructuredText Pitfalls
Use mkdocstrings `:::` directives for API documentation blocks:

The docstrings use **reST, not Markdown**. Key differences:

- **Lists** require an empty line before the first item
- **Code blocks** use `::` (with empty line + indentation) or `.. code-block:: python`
- **Links**: `` `Link text <https://example.com>`_ `` instead of `[text](url)`
```markdown
::: khiops.core.api
options:
heading_level: 3
```
2 changes: 1 addition & 1 deletion .github/instructions/docker-changes.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ containers.

### `api-docs.yml` (Consumer)

Builds the Sphinx documentation inside the `khiopspydev-ubuntu22.04` container.
Builds the Zensical documentation inside the `khiopspydev-ubuntu22.04` container.

## Editing Rules

Expand Down
8 changes: 4 additions & 4 deletions .github/instructions/python-changes.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ from `.github/copilot-instructions.md` first, then these Python-specific rules.
`line-too-long`, `unused-variable`, and `unused-import`. The overall pylint
score must stay at or above `9.9` (`fail-under`). Other pylint warnings are
lower priority.
- Pylint is **not run** on `doc/convert_samples.py` and `doc/conf.py` (excluded
in `.pre-commit-config.yaml`).
- Pylint is **not run** on `doc/util/convert_samples.py` (excluded in
`.pre-commit-config.yaml`).
- All code and comments must be in English.
- `pylint: disable=invalid-name` is used in `khiops/sklearn/estimators.py` to
permit scikit-learn's `X`, `y` naming convention. Do not add this suppression
Expand Down Expand Up @@ -79,7 +79,7 @@ The `.pre-commit-config.yaml` runs the following hooks on Python files:
| Hook | Scope | Notes |
|---|---|---|
| **black** | All `.py` files | Code formatting |
| **pylint** | All `.py` except `doc/convert_samples.py`, `doc/conf.py` | Linting |
| **pylint** | All `.py` except `doc/util/convert_samples.py` | Linting |
| **isort** | All `.py` except samples scripts | Import sorting (Black profile) |
| **isort-samples** | `khiops/samples/samples.py`, `samples_sklearn.py` | Import sorting with `--no-sections` |
| **samples-generation** | Triggered by changes to samples scripts | Runs `doc/convert-samples-hook` to regenerate reST pages and notebooks |
| **samples-generation** | Triggered by changes to samples scripts | Runs `doc/util/convert-samples-hook` to regenerate Markdown pages and notebooks |
Loading
Loading