Issue #27186: Update os.fspath()/PyOS_FSPath() to check the return

type of __fspath__().

As part of this change, also make sure that the pure Python
implementation of os.fspath() is tested.
This commit is contained in:
Brett Cannon 2016-06-24 12:03:43 -07:00
parent 19b2a53a82
commit c78ca1e044
7 changed files with 101 additions and 71 deletions

View file

@ -3112,55 +3112,59 @@ class TestScandir(unittest.TestCase):
class TestPEP519(unittest.TestCase):
"os.fspath()"
# Abstracted so it can be overridden to test pure Python implementation
# if a C version is provided.
fspath = staticmethod(os.fspath)
class PathLike:
def __init__(self, path=''):
self.path = path
def __fspath__(self):
return self.path
def test_return_bytes(self):
for b in b'hello', b'goodbye', b'some/path/and/file':
self.assertEqual(b, os.fspath(b))
self.assertEqual(b, self.fspath(b))
def test_return_string(self):
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
self.assertEqual(s, self.fspath(s))
def test_fsencode_fsdecode(self):
for p in "path/like/object", b"path/like/object":
pathlike = PathLike(p)
pathlike = self.PathLike(p)
self.assertEqual(p, os.fspath(pathlike))
self.assertEqual(p, self.fspath(pathlike))
self.assertEqual(b"path/like/object", os.fsencode(pathlike))
self.assertEqual("path/like/object", os.fsdecode(pathlike))
def test_fspathlike(self):
class PathLike:
def __init__(self, path=''):
self.path = path
def __fspath__(self):
return self.path
def test_pathlike(self):
self.assertEqual('#feelthegil', self.fspath(self.PathLike('#feelthegil')))
self.assertTrue(issubclass(self.PathLike, os.PathLike))
self.assertTrue(isinstance(self.PathLike(), os.PathLike))
self.assertEqual('#feelthegil', os.fspath(PathLike('#feelthegil')))
self.assertTrue(issubclass(PathLike, os.PathLike))
self.assertTrue(isinstance(PathLike(), os.PathLike))
message = 'expected str, bytes or os.PathLike object, not'
for fn in (os.fsencode, os.fsdecode):
for obj in PathLike(None), None:
with self.assertRaisesRegex(TypeError, message):
fn(obj)
with self.assertRaises(TypeError):
self.fspath(self.PathLike(42))
def test_garbage_in_exception_out(self):
vapor = type('blah', (), {})
for o in int, type, os, vapor():
self.assertRaises(TypeError, os.fspath, o)
self.assertRaises(TypeError, self.fspath, o)
def test_argument_required(self):
with self.assertRaises(TypeError):
os.fspath()
self.fspath()
# Only test if the C version is provided, otherwise TestPEP519 already tested
# the pure Python implementation.
if hasattr(os, "_fspath"):
class TestPEP519PurePython(TestPEP519):
"""Explicitly test the pure Python implementation of os.fspath()."""
fspath = staticmethod(os._fspath)
if __name__ == "__main__":