Skip to content

Commit b8506eb

Browse files
committed
Add support for showing all overload signatures for a function.
1 parent 8916055 commit b8506eb

File tree

4 files changed

+113
-12
lines changed

4 files changed

+113
-12
lines changed

pdoc/doc.py

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
from typing import TypeVar
4040
from typing import Union
4141
from typing import get_origin
42+
43+
try:
44+
# This only exists on Python 3.11 and later. On older versions,
45+
# we just replace it with a function that does nothing.
46+
from typing import get_overloads
47+
except ImportError:
48+
49+
def get_overloads(*args, **kwargs):
50+
return []
51+
52+
4253
import warnings
4354

4455
from pdoc import doc_ast
@@ -989,6 +1000,69 @@ def signature(self) -> inspect.Signature:
9891000
return inspect.Signature(
9901001
[inspect.Parameter("unknown", inspect.Parameter.POSITIONAL_OR_KEYWORD)]
9911002
)
1003+
1004+
return self._process_signature(sig)
1005+
1006+
@cached_property
1007+
def signature_without_self(self) -> inspect.Signature:
1008+
"""Like `signature`, but without the first argument.
1009+
1010+
This is useful to display constructors.
1011+
"""
1012+
return self.signature.replace(
1013+
parameters=list(self.signature.parameters.values())[1:]
1014+
)
1015+
1016+
@cached_property
1017+
def overloads(self) -> list[inspect.Signature]:
1018+
"""
1019+
The function's overloaded signatures, if any.
1020+
1021+
This should do the same processing as `signature`, but can return a list
1022+
of additional signatures when available.
1023+
"""
1024+
1025+
if self.obj is object.__init__:
1026+
# See `signature`.
1027+
return inspect.Signature()
1028+
1029+
try:
1030+
values = get_overloads(self.obj)
1031+
except Exception:
1032+
return []
1033+
1034+
results = []
1035+
for value in values:
1036+
try:
1037+
sig = _PrettySignature.from_callable(value)
1038+
results.append(self._process_signature(sig))
1039+
except Exception:
1040+
sig = inspect.Signature(
1041+
[
1042+
inspect.Parameter(
1043+
"unknown", inspect.Parameter.POSITIONAL_OR_KEYWORD
1044+
)
1045+
]
1046+
)
1047+
results.append(sig)
1048+
return results
1049+
1050+
@cached_property
1051+
def overloads_without_self(self) -> list[inspect.Signature]:
1052+
"""Like `overloads`, but without the first argument.
1053+
1054+
This is useful to display constructors.
1055+
"""
1056+
return [
1057+
sig.replace(parameters=list(self.signature.parameters.values())[1:])
1058+
for sig in self.overloads
1059+
]
1060+
1061+
def _process_signature(self, sig: inspect.Signature) -> inspect.Signature:
1062+
"""
1063+
A helper method for `signature` and `overloads` which performs
1064+
necessary post-processing on a signature object.
1065+
"""
9921066
mod = inspect.getmodule(self.obj)
9931067
globalns = _safe_getattr(mod, "__dict__", {})
9941068
localns = globalns
@@ -1012,16 +1086,6 @@ def signature(self) -> inspect.Signature:
10121086
)
10131087
return sig
10141088

1015-
@cached_property
1016-
def signature_without_self(self) -> inspect.Signature:
1017-
"""Like `signature`, but without the first argument.
1018-
1019-
This is useful to display constructors.
1020-
"""
1021-
return self.signature.replace(
1022-
parameters=list(self.signature.parameters.values())[1:]
1023-
)
1024-
10251089

10261090
class Variable(Doc[None]):
10271091
"""

pdoc/doc_pyi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def _patch_doc(target_doc: doc.Doc, stub_mod: doc.Module) -> None:
7777
stub_doc.docstring = ""
7878

7979
target_doc.signature = stub_doc.signature
80+
target_doc.overloads = stub_doc.overloads
8081
target_doc.funcdef = stub_doc.funcdef
8182
target_doc.docstring = stub_doc.docstring or target_doc.docstring
8283
elif isinstance(target_doc, doc.Variable) and isinstance(stub_doc, doc.Variable):

pdoc/templates/content.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,19 @@ This makes sure that the pdoc styling doesn't leak to the rest of the page when
300300
overflow-x: auto;
301301
}
302302

303+
.pdoc .overloads {
304+
margin-left: 2rem;
305+
}
306+
307+
/* The same as .pdoc .attr, but without the focused/target/hover rules. */
308+
.pdoc .extra-attr {
309+
display: block;
310+
margin: .5rem 0 .5rem;
311+
padding: .4rem .4rem .4rem 1rem;
312+
background-color: var(--accent);
313+
overflow-x: auto;
314+
}
315+
303316
.pdoc .classattr {
304317
margin-left: 2rem;
305318
}

pdoc/templates/default/module.html.jinja2

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,30 @@ See https://pdoc.dev/docs/pdoc/render_helpers.html#DefaultMacroExtension for an
172172
{{- fn.signature_without_self | format_signature(colon=False) | linkify }}
173173
{% else %}
174174
<span class="def">{{ fn.funcdef }}</span>
175-
<span class="name">{{ fn.name }}</span>
176-
{{- fn.signature | format_signature(colon=True) | linkify }}
175+
<span class="name">{{ fn.name }}</span>
176+
{{- fn.signature | format_signature(colon=True) | linkify }}
177177
{% endif %}
178178
{% enddefaultmacro %}
179+
{% defaultmacro overloads(fn) -%}
180+
<div class="overloads">
181+
{% if fn.name == "__init__" %}
182+
{% for sig in fn.overloads_without_self %}
183+
<div class="extra-attr {{ fn.kind }}">
184+
<span class="name">{{ ".".join(fn.qualname.split(".")[:-1]) }}</span>
185+
{{- sig | format_signature(colon=False) | linkify }}
186+
</div>
187+
{% endfor %}
188+
{% else %}
189+
{% for sig in fn.overloads %}
190+
<div class="extra-attr {{ fn.kind }}">
191+
<span class="def">{{ fn.funcdef }}</span>
192+
<span class="name">{{ fn.name }}</span>
193+
{{- sig | format_signature(colon=True) | linkify }}
194+
</div>
195+
{% endfor %}
196+
{% endif %}
197+
</div>
198+
{% enddefaultmacro %}
179199
{% defaultmacro variable(var) -%}
180200
{%- if var.is_type_alias_type %}<span class="def">type</span> {% endif -%}
181201
<span class="name">{{ var.name }}</span>{{ annotation(var) }}{{ default_value(var) }}
@@ -203,6 +223,9 @@ See https://pdoc.dev/docs/pdoc/render_helpers.html#DefaultMacroExtension for an
203223
{% endif %}
204224
{{ view_source_button(doc) }}
205225
</div>
226+
{% if doc.kind == "function" and doc.overloads|length > 0 %}
227+
{{ overloads(doc) }}
228+
{% endif %}
206229
<a class="headerlink" href="#{{ doc.qualname or doc.name }}"></a>
207230
{{ view_source_code(doc) }}
208231
{{ docstring(doc) }}

0 commit comments

Comments
 (0)