Skip to content

Commit

Permalink
Make port 0 mean pick an unused port
Browse files Browse the repository at this point in the history
  • Loading branch information
bmerry committed May 20, 2022
1 parent 031942c commit b0731cd
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 11 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ The host and port are associated with the event loop, and are remembered until
the server is closed. Attempting to connect after closing the server, or to an
address that hasn't been registered, will raise a `ConnectionRefusedError`.

If you don't want the bother of picking non-colliding ports, you can pass a
port number of 0, and async-solipsism will bind the first port number above
60000 that is unused.

### Integration with pytest-asyncio

async-solipsism and pytest-asyncio complement each other well: just write a
Expand Down Expand Up @@ -117,7 +121,7 @@ def event_loop():


def socket_factory(host, port, family):
return async_solipsism.ListenSocket((host, port if port else 80))
return async_solipsism.ListenSocket((host, port))


async def test_integration():
Expand All @@ -134,10 +138,6 @@ the socket factory, although it may be possible to do by monkeypatching. In
practice you will probably want to define your own fixtures for the client
and server.

If you need to run more than one test server concurrently, you'll need to
extend the socket factory to assign them each a different port
(async-solipsism does not currently handle mapping port 0 to an unused port).

## Limitations

The requirement to have no interaction with the outside world naturally
Expand Down Expand Up @@ -167,12 +167,16 @@ Calling functions that are not supported will generally raise

## Changelog

### 0.5

- Map port 0 to an unused port.

### 0.4

- Allow `call_soon_threadsafe` from the same thread.
- Don't warn when `SO_KEEPALIVE` is set on a socket.
- Update instructions for use with aiohttp.
- Add a pyproject.toml
- Add a pyproject.toml.

### 0.3

Expand Down
4 changes: 2 additions & 2 deletions src/async_solipsism/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020-2021 Bruce Merry
# Copyright 2020-2022 Bruce Merry
#
# This file is part of async-solipsism.
#
Expand All @@ -19,4 +19,4 @@
from .socket import * # noqa
from .loop import * # noqa

__version__ = '0.4'
__version__ = '0.5'
10 changes: 8 additions & 2 deletions src/async_solipsism/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,14 @@ async def create_server(
# TODO: what if host is actually a list?
addr = (host, port, 0, 0)
sock = _socket.ListenSocket(addr)
else:
addr = sock.getsockname()
addr = sock.getsockname()
if addr[1] == 0: # Port 0: pick a free port
addr_list = list(addr)
addr_list[1] = 60000
while tuple(addr_list) in self.__listening_sockets:
addr_list[1] += 1
addr = tuple(addr_list)
sock._sockname = addr
if addr in self.__listening_sockets:
raise SolipsismError("Reuse of listening addresses is not supported")
self.__listening_sockets[addr] = sock
Expand Down
14 changes: 13 additions & 1 deletion test/test_loop.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020 Bruce Merry
# Copyright 2020, 2022 Bruce Merry
#
# This file is part of async-solipsism.
#
Expand Down Expand Up @@ -156,6 +156,18 @@ def callback(reader, writer):
await server.wait_closed()


async def test_unused_port(event_loop):
def callback(reader, writer):
pass

listen_socket1 = async_solipsism.ListenSocket(('localhost', 0))
listen_socket2 = async_solipsism.ListenSocket(('localhost', 0))
server1 = await asyncio.start_server(callback, sock=listen_socket1)
server2 = await asyncio.start_server(callback, sock=listen_socket2)
assert listen_socket1.getsockname()[1] == 60000
assert listen_socket2.getsockname()[1] == 60001


async def test_close_server(event_loop):
server = await asyncio.start_server(lambda reader, writer: None, 'test.invalid', 1234)
server.close()
Expand Down

0 comments on commit b0731cd

Please # to comment.