From 83721b7d758dd8d7548823bad8225f29609d78ae Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 Oct 2026 20:57:30 +0200 Subject: [PATCH 1/2] Make Argument Clinic exit with an error if a warning was emitted --- Tools/clinic/libclinic/cli.py | 11 ++++++++--- Tools/clinic/libclinic/errors.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Tools/clinic/libclinic/cli.py b/Tools/clinic/libclinic/cli.py index 9629c173177945..f7a8022a24d54f 100644 --- a/Tools/clinic/libclinic/cli.py +++ b/Tools/clinic/libclinic/cli.py @@ -12,7 +12,7 @@ # Local imports. import libclinic -import libclinic.cpp +import libclinic.errors from libclinic import ClinicError from libclinic.language import Language, PythonLanguage from libclinic.block_parser import BlockParser @@ -340,10 +340,15 @@ def run_clinic(parser: argparse.ArgumentParser, ns: argparse.Namespace) -> None: def main(argv: list[str] | None = None) -> NoReturn: parser = create_cli() args = parser.parse_args(argv) + libclinic.errors.reset_warning_count() try: run_clinic(parser, args) except ClinicError as exc: sys.stderr.write(exc.report()) sys.exit(1) - else: - sys.exit(0) + count = libclinic.errors.warning_count + if count: + noun = "warning" if count == 1 else "warnings" + sys.stderr.write(f"{count} {noun} emitted\n") + sys.exit(1) + sys.exit(0) diff --git a/Tools/clinic/libclinic/errors.py b/Tools/clinic/libclinic/errors.py index f06bdfbd864b2c..d17c9a5a7050b5 100644 --- a/Tools/clinic/libclinic/errors.py +++ b/Tools/clinic/libclinic/errors.py @@ -27,6 +27,14 @@ class ParseError(ClinicError): pass +warning_count = 0 + + +def reset_warning_count() -> None: + global warning_count + warning_count = 0 + + @overload def warn_or_fail( *args: object, @@ -54,6 +62,8 @@ def warn_or_fail( if fail: raise error else: + global warning_count + warning_count += 1 print(error.report(warn_only=True)) From 52d30c52c014f869de7345d3765e817a0b65e2ba Mon Sep 17 00:00:00 2001 From: Stan Ulbrych Date: Tue, 6 Oct 2026 21:30:03 +0200 Subject: [PATCH 2/2] Add test --- Lib/test/test_clinic.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 3b440fed7f6ce8..16004b002f8ba3 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -3739,6 +3739,23 @@ def test_no_change(self): # if the content does not change self.assertEqual(pre_mtime, post_mtime) + def test_warning_is_failure(self): + code = dedent(""" + /*[clinic input] + @permit_long_summary + fn + + Short summary. + [clinic start generated code]*/ + """) + with os_helper.temp_dir() as tmp_dir: + fn = os.path.join(tmp_dir, "test.c") + with open(fn, "w", encoding="utf-8") as f: + f.write(code) + out, err = self.expect_failure(fn) + self.assertIn("Remove the @permit_long_summary decorator from 'fn'!", out) + self.assertEqual(err, "1 warning emitted\n") + TOUCH_CODE = dedent(""" /*[clinic input] module m