Skip to content

Commit

Permalink
Add auto-linking of fully qualified property and method names in "See…
Browse files Browse the repository at this point in the history
… also" lines. (#203)

* Add auto-linking of fully qualified property and method names in "See also" lines.

* Only look for methods and properties if the object is a MatClass.
  • Loading branch information
rdzman authored Jul 12, 2023
1 parent 516fd29 commit ddff5e0
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 9 deletions.
27 changes: 27 additions & 0 deletions sphinxcontrib/mat_documenters.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def auto_link_see_also(self, docstrings):
# autolink known names in See also
see_also_re = re.compile(r"(See also:?\s*)(\b.*\b)(.*)", re.IGNORECASE)
see_also_cond_re = re.compile(r"(\s*)(\b.*\b)(.*)")
class_re = re.compile(r"(.*)\.([^\.]+)")
is_see_also_line = False
for i in range(len(docstrings)):
for j in range(len(docstrings[i])):
Expand Down Expand Up @@ -252,6 +253,32 @@ def auto_link_see_also(self, docstrings):
] = f":attr:`{name} <{cls.fullname(self.env)}.{name}>`"
continue

# see if it is a fully qualified property or method name we recognize
match2 = class_re.search(entries[k])
if match2:
m1 = match2.group(1)
m2 = match2.group(2)
if (
self.env.config.matlab_keep_package_prefix
and m1 in entities_table
):
cls = entities_table[entries[k]]
elif (
not self.env.config.matlab_keep_package_prefix
and m1 in entities_name_map
):
cls = entities_table[entities_name_map[m1]]
else:
cls = None
if cls and cls.ref_role() == "class":
name = m2.rstrip("()")
if name in cls.methods:
entries[k] = f":meth:`{entries[k]}`"
continue
elif name in cls.properties:
entries[k] = f":attr:`{entries[k]}`"
continue

# not yet handled
entries[k] = f"``{entries[k]}``"

Expand Down
3 changes: 2 additions & 1 deletion tests/roots/test_autodoc/target/ClassExample.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
% ClassExample - the constructor and a reference to mymethod()
% mymethod - a method in ClassExample
%
% See also BaseClass, baseFunction, b, unknownEntity, mymethod.
% See also BaseClass, baseFunction, b, unknownEntity, mymethod,
% package.ClassBar.bars, package.ClassBar.doFoo.

properties
a % a property
Expand Down
8 changes: 4 additions & 4 deletions tests/test_autodoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_target(make_app, rootdir):
assert len(content) == 1
assert (
content[0].astext()
== "target\n\n\n\nclass target.ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb\n\na property with default value\n\n\n\nc\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
== "target\n\n\n\nclass target.ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod,\npackage.ClassBar.bars, package.ClassBar.doFoo.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb\n\na property with default value\n\n\n\nc\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
)
assert (
property_section.rawsource
Expand All @@ -61,7 +61,7 @@ def test_target_show_default_value(make_app, rootdir):
assert len(content) == 1
assert (
content[0].astext()
== "target\n\n\n\nclass target.ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb = 10\n\na property with default value\n\n\n\nc = [10; ... 30]\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
== "target\n\n\n\nclass target.ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod,\npackage.ClassBar.bars, package.ClassBar.doFoo.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb = 10\n\na property with default value\n\n\n\nc = [10; ... 30]\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
)
assert (
property_section.rawsource
Expand Down Expand Up @@ -95,7 +95,7 @@ def test_target_auto_link_basic(make_app, rootdir):
)
assert (
see_also_line.rawsource
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <target.ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <target.ClassExample.mymethod>`."
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <target.ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <target.ClassExample.mymethod>`,\n:attr:`package.ClassBar.bars`, :meth:`package.ClassBar.doFoo`."
)


Expand All @@ -122,7 +122,7 @@ def test_target_auto_link_all(make_app, rootdir):
)
assert (
see_also_line.rawsource
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <target.ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <target.ClassExample.mymethod>`."
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <target.ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <target.ClassExample.mymethod>`,\n:attr:`package.ClassBar.bars`, :meth:`package.ClassBar.doFoo`."
)
assert (
constructor_desc.rawsource
Expand Down
8 changes: 4 additions & 4 deletions tests/test_autodoc_short_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_target(make_app, rootdir):
assert len(content) == 1
assert (
content[0].astext()
== "target\n\n\n\nclass ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb\n\na property with default value\n\n\n\nc\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
== "target\n\n\n\nclass ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod,\npackage.ClassBar.bars, package.ClassBar.doFoo.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb\n\na property with default value\n\n\n\nc\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
)
assert (
property_section.rawsource
Expand All @@ -62,7 +62,7 @@ def test_target_show_default_value(make_app, rootdir):
assert len(content) == 1
assert (
content[0].astext()
== "target\n\n\n\nclass ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb = 10\n\na property with default value\n\n\n\nc = [10; ... 30]\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
== "target\n\n\n\nclass ClassExample\n\nBases: handle\n\nExample class\n\nClassExample Properties:\n\na - first property of ClassExample\nb - second property of ClassExample\nc - third property of ClassExample\n\nClassExample Methods:\n\nClassExample - the constructor and a reference to mymethod()\nmymethod - a method in ClassExample\n\nSee also BaseClass, baseFunction, b, unknownEntity, mymethod,\npackage.ClassBar.bars, package.ClassBar.doFoo.\n\nConstructor Summary\n\n\n\n\n\nClassExample(a)\n\nLinks to fully qualified names package.ClassBar.foos,\npackage.ClassBar.doBar, and ClassExample.mymethod.\n\nProperty Summary\n\n\n\n\n\na\n\na property\n\n\n\nb = 10\n\na property with default value\n\n\n\nc = [10; ... 30]\n\na property with multiline default value\n\nMethod Summary\n\n\n\n\n\nmymethod(b)\n\nA method in ClassExample\n\nParameters\n\nb – an input to mymethod()"
)
assert (
property_section.rawsource
Expand Down Expand Up @@ -96,7 +96,7 @@ def test_target_auto_link_basic(make_app, rootdir):
)
assert (
see_also_line.rawsource
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <ClassExample.mymethod>`."
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <ClassExample.mymethod>`,\n:attr:`package.ClassBar.bars`, :meth:`package.ClassBar.doFoo`."
)


Expand All @@ -123,7 +123,7 @@ def test_target_auto_link_all(make_app, rootdir):
)
assert (
see_also_line.rawsource
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <ClassExample.mymethod>`."
== "See also :class:`BaseClass`, :func:`baseFunction`, :attr:`b <ClassExample.b>`, ``unknownEntity``, :meth:`mymethod() <ClassExample.mymethod>`,\n:attr:`package.ClassBar.bars`, :meth:`package.ClassBar.doFoo`."
)
assert (
constructor_desc.rawsource
Expand Down

0 comments on commit ddff5e0

Please sign in to comment.