Skip to content

Commit 9d36581

Browse files
bpo-34966: Improve support of method aliases in pydoc. (GH-9823)
Pydoc now does not duplicate docstrings for aliases of inherited methods. (cherry picked from commit a44d34e) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 3ba5e25 commit 9d36581

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

‎Lib/pydoc.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -958,8 +958,7 @@ def docroutine(self, object, name=None, mod=None,
958958
if name == realname:
959959
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
960960
else:
961-
if (cl and realname in cl.__dict__ and
962-
cl.__dict__[realname] is object):
961+
if cl and inspect.getattr_static(cl, realname, []) is object:
963962
reallink = '<a href="#%s">%s</a>' % (
964963
cl.__name__ + '-' + realname, realname)
965964
skipdocs = 1
@@ -1375,8 +1374,7 @@ def docroutine(self, object, name=None, mod=None, cl=None):
13751374
if name == realname:
13761375
title = self.bold(realname)
13771376
else:
1378-
if (cl and realname in cl.__dict__ and
1379-
cl.__dict__[realname] is object):
1377+
if cl and inspect.getattr_static(cl, realname, []) is object:
13801378
skipdocs = 1
13811379
title = self.bold(name) + ' = ' + realname
13821380
argspec = None

‎Lib/test/test_pydoc.py‎

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ def call_url_handler(self, url, expected_title):
417417

418418

419419
class PydocDocTest(unittest.TestCase):
420+
maxDiff = None
420421

421422
@unittest.skipIf(sys.flags.optimize >= 2,
422423
"Docstrings are omitted with -O2 and above")
@@ -648,6 +649,104 @@ def method_returning_true(self):
648649
methods = pydoc.allmethods(TestClass)
649650
self.assertDictEqual(methods, expected)
650651

652+
def test_method_aliases(self):
653+
class A:
654+
def tkraise(self, aboveThis=None):
655+
"""Raise this widget in the stacking order."""
656+
lift = tkraise
657+
def a_size(self):
658+
"""Return size"""
659+
class B(A):
660+
def itemconfigure(self, tagOrId, cnf=None, **kw):
661+
"""Configure resources of an item TAGORID."""
662+
itemconfig = itemconfigure
663+
b_size = A.a_size
664+
665+
doc = pydoc.render_doc(B)
666+
# clean up the extra text formatting that pydoc performs
667+
doc = re.sub('\b.', '', doc)
668+
self.assertEqual(doc, '''\
669+
Python Library Documentation: class B in module %s
670+
671+
class B(A)
672+
| Method resolution order:
673+
| B
674+
| A
675+
| builtins.object
676+
|\x20\x20
677+
| Methods defined here:
678+
|\x20\x20
679+
| b_size = a_size(self)
680+
|\x20\x20
681+
| itemconfig = itemconfigure(self, tagOrId, cnf=None, **kw)
682+
|\x20\x20
683+
| itemconfigure(self, tagOrId, cnf=None, **kw)
684+
| Configure resources of an item TAGORID.
685+
|\x20\x20
686+
| ----------------------------------------------------------------------
687+
| Methods inherited from A:
688+
|\x20\x20
689+
| a_size(self)
690+
| Return size
691+
|\x20\x20
692+
| lift = tkraise(self, aboveThis=None)
693+
|\x20\x20
694+
| tkraise(self, aboveThis=None)
695+
| Raise this widget in the stacking order.
696+
|\x20\x20
697+
| ----------------------------------------------------------------------
698+
| Data descriptors inherited from A:
699+
|\x20\x20
700+
| __dict__
701+
| dictionary for instance variables (if defined)
702+
|\x20\x20
703+
| __weakref__
704+
| list of weak references to the object (if defined)
705+
''' % __name__)
706+
707+
doc = pydoc.render_doc(B, renderer=pydoc.HTMLDoc())
708+
self.assertEqual(doc, '''\
709+
Python Library Documentation: class B in module %s
710+
711+
<p>
712+
<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
713+
<tr bgcolor="#ffc8d8">
714+
<td colspan=3 valign=bottom>&nbsp;<br>
715+
<font color="#000000" face="helvetica, arial"><a name="B">class <strong>B</strong></a>(A)</font></td></tr>
716+
\x20\x20\x20\x20
717+
<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
718+
<td width="100%%"><dl><dt>Method resolution order:</dt>
719+
<dd>B</dd>
720+
<dd>A</dd>
721+
<dd><a href="builtins.html#object">builtins.object</a></dd>
722+
</dl>
723+
<hr>
724+
Methods defined here:<br>
725+
<dl><dt><a name="B-b_size"><strong>b_size</strong></a> = <a href="#B-a_size">a_size</a>(self)</dt></dl>
726+
727+
<dl><dt><a name="B-itemconfig"><strong>itemconfig</strong></a> = <a href="#B-itemconfigure">itemconfigure</a>(self, tagOrId, cnf=None, **kw)</dt></dl>
728+
729+
<dl><dt><a name="B-itemconfigure"><strong>itemconfigure</strong></a>(self, tagOrId, cnf=None, **kw)</dt><dd><tt>Configure&nbsp;resources&nbsp;of&nbsp;an&nbsp;item&nbsp;TAGORID.</tt></dd></dl>
730+
731+
<hr>
732+
Methods inherited from A:<br>
733+
<dl><dt><a name="B-a_size"><strong>a_size</strong></a>(self)</dt><dd><tt>Return&nbsp;size</tt></dd></dl>
734+
735+
<dl><dt><a name="B-lift"><strong>lift</strong></a> = <a href="#B-tkraise">tkraise</a>(self, aboveThis=None)</dt></dl>
736+
737+
<dl><dt><a name="B-tkraise"><strong>tkraise</strong></a>(self, aboveThis=None)</dt><dd><tt>Raise&nbsp;this&nbsp;widget&nbsp;in&nbsp;the&nbsp;stacking&nbsp;order.</tt></dd></dl>
738+
739+
<hr>
740+
Data descriptors inherited from A:<br>
741+
<dl><dt><strong>__dict__</strong></dt>
742+
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
743+
</dl>
744+
<dl><dt><strong>__weakref__</strong></dt>
745+
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
746+
</dl>
747+
</td></tr></table>\
748+
''' % __name__)
749+
651750

652751
class PydocImportTest(PydocBaseTest):
653752

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:mod:`pydoc` now supports aliases not only to methods defined in
2+
the end class, but also to inherited methods. The docstring is not
3+
duplicated for aliases.

0 commit comments

Comments
 (0)