Skip to content

Commit f4c2600

Browse files
committed
Updated package v4.14
1 parent d72a640 commit f4c2600

File tree

4 files changed

+75
-41
lines changed

4 files changed

+75
-41
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
All notable changes to LocalLab will be documented in this file.
44

5+
## 0.4.14 - 2025-03-11
6+
7+
### Fixed
8+
9+
- Fixed critical error: "LifespanOn.**init**() takes 2 positional arguments but 3 were given"
10+
- Enhanced lifespan initialization to handle different uvicorn versions with varying parameter requirements
11+
- Implemented comprehensive parameter testing for all lifespan classes to ensure compatibility
12+
- Added detailed logging for lifespan initialization to aid in troubleshooting
13+
- Improved error handling for all lifespan-related operations
14+
515
## 0.4.13 - 2025-03-11
616

717
### Fixed

locallab/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
LocalLab - A lightweight AI inference server for running LLMs locally
33
"""
44

5-
__version__ = "0.4.13"
5+
__version__ = "0.4.14"
66

77
# Only import what's necessary initially, lazy-load the rest
88
from .logger import get_logger

locallab/server.py

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -209,69 +209,93 @@ async def serve(self, sockets=None):
209209
try:
210210
# Try the newer location first (uvicorn >= 0.18.0)
211211
from uvicorn.lifespan.on import LifespanOn
212-
# LifespanOn doesn't accept logger parameter
213-
self.lifespan = LifespanOn(
214-
self.config.app,
215-
self.config.lifespan_on if hasattr(self.config, "lifespan_on") else "auto"
216-
)
217-
logger.info("Using LifespanOn from uvicorn.lifespan.on")
218-
except (ImportError, AttributeError) as e:
219-
logger.debug(f"Failed to import LifespanOn: {str(e)}")
212+
# LifespanOn may only accept app parameter in some versions
220213
try:
221-
# Try the older location (uvicorn < 0.18.0)
222-
from uvicorn.lifespan.lifespan import Lifespan
214+
# Try with just the app parameter
215+
self.lifespan = LifespanOn(self.config.app)
216+
logger.info("Using LifespanOn from uvicorn.lifespan.on (single parameter)")
217+
except TypeError:
218+
# If that fails, try with both parameters
223219
try:
224-
# Try with logger parameter first
225-
self.lifespan = Lifespan(
220+
self.lifespan = LifespanOn(
226221
self.config.app,
227-
"auto",
228-
logger
222+
self.config.lifespan_on if hasattr(self.config, "lifespan_on") else "auto"
229223
)
224+
logger.info("Using LifespanOn from uvicorn.lifespan.on (two parameters)")
230225
except TypeError:
231-
# If that fails, try without logger parameter
232-
self.lifespan = Lifespan(
233-
self.config.app,
234-
"auto"
235-
)
236-
logger.info("Using Lifespan from uvicorn.lifespan.lifespan")
237-
except (ImportError, AttributeError) as e:
238-
logger.debug(f"Failed to import Lifespan from lifespan.lifespan: {str(e)}")
226+
logger.debug("LifespanOn initialization failed with both one and two parameters")
227+
raise
228+
except (ImportError, AttributeError, TypeError) as e:
229+
logger.debug(f"Failed to import or initialize LifespanOn: {str(e)}")
230+
try:
231+
# Try the older location (uvicorn < 0.18.0)
232+
from uvicorn.lifespan.lifespan import Lifespan
239233
try:
240-
# Try the oldest location
241-
from uvicorn.lifespan import Lifespan
234+
# Try with just the app parameter
235+
self.lifespan = Lifespan(self.config.app)
236+
logger.info("Using Lifespan from uvicorn.lifespan.lifespan (single parameter)")
237+
except TypeError:
242238
try:
243-
# Try with logger parameter first
239+
# Try with two parameters
244240
self.lifespan = Lifespan(
245241
self.config.app,
246-
"auto",
247-
logger
242+
"auto"
248243
)
244+
logger.info("Using Lifespan from uvicorn.lifespan.lifespan (two parameters)")
249245
except TypeError:
250-
# If that fails, try without logger parameter
246+
# Try with three parameters
251247
self.lifespan = Lifespan(
252248
self.config.app,
253-
"auto"
249+
"auto",
250+
logger
254251
)
252+
logger.info("Using Lifespan from uvicorn.lifespan.lifespan (three parameters)")
253+
logger.info("Using Lifespan from uvicorn.lifespan.lifespan")
254+
except (ImportError, AttributeError, TypeError) as e:
255+
logger.debug(f"Failed to import or initialize Lifespan from lifespan.lifespan: {str(e)}")
256+
try:
257+
# Try the oldest location
258+
from uvicorn.lifespan import Lifespan
259+
try:
260+
# Try with just the app parameter
261+
self.lifespan = Lifespan(self.config.app)
262+
logger.info("Using Lifespan from uvicorn.lifespan (single parameter)")
263+
except TypeError:
264+
try:
265+
# Try with two parameters
266+
self.lifespan = Lifespan(
267+
self.config.app,
268+
"auto"
269+
)
270+
logger.info("Using Lifespan from uvicorn.lifespan (two parameters)")
271+
except TypeError:
272+
# Try with three parameters
273+
self.lifespan = Lifespan(
274+
self.config.app,
275+
"auto",
276+
logger
277+
)
278+
logger.info("Using Lifespan from uvicorn.lifespan (three parameters)")
255279
logger.info("Using Lifespan from uvicorn.lifespan")
256-
except (ImportError, AttributeError) as e:
257-
logger.debug(f"Failed to import Lifespan from uvicorn.lifespan: {str(e)}")
280+
except (ImportError, AttributeError, TypeError) as e:
281+
logger.debug(f"Failed to import or initialize Lifespan from uvicorn.lifespan: {str(e)}")
258282
try:
259283
# Try the newest location (uvicorn >= 0.21.0)
260284
from uvicorn.lifespan.state import LifespanState
261285
try:
262-
# Try with logger parameter first
286+
# Try with just the app parameter
287+
self.lifespan = LifespanState(self.config.app)
288+
logger.info("Using LifespanState from uvicorn.lifespan.state (single parameter)")
289+
except TypeError:
290+
# Try with logger parameter
263291
self.lifespan = LifespanState(
264292
self.config.app,
265293
logger=logger
266294
)
267-
except TypeError:
268-
# If that fails, try without logger parameter
269-
self.lifespan = LifespanState(
270-
self.config.app
271-
)
295+
logger.info("Using LifespanState from uvicorn.lifespan.state (with logger)")
272296
logger.info("Using LifespanState from uvicorn.lifespan.state")
273-
except (ImportError, AttributeError) as e:
274-
logger.debug(f"Failed to import LifespanState: {str(e)}")
297+
except (ImportError, AttributeError, TypeError) as e:
298+
logger.debug(f"Failed to import or initialize LifespanState: {str(e)}")
275299
# Fallback to no lifespan
276300
self.lifespan = None
277301
logger.warning("Could not initialize lifespan - server may not handle startup/shutdown events properly")

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="locallab",
8-
version="0.4.13",
8+
version="0.4.14",
99
packages=find_packages(include=["locallab", "locallab.*"]),
1010
install_requires=[
1111
"fastapi>=0.95.0,<1.0.0",

0 commit comments

Comments
 (0)