2020import os
2121from os .path import expanduser
2222import re
23+ import socket
2324import tempfile
2425from psycopg2 ._psycopg import OperationalError
2526from psycopg2 .extensions import ISOLATION_LEVEL_AUTOCOMMIT
@@ -172,15 +173,17 @@ def __init__(self, bin_dir, ports):
172173 'host all all ::1/128 md5\n ' .format (admin = DatabaseRunner .ADMIN_USER )
173174 )
174175
175- for port in ports :
176- self .proc = Popen ([self ._postgres_cmd , '-D' , self ._temp_dir , '-p' , str (port )])
177- # if the process is still running, then there was problem, most likely the port is taken so try the next one
178- if not self .proc .poll ():
179- self .running_port = port
180- break
181- else :
176+ def can_connect (port ):
177+ sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
178+ return sock .connect_ex (('127.0.0.1' , port )) != 0
179+
180+ self .running_port = next ((port for port in ports if can_connect (port )), None )
181+ if self .running_port is None :
182182 raise PyEmbedPgException ('Cannot run postgres on any of these ports [{ports}]' .format (ports = ', ' .join ((str (p ) for p in ports ))))
183183
184+ self .proc = Popen ([self ._postgres_cmd , '-D' , self ._temp_dir , '-p' , str (self .running_port )])
185+ logger .debug ('Postgres started on port {port}...' .format (port = self .running_port ))
186+
184187 # Loop until the server is started
185188 logger .debug ('Waiting for Postgres to start...' )
186189 start = time .time ()
@@ -194,8 +197,6 @@ def __init__(self, bin_dir, ports):
194197 else :
195198 raise PyEmbedPgException ('Cannot start postgres after {timeout} seconds' .format (timeout = DatabaseRunner .TIMEOUT ))
196199
197- logger .debug ('Postgres started on port {port}...' .format (port = self .running_port ))
198-
199200 def __enter__ (self ):
200201 return self
201202
0 commit comments