From 1f697bb0634fbda8d9be5f4ff302505650052955 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 19 Dec 2019 18:51:48 +0100 Subject: [PATCH 1/5] implement POSIX dirfd() --- Modules/posixmodule.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 322c2159812cdd0..0facf76d7242cc2 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -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); + if (fd == -1) + return path_error(&self->path); + return Py_BuildValue("i", fd); +} +#endif /* HAVE_DIRFD */ + static PyObject * ScandirIterator_enter(PyObject *self, PyObject *args) { @@ -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} }; From 33e289e352e2b0297780add8b99b731f979eece5 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 19 Dec 2019 18:58:14 +0100 Subject: [PATCH 2/5] add unit tests --- Lib/test/test_os.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index f44ddbad7d64183..4df7aa4fa318b3b 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4001,6 +4001,16 @@ def test_resource_warning(self): with self.check_no_resource_warning(): del iterator + def test_dirfd(self): + itr = os.scandir('.') + if not hasattr(itr, 'dirfd'): + self.skipTest("not supported") + fd = itr.dirfd() + self.assertIsInstance(fd, int) + self.assertGreater(fd, 0) + itr.close() + self.assertRaises(ValueError, itr.dirfd) + class TestPEP519(unittest.TestCase): From e42da320d58739059ca98963fc74c67a016f98ea Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 19 Dec 2019 19:06:20 +0100 Subject: [PATCH 3/5] update doc --- Doc/library/os.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 4fec647828e2506..093335f12181db1 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -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. From ee4fbda59f646d9e07f8c734979d004729798eda Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 19 Dec 2019 19:38:55 +0100 Subject: [PATCH 4/5] refactor test; add news entries --- Doc/whatsnew/3.9.rst | 10 +++------- Lib/test/test_os.py | 11 ++++------- .../Library/2019-12-19-19-37-01.bpo-39099.bZ8tpO.rst | 2 ++ 3 files changed, 9 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-12-19-19-37-01.bpo-39099.bZ8tpO.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 64361bb17f8a47d..a2d612c8f0974fc 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -129,13 +129,6 @@ that would produce an equivalent :class:`ast.AST` object when parsed. asyncio ------- -Due to significant security concerns, the *reuse_address* parameter of -:meth:`asyncio.loop.create_datagram_endpoint` is no longer supported. This is -because of the behavior of the socket option ``SO_REUSEADDR`` in UDP. For more -details, see the documentation for ``loop.create_datagram_endpoint()``. -(Contributed by Kyle Stanley, Antoine Pitrou, and Yury Selivanov in -:issue:`37228`.) - Added a new :term:`coroutine` :meth:`~asyncio.loop.shutdown_default_executor` that schedules a shutdown for the default executor that waits on the :class:`~concurrent.futures.ThreadPoolExecutor` to finish closing. Also, @@ -169,6 +162,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. +(Contributed by Giampaolo Rodola in :issue:`39099`) + threading --------- diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 4df7aa4fa318b3b..196fd2c9a7ebf9a 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -4002,13 +4002,10 @@ def test_resource_warning(self): del iterator def test_dirfd(self): - itr = os.scandir('.') - if not hasattr(itr, 'dirfd'): - self.skipTest("not supported") - fd = itr.dirfd() - self.assertIsInstance(fd, int) - self.assertGreater(fd, 0) - itr.close() + with os.scandir('.') as itr: + if not hasattr(itr, 'dirfd'): + self.skipTest("not supported") + self.assertGreater(itr.dirfd(), 0) self.assertRaises(ValueError, itr.dirfd) diff --git a/Misc/NEWS.d/next/Library/2019-12-19-19-37-01.bpo-39099.bZ8tpO.rst b/Misc/NEWS.d/next/Library/2019-12-19-19-37-01.bpo-39099.bZ8tpO.rst new file mode 100644 index 000000000000000..d8238df31e87335 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-19-19-37-01.bpo-39099.bZ8tpO.rst @@ -0,0 +1,2 @@ +os.scandir() object has a new dirfd() method. (patch contributed by +Giampaolo Rodola) From 90aad94a9b66faa23088aee1f9df092105e7a566 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Thu, 19 Dec 2019 19:48:38 +0100 Subject: [PATCH 5/5] restore text removed by accident --- Doc/whatsnew/3.9.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index a2d612c8f0974fc..07b6899a0c82b23 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -129,6 +129,13 @@ that would produce an equivalent :class:`ast.AST` object when parsed. asyncio ------- +Due to significant security concerns, the *reuse_address* parameter of +:meth:`asyncio.loop.create_datagram_endpoint` is no longer supported. This is +because of the behavior of the socket option ``SO_REUSEADDR`` in UDP. For more +details, see the documentation for ``loop.create_datagram_endpoint()``. +(Contributed by Kyle Stanley, Antoine Pitrou, and Yury Selivanov in +:issue:`37228`.) + Added a new :term:`coroutine` :meth:`~asyncio.loop.shutdown_default_executor` that schedules a shutdown for the default executor that waits on the :class:`~concurrent.futures.ThreadPoolExecutor` to finish closing. Also,