Skip to content

Commit

Permalink
improve TypedDict rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
mhils committed May 4, 2022
1 parent af758aa commit c876a0f
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 87 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

# Unreleased: pdoc next

- Improve rendering of `typing.TypedDict` subclasses.
([#389](https://github.com/mitmproxy/pdoc/issues/389), [@mhils](https://github.com/mhils))


# 2022-04-24: pdoc 11.1.0

- Display line numbers when viewing source code.
Expand Down
2 changes: 1 addition & 1 deletion pdoc/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
default="restructuredtext",
choices=("markdown", "google", "numpy", "restructuredtext"),
help="The default docstring format. For non-Markdown formats, pdoc will first convert matching syntax elements to "
"Markdown and then process everything as Markdown.",
"Markdown and then process everything as Markdown.",
)
renderopts.add_argument(
"-e",
Expand Down
13 changes: 13 additions & 0 deletions pdoc/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,15 @@ class Class(Namespace[type]):
def __repr__(self):
return f"<{_decorators(self)}class {self.modulename}.{self.qualname}{_docstr(self)}{_children(self)}>"

@cached_property
def docstring(self) -> str:
doc = Doc.docstring.__get__(self) # type: ignore
if doc == dict.__doc__:
# Don't display default docstring for dict subclasses (primarily TypedDict).
return ""
else:
return doc

@cached_property
def _var_docstrings(self) -> dict[str, str]:
docstrings: dict[str, str] = {}
Expand Down Expand Up @@ -603,6 +612,7 @@ def _taken_from(self, member_name: str, obj: Any) -> tuple[str, str]:
try:
return self._declarations[member_name]
except KeyError: # pragma: no cover
# TypedDict botches __mro__ and may need special casing here.
warnings.warn(
f"Cannot determine where {self.fullname}.{member_name} is taken from, assuming current file."
)
Expand Down Expand Up @@ -639,6 +649,9 @@ def _member_objects(self) -> dict[str, Any]:
# Special case: Do not show a constructor for enums. They are typically not constructed by users.
# The alternative would be showing __new__, as __call__ is too verbose.
del unsorted["__init__"]
elif issubclass(self.obj, dict):
# Special case: Do not show a constructor for dict subclasses.
del unsorted["__init__"]
else:
# Check if there's a helpful Metaclass.__call__ or Class.__new__. This dance is very similar to
# https://github.com/python/cpython/blob/9feae41c4f04ca27fd2c865807a5caeb50bf4fc4/Lib/inspect.py#L2359-L2376
Expand Down
2 changes: 1 addition & 1 deletion pdoc/doc_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import typing
import warnings
from types import BuiltinFunctionType, ModuleType
from typing import Any, TYPE_CHECKING
from typing import _GenericAlias # type: ignore
from typing import TYPE_CHECKING, Any

from . import extract
from ._compat import GenericAlias, Literal, UnionType, get_origin
Expand Down
4 changes: 3 additions & 1 deletion pdoc/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@

def configure(
*,
docformat: Literal["markdown", "google", "numpy", "restructuredtext"] = "restructuredtext",
docformat: Literal[
"markdown", "google", "numpy", "restructuredtext"
] = "restructuredtext",
edit_url_map: Mapping[str, str] | None = None,
favicon: str | None = None,
footer_text: str = "",
Expand Down
117 changes: 89 additions & 28 deletions test/testdata/misc.html
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ <h2>API Documentation</h2>
</ul>

</li>
<li>
<a class="class" href="#CustomCall">CustomCall</a>
<ul class="memberlist">
<li>
<a class="function" href="#CustomCall.__init__">CustomCall</a>
</li>
</ul>

</li>
</ul>


Expand Down Expand Up @@ -575,34 +584,44 @@ <h1 class="modulename">
</span><span id="L-326"><a href="#L-326"><span class="linenos">326</span></a> <span class="sd">&quot;&quot;&quot;No docstrings for the constructor here.&quot;&quot;&quot;</span>
</span><span id="L-327"><a href="#L-327"><span class="linenos">327</span></a>
</span><span id="L-328"><a href="#L-328"><span class="linenos">328</span></a>
</span><span id="L-329"><a href="#L-329"><span class="linenos">329</span></a><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span> <span class="c1"># noqa</span>
</span><span id="L-330"><a href="#L-330"><span class="linenos">330</span></a> <span class="s2">&quot;Issue226&quot;</span><span class="p">,</span>
</span><span id="L-331"><a href="#L-331"><span class="linenos">331</span></a> <span class="s2">&quot;var_with_default_obj&quot;</span><span class="p">,</span>
</span><span id="L-332"><a href="#L-332"><span class="linenos">332</span></a> <span class="s2">&quot;var_with_default_func&quot;</span><span class="p">,</span>
</span><span id="L-333"><a href="#L-333"><span class="linenos">333</span></a> <span class="s2">&quot;func_with_defaults&quot;</span><span class="p">,</span>
</span><span id="L-334"><a href="#L-334"><span class="linenos">334</span></a> <span class="s2">&quot;ClassmethodLink&quot;</span><span class="p">,</span>
</span><span id="L-335"><a href="#L-335"><span class="linenos">335</span></a> <span class="s2">&quot;GenericParent&quot;</span><span class="p">,</span>
</span><span id="L-336"><a href="#L-336"><span class="linenos">336</span></a> <span class="s2">&quot;NonGenericChild&quot;</span><span class="p">,</span>
</span><span id="L-337"><a href="#L-337"><span class="linenos">337</span></a> <span class="s2">&quot;Child&quot;</span><span class="p">,</span>
</span><span id="L-338"><a href="#L-338"><span class="linenos">338</span></a> <span class="s2">&quot;only_annotated&quot;</span><span class="p">,</span>
</span><span id="L-339"><a href="#L-339"><span class="linenos">339</span></a> <span class="s2">&quot;CustomException&quot;</span><span class="p">,</span>
</span><span id="L-340"><a href="#L-340"><span class="linenos">340</span></a> <span class="s2">&quot;_Private&quot;</span><span class="p">,</span>
</span><span id="L-341"><a href="#L-341"><span class="linenos">341</span></a> <span class="s2">&quot;LambdaAttr&quot;</span><span class="p">,</span>
</span><span id="L-342"><a href="#L-342"><span class="linenos">342</span></a> <span class="s2">&quot;foo&quot;</span><span class="p">,</span>
</span><span id="L-343"><a href="#L-343"><span class="linenos">343</span></a> <span class="s2">&quot;bar&quot;</span><span class="p">,</span>
</span><span id="L-344"><a href="#L-344"><span class="linenos">344</span></a> <span class="s2">&quot;baz&quot;</span><span class="p">,</span>
</span><span id="L-345"><a href="#L-345"><span class="linenos">345</span></a> <span class="s2">&quot;qux&quot;</span><span class="p">,</span>
</span><span id="L-346"><a href="#L-346"><span class="linenos">346</span></a> <span class="s2">&quot;Indented&quot;</span><span class="p">,</span>
</span><span id="L-347"><a href="#L-347"><span class="linenos">347</span></a> <span class="s2">&quot;fun_with_protected_decorator&quot;</span><span class="p">,</span>
</span><span id="L-348"><a href="#L-348"><span class="linenos">348</span></a> <span class="s2">&quot;unhashable&quot;</span><span class="p">,</span>
</span><span id="L-349"><a href="#L-349"><span class="linenos">349</span></a> <span class="s2">&quot;AbstractClass&quot;</span><span class="p">,</span>
</span><span id="L-350"><a href="#L-350"><span class="linenos">350</span></a> <span class="s2">&quot;add_four&quot;</span><span class="p">,</span>
</span><span id="L-351"><a href="#L-351"><span class="linenos">351</span></a> <span class="s2">&quot;add_five&quot;</span><span class="p">,</span>
</span><span id="L-352"><a href="#L-352"><span class="linenos">352</span></a> <span class="s2">&quot;add_six&quot;</span><span class="p">,</span>
</span><span id="L-353"><a href="#L-353"><span class="linenos">353</span></a> <span class="s2">&quot;linkify_links&quot;</span><span class="p">,</span>
</span><span id="L-354"><a href="#L-354"><span class="linenos">354</span></a> <span class="s2">&quot;Issue352a&quot;</span><span class="p">,</span>
</span><span id="L-355"><a href="#L-355"><span class="linenos">355</span></a> <span class="s2">&quot;Issue352b&quot;</span><span class="p">,</span>
</span><span id="L-356"><a href="#L-356"><span class="linenos">356</span></a><span class="p">]</span>
</span><span id="L-329"><a href="#L-329"><span class="linenos">329</span></a><span class="k">class</span> <span class="nc">CustomCallMeta</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
</span><span id="L-330"><a href="#L-330"><span class="linenos">330</span></a> <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span id="L-331"><a href="#L-331"><span class="linenos">331</span></a> <span class="sd">&quot;&quot;&quot;Custom docstring in metaclass.`__call__`&quot;&quot;&quot;</span>
</span><span id="L-332"><a href="#L-332"><span class="linenos">332</span></a>
</span><span id="L-333"><a href="#L-333"><span class="linenos">333</span></a>
</span><span id="L-334"><a href="#L-334"><span class="linenos">334</span></a><span class="k">class</span> <span class="nc">CustomCall</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">CustomCallMeta</span><span class="p">):</span>
</span><span id="L-335"><a href="#L-335"><span class="linenos">335</span></a> <span class="sd">&quot;&quot;&quot;A class where the constructor is defined by its metaclass.&quot;&quot;&quot;</span>
</span><span id="L-336"><a href="#L-336"><span class="linenos">336</span></a>
</span><span id="L-337"><a href="#L-337"><span class="linenos">337</span></a>
</span><span id="L-338"><a href="#L-338"><span class="linenos">338</span></a><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span> <span class="c1"># noqa</span>
</span><span id="L-339"><a href="#L-339"><span class="linenos">339</span></a> <span class="s2">&quot;Issue226&quot;</span><span class="p">,</span>
</span><span id="L-340"><a href="#L-340"><span class="linenos">340</span></a> <span class="s2">&quot;var_with_default_obj&quot;</span><span class="p">,</span>
</span><span id="L-341"><a href="#L-341"><span class="linenos">341</span></a> <span class="s2">&quot;var_with_default_func&quot;</span><span class="p">,</span>
</span><span id="L-342"><a href="#L-342"><span class="linenos">342</span></a> <span class="s2">&quot;func_with_defaults&quot;</span><span class="p">,</span>
</span><span id="L-343"><a href="#L-343"><span class="linenos">343</span></a> <span class="s2">&quot;ClassmethodLink&quot;</span><span class="p">,</span>
</span><span id="L-344"><a href="#L-344"><span class="linenos">344</span></a> <span class="s2">&quot;GenericParent&quot;</span><span class="p">,</span>
</span><span id="L-345"><a href="#L-345"><span class="linenos">345</span></a> <span class="s2">&quot;NonGenericChild&quot;</span><span class="p">,</span>
</span><span id="L-346"><a href="#L-346"><span class="linenos">346</span></a> <span class="s2">&quot;Child&quot;</span><span class="p">,</span>
</span><span id="L-347"><a href="#L-347"><span class="linenos">347</span></a> <span class="s2">&quot;only_annotated&quot;</span><span class="p">,</span>
</span><span id="L-348"><a href="#L-348"><span class="linenos">348</span></a> <span class="s2">&quot;CustomException&quot;</span><span class="p">,</span>
</span><span id="L-349"><a href="#L-349"><span class="linenos">349</span></a> <span class="s2">&quot;_Private&quot;</span><span class="p">,</span>
</span><span id="L-350"><a href="#L-350"><span class="linenos">350</span></a> <span class="s2">&quot;LambdaAttr&quot;</span><span class="p">,</span>
</span><span id="L-351"><a href="#L-351"><span class="linenos">351</span></a> <span class="s2">&quot;foo&quot;</span><span class="p">,</span>
</span><span id="L-352"><a href="#L-352"><span class="linenos">352</span></a> <span class="s2">&quot;bar&quot;</span><span class="p">,</span>
</span><span id="L-353"><a href="#L-353"><span class="linenos">353</span></a> <span class="s2">&quot;baz&quot;</span><span class="p">,</span>
</span><span id="L-354"><a href="#L-354"><span class="linenos">354</span></a> <span class="s2">&quot;qux&quot;</span><span class="p">,</span>
</span><span id="L-355"><a href="#L-355"><span class="linenos">355</span></a> <span class="s2">&quot;Indented&quot;</span><span class="p">,</span>
</span><span id="L-356"><a href="#L-356"><span class="linenos">356</span></a> <span class="s2">&quot;fun_with_protected_decorator&quot;</span><span class="p">,</span>
</span><span id="L-357"><a href="#L-357"><span class="linenos">357</span></a> <span class="s2">&quot;unhashable&quot;</span><span class="p">,</span>
</span><span id="L-358"><a href="#L-358"><span class="linenos">358</span></a> <span class="s2">&quot;AbstractClass&quot;</span><span class="p">,</span>
</span><span id="L-359"><a href="#L-359"><span class="linenos">359</span></a> <span class="s2">&quot;add_four&quot;</span><span class="p">,</span>
</span><span id="L-360"><a href="#L-360"><span class="linenos">360</span></a> <span class="s2">&quot;add_five&quot;</span><span class="p">,</span>
</span><span id="L-361"><a href="#L-361"><span class="linenos">361</span></a> <span class="s2">&quot;add_six&quot;</span><span class="p">,</span>
</span><span id="L-362"><a href="#L-362"><span class="linenos">362</span></a> <span class="s2">&quot;linkify_links&quot;</span><span class="p">,</span>
</span><span id="L-363"><a href="#L-363"><span class="linenos">363</span></a> <span class="s2">&quot;Issue352a&quot;</span><span class="p">,</span>
</span><span id="L-364"><a href="#L-364"><span class="linenos">364</span></a> <span class="s2">&quot;Issue352b&quot;</span><span class="p">,</span>
</span><span id="L-365"><a href="#L-365"><span class="linenos">365</span></a> <span class="s2">&quot;CustomCall&quot;</span><span class="p">,</span>
</span><span id="L-366"><a href="#L-366"><span class="linenos">366</span></a><span class="p">]</span>
</span></pre></div>

</details>
Expand Down Expand Up @@ -1858,6 +1877,48 @@ <h5>Inherited Members</h5>



</div>
</section>
<section id="CustomCall">
<div class="attr class">
<a class="headerlink" href="#CustomCall">#&nbsp;&nbsp</a>


<span class="def">class</span>
<span class="name">CustomCall</span>:
</div>

<details>
<summary>View Source</summary>
<div class="pdoc-code codehilite"><pre><span></span><span id="CustomCall-335"><a href="#CustomCall-335"><span class="linenos">335</span></a><span class="k">class</span> <span class="nc">CustomCall</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">CustomCallMeta</span><span class="p">):</span>
</span><span id="CustomCall-336"><a href="#CustomCall-336"><span class="linenos">336</span></a> <span class="sd">&quot;&quot;&quot;A class where the constructor is defined by its metaclass.&quot;&quot;&quot;</span>
</span></pre></div>

</details>

<div class="docstring"><p>A class where the constructor is defined by its metaclass.</p>
</div>


<div id="CustomCall.__init__" class="classattr">
<div class="attr function"><a class="headerlink" href="#CustomCall.__init__">#&nbsp;&nbsp</a>


<span class="name">CustomCall</span><span class="signature">(*args, **kwargs)</span>
</div>

<details>
<summary>View Source</summary>
<div class="pdoc-code codehilite"><pre><span></span><span id="CustomCall.__init__-331"><a href="#CustomCall.__init__-331"><span class="linenos">331</span></a> <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span id="CustomCall.__init__-332"><a href="#CustomCall.__init__-332"><span class="linenos">332</span></a> <span class="sd">&quot;&quot;&quot;Custom docstring in metaclass.`__call__`&quot;&quot;&quot;</span>
</span></pre></div>

</details>

<div class="docstring"><p>Custom docstring in metaclass.<code>__call__</code></p>
</div>


</div>
</section>
</main>
Expand Down
10 changes: 10 additions & 0 deletions test/testdata/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ class Issue352b(metaclass=Issue352bMeta):
"""No docstrings for the constructor here."""


class CustomCallMeta(type):
def __call__(cls, *args, **kwargs):
"""Custom docstring in metaclass.`__call__`"""


class CustomCall(metaclass=CustomCallMeta):
"""A class where the constructor is defined by its metaclass."""


__all__ = [ # noqa
"Issue226",
"var_with_default_obj",
Expand Down Expand Up @@ -354,4 +363,5 @@ class Issue352b(metaclass=Issue352bMeta):
"linkify_links",
"Issue352a",
"Issue352b",
"CustomCall",
]
4 changes: 3 additions & 1 deletion test/testdata/misc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@
<class misc.Issue352a
<method def __init__(self): ... # Issue352.__init__ sh…>>
<class misc.Issue352b # No docstrings for th…
<method def __init__(): ...>>>
<method def __init__(): ...>>
<class misc.CustomCall # A class where the co…
<method def __init__(cls, *args, **kwargs): ... # Custom docstring in …>>>
Loading

0 comments on commit c876a0f

Please sign in to comment.