Skip to content

Commit 0f249fc

Browse files
author
James William Pye
committed
Relocate port finder into a new socket module.
1 parent 9936bd5 commit 0f249fc

2 files changed

Lines changed: 52 additions & 24 deletions

File tree

postgresql/python/socket.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
##
2+
# copyright 2009, James William Pye
3+
# http://python.projects.postgresql.org
4+
##
5+
"""
6+
socket tools
7+
"""
8+
import random
9+
import socket
10+
import math
11+
import errno
12+
13+
__all__ = ['find_available_port']
14+
15+
def find_available_port(
16+
interface : "attempt to bind to interface" = 'localhost',
17+
address_family : "address family to use (default: AF_INET)" = socket.AF_INET,
18+
limit : "Number tries to make before giving up" = 1024,
19+
port_range = (6600, 56600)
20+
) -> (int, None):
21+
"""
22+
Find an available port on the given interface for the given address family.
23+
24+
Returns a port number that was successfully bound to or `None` if the attempt
25+
limit was reached.
26+
"""
27+
i = 0
28+
while i < limit:
29+
i += 1
30+
port = (
31+
math.floor(
32+
random.random() * (port_range[1] - port_range[0])
33+
) + port_range[0]
34+
)
35+
s = socket.socket(address_family, socket.SOCK_STREAM,)
36+
try:
37+
s.bind(('localhost', port))
38+
except socket.error as e:
39+
if e.errno in (errno.EACCES, errno.EADDRINUSE, errno.EINTR):
40+
# try again
41+
continue
42+
finally:
43+
s.close()
44+
break
45+
else:
46+
port = None
47+
48+
return port

postgresql/unittest.py

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@
77
"""
88
import sys
99
import os
10-
import random
11-
import socket
12-
import math
1310
import atexit
1411
import unittest
1512

1613
from . import exceptions as pg_exc
1714
from . import cluster as pg_cluster
1815
from . import installation as pg_inn
1916

17+
from .python.socket import find_available_port
18+
2019
class TestCaseWithCluster(unittest.TestCase):
2120
"""
2221
postgresql.driver *interface* tests.
@@ -42,30 +41,11 @@ def __init__(self, *args, **kw):
4241
if self.cluster.initialized():
4342
self.cluster.drop()
4443

45-
def _gen_cluster_port(self):
46-
i = 0
47-
limit = 1024
48-
while i < limit:
49-
i += 1
50-
port = (math.floor(random.random() * 50000) + 1024)
51-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM,)
52-
try:
53-
s.bind(('localhost', port))
54-
except socket.error as e:
55-
if e.errno in (errno.EACCES, errno.EADDRINUSE, errno.EINTR):
56-
# try again
57-
continue
58-
s.close()
59-
break
60-
else:
61-
port = None
62-
return port
63-
6444
def configure_cluster(self):
65-
self.cluster_port = self._gen_cluster_port()
45+
self.cluster_port = find_available_port()
6646
if self.cluster_port is None:
6747
e = pg_exc.ClusterError(
68-
'failed to find a port for the test cluster'
48+
'failed to find a port for the test cluster on localhost'
6949
)
7050
self.cluster.ife_descend(e)
7151
e.raise_exception()

0 commit comments

Comments
 (0)