From d9b1de8c3e0046e87dba46b11011d55f9bed2978 Mon Sep 17 00:00:00 2001 From: Patrick Dahlke Date: Wed, 10 Dec 2025 09:05:23 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=94=A7=20=20Enhance=20oneline=20parse?= =?UTF-8?q?r=20warning=20logging=20(#52)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + src/sphinx_codelinks/analyse/analyse.py | 23 +++++++++++++-------- tests/test_analyse.py | 27 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index bf5055a..8acb770 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ uv.lock # coverage files .coverage coverage.xml +invalid_objs.json diff --git a/src/sphinx_codelinks/analyse/analyse.py b/src/sphinx_codelinks/analyse/analyse.py index a8e9751..80f1d44 100644 --- a/src/sphinx_codelinks/analyse/analyse.py +++ b/src/sphinx_codelinks/analyse/analyse.py @@ -198,14 +198,21 @@ def extract_oneline_need( if not src_comment.source_file: row_offset += 1 continue - self.oneline_warnings.append( - AnalyseWarning( - str(src_comment.source_file.filepath), - src_comment.node.start_point.row + row_offset + 1, - resolved.msg, - MarkedContentType.need, - resolved.sub_type.value, - ) + lineno = src_comment.node.start_point.row + row_offset + 1 + warning = AnalyseWarning( + str(src_comment.source_file.filepath), + lineno, + resolved.msg, + MarkedContentType.need, + resolved.sub_type.value, + ) + self.oneline_warnings.append(warning) + logger.warning( + "Oneline parser warning in %s:%d - %s: %s", + src_comment.source_file.filepath, + lineno, + resolved.sub_type.value, + resolved.msg, ) row_offset += 1 continue diff --git a/tests/test_analyse.py b/tests/test_analyse.py index 9f74ca7..6c3ccd9 100644 --- a/tests/test_analyse.py +++ b/tests/test_analyse.py @@ -141,3 +141,30 @@ def test_analyse_oneline_needs( for src_file in src_analyse.src_files: cnt_comments += len(src_file.src_comments) assert cnt_comments == result["num_comments"] + + +def test_oneline_parser_warning_is_logged(tmp_path, caplog): + """Test that oneline parser warnings are logged to the console.""" + src_dir = TEST_DIR / "data" / "oneline_comment_default" + src_paths = [src_dir / "default_oneliners.c"] + + src_analyse_config = SourceAnalyseConfig( + src_files=src_paths, + src_dir=src_dir, + get_need_id_refs=False, + get_oneline_needs=True, + get_rst=False, + oneline_comment_style=ONELINE_COMMENT_STYLE_DEFAULT, + ) + + with caplog.at_level("WARNING", logger="sphinx_codelinks.analyse.analyse"): + src_analyse = SourceAnalyse(src_analyse_config) + src_analyse.run() + + # Verify that warnings were collected + assert len(src_analyse.oneline_warnings) == 1 + + # Verify that the warning was logged + assert len(caplog.records) == 1 + assert "Oneline parser warning" in caplog.records[0].message + assert "too_many_fields" in caplog.records[0].message From c5f90a4e8728bf0daceedc6a816080a8f77c076f Mon Sep 17 00:00:00 2001 From: Patrick Dahlke Date: Wed, 10 Dec 2025 09:16:43 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=94=A7=20=20Improve=20logging=20for?= =?UTF-8?q?=20oneline=20parser=20warnings=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_analyse.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/tests/test_analyse.py b/tests/test_analyse.py index 6c3ccd9..61db32b 100644 --- a/tests/test_analyse.py +++ b/tests/test_analyse.py @@ -1,5 +1,6 @@ # @Test suite for source code analysis and marker extraction, TEST_ANA_1, test, [IMPL_LNK_1, IMPL_ONE_1, IMPL_MRST_1] import json +import logging from pathlib import Path import pytest @@ -145,6 +146,7 @@ def test_analyse_oneline_needs( def test_oneline_parser_warning_is_logged(tmp_path, caplog): """Test that oneline parser warnings are logged to the console.""" + src_dir = TEST_DIR / "data" / "oneline_comment_default" src_paths = [src_dir / "default_oneliners.c"] @@ -157,14 +159,27 @@ def test_oneline_parser_warning_is_logged(tmp_path, caplog): oneline_comment_style=ONELINE_COMMENT_STYLE_DEFAULT, ) - with caplog.at_level("WARNING", logger="sphinx_codelinks.analyse.analyse"): - src_analyse = SourceAnalyse(src_analyse_config) - src_analyse.run() - - # Verify that warnings were collected - assert len(src_analyse.oneline_warnings) == 1 - - # Verify that the warning was logged - assert len(caplog.records) == 1 - assert "Oneline parser warning" in caplog.records[0].message - assert "too_many_fields" in caplog.records[0].message + # Ensure the logger propagates to root so caplog can capture it + analyse_logger = logging.getLogger("sphinx_codelinks.analyse.analyse") + original_propagate = analyse_logger.propagate + analyse_logger.propagate = True + + try: + with caplog.at_level( + logging.WARNING, logger="sphinx_codelinks.analyse.analyse" + ): + src_analyse = SourceAnalyse(src_analyse_config) + src_analyse.run() + + # Verify that warnings were collected + assert len(src_analyse.oneline_warnings) == 1 + + # Verify that the warning was logged + warning_records = [ + r for r in caplog.records if "Oneline parser warning" in r.message + ] + assert len(warning_records) >= 1 + assert "too_many_fields" in warning_records[0].message + finally: + # Restore original propagate setting + analyse_logger.propagate = original_propagate From 764a914864cdd98386f1b558360541911fc722e0 Mon Sep 17 00:00:00 2001 From: Patrick Dahlke Date: Wed, 10 Dec 2025 10:57:22 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=A7=20=20Refactor=20oneline=20pars?= =?UTF-8?q?er=20warning=20logging=20and=20enhance=20CLI=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/sphinx_codelinks/analyse/analyse.py | 7 ----- src/sphinx_codelinks/cmd.py | 11 ++++++- tests/test_analyse.py | 38 +++++++------------------ tests/test_cmd.py | 37 ++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/sphinx_codelinks/analyse/analyse.py b/src/sphinx_codelinks/analyse/analyse.py index 80f1d44..50b7b84 100644 --- a/src/sphinx_codelinks/analyse/analyse.py +++ b/src/sphinx_codelinks/analyse/analyse.py @@ -207,13 +207,6 @@ def extract_oneline_need( resolved.sub_type.value, ) self.oneline_warnings.append(warning) - logger.warning( - "Oneline parser warning in %s:%d - %s: %s", - src_comment.source_file.filepath, - lineno, - resolved.sub_type.value, - resolved.msg, - ) row_offset += 1 continue yield resolved, row_offset diff --git a/src/sphinx_codelinks/cmd.py b/src/sphinx_codelinks/cmd.py index a702414..e341615 100644 --- a/src/sphinx_codelinks/cmd.py +++ b/src/sphinx_codelinks/cmd.py @@ -56,7 +56,7 @@ @app.command(no_args_is_help=True) -def analyse( +def analyse( # noqa: PLR0912 config: Annotated[ Path, typer.Argument( @@ -151,6 +151,15 @@ def analyse( codelinks_config.projects = specifed_project_configs analyse_projects = AnalyseProjects(codelinks_config) analyse_projects.run() + + # Output warnings to console for CLI users + for src_analyse in analyse_projects.projects_analyse.values(): + for warning in src_analyse.oneline_warnings: + logger.warning( + f"Oneline parser warning in {warning.file_path}:{warning.lineno} " + f"- {warning.sub_type}: {warning.msg}", + ) + analyse_projects.dump_markers() diff --git a/tests/test_analyse.py b/tests/test_analyse.py index 61db32b..ab8dc16 100644 --- a/tests/test_analyse.py +++ b/tests/test_analyse.py @@ -1,6 +1,5 @@ # @Test suite for source code analysis and marker extraction, TEST_ANA_1, test, [IMPL_LNK_1, IMPL_ONE_1, IMPL_MRST_1] import json -import logging from pathlib import Path import pytest @@ -144,9 +143,8 @@ def test_analyse_oneline_needs( assert cnt_comments == result["num_comments"] -def test_oneline_parser_warning_is_logged(tmp_path, caplog): - """Test that oneline parser warnings are logged to the console.""" - +def test_oneline_parser_warnings_are_collected(tmp_path): + """Test that oneline parser warnings are collected for later output.""" src_dir = TEST_DIR / "data" / "oneline_comment_default" src_paths = [src_dir / "default_oneliners.c"] @@ -159,27 +157,11 @@ def test_oneline_parser_warning_is_logged(tmp_path, caplog): oneline_comment_style=ONELINE_COMMENT_STYLE_DEFAULT, ) - # Ensure the logger propagates to root so caplog can capture it - analyse_logger = logging.getLogger("sphinx_codelinks.analyse.analyse") - original_propagate = analyse_logger.propagate - analyse_logger.propagate = True - - try: - with caplog.at_level( - logging.WARNING, logger="sphinx_codelinks.analyse.analyse" - ): - src_analyse = SourceAnalyse(src_analyse_config) - src_analyse.run() - - # Verify that warnings were collected - assert len(src_analyse.oneline_warnings) == 1 - - # Verify that the warning was logged - warning_records = [ - r for r in caplog.records if "Oneline parser warning" in r.message - ] - assert len(warning_records) >= 1 - assert "too_many_fields" in warning_records[0].message - finally: - # Restore original propagate setting - analyse_logger.propagate = original_propagate + src_analyse = SourceAnalyse(src_analyse_config) + src_analyse.run() + + # Verify that warnings were collected + assert len(src_analyse.oneline_warnings) == 1 + warning = src_analyse.oneline_warnings[0] + assert "too_many_fields" in warning.sub_type + assert warning.lineno == 17 diff --git a/tests/test_cmd.py b/tests/test_cmd.py index 4222dca..247e50d 100644 --- a/tests/test_cmd.py +++ b/tests/test_cmd.py @@ -67,6 +67,43 @@ def test_analyse(config_path: Path, tmp_path: Path) -> None: assert marked_content +def test_analyse_outputs_warnings(tmp_path: Path) -> None: + """Test that the analyse CLI command outputs warnings to console.""" + # Create a config file that will produce warnings + src_dir = TEST_DIR / "data" / "oneline_comment_default" + config_dict = { + "codelinks": { + "outdir": str(tmp_path), + "projects": { + "test_project": { + "source_discover": { + "src_dir": str(src_dir), + "include": ["*.c"], + "comment_type": "cpp", + }, + "analyse": { + "get_oneline_needs": True, + # Use default oneline_comment_style which will cause warnings + # for the test file with too many fields + }, + } + }, + } + } + + config_file = tmp_path / "test_config.toml" + with config_file.open("w", encoding="utf-8") as f: + toml.dump(config_dict, f) + + options: list[str] = ["analyse", str(config_file)] + result = runner.invoke(app, options) + + assert result.exit_code == 0 + # Verify that warnings are output to console + assert "Oneline parser warning" in result.output + assert "too_many_fields" in result.output + + @pytest.mark.parametrize( ("options", "stdout"), [