summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanyam Khurana <8039608+CuriousLearner@users.noreply.github.com>2018-10-21 07:22:02 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2018-10-21 07:22:02 (GMT)
commita323cdcb33c8c856e5668acfb2c67ab5198672c4 (patch)
treea53d57bcb7b958f1517a59603e07c8c205cf6f6e
parentd31e7730cd5d74efbd7320751dacd51d09cc415d (diff)
downloadcpython-a323cdcb33c8c856e5668acfb2c67ab5198672c4.zip
cpython-a323cdcb33c8c856e5668acfb2c67ab5198672c4.tar.gz
cpython-a323cdcb33c8c856e5668acfb2c67ab5198672c4.tar.bz2
bpo-8525: help() on a type now shows builtin subclasses (GH-5066)
For builtin types with builtin subclasses, help() on the type now shows up to 4 of the subclasses. This partially replaces the exception hierarchy information previously displayed in Python 2.7.
-rw-r--r--Lib/pydoc.py18
-rw-r--r--Lib/test/test_pydoc.py118
-rw-r--r--Misc/NEWS.d/next/Library/2018-01-01-00-16-59.bpo-8525.Dq8s63.rst4
3 files changed, 140 insertions, 0 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 8a6b27b..3a46171 100644
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -1254,6 +1254,24 @@ location listed above.
push(' ' + makename(base))
push('')
+ # List the built-in subclasses, if any:
+ subclasses = sorted(
+ (str(cls.__name__) for cls in object.__subclasses__()
+ if not cls.__name__.startswith("_") and cls.__module__ == "builtins"),
+ key=str.lower
+ )
+ no_of_subclasses = len(subclasses)
+ MAX_SUBCLASSES_TO_DISPLAY = 4
+ if subclasses:
+ push("Built-in subclasses:")
+ for subclassname in subclasses[:MAX_SUBCLASSES_TO_DISPLAY]:
+ push(' ' + subclassname)
+ if no_of_subclasses > MAX_SUBCLASSES_TO_DISPLAY:
+ push(' ... and ' +
+ str(no_of_subclasses - MAX_SUBCLASSES_TO_DISPLAY) +
+ ' other subclasses')
+ push('')
+
# Cute little class to pump out a horizontal rule between sections.
class HorizontalRule:
def __init__(self):
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index 06f8729..6cd81ec 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -517,6 +517,124 @@ class PydocDocTest(unittest.TestCase):
self.assertEqual(stripid("<type 'exceptions.Exception'>"),
"<type 'exceptions.Exception'>")
+ def test_builtin_with_more_than_four_children(self):
+ """Tests help on builtin object which have more than four child classes.
+
+ When running help() on a builtin class which has child classes, it
+ should contain a "Built-in subclasses" section and only 4 classes
+ should be displayed with a hint on how many more subclasses are present.
+ For example:
+
+ >>> help(object)
+ Help on class object in module builtins:
+
+ class object
+ | The most base type
+ |
+ | Built-in subclasses:
+ | async_generator
+ | BaseException
+ | builtin_function_or_method
+ | bytearray
+ | ... and 82 other subclasses
+ """
+ doc = pydoc.TextDoc()
+ text = doc.docclass(object)
+ snip = (" | Built-in subclasses:\n"
+ " | async_generator\n"
+ " | BaseException\n"
+ " | builtin_function_or_method\n"
+ " | bytearray\n"
+ " | ... and \\d+ other subclasses")
+ self.assertRegex(text, snip)
+
+ def test_builtin_with_child(self):
+ """Tests help on builtin object which have only child classes.
+
+ When running help() on a builtin class which has child classes, it
+ should contain a "Built-in subclasses" section. For example:
+
+ >>> help(ArithmeticError)
+ Help on class ArithmeticError in module builtins:
+
+ class ArithmeticError(Exception)
+ | Base class for arithmetic errors.
+ |
+ ...
+ |
+ | Built-in subclasses:
+ | FloatingPointError
+ | OverflowError
+ | ZeroDivisionError
+ """
+ doc = pydoc.TextDoc()
+ text = doc.docclass(ArithmeticError)
+ snip = (" | Built-in subclasses:\n"
+ " | FloatingPointError\n"
+ " | OverflowError\n"
+ " | ZeroDivisionError")
+ self.assertIn(snip, text)
+
+ def test_builtin_with_grandchild(self):
+ """Tests help on builtin classes which have grandchild classes.
+
+ When running help() on a builtin class which has child classes, it
+ should contain a "Built-in subclasses" section. However, if it also has
+ grandchildren, these should not show up on the subclasses section.
+ For example:
+
+ >>> help(Exception)
+ Help on class Exception in module builtins:
+
+ class Exception(BaseException)
+ | Common base class for all non-exit exceptions.
+ |
+ ...
+ |
+ | Built-in subclasses:
+ | ArithmeticError
+ | AssertionError
+ | AttributeError
+ ...
+ """
+ doc = pydoc.TextDoc()
+ text = doc.docclass(Exception)
+ snip = (" | Built-in subclasses:\n"
+ " | ArithmeticError\n"
+ " | AssertionError\n"
+ " | AttributeError")
+ self.assertIn(snip, text)
+ # Testing that the grandchild ZeroDivisionError does not show up
+ self.assertNotIn('ZeroDivisionError', text)
+
+ def test_builtin_no_child(self):
+ """Tests help on builtin object which have no child classes.
+
+ When running help() on a builtin class which has no child classes, it
+ should not contain any "Built-in subclasses" section. For example:
+
+ >>> help(ZeroDivisionError)
+
+ Help on class ZeroDivisionError in module builtins:
+
+ class ZeroDivisionError(ArithmeticError)
+ | Second argument to a division or modulo operation was zero.
+ |
+ | Method resolution order:
+ | ZeroDivisionError
+ | ArithmeticError
+ | Exception
+ | BaseException
+ | object
+ |
+ | Methods defined here:
+ ...
+ """
+ doc = pydoc.TextDoc()
+ text = doc.docclass(ZeroDivisionError)
+ # Testing that the subclasses section does not appear
+ self.assertNotIn('Built-in subclasses', text)
+
@unittest.skipIf(sys.flags.optimize >= 2,
'Docstrings are omitted with -O2 and above')
@unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(),
diff --git a/Misc/NEWS.d/next/Library/2018-01-01-00-16-59.bpo-8525.Dq8s63.rst b/Misc/NEWS.d/next/Library/2018-01-01-00-16-59.bpo-8525.Dq8s63.rst
new file mode 100644
index 0000000..d8af500
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-01-01-00-16-59.bpo-8525.Dq8s63.rst
@@ -0,0 +1,4 @@
+help() on a type now displays builtin subclasses. This is intended primarily
+to help with notification of more specific exception subclasses.
+
+Patch by Sanyam Khurana.