changeset: 101858:5a62d682636e user: Brett Cannon date: Fri Jun 10 14:37:21 2016 -0700 files: Doc/library/os.rst Lib/test/test_os.py Misc/NEWS Modules/posixmodule.c description: Issue #27186: Add os.PathLike support to DirEntry Initial patch thanks to Jelle Zijlstra. diff -r b0be24a2f16c -r 5a62d682636e Doc/library/os.rst --- a/Doc/library/os.rst Fri Jun 10 23:02:04 2016 +0300 +++ b/Doc/library/os.rst Fri Jun 10 14:37:21 2016 -0700 @@ -1994,6 +1994,9 @@ control over errors, you can catch :exc:`OSError` when calling one of the ``DirEntry`` methods and handle as appropriate. + To be directly usable as a path-like object, ``DirEntry`` implements the + :class:`os.PathLike` interface. + Attributes and methods on a ``DirEntry`` instance are as follows: .. attribute:: name @@ -2106,6 +2109,9 @@ .. versionadded:: 3.5 + .. versionchanged:: 3.6 + Added support for the :class:`os.PathLike` interface. + .. function:: stat(path, \*, dir_fd=None, follow_symlinks=True) diff -r b0be24a2f16c -r 5a62d682636e Lib/test/test_os.py --- a/Lib/test/test_os.py Fri Jun 10 23:02:04 2016 +0300 +++ b/Lib/test/test_os.py Fri Jun 10 14:37:21 2016 -0700 @@ -2824,11 +2824,13 @@ def setUp(self): self.path = os.path.realpath(support.TESTFN) + self.bytes_path = os.fsencode(self.path) self.addCleanup(support.rmtree, self.path) os.mkdir(self.path) def create_file(self, name="file.txt"): - filename = os.path.join(self.path, name) + path = self.bytes_path if isinstance(name, bytes) else self.path + filename = os.path.join(path, name) create_file(filename, b'python') return filename @@ -2917,15 +2919,16 @@ self.check_entry(entry, 'symlink_file.txt', False, True, True) def get_entry(self, name): - entries = list(os.scandir(self.path)) + path = self.bytes_path if isinstance(name, bytes) else self.path + entries = list(os.scandir(path)) self.assertEqual(len(entries), 1) entry = entries[0] self.assertEqual(entry.name, name) return entry - def create_file_entry(self): - filename = self.create_file() + def create_file_entry(self, name='file.txt'): + filename = self.create_file(name=name) return self.get_entry(os.path.basename(filename)) def test_current_directory(self): @@ -2946,6 +2949,18 @@ entry = self.create_file_entry() self.assertEqual(repr(entry), "") + def test_fspath_protocol(self): + entry = self.create_file_entry() + self.assertEqual(os.fspath(entry), os.path.join(self.path, 'file.txt')) + + def test_fspath_protocol_bytes(self): + bytes_filename = os.fsencode('bytesfile.txt') + bytes_entry = self.create_file_entry(name=bytes_filename) + fspath = os.fspath(bytes_entry) + self.assertIsInstance(fspath, bytes) + self.assertEqual(fspath, + os.path.join(os.fsencode(self.path),bytes_filename)) + def test_removed_dir(self): path = os.path.join(self.path, 'dir') diff -r b0be24a2f16c -r 5a62d682636e Misc/NEWS --- a/Misc/NEWS Fri Jun 10 23:02:04 2016 +0300 +++ b/Misc/NEWS Fri Jun 10 14:37:21 2016 -0700 @@ -38,11 +38,14 @@ Library ------- +- Issue #27186: Add os.PathLike support to DirEntry (part of PEP 519). + Initial patch by Jelle Zijlstra. + - Issue #20900: distutils register command now decodes HTTP responses correctly. Initial patch by ingrid. - Issue #27186: Add os.PathLike support to pathlib, removing its provisional - status (part of PEP 519). + status (part of PEP 519). Initial patch by Dusty Phillips. - Issue #27186: Add support for os.PathLike objects to os.fsencode() and os.fsdecode() (part of PEP 519). diff -r b0be24a2f16c -r 5a62d682636e Modules/posixmodule.c --- a/Modules/posixmodule.c Fri Jun 10 23:02:04 2016 +0300 +++ b/Modules/posixmodule.c Fri Jun 10 14:37:21 2016 -0700 @@ -11718,6 +11718,13 @@ return PyUnicode_FromFormat("", self->name); } +static PyObject * +DirEntry_fspath(DirEntry *self) +{ + Py_INCREF(self->path); + return self->path; +} + static PyMemberDef DirEntry_members[] = { {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, "the entry's base filename, relative to scandir() \"path\" argument"}, @@ -11742,6 +11749,9 @@ {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS, "return inode of the entry; cached per entry", }, + {"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS, + "returns the path for the entry", + }, {NULL} };