]> granicus.if.org Git - python/commitdiff
issue27182: update fsencode and fsdecode for os.path(); patch by Dusty Phillips
authorEthan Furman <ethan@stoneleaf.us>
Sat, 4 Jun 2016 17:19:27 +0000 (10:19 -0700)
committerEthan Furman <ethan@stoneleaf.us>
Sat, 4 Jun 2016 17:19:27 +0000 (10:19 -0700)
Lib/os.py
Lib/test/test_os.py

index edd61ab8f8036c5d1dbb782409626f398093dc56..1318de6b5add541ba39d760340b4cff531820587 100644 (file)
--- 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
 
index f52de2876843a0060e0fed7f30b2cb2d7dfbedc4..84ef150f8275961ffd39205872875c8b7a2c6145 100644 (file)
@@ -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():