diff --git a/Lib/test/script_helper.py b/Lib/test/script_helper.py index f29143057d4..efb0523f323 100644 --- a/Lib/test/script_helper.py +++ b/Lib/test/script_helper.py @@ -19,11 +19,12 @@ def python_exit_code(*args): return subprocess.call(cmd_line, stdout=devnull, stderr=subprocess.STDOUT) -def spawn_python(*args): +def spawn_python(*args, **kwargs): cmd_line = [sys.executable, '-E'] cmd_line.extend(args) return subprocess.Popen(cmd_line, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + **kwargs) def kill_python(p): p.stdin.close() @@ -35,11 +36,11 @@ def kill_python(p): subprocess._cleanup() return data -def run_python(*args): +def run_python(*args, **kwargs): if __debug__: - p = spawn_python(*args) + p = spawn_python(*args, **kwargs) else: - p = spawn_python('-O', *args) + p = spawn_python('-O', *args, **kwargs) stdout_data = kill_python(p) return p.wait(), stdout_data diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index 21d231fc012..930b6543b61 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -12,6 +12,7 @@ from functools import wraps from test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd from test.test_support import py3k_bytes as bytes +from test.script_helper import run_python from _io import FileIO as _FileIO @@ -397,6 +398,25 @@ class OtherFileTests(unittest.TestCase): self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt") self.assertEqual(w.warnings, []) + def test_surrogates(self): + # Issue #8438: try to open a filename containing surrogates. + # It should either fail because the file doesn't exist or the filename + # can't be represented using the filesystem encoding, but not because + # of a LookupError for the error handler "surrogateescape". + filename = u'\udc80.txt' + try: + with _FileIO(filename): + pass + except (UnicodeEncodeError, IOError): + pass + # Spawn a separate Python process with a different "file system + # default encoding", to exercise this further. + env = dict(os.environ) + env[b'LC_CTYPE'] = b'C' + _, out = run_python('-c', 'import _io; _io.FileIO(%r)' % filename, env=env) + if ('UnicodeEncodeError' not in out and + 'IOError: [Errno 2] No such file or directory' not in out): + self.fail('Bad output: %r' % out) def test_main(): # Historically, these tests have been sloppy about removing TESTFN. diff --git a/Misc/NEWS b/Misc/NEWS index edf2ab008d2..b597cdf31d7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,9 @@ Core and Builtins Library ------- +- Issue #8438: Remove reference to the missing "surrogateescape" encoding + error handler from the new IO library. + - Issue #3817: ftplib.FTP.abort() method now considers 225 a valid response code as stated in RFC-959 at chapter 5.4. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index ec320f79b97..af98fd0de8b 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -248,7 +248,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) return -1; stringobj = PyUnicode_AsEncodedString( - u, Py_FileSystemDefaultEncoding, "surrogateescape"); + u, Py_FileSystemDefaultEncoding, NULL); Py_DECREF(u); if (stringobj == NULL) return -1;