Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d80d5f4

Browse files
committed
#940286: pydoc.Helper.help() ignores input/output init parameters.
1 parent 4c4c0f2 commit d80d5f4

3 files changed

Lines changed: 60 additions & 8 deletions

File tree

Lib/pydoc.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,11 @@ def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=No
13101310
line += '\n' + self.indent(str(doc))
13111311
return line
13121312

1313+
class _PlainTextDoc(TextDoc):
1314+
"""Subclass of TextDoc which overrides string styling"""
1315+
def bold(self, text):
1316+
return text
1317+
13131318
# --------------------------------------------------------- user interfaces
13141319

13151320
def pager(text):
@@ -1464,6 +1469,7 @@ def locate(path, forceload=0):
14641469
# --------------------------------------- interactive interpreter interface
14651470

14661471
text = TextDoc()
1472+
plaintext = _PlainTextDoc()
14671473
html = HTMLDoc()
14681474

14691475
def resolve(thing, forceload=0):
@@ -1476,8 +1482,11 @@ def resolve(thing, forceload=0):
14761482
else:
14771483
return thing, getattr(thing, '__name__', None)
14781484

1479-
def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1485+
def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1486+
renderer=None):
14801487
"""Render text documentation, given an object or a path to an object."""
1488+
if renderer is None:
1489+
renderer = text
14811490
object, name = resolve(thing, forceload)
14821491
desc = describe(object)
14831492
module = inspect.getmodule(object)
@@ -1496,12 +1505,16 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
14961505
# document its available methods instead of its value.
14971506
object = type(object)
14981507
desc += ' object'
1499-
return title % desc + '\n\n' + text.document(object, name)
1508+
return title % desc + '\n\n' + renderer.document(object, name)
15001509

1501-
def doc(thing, title='Python Library Documentation: %s', forceload=0):
1510+
def doc(thing, title='Python Library Documentation: %s', forceload=0,
1511+
output=None):
15021512
"""Display text documentation, given an object or a path to an object."""
15031513
try:
1504-
pager(render_doc(thing, title, forceload))
1514+
if output is None:
1515+
pager(render_doc(thing, title, forceload))
1516+
else:
1517+
output.write(render_doc(thing, title, forceload, plaintext))
15051518
except (ImportError, ErrorDuringImport) as value:
15061519
print(value)
15071520

@@ -1755,9 +1768,9 @@ def help(self, request):
17551768
elif request in self.symbols: self.showsymbol(request)
17561769
elif request in self.keywords: self.showtopic(request)
17571770
elif request in self.topics: self.showtopic(request)
1758-
elif request: doc(request, 'Help on %s:')
1771+
elif request: doc(request, 'Help on %s:', output=self._output)
17591772
elif isinstance(request, Helper): self()
1760-
else: doc(request, 'Help on %s:')
1773+
else: doc(request, 'Help on %s:', output=self._output)
17611774
self.output.write('\n')
17621775

17631776
def intro(self):

Lib/test/test_pydoc.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import unittest
1010
import test.support
1111
import xml.etree
12+
import textwrap
13+
from io import StringIO
1214
from contextlib import contextmanager
13-
from test.support import (
14-
TESTFN, forget, rmtree, EnvironmentVarGuard, reap_children)
15+
from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard, \
16+
reap_children, captured_output
1517

1618
from test import pydoc_mod
1719

@@ -327,6 +329,41 @@ def test_stripid(self):
327329
self.assertEqual(stripid("<type 'exceptions.Exception'>"),
328330
"<type 'exceptions.Exception'>")
329331

332+
@unittest.skipIf(sys.flags.optimize >= 2,
333+
'Docstrings are omitted with -O2 and above')
334+
def test_help_output_redirect(self):
335+
# issue 940286, if output is set in Helper, then all output from
336+
# Helper.help should be redirected
337+
old_pattern = expected_text_pattern
338+
getpager_old = pydoc.getpager
339+
getpager_new = lambda: (lambda x: x)
340+
self.maxDiff = None
341+
342+
buf = StringIO()
343+
helper = pydoc.Helper(output=buf)
344+
unused, doc_loc = get_pydoc_text(pydoc_mod)
345+
module = "test.pydoc_mod"
346+
help_header = """
347+
Help on module test.pydoc_mod in test:
348+
349+
""".lstrip()
350+
help_header = textwrap.dedent(help_header)
351+
expected_help_pattern = help_header + expected_text_pattern
352+
353+
pydoc.getpager = getpager_new
354+
try:
355+
with captured_output('stdout') as output, \
356+
captured_output('stderr') as err:
357+
helper.help(module)
358+
result = buf.getvalue().strip()
359+
expected_text = expected_help_pattern % \
360+
(doc_loc, inspect.getabsfile(pydoc_mod))
361+
self.assertEqual('', output.getvalue())
362+
self.assertEqual('', err.getvalue())
363+
self.assertEqual(expected_text, result)
364+
finally:
365+
pydoc.getpager = getpager_old
366+
330367

331368
class TestDescriptions(unittest.TestCase):
332369

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Core and Builtins
3333
Library
3434
-------
3535

36+
- Issue #940286: pydoc.Helper.help() ignores input/output init parameters.
37+
3638
- Issue #1745035: Add a command size and data size limit to smtpd.py, to
3739
prevent DoS attacks. Patch by Savio Sena.
3840

0 commit comments

Comments
 (0)