From 423fd362f8e4d6c867a5afc8ac7cbeeb66cac19c Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Mon, 20 Nov 2017 17:26:28 -0500 Subject: bpo-32066: Support pathlib.Path in create_unix_connection; sock arg should be optional (#4447) --- Doc/library/asyncio-eventloop.rst | 18 +++++++++++++++--- Lib/asyncio/events.py | 4 ++-- Lib/asyncio/unix_events.py | 3 ++- Lib/test/test_asyncio/test_unix_events.py | 12 ++++++++++-- .../Library/2017-11-17-18-28-53.bpo-32066.OMQFLH.rst | 2 ++ 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-11-17-18-28-53.bpo-32066.OMQFLH.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index e635cba..dd75a23 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -391,7 +391,7 @@ Creating connections :ref:`UDP echo server protocol ` examples. -.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path, \*, ssl=None, sock=None, server_hostname=None) +.. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None) Create UNIX connection: socket family :py:data:`~socket.AF_UNIX`, socket type :py:data:`~socket.SOCK_STREAM`. The :py:data:`~socket.AF_UNIX` socket @@ -403,13 +403,17 @@ Creating connections coroutine returns a ``(transport, protocol)`` pair. *path* is the name of a UNIX domain socket, and is required unless a *sock* - parameter is specified. Abstract UNIX sockets, :class:`str`, and - :class:`bytes` paths are supported. + parameter is specified. Abstract UNIX sockets, :class:`str`, + :class:`bytes`, and :class:`~pathlib.Path` paths are supported. See the :meth:`AbstractEventLoop.create_connection` method for parameters. Availability: UNIX. + .. versionchanged:: 3.7 + + The *path* parameter can now be a :class:`~pathlib.Path` object. + Creating listening connections ------------------------------ @@ -479,10 +483,18 @@ Creating listening connections Similar to :meth:`AbstractEventLoop.create_server`, but specific to the socket family :py:data:`~socket.AF_UNIX`. + *path* is the name of a UNIX domain socket, and is required unless a *sock* + parameter is specified. Abstract UNIX sockets, :class:`str`, + :class:`bytes`, and :class:`~pathlib.Path` paths are supported. + This method is a :ref:`coroutine `. Availability: UNIX. + .. versionchanged:: 3.7 + + The *path* parameter can now be a :class:`~pathlib.Path` object. + .. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None) Handle an accepted connection. diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index f2f2e28..e59d3d2 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -362,12 +362,12 @@ class AbstractEventLoop: """ raise NotImplementedError - def create_unix_connection(self, protocol_factory, path, *, + def create_unix_connection(self, protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None): raise NotImplementedError - def create_unix_server(self, protocol_factory, path, *, + def create_unix_server(self, protocol_factory, path=None, *, sock=None, backlog=100, ssl=None): """A coroutine which creates a UNIX Domain Socket server. diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index bf682a1..be98f33 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -212,7 +212,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): self.call_soon_threadsafe(transp._process_exited, returncode) @coroutine - def create_unix_connection(self, protocol_factory, path, *, + def create_unix_connection(self, protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None): assert server_hostname is None or isinstance(server_hostname, str) @@ -229,6 +229,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): raise ValueError( 'path and sock can not be specified at the same time') + path = _fspath(path) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) try: sock.setblocking(False) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index d558842..fe758ba 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -251,7 +251,6 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): srv.close() self.loop.run_until_complete(srv.wait_closed()) - @unittest.skipUnless(hasattr(os, 'fspath'), 'no os.fspath') def test_create_unix_server_pathlib(self): with test_utils.unix_socket_path() as path: path = pathlib.Path(path) @@ -260,6 +259,15 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): srv.close() self.loop.run_until_complete(srv.wait_closed()) + def test_create_unix_connection_pathlib(self): + with test_utils.unix_socket_path() as path: + path = pathlib.Path(path) + coro = self.loop.create_unix_connection(lambda: None, path) + with self.assertRaises(FileNotFoundError): + # If pathlib.Path wasn't supported, the exception would be + # different. + self.loop.run_until_complete(coro) + def test_create_unix_server_existing_path_nonsock(self): with tempfile.NamedTemporaryFile() as file: coro = self.loop.create_unix_server(lambda: None, file.name) @@ -319,7 +327,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): def test_create_unix_connection_path_inetsock(self): sock = socket.socket() with sock: - coro = self.loop.create_unix_connection(lambda: None, path=None, + coro = self.loop.create_unix_connection(lambda: None, sock=sock) with self.assertRaisesRegex(ValueError, 'A UNIX Domain Stream.*was expected'): diff --git a/Misc/NEWS.d/next/Library/2017-11-17-18-28-53.bpo-32066.OMQFLH.rst b/Misc/NEWS.d/next/Library/2017-11-17-18-28-53.bpo-32066.OMQFLH.rst new file mode 100644 index 0000000..cbe0705 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-17-18-28-53.bpo-32066.OMQFLH.rst @@ -0,0 +1,2 @@ +asyncio: Support pathlib.Path in create_unix_connection; sock arg should be +optional -- cgit v0.12