diff options
author | Sanyam Khurana <8039608+CuriousLearner@users.noreply.github.com> | 2018-10-21 07:22:02 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2018-10-21 07:22:02 (GMT) |
commit | a323cdcb33c8c856e5668acfb2c67ab5198672c4 (patch) | |
tree | a53d57bcb7b958f1517a59603e07c8c205cf6f6e | |
parent | d31e7730cd5d74efbd7320751dacd51d09cc415d (diff) | |
download | cpython-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.py | 18 | ||||
-rw-r--r-- | Lib/test/test_pydoc.py | 118 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2018-01-01-00-16-59.bpo-8525.Dq8s63.rst | 4 |
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. |