Commit 423fd362 authored by Yury Selivanov's avatar Yury Selivanov Committed by GitHub

bpo-32066: Support pathlib.Path in create_unix_connection; sock arg should be optional (#4447)

parent 895862aa
...@@ -391,7 +391,7 @@ Creating connections ...@@ -391,7 +391,7 @@ Creating connections
:ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples. :ref:`UDP echo server protocol <asyncio-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 Create UNIX connection: socket family :py:data:`~socket.AF_UNIX`, socket
type :py:data:`~socket.SOCK_STREAM`. The :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 ...@@ -403,13 +403,17 @@ Creating connections
coroutine returns a ``(transport, protocol)`` pair. coroutine returns a ``(transport, protocol)`` pair.
*path* is the name of a UNIX domain socket, and is required unless a *sock* *path* is the name of a UNIX domain socket, and is required unless a *sock*
parameter is specified. Abstract UNIX sockets, :class:`str`, and parameter is specified. Abstract UNIX sockets, :class:`str`,
:class:`bytes` paths are supported. :class:`bytes`, and :class:`~pathlib.Path` paths are supported.
See the :meth:`AbstractEventLoop.create_connection` method for parameters. See the :meth:`AbstractEventLoop.create_connection` method for parameters.
Availability: UNIX. Availability: UNIX.
.. versionchanged:: 3.7
The *path* parameter can now be a :class:`~pathlib.Path` object.
Creating listening connections Creating listening connections
------------------------------ ------------------------------
...@@ -479,10 +483,18 @@ Creating listening connections ...@@ -479,10 +483,18 @@ Creating listening connections
Similar to :meth:`AbstractEventLoop.create_server`, but specific to the Similar to :meth:`AbstractEventLoop.create_server`, but specific to the
socket family :py:data:`~socket.AF_UNIX`. 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 <coroutine>`. This method is a :ref:`coroutine <coroutine>`.
Availability: UNIX. 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) .. coroutinemethod:: BaseEventLoop.connect_accepted_socket(protocol_factory, sock, \*, ssl=None)
Handle an accepted connection. Handle an accepted connection.
......
...@@ -362,12 +362,12 @@ class AbstractEventLoop: ...@@ -362,12 +362,12 @@ class AbstractEventLoop:
""" """
raise NotImplementedError raise NotImplementedError
def create_unix_connection(self, protocol_factory, path, *, def create_unix_connection(self, protocol_factory, path=None, *,
ssl=None, sock=None, ssl=None, sock=None,
server_hostname=None): server_hostname=None):
raise NotImplementedError 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): sock=None, backlog=100, ssl=None):
"""A coroutine which creates a UNIX Domain Socket server. """A coroutine which creates a UNIX Domain Socket server.
......
...@@ -212,7 +212,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): ...@@ -212,7 +212,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
self.call_soon_threadsafe(transp._process_exited, returncode) self.call_soon_threadsafe(transp._process_exited, returncode)
@coroutine @coroutine
def create_unix_connection(self, protocol_factory, path, *, def create_unix_connection(self, protocol_factory, path=None, *,
ssl=None, sock=None, ssl=None, sock=None,
server_hostname=None): server_hostname=None):
assert server_hostname is None or isinstance(server_hostname, str) assert server_hostname is None or isinstance(server_hostname, str)
...@@ -229,6 +229,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): ...@@ -229,6 +229,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
raise ValueError( raise ValueError(
'path and sock can not be specified at the same time') 'path and sock can not be specified at the same time')
path = _fspath(path)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
try: try:
sock.setblocking(False) sock.setblocking(False)
......
...@@ -251,7 +251,6 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -251,7 +251,6 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
srv.close() srv.close()
self.loop.run_until_complete(srv.wait_closed()) self.loop.run_until_complete(srv.wait_closed())
@unittest.skipUnless(hasattr(os, 'fspath'), 'no os.fspath')
def test_create_unix_server_pathlib(self): def test_create_unix_server_pathlib(self):
with test_utils.unix_socket_path() as path: with test_utils.unix_socket_path() as path:
path = pathlib.Path(path) path = pathlib.Path(path)
...@@ -260,6 +259,15 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -260,6 +259,15 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
srv.close() srv.close()
self.loop.run_until_complete(srv.wait_closed()) 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): def test_create_unix_server_existing_path_nonsock(self):
with tempfile.NamedTemporaryFile() as file: with tempfile.NamedTemporaryFile() as file:
coro = self.loop.create_unix_server(lambda: None, file.name) coro = self.loop.create_unix_server(lambda: None, file.name)
...@@ -319,7 +327,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase): ...@@ -319,7 +327,7 @@ class SelectorEventLoopUnixSocketTests(test_utils.TestCase):
def test_create_unix_connection_path_inetsock(self): def test_create_unix_connection_path_inetsock(self):
sock = socket.socket() sock = socket.socket()
with sock: with sock:
coro = self.loop.create_unix_connection(lambda: None, path=None, coro = self.loop.create_unix_connection(lambda: None,
sock=sock) sock=sock)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
'A UNIX Domain Stream.*was expected'): 'A UNIX Domain Stream.*was expected'):
......
asyncio: Support pathlib.Path in create_unix_connection; sock arg should be
optional
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment