Skip to content
This repository was archived by the owner on Mar 18, 2025. It is now read-only.

Commit d9f094f

Browse files
committed
Fix pylume use_existing_server
1 parent 885f918 commit d9f094f

File tree

2 files changed

+58
-49
lines changed

2 files changed

+58
-49
lines changed

pylume/pylume.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class PyLume:
4747
def __init__(
4848
self,
4949
debug: bool = False,
50-
auto_start_server: bool = True,
5150
server_start_timeout: int = 60,
5251
port: Optional[int] = None,
5352
use_existing_server: bool = False

pylume/server.py

Lines changed: 58 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,30 +40,59 @@ def __init__(
4040
def _check_port_available(self, port: int) -> bool:
4141
"""Check if a specific port is available."""
4242
try:
43-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
44-
s.bind(('localhost', port))
43+
# Create a socket
44+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
45+
self.logger.debug(f"Created socket for port {port} check")
46+
47+
# Set socket options
48+
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
49+
self.logger.debug("Set SO_REUSEADDR")
50+
51+
# Bind to the port
52+
try:
53+
s.bind(('127.0.0.1', port))
54+
self.logger.debug(f"Successfully bound to port {port}")
55+
s.listen(1)
56+
self.logger.debug(f"Successfully listening on port {port}")
57+
s.close()
58+
self.logger.debug(f"Port {port} is available")
4559
return True
46-
except OSError:
60+
except OSError as e:
61+
self.logger.debug(f"Failed to bind to port {port}: {str(e)}")
62+
return False
63+
finally:
64+
try:
65+
s.close()
66+
self.logger.debug("Socket closed")
67+
except:
68+
pass
69+
70+
except Exception as e:
71+
self.logger.debug(f"Unexpected error checking port {port}: {str(e)}")
4772
return False
4873

4974
def _get_server_port(self) -> int:
50-
"""Get and validate the server port.
75+
"""Get and validate the server port."""
76+
from .exceptions import LumeConfigError
5177

52-
Returns:
53-
int: The validated port number
54-
55-
Raises:
56-
RuntimeError: If no port was specified
57-
LumeConfigError: If the requested port is not available
58-
"""
5978
if self.requested_port is None:
60-
raise RuntimeError("No port specified for lume server")
79+
raise LumeConfigError("Port must be specified when starting a new server")
6180

62-
if not self._check_port_available(self.requested_port):
63-
from .exceptions import LumeConfigError
64-
raise LumeConfigError(f"Requested port {self.requested_port} is not available")
81+
self.logger.debug(f"Checking availability of port {self.requested_port}")
82+
83+
# Try multiple times with a small delay
84+
for attempt in range(3):
85+
if attempt > 0:
86+
self.logger.debug(f"Retrying port check (attempt {attempt + 1})")
87+
time.sleep(1)
88+
89+
if self._check_port_available(self.requested_port):
90+
self.logger.debug(f"Port {self.requested_port} is available")
91+
return self.requested_port
92+
else:
93+
self.logger.debug(f"Port {self.requested_port} check failed on attempt {attempt + 1}")
6594

66-
return self.requested_port
95+
raise LumeConfigError(f"Requested port {self.requested_port} is not available after 3 attempts")
6796

6897
async def _ensure_server_running(self) -> None:
6998
"""Ensure the lume server is running, start it if it's not."""
@@ -228,46 +257,34 @@ async def _ensure_server_running(self) -> None:
228257
raise RuntimeError(f"Failed to start lume server: {str(e)}")
229258

230259
async def _start_server(self) -> None:
231-
"""Start the lume server using a managed shell script."""
260+
"""Start the lume server using the lume executable."""
232261
self.logger.debug("Starting PyLume server")
262+
263+
# Get absolute path to lume executable in the same directory as this file
233264
lume_path = os.path.join(os.path.dirname(__file__), "lume")
234265
if not os.path.exists(lume_path):
235266
raise RuntimeError(f"Could not find lume binary at {lume_path}")
236-
237-
script_file = None
267+
238268
try:
269+
# Make executable
239270
os.chmod(lume_path, 0o755)
271+
272+
# Get and validate port
240273
self.port = self._get_server_port()
241274
self.base_url = f"http://localhost:{self.port}/lume"
242-
243-
# Create shell script with trap for process management
244-
script_content = f"""#!/bin/bash
245-
trap 'kill $(jobs -p)' EXIT
246-
exec {lume_path} serve --port {self.port}
247-
"""
248-
script_dir = os.path.dirname(lume_path)
249-
script_file = tempfile.NamedTemporaryFile(
250-
mode='w',
251-
suffix='.sh',
252-
dir=script_dir,
253-
delete=True
254-
)
255-
script_file.write(script_content)
256-
script_file.flush()
257-
os.chmod(script_file.name, 0o755)
258-
259-
# Set up output handling - just use a temp file
275+
276+
# Set up output handling
260277
self.output_file = tempfile.NamedTemporaryFile(mode='w+', delete=False)
261278

262-
# Start the managed server process
279+
# Start the server process with the lume executable
263280
env = os.environ.copy()
264-
env["RUST_BACKTRACE"] = "1"
281+
env["RUST_BACKTRACE"] = "1" # Enable backtrace for better error reporting
265282

266283
self.server_process = subprocess.Popen(
267-
['/bin/bash', script_file.name],
284+
[lume_path, "serve", "--port", str(self.port)],
268285
stdout=self.output_file,
269286
stderr=subprocess.STDOUT,
270-
cwd=script_dir,
287+
cwd=os.path.dirname(lume_path), # Run from same directory as executable
271288
env=env
272289
)
273290

@@ -278,13 +295,6 @@ async def _start_server(self) -> None:
278295
except Exception as e:
279296
await self._cleanup()
280297
raise RuntimeError(f"Failed to start lume server process: {str(e)}")
281-
finally:
282-
# Ensure script file is cleaned up
283-
if script_file:
284-
try:
285-
script_file.close()
286-
except:
287-
pass
288298

289299
async def _tail_log(self) -> None:
290300
"""Read and display server log output in debug mode."""

0 commit comments

Comments
 (0)