Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link partially qualified identifiers when documenting single module #544

Merged
merged 18 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

- Add compatibility with Python 3.12
([#620](https://github.com/mitmproxy/pdoc/pull/620), @mhils)
- Add support for relative links. Instead of explicitly referring to `mypackage.helpers.foo`,
one can now also refer to `.helpers.foo` within the `mypackage` module, or `..helpers.foo` in a submodule.
([#544](https://github.com/mitmproxy/pdoc/pull/544), @Crozzers)
- Function signatures will now display "Foo" instead "demo.Foo" if the function is in the same module.
([#544](https://github.com/mitmproxy/pdoc/pull/544), @mhils)
- pdoc now also picks up docstrings from `.pyi` stub files.
([#619](https://github.com/mitmproxy/pdoc/pull/619), @mhils)
- Fix horizontal scroll navigation z-index issue.
Expand Down
48 changes: 34 additions & 14 deletions pdoc/render_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@
anchorlinenos=True,
)
"""
The pygments formatter used for pdoc.render_helpers.highlight.
The pygments formatter used for pdoc.render_helpers.highlight.
Overwrite this to configure pygments highlighting of code blocks.

The usage of the `.codehilite` CSS selector in custom templates is deprecated since pdoc 10, use `.pdoc-code` instead.
"""

signature_formatter = pygments.formatters.HtmlFormatter(nowrap=True)
"""
The pygments formatter used for pdoc.render_helpers.format_signature.
The pygments formatter used for pdoc.render_helpers.format_signature.
Overwrite this to configure pygments highlighting of signatures.
"""

Expand Down Expand Up @@ -287,13 +287,26 @@ def linkify_repl(m: re.Match):
'</span><span class="o">.</span><span class="n">', "."
)
identifier = removesuffix(plain_text, "()")

# Check if this is a local reference within this module?
mod: pdoc.doc.Module = context["module"]
for qualname in qualname_candidates(identifier, namespace):
doc = mod.get(qualname)
if doc and context["is_public"](doc).strip():
return f'<a href="#{qualname}">{plain_text}</a>'

# Check if this is a relative reference?
if identifier.startswith("."):
if mod.is_package:
# If we are in __init__.py, we want `.foo` to refer to a child module.
parent_module = mod.modulename
else:
# If we are in a leaf module, we want `.foo` to refer to the adjacent module.
parent_module = mod.modulename.rpartition(".")[0]
while identifier.startswith(".."):
identifier = identifier[1:]
parent_module = parent_module.rpartition(".")[0]
identifier = parent_module + identifier
else:
# Check if this is a local reference within this module?
for qualname in qualname_candidates(identifier, namespace):
doc = mod.get(qualname)
if doc and context["is_public"](doc).strip():
return f'<a href="#{qualname}">{plain_text}</a>'

module = ""
qualname = ""
Expand All @@ -309,9 +322,9 @@ def linkify_repl(m: re.Match):
and context["is_public"](doc).strip()
):
if plain_text.endswith("()"):
plain_text = f"{doc.fullname}()"
plain_text = f"{doc.qualname}()"
else:
plain_text = doc.fullname
plain_text = doc.qualname
return f'<a href="#{qualname}">{plain_text}</a>'
except ValueError:
# possible_sources did not find a parent module.
Expand All @@ -326,8 +339,13 @@ def linkify_repl(m: re.Match):
doc is not None and context["is_public"](doc).strip()
)
if target_exists_and_public:
assert doc is not None # mypy
if qualname:
qualname = f"#{qualname}"
if plain_text.endswith("()"):
plain_text = f"{doc.fullname}()"
else:
plain_text = doc.fullname
return f'<a href="{relative_link(context["module"].modulename, module)}{qualname}">{plain_text}</a>'
else:
return text
Expand All @@ -337,10 +355,11 @@ def linkify_repl(m: re.Match):
r"""
# Part 1: foo.bar or foo.bar() (without backticks)
(?<![/=?#&]) # heuristic: not part of a URL
\b

# First part of the identifier (e.g. "foo")
(?!\d)[a-zA-Z0-9_]+
# First part of the identifier (e.g. "foo") - this is optional for relative references.
(?:
\b
(?!\d)[a-zA-Z0-9_]+
)?
# Rest of the identifier (e.g. ".bar")
(?:
# A single dot or a dot surrounded with pygments highlighting.
Expand All @@ -353,6 +372,7 @@ def linkify_repl(m: re.Match):

| # Part 2: `foo` or `foo()`. `foo.bar` is already covered with part 1.
(?<=<code>)
\.*
(?!\d)[a-zA-Z0-9_]+
(?:\(\))?
(?=</code>(?!</a>))
Expand Down
Empty file modified test/syntax_err/syntax_err.py
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions test/test_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def test_walk_specs():
"demopackage._child_e",
"demopackage.child_b",
"demopackage.child_c",
"demopackage.subpackage",
]
with pytest.raises(ValueError, match="No modules found matching spec: unknown"):
with pytest.warns(UserWarning, match="Cannot find spec for unknown"):
Expand Down
2 changes: 1 addition & 1 deletion test/testdata/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ <h1 class="modulename">
</div>
<div id="Dog.friends" class="classattr">
<div class="attr variable">
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">demo.Dog</a>]</span>
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">Dog</a>]</span>


</div>
Expand Down
6 changes: 3 additions & 3 deletions test/testdata/demo_long.html
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ <h1 id="a-second-section">A Second Section</h1>
</section>
<section id="FOO_SINGLETON">
<div class="attr variable">
<span class="name">FOO_SINGLETON</span><span class="annotation">: <a href="#Foo">demo_long.Foo</a></span>
<span class="name">FOO_SINGLETON</span><span class="annotation">: <a href="#Foo">Foo</a></span>


</div>
Expand Down Expand Up @@ -595,7 +595,7 @@ <h1 id="a-second-section">A Second Section</h1>
<div class="attr function">

<span class="def">def</span>
<span class="name">a_complex_function</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">a</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="n">b</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n"><a href="#Foo">demo_long.Foo</a></span><span class="p">,</span> <span class="nb">str</span><span class="p">]</span>,</span><span class="param"> <span class="o">*</span>,</span><span class="param"> <span class="n">c</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">~</span><span class="n">T</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n">Optional</span><span class="p">[</span><span class="o">~</span><span class="n">T</span><span class="p">]</span>:</span></span>
<span class="name">a_complex_function</span><span class="signature pdoc-code multiline">(<span class="param"> <span class="n">a</span><span class="p">:</span> <span class="nb">str</span>,</span><span class="param"> <span class="n">b</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n"><a href="#Foo">Foo</a></span><span class="p">,</span> <span class="nb">str</span><span class="p">]</span>,</span><span class="param"> <span class="o">*</span>,</span><span class="param"> <span class="n">c</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="o">~</span><span class="n">T</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span></span><span class="return-annotation">) -> <span class="n">Optional</span><span class="p">[</span><span class="o">~</span><span class="n">T</span><span class="p">]</span>:</span></span>

<label class="view-source-button" for="a_complex_function-view-source"><span>View Source</span></label>

Expand Down Expand Up @@ -782,7 +782,7 @@ <h1 id="a-second-section">A Second Section</h1>
<div class="attr function">

<span class="def">def</span>
<span class="name">a_regular_function</span><span class="signature pdoc-code condensed">(<span class="param"><span class="bp">self</span></span><span class="return-annotation">) -> <span class="n"><a href="#Foo">demo_long.Foo</a></span>:</span></span>
<span class="name">a_regular_function</span><span class="signature pdoc-code condensed">(<span class="param"><span class="bp">self</span></span><span class="return-annotation">) -> <span class="n"><a href="#Foo">Foo</a></span>:</span></span>

<label class="view-source-button" for="Foo.a_regular_function-view-source"><span>View Source</span></label>

Expand Down
16 changes: 9 additions & 7 deletions test/testdata/demopackage.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ <h2>Submodules</h2>
<li><a href="demopackage/child_b.html">child_b</a></li>
<li><a href="demopackage/child_c.html">child_c</a></li>
<li><a href="demopackage/_child_e.html">_child_e</a></li>
<li><a href="demopackage/subpackage.html">subpackage</a></li>
</ul>

<h2>API Documentation</h2>
Expand Down Expand Up @@ -77,14 +78,14 @@ <h2>API Documentation</h2>
<h1 class="modulename">
demopackage </h1>

<div class="docstring"><p>A test package</p>
<div class="docstring"><p>A test package with a sub-package at <code><a href="demopackage/subpackage.html">demopackage.subpackage</a></code>.</p>
</div>

<input id="mod-demopackage-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">

<label class="view-source-button" for="mod-demopackage-view-source"><span>View Source</span></label>

<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="sd">&quot;&quot;&quot;A test package&quot;&quot;&quot;</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="sd">&quot;&quot;&quot;A test package with a sub-package at `.subpackage`.&quot;&quot;&quot;</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="kn">import</span> <span class="nn">demopackage2</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">_child_e</span>
Expand All @@ -105,7 +106,8 @@ <h1 class="modulename">
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a> <span class="s2">&quot;demopackage2&quot;</span><span class="p">,</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a> <span class="s2">&quot;_child_e&quot;</span><span class="p">,</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a> <span class="s2">&quot;child_excluded&quot;</span><span class="p">,</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="p">]</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a> <span class="s2">&quot;subpackage&quot;</span><span class="p">,</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="p">]</span>
</span></pre></div>


Expand Down Expand Up @@ -167,7 +169,7 @@ <h1 class="modulename">
</div>
<a class="headerlink" href="#B"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="B-8"><a href="#B-8"><span class="linenos"> 8</span></a><span class="k">class</span> <span class="nc">B</span><span class="p">:</span>
</span><span id="B-9"><a href="#B-9"><span class="linenos"> 9</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;This class is defined in .child_b.&quot;&quot;&quot;</span>
</span><span id="B-9"><a href="#B-9"><span class="linenos"> 9</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;This class is defined in .child_b. It has a B.b method.&quot;&quot;&quot;</span>
</span><span id="B-10"><a href="#B-10"><span class="linenos">10</span></a>
</span><span id="B-11"><a href="#B-11"><span class="linenos">11</span></a> <span class="n">b_type</span><span class="p">:</span> <span class="n">typing</span><span class="o">.</span><span class="n">Type</span><span class="p">[</span><span class="n">B</span><span class="p">]</span>
</span><span id="B-12"><a href="#B-12"><span class="linenos">12</span></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;we have a self-referential attribute here&quot;&quot;&quot;</span>
Expand All @@ -177,13 +179,13 @@ <h1 class="modulename">
</span></pre></div>


<div class="docstring"><p>This class is defined in .child_b.</p>
<div class="docstring"><p>This class is defined in <a href="demopackage/child_b.html">demopackage.child_b</a>. It has a <a href="#B.b">B.b</a> method.</p>
</div>


<div id="B.b_type" class="classattr">
<div class="attr variable">
<span class="name">b_type</span><span class="annotation">: Type[<a href="#B">demopackage.B</a>]</span>
<span class="name">b_type</span><span class="annotation">: Type[<a href="#B">B</a>]</span>


</div>
Expand Down Expand Up @@ -233,7 +235,7 @@ <h1 class="modulename">
</span></pre></div>


<div class="docstring"><p>This class is defined in .child_c and inherits from .child_b.B</p>
<div class="docstring"><p>This class is defined in <a href="demopackage/child_c.html">demopackage.child_c</a> and inherits from <a href="#B">B</a></p>
</div>


Expand Down
2 changes: 1 addition & 1 deletion test/testdata/demopackage.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<module demopackage # A test package
<module demopackage # A test package with …
<class demopackage.Test # inherited from demopackage._child_d.Test, The Test class from …
<method def __init__(): ... # inherited from demopackage._child_d.Test.__init__>
<method def foo(self, a: int): ... # inherited from demopackage._child_d.Test.foo, Do foo.>
Expand Down
3 changes: 2 additions & 1 deletion test/testdata/demopackage/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""A test package"""
"""A test package with a sub-package at `.subpackage`."""
import demopackage2

from . import _child_e
Expand All @@ -19,4 +19,5 @@
"demopackage2",
"_child_e",
"child_excluded",
"subpackage",
]
2 changes: 1 addition & 1 deletion test/testdata/demopackage/child_b.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class B:
"""This class is defined in .child_b."""
"""This class is defined in .child_b. It has a B.b method."""

b_type: typing.Type[B]
"""we have a self-referential attribute here"""
Expand Down
11 changes: 11 additions & 0 deletions test/testdata/demopackage/subpackage/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""
A sub-package.

It imports and re-exposes ..child_b.B, and links to `..C` .
"""

from ..child_b import B

__all__ = [
"B"
]
361 changes: 348 additions & 13 deletions test/testdata/demopackage_dir.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/testdata/example_customtemplate.html
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ <h1 class="modulename">
</div>
<div id="Dog.friends" class="classattr">
<div class="attr variable">
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">demo.Dog</a>]</span>
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">Dog</a>]</span>


</div>
Expand Down
2 changes: 1 addition & 1 deletion test/testdata/example_darkmode.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ <h1 class="modulename">
</div>
<div id="Dog.friends" class="classattr">
<div class="attr variable">
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">demo.Dog</a>]</span>
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">Dog</a>]</span>


</div>
Expand Down
2 changes: 1 addition & 1 deletion test/testdata/example_mkdocs.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ <h1 class="modulename">
</div>
<div id="Dog.friends" class="classattr">
<div class="attr variable">
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">demo.Dog</a>]</span>
<span class="name">friends</span><span class="annotation">: list[<a href="#Dog">Dog</a>]</span>


</div>
Expand Down
2 changes: 1 addition & 1 deletion test/testdata/mermaid_demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ <h1 class="modulename">
</div>
<div id="Pet.friends" class="classattr">
<div class="attr variable">
<span class="name">friends</span><span class="annotation">: list[<a href="#Pet">mermaid_demo.Pet</a>]</span>
<span class="name">friends</span><span class="annotation">: list[<a href="#Pet">Pet</a>]</span>


</div>
Expand Down
8 changes: 4 additions & 4 deletions test/testdata/misc.html
Original file line number Diff line number Diff line change
Expand Up @@ -2067,7 +2067,7 @@ <h6 id="heading-6">Heading 6</h6>
<section id="another_decorated_function">
<div class="attr variable">
<span class="name">another_decorated_function</span> =
<span class="default_value">&lt;<a href="#ClassDecorator">misc.ClassDecorator</a> object&gt;</span>
<span class="default_value">&lt;<a href="#ClassDecorator">ClassDecorator</a> object&gt;</span>


</div>
Expand Down Expand Up @@ -2104,7 +2104,7 @@ <h6 id="heading-6">Heading 6</h6>
<input id="SubclassRef.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<div class="attr function">

<span class="name">SubclassRef</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">x</span><span class="p">:</span> <span class="n"><a href="#SubclassRef.SubClass">misc.SubclassRef.SubClass</a></span></span>)</span>
<span class="name">SubclassRef</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">x</span><span class="p">:</span> <span class="n"><a href="#SubclassRef.SubClass">SubclassRef.SubClass</a></span></span>)</span>

<label class="view-source-button" for="SubclassRef.__init__-view-source"><span>View Source</span></label>

Expand Down Expand Up @@ -2163,7 +2163,7 @@ <h6 id="heading-6">Heading 6</h6>
<div id="ClassAsAttribute.static_attr_to_class" class="classattr">
<div class="attr variable">
<span class="name">static_attr_to_class</span> =
<span class="default_value">&lt;class &#39;<a href="#ClassDecorator">misc.ClassDecorator</a>&#39;&gt;</span>
<span class="default_value">&lt;class &#39;<a href="#ClassDecorator">ClassDecorator</a>&#39;&gt;</span>


</div>
Expand All @@ -2177,7 +2177,7 @@ <h6 id="heading-6">Heading 6</h6>
<div id="ClassAsAttribute.static_attr_to_instance" class="classattr">
<div class="attr variable">
<span class="name">static_attr_to_instance</span> =
<span class="default_value">&lt;<a href="#ClassDecorator">misc.ClassDecorator</a> object&gt;</span>
<span class="default_value">&lt;<a href="#ClassDecorator">ClassDecorator</a> object&gt;</span>


</div>
Expand Down
Loading