Skip to content
Open
2 changes: 1 addition & 1 deletion Lib/pydoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2059,7 +2059,7 @@ def interact(self):
while True:
try:
request = self.getline('help> ')
if not request: break
if not request.strip(): continue
except (KeyboardInterrupt, EOFError):
break
request = request.strip()
Expand Down
36 changes: 36 additions & 0 deletions Lib/test/test_pydoc/test_pydoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2161,10 +2161,46 @@ def test_url_requests(self):


class TestHelper(unittest.TestCase):
def mock_interactive_session(self, inputs):
"""
Given a list of inputs, run an interactive help session. Returns a string
of what would be shown on screen.
"""
input_iter = iter(inputs)

def mock_getline(prompt):
output.write(prompt)
next_input = next(input_iter)
output.write(next_input + os.linesep)
return next_input

with captured_stdout() as output:
helper = pydoc.Helper(output=output)
with unittest.mock.patch.object(helper, "getline", mock_getline):
helper.interact()

return output.getvalue().replace(os.linesep, "\n")

def test_keywords(self):
self.assertEqual(sorted(pydoc.Helper.keywords),
sorted(keyword.kwlist))

def test_interact_empty_line_continues(self):
# gh-138568: test pressing Enter without input should continue in help session
self.assertEqual(
self.mock_interactive_session(["", " ", "quit"]),
"\nhelp> \nhelp> \nhelp> quit\n",
)

def test_interact_quit_commands_exit(self):
quit_commands = ["quit", "q", "exit"]
for quit_cmd in quit_commands:
with self.subTest(quit_command=quit_cmd):
self.assertEqual(
self.mock_interactive_session([quit_cmd]),
f"\nhelp> {quit_cmd}\n",
)


class PydocWithMetaClasses(unittest.TestCase):
def tearDown(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Adjusted the built-in :func:`help` function so that empty inputs are ignored in
interactive mode.
Loading