From c1cbeedf0c650c3f7c64f04479070d39e15e1baf Mon Sep 17 00:00:00 2001 From: Ethan Furman Date: Sat, 4 Jun 2016 10:19:27 -0700 Subject: [PATCH] issue27182: update fsencode and fsdecode for os.path(); patch by Dusty Phillips --- Lib/os.py | 22 ++++++++++++++-------- Lib/test/test_os.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Lib/os.py b/Lib/os.py index edd61ab8f80..1318de6b5ad 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -877,29 +877,35 @@ def _fscodec(): def fsencode(filename): """ - Encode filename to the filesystem encoding with 'surrogateescape' error - handler, return bytes unchanged. On Windows, use 'strict' error handler if - the file system encoding is 'mbcs' (which is the default encoding). + Encode filename (an os.PathLike, bytes, or str) to the filesystem + encoding with 'surrogateescape' error handler, return bytes unchanged. + 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): return filename elif isinstance(filename, str): return filename.encode(encoding, errors) 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): """ - Decode filename from the filesystem encoding with 'surrogateescape' error - handler, return str unchanged. On Windows, use 'strict' error handler if - the file system encoding is 'mbcs' (which is the default encoding). + Decode filename (an os.PathLike, bytes, or str) from the filesystem + encoding with 'surrogateescape' error handler, return str unchanged. On + Windows, use 'strict' error handler if the file system encoding is + 'mbcs' (which is the default encoding). """ + filename = fspath(filename) if isinstance(filename, str): return filename elif isinstance(filename, bytes): return filename.decode(encoding, errors) 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 diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index f52de287684..84ef150f827 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3106,6 +3106,21 @@ class TestPEP519(unittest.TestCase): for s in 'hello', 'goodbye', 'some/path/and/file': 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): vapor = type('blah', (), {}) for o in int, type, os, vapor():