From f515f908f9e29b7fe8732be1cf0a7e6aade2851a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Tue, 4 Nov 2025 17:06:07 +0100 Subject: [PATCH 1/2] Fix missing warning for docstring parameters without type Also applies for attributes --- src/docstub/_docstrings.py | 13 +++++++------ tests/test_stubs.py | 12 ++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/docstub/_docstrings.py b/src/docstub/_docstrings.py index 245c3f0..48541ae 100644 --- a/src/docstub/_docstrings.py +++ b/src/docstub/_docstrings.py @@ -816,19 +816,20 @@ def _section_annotations(self, name): for param in params: param = self._handle_missing_whitespace(param) # noqa: PLW2901 + if param.type.strip() == "": + # Missing doctype in docstring, might have an inlined annotation + # so skip + continue + if param.name in annotated_params: - # TODO make error self.reporter.warn( "Duplicate parameter / attribute name in docstring", details=self.reporter.underline(param.name), ) continue - if param.type: - ds_line = self._find_docstring_line(param.name, param.type) - annotation = self._doctype_to_annotation(param.type, ds_line=ds_line) - else: - annotation = FallbackAnnotation + ds_line = self._find_docstring_line(param.name, param.type) + annotation = self._doctype_to_annotation(param.type, ds_line=ds_line) annotated_params[param.name.strip()] = annotation return annotated_params diff --git a/tests/test_stubs.py b/tests/test_stubs.py index 6da2098..10dc36c 100644 --- a/tests/test_stubs.py +++ b/tests/test_stubs.py @@ -481,14 +481,16 @@ def foo(a: int) -> None: ... assert "ignoring docstring: Sized" in caplog.records[0].details assert caplog.records[0].levelno == logging.WARNING - def test_missing_param(self, caplog): + @pytest.mark.parametrize("missing", ["", "b", "b :"]) + def test_missing_param(self, missing, caplog): source = dedent( - ''' + f''' def foo(a, b) -> None: """ Parameters ---------- a : int + {missing} """ ''' ) @@ -523,14 +525,16 @@ def foo(a: int, b: Incomplete) -> None: ... assert caplog.messages == ["Missing annotation for parameter 'b'"] assert caplog.records[0].levelno == logging.WARNING - def test_missing_attr(self, caplog): + @pytest.mark.parametrize("missing", ["", "b", "b :"]) + def test_missing_attr(self, missing, caplog): source = dedent( - ''' + f''' class Foo: """ Attributes ---------- a : ClassVar[int] + {missing} """ a = 3 b = True From 415658aaa4b5f38c20bfe756b714c1e5aa25bc9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Tue, 4 Nov 2025 18:01:55 +0100 Subject: [PATCH 2/2] Fix outdated tests --- tests/test_docstrings.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/test_docstrings.py b/tests/test_docstrings.py index c988fac..b996949 100644 --- a/tests/test_docstrings.py +++ b/tests/test_docstrings.py @@ -348,10 +348,9 @@ def test_parameters(self, doctype, expected): ) transformer = DoctypeTransformer() annotations = DocstringAnnotations(docstring, transformer=transformer) - assert len(annotations.parameters) == 2 + assert len(annotations.parameters) == 1 assert annotations.parameters["a"].value == expected - assert annotations.parameters["b"].value == "Incomplete" - assert annotations.parameters["b"].imports == {PyImport.typeshed_Incomplete()} + assert "b" not in annotations.parameters @pytest.mark.parametrize( ("doctypes", "expected"), @@ -539,12 +538,10 @@ def test_combined_numpydoc_params(self): ) transformer = DoctypeTransformer() annotations = DocstringAnnotations(docstring, transformer=transformer) - assert len(annotations.parameters) == 5 + assert len(annotations.parameters) == 3 assert annotations.parameters["a"].value == "bool" assert annotations.parameters["b"].value == "bool" assert annotations.parameters["c"].value == "bool" - assert annotations.parameters["d"].value == "Incomplete" - assert annotations.parameters["e"].value == "Incomplete" - assert annotations.parameters["d"].imports == {PyImport.typeshed_Incomplete()} - assert annotations.parameters["e"].imports == {PyImport.typeshed_Incomplete()} + assert "d" not in annotations.parameters + assert "e" not in annotations.parameters