Commit 8d7fb404 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #23374: Fixed pydoc failure with non-ASCII files when stdout encoding

differs from file system encoding (e.g. on Mac OS).
parent 9c85b072
...@@ -1407,9 +1407,6 @@ class _PlainTextDoc(TextDoc): ...@@ -1407,9 +1407,6 @@ class _PlainTextDoc(TextDoc):
def pager(text): def pager(text):
"""The first time this is called, determine what kind of pager to use.""" """The first time this is called, determine what kind of pager to use."""
global pager global pager
# Escape non-encodable characters to avoid encoding errors later
encoding = sys.getfilesystemencoding()
text = text.encode(encoding, 'backslashreplace').decode(encoding)
pager = getpager() pager = getpager()
pager(text) pager(text)
...@@ -1452,10 +1449,12 @@ def plain(text): ...@@ -1452,10 +1449,12 @@ def plain(text):
def pipepager(text, cmd): def pipepager(text, cmd):
"""Page through text by feeding it to another program.""" """Page through text by feeding it to another program."""
pipe = os.popen(cmd, 'w') import subprocess
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
try: try:
pipe.write(text) with proc:
pipe.close() with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
pipe.write(text)
except OSError: except OSError:
pass # Ignore broken pipes caused by quitting the pager program. pass # Ignore broken pipes caused by quitting the pager program.
...@@ -1463,16 +1462,21 @@ def tempfilepager(text, cmd): ...@@ -1463,16 +1462,21 @@ def tempfilepager(text, cmd):
"""Page through text by invoking a program on a temporary file.""" """Page through text by invoking a program on a temporary file."""
import tempfile import tempfile
filename = tempfile.mktemp() filename = tempfile.mktemp()
with open(filename, 'w') as file: with open(filename, 'w', errors='backslashreplace') as file:
file.write(text) file.write(text)
try: try:
os.system(cmd + ' "' + filename + '"') os.system(cmd + ' "' + filename + '"')
finally: finally:
os.unlink(filename) os.unlink(filename)
def _escape_stdout(text):
# Escape non-encodable characters to avoid encoding errors later
encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
return text.encode(encoding, 'backslashreplace').decode(encoding)
def ttypager(text): def ttypager(text):
"""Page through text on a text terminal.""" """Page through text on a text terminal."""
lines = plain(text).split('\n') lines = plain(_escape_stdout(text)).split('\n')
try: try:
import tty import tty
fd = sys.stdin.fileno() fd = sys.stdin.fileno()
...@@ -1516,7 +1520,7 @@ def ttypager(text): ...@@ -1516,7 +1520,7 @@ def ttypager(text):
def plainpager(text): def plainpager(text):
"""Simply print unformatted text. This is the ultimate fallback.""" """Simply print unformatted text. This is the ultimate fallback."""
sys.stdout.write(plain(text)) sys.stdout.write(plain(_escape_stdout(text)))
def describe(thing): def describe(thing):
"""Produce a short description of the given thing.""" """Produce a short description of the given thing."""
......
...@@ -35,6 +35,10 @@ try: ...@@ -35,6 +35,10 @@ try:
except ImportError: except ImportError:
threading = None threading = None
class nonascii:
'Це не латиниця'
pass
if test.support.HAVE_DOCSTRINGS: if test.support.HAVE_DOCSTRINGS:
expected_data_docstrings = ( expected_data_docstrings = (
'dictionary for instance variables (if defined)', 'dictionary for instance variables (if defined)',
...@@ -474,6 +478,11 @@ class PydocDocTest(unittest.TestCase): ...@@ -474,6 +478,11 @@ class PydocDocTest(unittest.TestCase):
self.assertEqual(expected, result, self.assertEqual(expected, result,
"documentation for missing module found") "documentation for missing module found")
def test_not_ascii(self):
result = run_pydoc('test.test_pydoc.nonascii', PYTHONIOENCODING='ascii')
encoded = nonascii.__doc__.encode('ascii', 'backslashreplace')
self.assertIn(encoded, result)
def test_input_strip(self): def test_input_strip(self):
missing_module = " test.i_am_not_here " missing_module = " test.i_am_not_here "
result = str(run_pydoc(missing_module), 'ascii') result = str(run_pydoc(missing_module), 'ascii')
......
...@@ -13,6 +13,9 @@ Core and Builtins ...@@ -13,6 +13,9 @@ Core and Builtins
Library Library
------- -------
- Issue #23374: Fixed pydoc failure with non-ASCII files when stdout encoding
differs from file system encoding (e.g. on Mac OS).
- Issue #23481: Remove RC4 from the SSL module's default cipher list. - Issue #23481: Remove RC4 from the SSL module's default cipher list.
- Issue #21548: Fix pydoc.synopsis() and pydoc.apropos() on modules with empty - Issue #21548: Fix pydoc.synopsis() and pydoc.apropos() on modules with empty
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment