From bd09d519604ed4fa396efea220a0be4066a57158 Mon Sep 17 00:00:00 2001 From: Ali Hamdan Date: Sat, 8 Jul 2023 09:46:33 +0200 Subject: [PATCH 1/2] stubdoc: Fix crash on non-str docstring Encourted this while testing stubgen on pandas: ```console $ stubgen -p pandas Traceback (most recent call last): File "/tmp/.venv/bin/stubgen", line 8, in sys.exit(main()) File "mypy/stubgen.py", line 1945, in main File "mypy/stubgen.py", line 1799, in generate_stubs File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubgenc.py", line 212, in generate_stub_for_c_module generate_c_type_stub( File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubgenc.py", line 528, in generate_c_type_stub generate_c_function_stub( File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubgenc.py", line 337, in generate_c_function_stub inferred = sig_gen.get_method_sig( File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubgenc.py", line 140, in get_method_sig inferred = self.get_function_sig(cls, module_name, class_name) File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubgenc.py", line 120, in get_function_sig inferred = infer_sig_from_docstring(docstr, name) File "/tmp/.venv/lib/python3.10/site-packages/mypy/stubdoc.py", line 264, in infer_sig_from_docstring tokens = tokenize.tokenize(io.BytesIO(docstr.encode("utf-8")).readline) AttributeError: 'getset_descriptor' object has no attribute 'encode' ``` This is because of the definition of docstring as a descriptor here https://github.com/pandas-dev/pandas/blob/main/pandas/_libs/properties.pyx --- mypy/stubdoc.py | 2 +- mypy/test/teststubgen.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mypy/stubdoc.py b/mypy/stubdoc.py index 232d9e9762e9..145f57fd7751 100644 --- a/mypy/stubdoc.py +++ b/mypy/stubdoc.py @@ -254,7 +254,7 @@ def infer_sig_from_docstring(docstr: str | None, name: str) -> list[FunctionSig] * docstr: docstring * name: name of function for which signatures are to be found """ - if not docstr: + if not (isinstance(docstr, str) and docstr): return None state = DocStringParser(name) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 884cf87ac5d8..0691decb027c 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -1213,6 +1213,27 @@ def test(arg0: str) -> None: assert_equal(output, ["def test(arg0: foo.bar.Action) -> other.Thing: ..."]) assert_equal(set(imports), {"import foo", "import other"}) + def test_generate_c_function_no_crash_for_non_str_docstring(self) -> None: + def test(arg0): + ... + + test.__doc__ = property(lambda self: "test(arg0: str) -> None") + + output: list[str] = [] + imports: list[str] = [] + mod = ModuleType(self.__module__, "") + generate_c_function_stub( + mod, + "test", + test, + output=output, + imports=imports, + known_modules=[mod.__name__], + sig_generators=get_sig_generators(parse_options([])), + ) + assert_equal(output, ["def test(*args, **kwargs) -> Any: ..."]) + assert_equal(imports, []) + def test_generate_c_property_with_pybind11(self) -> None: """Signatures included by PyBind11 inside property.fget are read.""" From f6c74a51647fe691f3927f82129e70618a3607d1 Mon Sep 17 00:00:00 2001 From: Ali Hamdan Date: Sat, 8 Jul 2023 11:46:29 +0200 Subject: [PATCH 2/2] Self check --- mypy/test/teststubgen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index 0691decb027c..79d380785a39 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -1214,10 +1214,10 @@ def test(arg0: str) -> None: assert_equal(set(imports), {"import foo", "import other"}) def test_generate_c_function_no_crash_for_non_str_docstring(self) -> None: - def test(arg0): + def test(arg0: str) -> None: ... - test.__doc__ = property(lambda self: "test(arg0: str) -> None") + test.__doc__ = property(lambda self: "test(arg0: str) -> None") # type: ignore[assignment] output: list[str] = [] imports: list[str] = []