From 4c73319d3bb5c017f302885fed66c5953dd86d6f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 28 Sep 2026 18:42:34 +0200 Subject: [PATCH] Use one-line module docstrings in the API checker scripts Codacy runs two docstring checkers with opposite rules for module docstrings: with the summary on the first line it reported D213, with the summary on the second line it reports D212. A one-line docstring satisfies both. Keep the summary as the docstring and move the details into a comment below it; nothing reads the module docstrings. Signed-off-by: Niels Lohmann --- tools/api_checker/check_docs.py | 12 ++++---- tools/api_checker/check_macros.py | 20 ++++++-------- tools/api_checker/diff_api.py | 40 +++++++++++++-------------- tools/api_checker/extract_api.py | 36 ++++++++++++------------ tools/api_checker/snapshot_release.py | 16 +++++------ 5 files changed, 57 insertions(+), 67 deletions(-) diff --git a/tools/api_checker/check_docs.py b/tools/api_checker/check_docs.py index 84ec96d2d..384772e04 100755 --- a/tools/api_checker/check_docs.py +++ b/tools/api_checker/check_docs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -""" -Verify that public API entries have documentation links. +"""Verify that public API entries have documentation links.""" -Consumes an API snapshot from extract_api.py and checks: -1. Every public callable/type-tier entry has an @sa comment (with exceptions) -2. Every @sa URL resolves to an existing documentation file -3. No @sa comments appear on non-public entities -""" +# Consumes an API snapshot from extract_api.py and checks: +# 1. Every public callable/type-tier entry has an @sa comment (with exceptions) +# 2. Every @sa URL resolves to an existing documentation file +# 3. No @sa comments appear on non-public entities import argparse import json diff --git a/tools/api_checker/check_macros.py b/tools/api_checker/check_macros.py index 0657270fb..3bcb89728 100755 --- a/tools/api_checker/check_macros.py +++ b/tools/api_checker/check_macros.py @@ -1,16 +1,14 @@ #!/usr/bin/env python3 -""" -Advisory-only cross-check between documented macros and their #define sites. +"""Advisory-only cross-check between documented macros and their #define sites.""" -Macros have no C++ access-specifier concept, so the AST-based public/private test that -extract_api.py uses for classes doesn't transfer -- see tools/api_checker/POLICY.md's "Known -limitations" section. This script only checks one direction: that every macro documented under -docs/mkdocs/docs/api/macros/ still has a matching #define somewhere under include/nlohmann/, -catching stale or renamed doc pages. It does NOT check the converse (undocumented macros) -- -no reliable signal exists for that direction given this codebase's conventions. - -Never blocks CI -- always exits 0, even when it reports findings. -""" +# Macros have no C++ access-specifier concept, so the AST-based public/private test that +# extract_api.py uses for classes doesn't transfer -- see tools/api_checker/POLICY.md's "Known +# limitations" section. This script only checks one direction: that every macro documented under +# docs/mkdocs/docs/api/macros/ still has a matching #define somewhere under include/nlohmann/, +# catching stale or renamed doc pages. It does NOT check the converse (undocumented macros) -- +# no reliable signal exists for that direction given this codebase's conventions. +# +# Never blocks CI -- always exits 0, even when it reports findings. import argparse import glob diff --git a/tools/api_checker/diff_api.py b/tools/api_checker/diff_api.py index a61628152..8524346a9 100755 --- a/tools/api_checker/diff_api.py +++ b/tools/api_checker/diff_api.py @@ -1,26 +1,24 @@ #!/usr/bin/env python3 -""" -Diff the public API surface between two refs to flag breaking vs. feature changes. +"""Diff the public API surface between two refs to flag breaking vs. feature changes.""" -A "ref" for --old/--new is resolved in this order: -1. A stored, committed historical record at tools/api_checker/history/.json, if one exists - and --no-history wasn't passed (fast path -- no libclang/git-archive needed). -2. Live extraction: check the ref out via `git archive` into a temp dir and run extract_api.py - against it (needed for HEAD, branches, or any tag not yet backfilled into history/). ---old-file/--new-file bypass both and load an arbitrary surface JSON file directly. - -Uses extract_api.py's --surface-output (identity-only: scope, kind, name, identity_name, tier, -signature, pretty_signature -- no location, no doc_url) for both sides, so the diff reflects only -genuine API changes, never unrelated code motion or documentation-site restructuring. Identity is -(scope, identity_name, kind, signature) -- see extract_api.py's identity_key()/get_signature_text() -docstrings for the full history of why this is what it is: a naive {scope,name,kind,params} key -silently collided on overloads differing only by constness/SFINAE; switching to libclang's USR -fixed that but encoded the *enclosing class template's own arity* into every member's identity, so -a single backward-compatible template-parameter addition (confirmed via real release tags -v3.11.2->v3.11.3) made ~228 of 330 entries look "changed" for a release with no real breaking -changes. The current raw-source-text-signature approach was arrived at, and each of several further -refinements verified, by testing against real historical releases -- not by inspecting code alone. -""" +# A "ref" for --old/--new is resolved in this order: +# 1. A stored, committed historical record at tools/api_checker/history/.json, if one exists +# and --no-history wasn't passed (fast path -- no libclang/git-archive needed). +# 2. Live extraction: check the ref out via `git archive` into a temp dir and run extract_api.py +# against it (needed for HEAD, branches, or any tag not yet backfilled into history/). +# --old-file/--new-file bypass both and load an arbitrary surface JSON file directly. +# +# Uses extract_api.py's --surface-output (identity-only: scope, kind, name, identity_name, tier, +# signature, pretty_signature -- no location, no doc_url) for both sides, so the diff reflects only +# genuine API changes, never unrelated code motion or documentation-site restructuring. Identity is +# (scope, identity_name, kind, signature) -- see extract_api.py's identity_key()/get_signature_text() +# docstrings for the full history of why this is what it is: a naive {scope,name,kind,params} key +# silently collided on overloads differing only by constness/SFINAE; switching to libclang's USR +# fixed that but encoded the *enclosing class template's own arity* into every member's identity, so +# a single backward-compatible template-parameter addition (confirmed via real release tags +# v3.11.2->v3.11.3) made ~228 of 330 entries look "changed" for a release with no real breaking +# changes. The current raw-source-text-signature approach was arrived at, and each of several further +# refinements verified, by testing against real historical releases -- not by inspecting code alone. import argparse import json diff --git a/tools/api_checker/extract_api.py b/tools/api_checker/extract_api.py index edef1126c..54cddccd4 100755 --- a/tools/api_checker/extract_api.py +++ b/tools/api_checker/extract_api.py @@ -1,24 +1,22 @@ #!/usr/bin/env python3 -""" -Extract the public API surface of nlohmann/json using libclang AST. +"""Extract the public API surface of nlohmann/json using libclang AST.""" -This tool derives the public API from C++ semantics (class templates, access specifiers, -namespace scoping) independently of documentation status. The extracted surface is the -source of truth for what is considered "public API" — doc-checking and API diffing are -downstream consumers of this snapshot. - -Strategy: -1. Parse include/nlohmann/json.hpp with libclang (with proper system includes) -2. Walk the primary class-template definitions of the 6 known public classes -3. Extract callable members (methods, constructors, destructors, conversion ops) and type aliases -4. Extract free functions/operators in nlohmann:: (excluding detail::) -5. Handle alias-exposed exception types by following the alias to the detail:: definition -6. Normalize away the ABI inline-namespace (json_abi_v3_12_0, json_abi_diag_v3_12_0, etc.) -7. Emit a snapshot with an overload-disambiguating identity key and documentation status - -Output includes both public_api (all tracked public entities) and documented_non_public -(entities with @sa comments that are NOT in the public surface — used for validation). -""" +# This tool derives the public API from C++ semantics (class templates, access specifiers, +# namespace scoping) independently of documentation status. The extracted surface is the +# source of truth for what is considered "public API" — doc-checking and API diffing are +# downstream consumers of this snapshot. +# +# Strategy: +# 1. Parse include/nlohmann/json.hpp with libclang (with proper system includes) +# 2. Walk the primary class-template definitions of the 6 known public classes +# 3. Extract callable members (methods, constructors, destructors, conversion ops) and type aliases +# 4. Extract free functions/operators in nlohmann:: (excluding detail::) +# 5. Handle alias-exposed exception types by following the alias to the detail:: definition +# 6. Normalize away the ABI inline-namespace (json_abi_v3_12_0, json_abi_diag_v3_12_0, etc.) +# 7. Emit a snapshot with an overload-disambiguating identity key and documentation status +# +# Output includes both public_api (all tracked public entities) and documented_non_public +# (entities with @sa comments that are NOT in the public surface — used for validation). import argparse import json diff --git a/tools/api_checker/snapshot_release.py b/tools/api_checker/snapshot_release.py index 417a4b8a7..8e3859cd2 100755 --- a/tools/api_checker/snapshot_release.py +++ b/tools/api_checker/snapshot_release.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 -""" -Capture immutable, per-release API surface records into tools/api_checker/history/. +"""Capture immutable, per-release API surface records into tools/api_checker/history/.""" -These are the durable, committed counterpart to diff_api.py's live git-archive-and-extract path: -once a release is tagged, run this once to capture tools/api_checker/history/.json, commit -it, and future diffs against that tag hit the fast, no-libclang-needed stored-file path in -diff_api.py automatically. See tools/api_checker/README.md's "Workflow: Release Checklist" and -POLICY.md for the full policy (manual step, not CI-automated; files are immutable once committed --- regenerate only via --force, and only as a deliberate, reviewed choice). -""" +# These are the durable, committed counterpart to diff_api.py's live git-archive-and-extract path: +# once a release is tagged, run this once to capture tools/api_checker/history/.json, commit +# it, and future diffs against that tag hit the fast, no-libclang-needed stored-file path in +# diff_api.py automatically. See tools/api_checker/README.md's "Workflow: Release Checklist" and +# POLICY.md for the full policy (manual step, not CI-automated; files are immutable once committed +# -- regenerate only via --force, and only as a deliberate, reviewed choice). import argparse import datetime