Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2218,6 +2218,14 @@ features:
The :func:`scandir` iterator supports the :term:`context manager` protocol
and has the following method:

.. method:: scandir.dirfd()

Return directory file descriptor.

.. versionadded:: 3.9

.. availability:: POSIX

.. method:: scandir.close()

Close the iterator and free acquired resources.
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ Exposed the Linux-specific :func:`os.pidfd_open` (:issue:`38692`) and
:data:`os.P_PIDFD` (:issue:`38713`) for process management with file
descriptors.

Added :meth:`~os.scandir.dirfd` method.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ~ will cause only dirfd to be displayed.

(Contributed by Giampaolo Rodola in :issue:`39099`)

threading
---------

Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -4001,6 +4001,13 @@ def test_resource_warning(self):
with self.check_no_resource_warning():
del iterator

def test_dirfd(self):
with os.scandir('.') as itr:
if not hasattr(itr, 'dirfd'):
self.skipTest("not supported")
self.assertGreater(itr.dirfd(), 0)
self.assertRaises(ValueError, itr.dirfd)


class TestPEP519(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
os.scandir() object has a new dirfd() method. (patch contributed by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markup could be used here.

Giampaolo Rodola)
20 changes: 20 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -13180,6 +13180,23 @@ ScandirIterator_close(ScandirIterator *self, PyObject *args)
Py_RETURN_NONE;
}

#ifdef HAVE_DIRFD
static PyObject *
ScandirIterator_dirfd(ScandirIterator *self, PyObject *args)
{
int fd;

if (ScandirIterator_is_closed(self)) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed directory");
return NULL;
}
fd = dirfd(self->dirp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fd can be declared here.

if (fd == -1)
return path_error(&self->path);
return Py_BuildValue("i", fd);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyLong_FromLong(fd); could be used here.

}
#endif /* HAVE_DIRFD */

static PyObject *
ScandirIterator_enter(PyObject *self, PyObject *args)
{
Expand Down Expand Up @@ -13235,6 +13252,9 @@ ScandirIterator_dealloc(ScandirIterator *iterator)
static PyMethodDef ScandirIterator_methods[] = {
{"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
{"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
#ifdef HAVE_DIRFD
{"dirfd", (PyCFunction)ScandirIterator_dirfd, METH_NOARGS},
#endif
{"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
{NULL}
};
Expand Down