From a8cab1e95b3942f0f50de907b46fc10be6364b53 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Mon, 29 Sep 2025 14:22:56 +0100 Subject: [PATCH 1/2] Add tests to match API reference and package modules See https://github.com/collective/icalendar/pull/822#discussion_r2385523339 --- CHANGES.rst | 1 + src/icalendar/tests/test_documentation.py | 89 +++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/icalendar/tests/test_documentation.py diff --git a/CHANGES.rst b/CHANGES.rst index 6ef83e5..b97646c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -30,6 +30,7 @@ Minor changes: - Improve contributing documentation by adding a change log requirement, adding a pull request template, adding clear CI enforcement warnings, and updating ``README.rst``. See `Issue 890 `_. - Make coverage submission optional for CI. - Bump ``actions/setup-python`` version from 5 to 6 for CI. +- Ensure API Reference documentation matches ``icalendar``'s source code structure. Breaking changes: diff --git a/src/icalendar/tests/test_documentation.py b/src/icalendar/tests/test_documentation.py new file mode 100644 index 0000000..4f1282d --- /dev/null +++ b/src/icalendar/tests/test_documentation.py @@ -0,0 +1,89 @@ +"""This tests the documentation of icalendar. + +See `PR 822 `__. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +## Configuration ## + +# Modules that are not considered for documentation +# because they are private or otherwise not relevant. +EXCLUDED_MODULES = { + "icalendar.tests.conftest", # only for tests + "icalendar.tests.timezone_ids", # only for tests + "icalendar.fuzzing.ical_fuzzer", # only for fuzzing + "icalendar.cal.examples", # only for examples, exposed through components +} + +# Reference files that are not considered to match a module. +EXCLUDED_REFERENCE_FILES = { + "modules", # TODO: why is this here? +} + +## Tests ## + +HERE = Path(__file__).parent +DOCS = HERE.parent.parent.parent / "docs" + +if not DOCS.exists(): + # we might need to skip this if we have a package installation + # without docs + pytest.skip("No docs found", allow_module_level=True) + + +DOCS_REFERENCE_FILES = {file.stem for file in (DOCS / "reference").glob("*.rst")} + +DOCUMENTED_MODULES = DOCS_REFERENCE_FILES - EXCLUDED_REFERENCE_FILES + +ICALENDAR_BASE_PATH = HERE.parent.parent.absolute() + + +def convert_python_file_to_module(file: Path) -> str: + """Convert a python file path to a module name.""" + relative = file.absolute().relative_to(ICALENDAR_BASE_PATH) + parts = relative.with_suffix("").parts + if parts[-1] == "__init__": + parts = parts[:-1] + return ".".join(parts) + + +PYTHON_MODULES = { + convert_python_file_to_module(file) + for file in (HERE.parent).glob("**/*.py") + # exclude test files + if not file.name.startswith("test_") + # exclude private modules + and not (file.stem.startswith("_") and file.stem != "__init__") +} - EXCLUDED_MODULES + + +def test_all_python_modules_are_documented(): + """Test that all python modules are documented.""" + undocumented = PYTHON_MODULES - DOCUMENTED_MODULES + message = f"""{", ".join(undocumented)} are undocumented. + + Please add documentation for them in docs/reference. + + If they only contain private code, you can ignore them + by editing the name to EXCLUDED_MODULES in this test file. + """ + assert not undocumented, message + + +def test_reference_documentation_refers_to_an_existing_module(): + """Test that all documented modules exist.""" + nonexisting = DOCUMENTED_MODULES - PYTHON_MODULES + message = f"""{", ".join(nonexisting)} don't have a corresponding module. + + Please remove them from the documentation in docs/reference or + rename them to match an existing module. + + If they are correct, you can ignore them by adding the name to + EXCLUDED_REFERENCE_FILES in this test file. + """ + assert not nonexisting, message From e02fbce3f9322d8ce85a3dbb77c720549d94dbd6 Mon Sep 17 00:00:00 2001 From: Nicco Kunzmann Date: Mon, 29 Sep 2025 14:29:44 +0100 Subject: [PATCH 2/2] rephrase error message --- src/icalendar/tests/test_documentation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/icalendar/tests/test_documentation.py b/src/icalendar/tests/test_documentation.py index 4f1282d..d40d328 100644 --- a/src/icalendar/tests/test_documentation.py +++ b/src/icalendar/tests/test_documentation.py @@ -70,7 +70,7 @@ def test_all_python_modules_are_documented(): Please add documentation for them in docs/reference. If they only contain private code, you can ignore them - by editing the name to EXCLUDED_MODULES in this test file. + by adding the name to EXCLUDED_MODULES in this test file. """ assert not undocumented, message