diff --git a/Lib/pydoc.py b/Lib/pydoc.py index d508fb70ea429e..019c65a2ae4bd9 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1771,7 +1771,7 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0, return title % desc + '\n\n' + renderer.document(object, name) def doc(thing, title='Python Library Documentation: %s', forceload=0, - output=None, is_cli=False): + output=None, is_cli=False, is_interactive=False): """Display text documentation, given an object or a path to an object.""" if output is None: try: @@ -1787,7 +1787,11 @@ def doc(thing, title='Python Library Documentation: %s', forceload=0, except ImportError as exc: if is_cli: raise - print(exc) + if is_interactive: + # don't show the usual hints if we're running interactively + print(exc.args[0].splitlines(False)[0]) + else: + print(exc) else: try: s = render_doc(thing, title, forceload, plaintext) @@ -2070,10 +2074,7 @@ def interact(self): and request[0] not in request[1:-1]): request = request[1:-1] if request.lower() in ('q', 'quit', 'exit'): break - if request == 'help': - self.intro() - else: - self.help(request) + self.help(request, is_interactive=True) def getline(self, prompt): """Read one line, using input() when appropriate.""" @@ -2084,10 +2085,12 @@ def getline(self, prompt): self.output.flush() return self.input.readline() - def help(self, request, is_cli=False): + def help(self, request, is_cli=False, is_interactive=False): if isinstance(request, str): request = request.strip() - if request == 'keywords': self.listkeywords() + if request == 'help': + self.helphelp(is_interactive=is_interactive) + elif request == 'keywords': self.listkeywords() elif request == 'symbols': self.listsymbols() elif request == 'topics': self.listtopics() elif request == 'modules': self.listmodules() @@ -2099,12 +2102,42 @@ def help(self, request, is_cli=False): doc(eval(request), 'Help on %s:', output=self._output, is_cli=is_cli) elif request in self.keywords: self.showtopic(request) elif request in self.topics: self.showtopic(request) - elif request: doc(request, 'Help on %s:', output=self._output, is_cli=is_cli) + elif request: + doc(request, 'Help on %s:', output=self._output, is_cli=is_cli, is_interactive=is_interactive) else: doc(str, 'Help on %s:', output=self._output, is_cli=is_cli) - elif isinstance(request, Helper): self() + elif isinstance(request, (Helper, type(builtins.help))): + self.helphelp(is_interactive=is_interactive) else: doc(request, 'Help on %s:', output=self._output, is_cli=is_cli) self.output.write('\n') + def helphelp(self, is_interactive=False): + if is_interactive: + self.intro() + else: + pager(textwrap.dedent("""\ + help - Interactive Help + ======================= + + The built-in help function implements an interactive help utility. You + can make use of it in a few different ways: + + * Calling help() with no arguments starts an interactive help session. + + * The behavior of help(x) depends on the type of the argument: + + * If x is a string, help(x) provides information about the given + topic. For example, help("class") will provide information about + the "class" keyword, and help("math.sqrt") will provide + information about the "math.sqrt" function. + + * If x is a class or a built-in type, help(x) provides information + about that type. For example, help(str) will provide information + about the str type. + + * Otherwise, help(x) provides information about x's type. For + example, help(42) will provide information about the int type. + """)) + def intro(self): self.output.write(_introdoc()) diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 3b50ead00bdd31..b62416ec66027e 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -664,10 +664,10 @@ def test_builtin_on_metaclasses(self): self.assertNotIn('Built-in subclasses', text) def test_fail_help_cli(self): - elines = (missing_pattern % 'abd').splitlines() + elines = (missing_pattern % 'abd').splitlines(False)[:1] with spawn_python("-c" "help()") as proc: out, _ = proc.communicate(b"abd") - olines = out.decode().splitlines()[-9:-6] + olines = out.decode().splitlines(False)[-7:-6] olines[0] = olines[0].removeprefix('help> ') self.assertEqual(elines, olines) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-23-14-07-56.gh-issue-138094.U92SHS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-23-14-07-56.gh-issue-138094.U92SHS.rst new file mode 100644 index 00000000000000..d831dc41885872 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-23-14-07-56.gh-issue-138094.U92SHS.rst @@ -0,0 +1,2 @@ +Removed potentially-misleading suggestions from the interactive :func:`help` +prompt. Patch by Adam Hartz.