Skip to content

Commit

Permalink
add find_free_port
Browse files Browse the repository at this point in the history
  • Loading branch information
lidong committed May 10, 2024
1 parent cadb5aa commit ee727d6
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ Module Docs - https://github.com/ClericPy/morebuiltins/blob/master/doc.md

3.5 `SocketServer` - To see an example in action, view the test code: morebuiltins/ipc.py:_test_ipc.

3.7 `find_free_port` - Finds and returns an available port number.


## 4. morebuiltins.request

Expand Down
19 changes: 19 additions & 0 deletions doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,25 @@
```


---


3.7 `find_free_port` - Finds and returns an available port number.

Parameters:
- host: The host address to bind, default is "127.0.0.1".
- port: The port number to attempt binding, default is 0 (for OS allocation).

Returns:
- If a free port is found, it returns the port number; otherwise, returns None.

Demo:

>>> free_port = find_free_port()
>>> isinstance(free_port, int)
True


---

======================
Expand Down
2 changes: 1 addition & 1 deletion morebuiltins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.0.4"
__version__ = "0.0.5"
__all__ = [
"morebuiltins.utils",
"morebuiltins.functools",
Expand Down
33 changes: 33 additions & 0 deletions morebuiltins/ipc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import pickle
import socket
import sys
from abc import ABC, abstractmethod
from logging import LogRecord
Expand All @@ -13,6 +14,7 @@
"SocketLogHandlerEncoder",
"SocketServer",
"SocketClient",
"find_free_port",
]


Expand Down Expand Up @@ -310,6 +312,35 @@ async def recv(self) -> Any:
return self.encoder.loads(head)


def find_free_port(host="127.0.0.1", port=0):
"""Finds and returns an available port number.
Parameters:
- host: The host address to bind, default is "127.0.0.1".
- port: The port number to attempt binding, default is 0 (for OS allocation).
Returns:
- If a free port is found, it returns the port number; otherwise, returns None.
Demo:
>>> free_port = find_free_port()
>>> isinstance(free_port, int)
True
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create an IPv4 TCP socket
try:
s.bind((host, port)) # Try to bind the socket to the specified host and port
result = s.getsockname()[1] # Get the bound port number
s.close() # Close the socket
return result
except socket.error:
# Catch socket errors (e.g., port already in use) and proceed without returning
pass
finally:
s.close() # Ensure the socket is closed before exiting


async def test_client(host="127.0.0.1", port=8090, encoder=None, cases=None):
async with SocketClient(host=host, port=port, encoder=encoder) as c:
for case in cases:
Expand Down Expand Up @@ -350,7 +381,9 @@ async def _test_ipc_logging():

host = "127.0.0.1"
port = 8090
assert find_free_port(host, port) == port
async with SocketServer(host=host, port=port, encoder=SocketLogHandlerEncoder()):
assert find_free_port(host, port) is None
# socket logger demo
# ==================
logger = logging.getLogger("test_logger")
Expand Down

0 comments on commit ee727d6

Please sign in to comment.