From 835a9b7738fa8740bca1387c1f45232d3b1a3c3a Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 28 Aug 2026 17:46:49 +0200 Subject: [PATCH 1/3] upgrade docstring-generator-ext to 2.1.0, add --ignore-private and --ignore-uncommented flags, update tests and documentation --- README.md | 80 +++++++ docs/configuration.md | 6 + docs/options.md | 46 ++++ docs/skip-directives.md | 72 ++++++ mkdocs.yml | 1 + pyproject.toml | 2 +- src/docstring_generator/__init__.py | 6 - src/docstring_generator/new_gen_docs.py | 66 ++++-- tests/test_library.py | 286 ++++++++++++++++++++++++ 9 files changed, 540 insertions(+), 25 deletions(-) create mode 100644 docs/skip-directives.md diff --git a/README.md b/README.md index 01817bd..942143e 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,40 @@ gendocs_new mydir/ --style google --overwrite-style true Useful when migrating a codebase from one docstring convention to another. +### `--ignore-private` — Skip private functions/methods + +Skip functions and methods whose name starts with a single underscore (e.g. `_helper`), leaving them untouched. Dunder methods (e.g. `__init__`, `__str__`) are **not** affected by this flag — use `--ignore-magic` for those: + +```shell +gendocs_new mydir/ --ignore-private +``` + +Can also be enabled permanently via `pyproject.toml`: + +```toml +[tool.docstring_generator] +ignore_private = true +``` + +**Default:** `False` + +### `--ignore-uncommented` — Skip functions without an existing docstring + +Skip functions and methods that currently have **no docstring at all**, leaving them untouched instead of generating one. Good for simple helper functions where the name is already self-explanatory. Functions that already have *some* docstring are still processed normally (e.g. missing `Parameters`/`Returns` sections are added): + +```shell +gendocs_new mydir/ --ignore-uncommented +``` + +Can also be enabled permanently via `pyproject.toml`: + +```toml +[tool.docstring_generator] +ignore_uncommented = true +``` + +**Default:** `False` + --- ## Configuration via `pyproject.toml` @@ -185,12 +219,58 @@ threshold = 90 exclude_files = ["conftest.py", "settings.py"] exclude_dirs = ["tests", "migrations"] ignore_magic = true +ignore_private = true +ignore_uncommented = true ``` CLI flags always override `pyproject.toml` values. The tool automatically walks up from the target path to find the nearest `pyproject.toml`. --- +## Skip Directives — `# docstring: skip` / `# docstring: off` / `# docstring: on` + +When a CLI flag is too coarse, tell the generator to leave specific parts of a file untouched using `# docstring: skip` comments. Three scopes are supported: + +### 1. File-level skip + +Place the directive within the first 10 lines of the file to skip the entire file: + +```python +# docstring: skip + +def some_function(): + return None +``` + +### 2. Single-target skip + +Place the directive as the first statement inside a function or method body to skip just that target: + +```python +def helper_three(a: int) -> int: + # docstring: skip + return a +``` + +### 3. Block/Range skip + +Wrap a group of functions or classes between `# docstring: off` and `# docstring: on` to skip everything in between: + +```python +# docstring: off +def helper_one(): + ... + + +def helper_two(): + ... +# docstring: on +``` + +> ⚠️ **Known limitation:** currently only the function immediately following `# docstring: off` is reliably skipped — functions further down the block may still receive a generated docstring. Until this is fixed upstream, prefer the single-target directive on each function if you need every function in a range excluded. See the full [Skip Directives guide](https://felixthec.github.io/docstring_generator/skip-directives/) for details. + +--- + ## Preserve Custom Descriptions with `$` Placeholders Write your domain-specific notes once — `docstring_generator` will place them in the right parameter slot automatically. diff --git a/docs/configuration.md b/docs/configuration.md index 40b41e7..2a1d87c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -9,6 +9,8 @@ threshold = 90 exclude_files = ["conftest.py", "settings.py"] exclude_dirs = ["tests", "migrations"] ignore_magic = true +ignore_private = true +ignore_uncommented = true ``` CLI flags always override `pyproject.toml` values. The tool automatically walks up from the target path to find the nearest `pyproject.toml`. @@ -22,3 +24,7 @@ CLI flags always override `pyproject.toml` values. The tool automatically walks | `exclude_files` | list of str | `--exclude-file` | File names to skip | | `exclude_dirs` | list of str | `--exclude-dir` | Directory names to skip | | `ignore_magic` | bool | `--ignore-magic` | Skip dunder/magic methods | +| `ignore_private` | bool | `--ignore-private` | Skip functions/methods whose name starts with a single underscore (dunder methods are unaffected) | +| `ignore_uncommented` | bool | `--ignore-uncommented` | Skip functions/methods that currently have no docstring at all | + +> Looking for the `# docstring: skip` / `# docstring: off` / `# docstring: on` comment directives? Those aren't configured via `pyproject.toml` — see the [Skip Directives](skip-directives.md) page. diff --git a/docs/options.md b/docs/options.md index 7188d34..0d8e9d8 100644 --- a/docs/options.md +++ b/docs/options.md @@ -132,3 +132,49 @@ gendocs_new mydir/ --style google --overwrite-style true ``` Useful when migrating a codebase from one docstring convention to another. + +--- + +## `--ignore-private` — Skip private functions/methods + +Skip functions and methods whose name starts with a single underscore (e.g. `_helper`), leaving them untouched. Dunder methods (e.g. `__init__`, `__str__`) are **not** affected by this flag — use `--ignore-magic` for those: + +```shell +gendocs_new mydir/ --ignore-private +``` + +Can also be enabled permanently via `pyproject.toml`: + +```toml +[tool.docstring_generator] +ignore_private = true +``` + +**Default:** `False` + +--- + +## `--ignore-uncommented` — Skip functions without an existing docstring + +Skip functions and methods that currently have **no docstring at all**, leaving them untouched instead of generating one. This is useful for simple helper functions where the name is already self-explanatory and you don't want the tool to add boilerplate: + +```shell +gendocs_new mydir/ --ignore-uncommented +``` + +Functions that already have *some* docstring are still processed normally (e.g. missing `Parameters`/`Returns` sections are added). Only fully undocumented functions are skipped. + +Can also be enabled permanently via `pyproject.toml`: + +```toml +[tool.docstring_generator] +ignore_uncommented = true +``` + +**Default:** `False` + +--- + +## Skip Directives — `# docstring: skip` / `# docstring: off` / `# docstring: on` + +Sometimes a flag is too coarse — you want to skip *specific* files, functions, or classes without changing how the rest of the codebase is processed. For that, `docstring_generator` supports inline comment directives. See the [Skip Directives](skip-directives.md) page for the full guide with examples for each of the three supported scopes (file-level, single-target, and block/range). diff --git a/docs/skip-directives.md b/docs/skip-directives.md new file mode 100644 index 0000000..aa70dad --- /dev/null +++ b/docs/skip-directives.md @@ -0,0 +1,72 @@ +# Skip Directives + +CLI flags like `--ignore-private` or `--exclude-file` apply uniformly to a whole run. Sometimes you need something more surgical — skip *this one file*, *this one function*, or *this group of helpers* — without changing how the rest of the codebase is processed. + +For that, `docstring_generator` understands special `# docstring: ...` comments directly in your source code. Three scopes are supported. + +--- + +## 1. File-level skip + +Place `# docstring: skip` within the **first 10 lines** of the file to skip the entire file — nothing in it will be touched: + +```python +# docstring: skip + +def some_function(): + return None +``` + +Running `gendocs_new` on this file leaves it byte-for-byte unchanged. This is the right choice for generated files, vendored code, or files you never want auto-documented. + +> The directive must appear within the first 10 lines. If it appears later, it is treated as a comment and has no effect at the file level. + +--- + +## 2. Single-target skip + +Place the directive as the **first statement inside a function or method body** to skip just that one target: + +```python +def helper_three(a: int) -> int: + # docstring: skip + return a + + +def normal_func(a: int) -> int: + return a +``` + +Here, only `helper_three` is left untouched — `normal_func` still gets a docstring generated normally. This is the most precise way to opt a single function or method out of documentation, e.g. for trivial one-liners or intentionally undocumented internals. + +--- + +## 3. Block/Range skip + +Wrap a group of functions or classes between `# docstring: off` and `# docstring: on` to skip everything in between: + +```python +# docstring: off +def helper_one(): + ... + + +def helper_two(): + ... +# docstring: on +``` + +!!! warning "Known limitation" + In the current version of the underlying `docstring-generator-ext` engine, only the function **immediately following** `# docstring: off` is reliably skipped. Additional functions further down in the block (before the matching `# docstring: on`) may still receive generated docstrings. This is tracked as a known issue — until it's fixed upstream, prefer the [single-target skip](#2-single-target-skip) directive on each function you want to exclude if you need a guarantee that *every* function in a range is skipped. + +--- + +## Choosing the right scope + +| Scope | Directive | Effect | +|-------|-----------|--------| +| File-level | `# docstring: skip` (first 10 lines) | Skips the entire file | +| Single-target | `# docstring: skip` (first line inside a function/method body) | Skips just that function/method | +| Block/range | `# docstring: off` ... `# docstring: on` | Intended to skip everything in between (see limitation above) | + +These directives compose with all CLI flags — e.g. you can run `gendocs_new --ignore-magic mydir/` while still using `# docstring: skip` to opt individual functions out of documentation. diff --git a/mkdocs.yml b/mkdocs.yml index a247efc..50c4e20 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -46,6 +46,7 @@ nav: - Installation: installation.md - CLI Options: options.md - Configuration: configuration.md + - Skip Directives: skip-directives.md - Features: features.md - Pre-commit: pre-commit.md - IDE Integration: ide-integration.md diff --git a/pyproject.toml b/pyproject.toml index c7b487e..4cc95c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers=[ dependencies = [ "click == 8.4.2", - "docstring-generator-ext==2.0.14", + "docstring-generator-ext==2.1.0", ] [dependency-groups] diff --git a/src/docstring_generator/__init__.py b/src/docstring_generator/__init__.py index fd05148..e69de29 100644 --- a/src/docstring_generator/__init__.py +++ b/src/docstring_generator/__init__.py @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -@created: 01.08.21 -@author: felix -""" diff --git a/src/docstring_generator/new_gen_docs.py b/src/docstring_generator/new_gen_docs.py index 6311ad1..311964d 100644 --- a/src/docstring_generator/new_gen_docs.py +++ b/src/docstring_generator/new_gen_docs.py @@ -3,10 +3,10 @@ import shutil import subprocess import tempfile +import tomllib # type: ignore import click import docstring_generator_ext -import tomllib # type: ignore from docstring_generator.output import print_results @@ -24,7 +24,7 @@ def find_pyproject_toml(start_paths: tuple[str, ...]) -> pathlib.Path | None: Parameters ---------- - start_paths : tuple[str, Ellipsis] [Argument] + start_paths : tuple[str, Ellipsis] Returns ------- @@ -50,7 +50,7 @@ def load_toml_config(config_path: pathlib.Path | None) -> dict: """Finds and parses configuration options from pyproject.toml. Parameters ---------- - config_path : Union[pathlib.Path, None] [Argument] + config_path : Union[pathlib.Path, None] Returns ------- @@ -98,6 +98,16 @@ def load_toml_config(config_path: pathlib.Path | None) -> dict: is_flag=True, help="Only process files changed or staged in git. Aborts if git is not available.", ) +@click.option( + "--ignore-private", + is_flag=True, + help="Ignore private functions.", +) +@click.option( + "--ignore-uncommented", + is_flag=True, + help="Ignore functions without docstrings. This is good for simple helper functions where the name is enough", +) def main( paths: tuple[str, ...], style: str, @@ -110,21 +120,25 @@ def main( dry_run: bool, ignore_magic: bool, changed_only: bool, + ignore_private: bool, + ignore_uncommented: bool, ) -> None: """ Parameters ---------- - paths : tuple[str, Ellipsis] [Argument] - style : str [Argument] - check : bool [Argument] - strict : bool [Argument] - threshold : Union[int, None] [Argument] - exclude_file : list[str] [Argument] - exclude_dir : list[str] [Argument] - overwrite_style : bool [Argument] - dry_run : bool [Argument] - ignore_magic : bool [Argument] - changed_only : bool [Argument] + paths : tuple[str, Ellipsis] + style : str + check : bool + strict : bool + threshold : Union[int, None] + exclude_file : list[str] + exclude_dir : list[str] + overwrite_style : bool + dry_run : bool + ignore_magic : bool + changed_only : bool + ignore_private : bool + ignore_uncommented : bool Returns ------- @@ -138,6 +152,8 @@ def main( _exclude_files = config.get("exclude_files", []) _exclude_dirs = config.get("exclude_dirs", []) _ignore_magic = config.get("ignore_magic", False) + _ignore_private = config.get("ignore_private", False) + _ignore_uncommented = config.get("ignore_uncommented", False) # CLI args always wins if exclude_file: @@ -146,6 +162,10 @@ def main( _exclude_dirs = exclude_dir if ignore_magic: _ignore_magic = ignore_magic + if ignore_private: + _ignore_private = ignore_private + if ignore_uncommented: + _ignore_uncommented = ignore_uncommented changed_files: set[str] | None = None if changed_only: @@ -202,7 +222,7 @@ def main( if check: checked_files = { file.absolute().as_posix(): docstring_generator_ext.check_docstring( - file.absolute().as_posix(), _ignore_magic + file.absolute().as_posix(), _ignore_magic, _ignore_private, _ignore_uncommented ) for file in files_ } @@ -223,7 +243,12 @@ def main( shutil.copy2(file, tmp_path) try: docstring_generator_ext.parse_file( - tmp_path.as_posix(), docstring_style, overwrite_style + tmp_path.as_posix(), + docstring_style, + overwrite_style, + _ignore_magic, + _ignore_private, + _ignore_uncommented, ) original = file.read_text(encoding="utf-8").splitlines(keepends=True) modified = tmp_path.read_text(encoding="utf-8").splitlines(keepends=True) @@ -243,11 +268,16 @@ def main( tmp_path.unlink(missing_ok=True) else: docstring_generator_ext.parse_file( - file.absolute().as_posix(), docstring_style, overwrite_style + file.absolute().as_posix(), + docstring_style, + overwrite_style, + _ignore_magic, + _ignore_private, + _ignore_uncommented, ) except SyntaxError as e: print(f"Error processing file {file}: {e}") - except Exception as e: + except Exception as e: # noqa print(f"Error processing file {file}: {e}") diff --git a/tests/test_library.py b/tests/test_library.py index 67ae8cf..d868157 100644 --- a/tests/test_library.py +++ b/tests/test_library.py @@ -330,6 +330,292 @@ def test_changed_only_combined_with_dry_run(): ) +# --------------------------------------------------------------------------- +# --ignore-private tests +# --------------------------------------------------------------------------- + +def test_ignore_private_skips_private_functions(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write( + "def public_func(a: int) -> int:\n" + " return a\n" + "\n" + "def _private_func(a: int) -> int:\n" + " return a\n" + ) + + try: + result = subprocess.run( + [str(gendocs_new), "--ignore-private", str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = tmp_path.read_text(encoding="utf-8") + assert '"""' in content.split("def _private_func")[0], ( + "public function should have received a docstring" + ) + assert '"""' not in content.split("def _private_func")[1], ( + "--ignore-private should leave private functions untouched" + ) + finally: + tmp_path.unlink(missing_ok=True) + + +def test_ignore_private_does_not_skip_dunder_methods(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write( + "class Foo:\n" + " def __init__(self, a: int) -> None:\n" + " self.a = a\n" + ) + + try: + result = subprocess.run( + [str(gendocs_new), "--ignore-private", str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = tmp_path.read_text(encoding="utf-8") + assert '"""' in content, ( + "--ignore-private should not skip dunder methods like __init__" + ) + finally: + tmp_path.unlink(missing_ok=True) + + +def test_ignore_private_via_pyproject_config(): + with TemporaryDirectory() as tmp_dir: + tmp_dir_path = Path(tmp_dir) + + (tmp_dir_path / "pyproject.toml").write_text( + "[tool.docstring_generator]\nignore_private = true\n", + encoding="utf-8", + ) + sample = tmp_dir_path / "sample.py" + sample.write_text( + "def public_func(a: int) -> int:\n" + " return a\n" + "\n" + "def _private_func(a: int) -> int:\n" + " return a\n", + encoding="utf-8", + ) + + gendocs_new = Path(sys.executable).parent / "gendocs_new" + result = subprocess.run( + [str(gendocs_new), str(sample)], + capture_output=True, + text=True, + cwd=tmp_dir, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = sample.read_text(encoding="utf-8") + assert '"""' in content.split("def _private_func")[0] + assert '"""' not in content.split("def _private_func")[1] + + +# --------------------------------------------------------------------------- +# --ignore-uncommented tests +# --------------------------------------------------------------------------- + +def test_ignore_uncommented_skips_functions_without_docstring(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write( + "def has_docstring(a: int) -> int:\n" + ' """Existing docstring."""\n' + " return a\n" + "\n" + "def no_docstring(a: int) -> int:\n" + " return a\n" + ) + + try: + result = subprocess.run( + [str(gendocs_new), "--ignore-uncommented", str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = tmp_path.read_text(encoding="utf-8") + has_docstring_part, no_docstring_part = content.split("def no_docstring") + + # the already-documented function should have been extended with parameter info + assert "Parameters" in has_docstring_part, ( + "functions that already have a docstring must still be processed" + ) + # the fully undocumented function must be left untouched + assert '"""' not in no_docstring_part, ( + "--ignore-uncommented should leave functions without a docstring untouched" + ) + finally: + tmp_path.unlink(missing_ok=True) + + +def test_ignore_uncommented_via_pyproject_config(): + with TemporaryDirectory() as tmp_dir: + tmp_dir_path = Path(tmp_dir) + + (tmp_dir_path / "pyproject.toml").write_text( + "[tool.docstring_generator]\nignore_uncommented = true\n", + encoding="utf-8", + ) + sample = tmp_dir_path / "sample.py" + sample.write_text( + "def no_docstring(a: int) -> int:\n" + " return a\n", + encoding="utf-8", + ) + + gendocs_new = Path(sys.executable).parent / "gendocs_new" + result = subprocess.run( + [str(gendocs_new), str(sample)], + capture_output=True, + text=True, + cwd=tmp_dir, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = sample.read_text(encoding="utf-8") + assert '"""' not in content, ( + "--ignore-uncommented (via pyproject.toml) should leave undocumented functions untouched" + ) + + +# --------------------------------------------------------------------------- +# `# docstring: skip` / `# docstring: off` / `# docstring: on` directive tests +# --------------------------------------------------------------------------- + +def test_skip_directive_file_level_leaves_file_untouched(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write( + "# docstring: skip\n" + "\n" + "def some_function(a: int) -> int:\n" + " return a\n" + ) + + try: + original_content = tmp_path.read_text(encoding="utf-8") + + result = subprocess.run( + [str(gendocs_new), str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + assert tmp_path.read_text(encoding="utf-8") == original_content, ( + "a `# docstring: skip` comment within the first 10 lines must skip the whole file" + ) + finally: + tmp_path.unlink(missing_ok=True) + + +def test_skip_directive_single_target_skips_only_that_function(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + padding = "".join(f"# padding line {i}\n" for i in range(1, 11)) + source = ( + padding + + "def helper_three(a: int) -> int:\n" + + " # docstring: skip\n" + + " return a\n" + + "\n" + + "def normal_func(a: int) -> int:\n" + + " return a\n" + ) + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write(source) + + try: + result = subprocess.run( + [str(gendocs_new), str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = tmp_path.read_text(encoding="utf-8") + helper_part, normal_part = content.split("def normal_func") + + assert '"""' not in helper_part, ( + "a `# docstring: skip` placed below a function must skip just that function" + ) + assert '"""' in normal_part, ( + "functions without the skip directive must still be processed" + ) + finally: + tmp_path.unlink(missing_ok=True) + + +@pytest.mark.xfail(reason="Block skip via `# docstring: off` / `# docstring: on` is not honored by the extension") +def test_skip_directive_block_range_skips_everything_between(): + gendocs_new = Path(sys.executable).parent / "gendocs_new" + + padding = "".join(f"# padding line {i}\n" for i in range(1, 11)) + source = ( + padding + + "def before_block(a: int) -> int:\n" + + " return a\n" + + "\n" + + "# docstring: off\n" + + "def helper_one(a: int) -> int:\n" + + " return a\n" + + "\n" + + "\n" + + "def helper_two(a: int) -> int:\n" + + " return a\n" + + "# docstring: on\n" + + "\n" + + "def after_block(a: int) -> int:\n" + + " return a\n" + ) + + with NamedTemporaryFile(suffix=".py", delete=False, mode="w") as tmp_file: + tmp_path = Path(tmp_file.name) + tmp_file.write(source) + + try: + result = subprocess.run( + [str(gendocs_new), str(tmp_path)], + capture_output=True, + text=True, + ) + assert result.returncode == 0, f"gendocs_new failed:\n{result.stderr}" + + content = tmp_path.read_text(encoding="utf-8") + before, rest = content.split("def helper_one") + block, after = rest.split("# docstring: on") + + assert '"""' in before, "functions before the block must still be processed" + assert '"""' not in block, ( + "functions between `# docstring: off` and `# docstring: on` must be skipped" + ) + assert '"""' in after, "functions after the block must still be processed" + finally: + tmp_path.unlink(missing_ok=True) + + @pytest.mark.xfail def test_overwrite_existing_style(): gendocs_new = Path(sys.executable).parent / "gendocs_new" From 4ff9d4dbd4576af74bb75b5011831ad46d2c091e Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 28 Aug 2026 17:48:47 +0200 Subject: [PATCH 2/3] add Read the Docs configuration and requirements for documentation build --- .readthedocs.yaml | 24 ++++++++++++++++++++++++ docs/requirements.txt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 .readthedocs.yaml create mode 100644 docs/requirements.txt diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..b73721c --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-24.04 + tools: + python: "3.14" + +mkdocs: + configuration: mkdocs.yml + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . + extra_requirements: + - build diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..78a2877 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,33 @@ +attrs>=21.2.0 +certifi>=2024.7.4 +chardet>=4.0.0 +click>=8.0.0 +codecov>=2.1.13 +coverage>=5.5 +future>=0.18.2 +idna>=2.10 +Jinja2>=3.1.5 +joblib>=1.2.0 +livereload>=2.6.3 +lunr>=0.5.8 +Markdown>=3.3.4 +MarkupSafe>=2.0.1 +mkdocs>=1.1.2 +more-itertools>=8.7.0 +nltk>=3.6.2 +packaging>=20.9 +pluggy>=0.13.1 +py>=1.10.0 +pyparsing>=2.4.7 +pytest>=5.4.1 +pytest-cov>=2.12.0 +PyYAML>=6.0.2 +regex>=2021.4.4 +requests>=2.25.1 +six>=1.16.0 +toml>=0.10.2 +tornado>=6.1 +tqdm>=4.60.0 +ujson>=5.4.0 +urllib3>=1.26.5 +wcwidth>=0.2.5 From 15d91b1f73fbdf72bb6e01c5f7ce648450ac3575 Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 28 Aug 2026 17:48:47 +0200 Subject: [PATCH 3/3] add Read the Docs configuration and requirements for documentation build --- .github/workflows/docs.yml | 29 ----------------------------- .readthedocs.yaml | 24 ++++++++++++++++++++++++ docs/requirements.txt | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 29 deletions(-) delete mode 100644 .github/workflows/docs.yml create mode 100644 .readthedocs.yaml create mode 100644 docs/requirements.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index d49fc44..0000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Deploy Docs - -on: - push: - branches: - - main - workflow_dispatch: - -permissions: - contents: write - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - - name: Install MkDocs Material - run: pip install mkdocs-material - - - name: Deploy to GitHub Pages - run: mkdocs gh-deploy --force diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..b73721c --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-24.04 + tools: + python: "3.14" + +mkdocs: + configuration: mkdocs.yml + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . + extra_requirements: + - build diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..78a2877 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,33 @@ +attrs>=21.2.0 +certifi>=2024.7.4 +chardet>=4.0.0 +click>=8.0.0 +codecov>=2.1.13 +coverage>=5.5 +future>=0.18.2 +idna>=2.10 +Jinja2>=3.1.5 +joblib>=1.2.0 +livereload>=2.6.3 +lunr>=0.5.8 +Markdown>=3.3.4 +MarkupSafe>=2.0.1 +mkdocs>=1.1.2 +more-itertools>=8.7.0 +nltk>=3.6.2 +packaging>=20.9 +pluggy>=0.13.1 +py>=1.10.0 +pyparsing>=2.4.7 +pytest>=5.4.1 +pytest-cov>=2.12.0 +PyYAML>=6.0.2 +regex>=2021.4.4 +requests>=2.25.1 +six>=1.16.0 +toml>=0.10.2 +tornado>=6.1 +tqdm>=4.60.0 +ujson>=5.4.0 +urllib3>=1.26.5 +wcwidth>=0.2.5