summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-02-20 21:47:09 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-02-20 21:47:09 (GMT)
commit7065f376e08bce1657904d3b2acb9989949f3efc (patch)
tree2e2faf88ac5e8d5298a0739ae4bc3fce12e731cd /Lib
parent78a82491277bc4ed3058757857abffd6119aea8e (diff)
parent5e3d7a401d8568d3308b8928b146a9c306bc3ca8 (diff)
downloadcpython-7065f376e08bce1657904d3b2acb9989949f3efc.zip
cpython-7065f376e08bce1657904d3b2acb9989949f3efc.tar.gz
cpython-7065f376e08bce1657904d3b2acb9989949f3efc.tar.bz2
Issue #23374: Fixed pydoc failure with non-ASCII files when stdout encoding
differs from file system encoding (e.g. on Mac OS).
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/pydoc.py22
-rw-r--r--Lib/test/test_pydoc.py9
2 files changed, 22 insertions, 9 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 1fc8cc7..b762389 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -1405,9 +1405,6 @@ class _PlainTextDoc(TextDoc):
def pager(text):
"""The first time this is called, determine what kind of pager to use."""
global pager
- # Escape non-encodable characters to avoid encoding errors later
- encoding = sys.getfilesystemencoding()
- text = text.encode(encoding, 'backslashreplace').decode(encoding)
pager = getpager()
pager(text)
@@ -1450,10 +1447,12 @@ def plain(text):
def pipepager(text, cmd):
"""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:
- pipe.write(text)
- pipe.close()
+ with proc:
+ with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
+ pipe.write(text)
except OSError:
pass # Ignore broken pipes caused by quitting the pager program.
@@ -1461,16 +1460,21 @@ def tempfilepager(text, cmd):
"""Page through text by invoking a program on a temporary file."""
import tempfile
filename = tempfile.mktemp()
- with open(filename, 'w') as file:
+ with open(filename, 'w', errors='backslashreplace') as file:
file.write(text)
try:
os.system(cmd + ' "' + filename + '"')
finally:
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):
"""Page through text on a text terminal."""
- lines = plain(text).split('\n')
+ lines = plain(_escape_stdout(text)).split('\n')
try:
import tty
fd = sys.stdin.fileno()
@@ -1514,7 +1518,7 @@ def ttypager(text):
def plainpager(text):
"""Simply print unformatted text. This is the ultimate fallback."""
- sys.stdout.write(plain(text))
+ sys.stdout.write(plain(_escape_stdout(text)))
def describe(thing):
"""Produce a short description of the given thing."""
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index 41ad792..e9fed0a 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -34,6 +34,10 @@ try:
except ImportError:
threading = None
+class nonascii:
+ 'Це не латиниця'
+ pass
+
if test.support.HAVE_DOCSTRINGS:
expected_data_docstrings = (
'dictionary for instance variables (if defined)',
@@ -460,6 +464,11 @@ class PydocDocTest(unittest.TestCase):
self.assertEqual(expected, result,
"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):
missing_module = " test.i_am_not_here "
result = str(run_pydoc(missing_module), 'ascii')