issue27182: update fsencode and fsdecode for os.path(); patch by Dusty Phillips

This commit is contained in:
Ethan Furman 2016-06-04 10:19:27 -07:00
parent 7a3827f61f
commit c1cbeedf0c
2 changed files with 29 additions and 8 deletions

View File

@ -877,29 +877,35 @@ def _fscodec():
def fsencode(filename): def fsencode(filename):
""" """
Encode filename to the filesystem encoding with 'surrogateescape' error Encode filename (an os.PathLike, bytes, or str) to the filesystem
handler, return bytes unchanged. On Windows, use 'strict' error handler if encoding with 'surrogateescape' error handler, return bytes unchanged.
the file system encoding is 'mbcs' (which is the default encoding). On Windows, use 'strict' error handler if the file system encoding is
'mbcs' (which is the default encoding).
""" """
filename = fspath(filename)
if isinstance(filename, bytes): if isinstance(filename, bytes):
return filename return filename
elif isinstance(filename, str): elif isinstance(filename, str):
return filename.encode(encoding, errors) return filename.encode(encoding, errors)
else: else:
raise TypeError("expect bytes or str, not %s" % type(filename).__name__) raise TypeError("expected str, bytes or os.PathLike object, not "
+ path_type.__name__)
def fsdecode(filename): def fsdecode(filename):
""" """
Decode filename from the filesystem encoding with 'surrogateescape' error Decode filename (an os.PathLike, bytes, or str) from the filesystem
handler, return str unchanged. On Windows, use 'strict' error handler if encoding with 'surrogateescape' error handler, return str unchanged. On
the file system encoding is 'mbcs' (which is the default encoding). Windows, use 'strict' error handler if the file system encoding is
'mbcs' (which is the default encoding).
""" """
filename = fspath(filename)
if isinstance(filename, str): if isinstance(filename, str):
return filename return filename
elif isinstance(filename, bytes): elif isinstance(filename, bytes):
return filename.decode(encoding, errors) return filename.decode(encoding, errors)
else: else:
raise TypeError("expect bytes or str, not %s" % type(filename).__name__) raise TypeError("expected str, bytes or os.PathLike object, not "
+ path_type.__name__)
return fsencode, fsdecode return fsencode, fsdecode

View File

@ -3106,6 +3106,21 @@ class TestPEP519(unittest.TestCase):
for s in 'hello', 'goodbye', 'some/path/and/file': for s in 'hello', 'goodbye', 'some/path/and/file':
self.assertEqual(s, os.fspath(s)) self.assertEqual(s, os.fspath(s))
def test_fsencode_fsdecode_return_pathlike(self):
class Pathlike:
def __init__(self, path):
self.path = path
def __fspath__(self):
return self.path
for p in "path/like/object", b"path/like/object":
pathlike = Pathlike(p)
self.assertEqual(p, os.fspath(pathlike))
self.assertEqual(b"path/like/object", os.fsencode(pathlike))
self.assertEqual("path/like/object", os.fsdecode(pathlike))
def test_garbage_in_exception_out(self): def test_garbage_in_exception_out(self):
vapor = type('blah', (), {}) vapor = type('blah', (), {})
for o in int, type, os, vapor(): for o in int, type, os, vapor():