Skip to content

Commit 32dc422

Browse files
Added options to retain original typehints in signatures (#278)
* Update __init__.py * Update __init__.py * Updated README.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added tests for use_signature and use_signature_return * Removed .idea* from gitignore Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 477c438 commit 32dc422

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ The following configuration options are accepted:
8383
- `typehints_formatter` (default: `None`): If set to a function, this function will be called with `annotation` as first
8484
argument and `sphinx.config.Config` argument second. The function is expected to return a string with reStructuredText
8585
code or `None` to fall back to the default formatter.
86+
- `typehints_use_signature` (default: `False`): If `True`, typehints for parameters in the signature are shown.
87+
- `typehints_use_signature_return` (default: `False`): If `True`, return annotations in the signature are shown.
8688

8789
## How it works
8890

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,11 @@ def process_signature(
254254

255255
obj = inspect.unwrap(obj)
256256
sph_signature = sphinx_signature(obj)
257-
parameters = [param.replace(annotation=inspect.Parameter.empty) for param in sph_signature.parameters.values()]
257+
258+
if app.config.typehints_use_signature:
259+
parameters = list(sph_signature.parameters.values())
260+
else:
261+
parameters = [param.replace(annotation=inspect.Parameter.empty) for param in sph_signature.parameters.values()]
258262

259263
# if we have parameters we may need to delete first argument that's not documented, e.g. self
260264
start = 0
@@ -277,7 +281,10 @@ def process_signature(
277281
if not isinstance(method_object, (classmethod, staticmethod)):
278282
start = 1
279283

280-
sph_signature = sph_signature.replace(parameters=parameters[start:], return_annotation=inspect.Signature.empty)
284+
sph_signature = sph_signature.replace(parameters=parameters[start:])
285+
if not app.config.typehints_use_signature_return:
286+
sph_signature = sph_signature.replace(return_annotation=inspect.Signature.empty)
287+
281288
return stringify_signature(sph_signature).replace("\\", "\\\\"), None
282289

283290

@@ -634,6 +641,8 @@ def setup(app: Sphinx) -> dict[str, bool]:
634641
app.add_config_value("typehints_defaults", None, "env")
635642
app.add_config_value("simplify_optional_unions", True, "env")
636643
app.add_config_value("typehints_formatter", None, "env")
644+
app.add_config_value("typehints_use_signature", False, "env")
645+
app.add_config_value("typehints_use_signature_return", False, "env")
637646
app.connect("env-before-read-docs", validate_config) # config may be changed after “config-inited” event
638647
app.connect("autodoc-process-signature", process_signature)
639648
app.connect("autodoc-process-docstring", process_docstring)

tests/test_sphinx_autodoc_typehints.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,3 +1033,91 @@ def test_sphinx_output_formatter_no_use_rtype(app: SphinxTestApp, status: String
10331033
"str" -- A string
10341034
"""
10351035
assert text_contents == dedent(expected_contents)
1036+
1037+
1038+
@pytest.mark.sphinx("text", testroot="dummy")
1039+
@patch("sphinx.writers.text.MAXWIDTH", 2000)
1040+
def test_sphinx_output_with_use_signature(app: SphinxTestApp, status: StringIO) -> None:
1041+
set_python_path()
1042+
app.config.master_doc = "simple" # type: ignore # create flag
1043+
app.config.typehints_use_signature = True # type: ignore
1044+
app.build()
1045+
assert "build succeeded" in status.getvalue()
1046+
text_path = pathlib.Path(app.srcdir) / "_build" / "text" / "simple.txt"
1047+
text_contents = text_path.read_text().replace("–", "--")
1048+
expected_contents = """\
1049+
Simple Module
1050+
*************
1051+
1052+
dummy_module_simple.function(x: bool, y: int = 1)
1053+
1054+
Function docstring.
1055+
1056+
Parameters:
1057+
* **x** ("bool") -- foo
1058+
1059+
* **y** ("int") -- bar
1060+
1061+
Return type:
1062+
"str"
1063+
"""
1064+
assert text_contents == dedent(expected_contents)
1065+
1066+
1067+
@pytest.mark.sphinx("text", testroot="dummy")
1068+
@patch("sphinx.writers.text.MAXWIDTH", 2000)
1069+
def test_sphinx_output_with_use_signature_return(app: SphinxTestApp, status: StringIO) -> None:
1070+
set_python_path()
1071+
app.config.master_doc = "simple" # type: ignore # create flag
1072+
app.config.typehints_use_signature_return = True # type: ignore
1073+
app.build()
1074+
assert "build succeeded" in status.getvalue()
1075+
text_path = pathlib.Path(app.srcdir) / "_build" / "text" / "simple.txt"
1076+
text_contents = text_path.read_text().replace("–", "--")
1077+
expected_contents = """\
1078+
Simple Module
1079+
*************
1080+
1081+
dummy_module_simple.function(x, y=1) -> str
1082+
1083+
Function docstring.
1084+
1085+
Parameters:
1086+
* **x** ("bool") -- foo
1087+
1088+
* **y** ("int") -- bar
1089+
1090+
Return type:
1091+
"str"
1092+
"""
1093+
assert text_contents == dedent(expected_contents)
1094+
1095+
1096+
@pytest.mark.sphinx("text", testroot="dummy")
1097+
@patch("sphinx.writers.text.MAXWIDTH", 2000)
1098+
def test_sphinx_output_with_use_signature_and_return(app: SphinxTestApp, status: StringIO) -> None:
1099+
set_python_path()
1100+
app.config.master_doc = "simple" # type: ignore # create flag
1101+
app.config.typehints_use_signature = True # type: ignore
1102+
app.config.typehints_use_signature_return = True # type: ignore
1103+
app.build()
1104+
assert "build succeeded" in status.getvalue()
1105+
text_path = pathlib.Path(app.srcdir) / "_build" / "text" / "simple.txt"
1106+
text_contents = text_path.read_text().replace("–", "--")
1107+
expected_contents = """\
1108+
Simple Module
1109+
*************
1110+
1111+
dummy_module_simple.function(x: bool, y: int = 1) -> str
1112+
1113+
Function docstring.
1114+
1115+
Parameters:
1116+
* **x** ("bool") -- foo
1117+
1118+
* **y** ("int") -- bar
1119+
1120+
Return type:
1121+
"str"
1122+
"""
1123+
assert text_contents == dedent(expected_contents)

0 commit comments

Comments
 (0)