Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Terminate a generated __text_signature__ that carries no documentation
A signature and its documentation share one string, separated by
`\n--\n\n`, and readers find the signature by searching for that marker.
A #[pyfunction] with no doc comment stored the bare signature, which no
reader could parse:

    >>> time.clock_getres.__doc__
    'clock_getres(clk_id, /)'
    >>> time.clock_getres.__text_signature__
    None

Emit the marker in that case too, as Argument Clinic does for an
undocumented function. 136 of the 915 functions reachable from the
importable modules were affected.

__doc__ now reports None for them, matching CPython, because nothing
follows the marker.

Assisted-by: Claude Code:claude-opus-5
  • Loading branch information
leehanjeong committed Aug 29, 2026
commit 80dff4eb1c18aa9ce87ae52c790f93b225c48e5f
2 changes: 1 addition & 1 deletion crates/derive-impl/src/pymodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ impl ModuleItem for FunctionItem {
});
let doc = match (sig_doc, doc) {
(Some(sig_doc), Some(doc)) => Some(format_doc(&sig_doc, &doc)),
(Some(sig_doc), None) => Some(sig_doc),
(Some(sig_doc), None) => Some(format_doc(&sig_doc, "")),
(None, doc) => doc,
};

Expand Down
6 changes: 6 additions & 0 deletions extra_tests/snippets/builtin_signature.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import inspect
import os
import sys

# __text_signature__ is generated from the Rust parameter list, so it must not
Expand Down Expand Up @@ -47,6 +48,11 @@
assert str(inspect.signature(issubclass)) == "(cls, class_or_tuple, /)"
assert str(inspect.signature(aiter)) == "(async_iterable, /)"

# A generated signature is stored in __doc__ and read back out of it, so it
# needs the `--` terminator even when the function has no documentation.
assert str(inspect.signature(os.getpid)) == "()"
assert str(inspect.signature(os.getcwd)) == "()"

if sys.implementation.name == "rustpython":
# Functions whose Rust arguments are destructuring patterns rather than
# plain names get no signature at all, instead of emitting text that is not
Expand Down