Skip to content

Commit f45f19b

Browse files
committed
fix pytest warnings
Introduce a pytest warning filter and replace pkg_resources with importlib APIs for safer resource/version lookup. Add an asynccontextmanager lifespan for the FastAPI app to close the DB connection and terminate the LSP server on shutdown (replacing the deprecated on_event shutdown hook). Harden numeric routines: prevent divide-by-zero in RVI (returns 50 when denominator is zero) and clamp/guard ratios in cagr and calmar_ratio to avoid overflow/invalid results. Minor formatting/import cleanup in web module.
1 parent 3d7c7f4 commit f45f19b

File tree

6 files changed

+41
-15
lines changed

6 files changed

+41
-15
lines changed

conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def pytest_configure(config):
2+
config.addinivalue_line(
3+
"filterwarnings",
4+
"ignore:Please use `import python_multipart` instead.:PendingDeprecationWarning",
5+
)

jesse/__init__.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import warnings
2-
import pkg_resources
2+
from contextlib import asynccontextmanager
3+
from importlib.resources import files as importlib_files
34
from fastapi.responses import FileResponse
45
from fastapi.staticfiles import StaticFiles
56
from jesse.services.web import fastapi_app
@@ -13,21 +14,27 @@
1314
warnings.simplefilter(action='ignore', category=FutureWarning)
1415

1516
# get the jesse directory
16-
JESSE_DIR = pkg_resources.resource_filename(__name__, '')
17+
JESSE_DIR = str(importlib_files(__name__))
18+
19+
# define lifespan (replaces deprecated @on_event("shutdown"))
20+
@asynccontextmanager
21+
async def lifespan(app):
22+
yield
23+
from jesse.services.db import database
24+
database.close_connection()
25+
from jesse.services.lsp import terminate_lsp_server
26+
terminate_lsp_server()
27+
28+
fastapi_app.router.lifespan_context = lifespan
1729

1830
# load homepage
1931
@fastapi_app.get("/")
2032
async def index():
2133
return FileResponse(f"{JESSE_DIR}/static/index.html")
2234

2335

24-
@fastapi_app.on_event("shutdown")
25-
def shutdown_event():
26-
from jesse.services.db import database
27-
database.close_connection()
28-
# terminate the lsp server
29-
from jesse.services.lsp import terminate_lsp_server
30-
terminate_lsp_server()
36+
37+
3138

3239

3340
# # # # # # # # # # # # # # # # # # # # # # # # # # # #

jesse/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import time
22

33
import click
4-
import pkg_resources
4+
from importlib.metadata import version as get_version
55
import uvicorn
66

77
import jesse.helpers as jh
@@ -10,7 +10,7 @@
1010

1111

1212
@click.group()
13-
@click.version_option(pkg_resources.get_distribution("jesse").version)
13+
@click.version_option(get_version("jesse"))
1414
def cli() -> None:
1515
"""CLI entrypoint for Jesse."""
1616
pass
@@ -42,7 +42,7 @@ def run() -> None:
4242
╚════╝ ╚══════╝╚══════╝╚══════╝╚══════╝
4343
4444
"""
45-
version = pkg_resources.get_distribution("jesse").version
45+
version = get_version("jesse")
4646
print(welcome_message)
4747
print(f"Main Framework Version: {version}")
4848

jesse/indicators/rvi.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ def rvi(candles: np.ndarray, period: int = 10, ma_len: int = 14, matype: int = 1
4444
up_avg = ma(up, period=ma_len, matype=matype, sequential=True)
4545
down_avg = ma(down, period=ma_len, matype=matype, sequential=True)
4646

47-
result = 100 * (up_avg / (up_avg + down_avg))
47+
# Avoid division by zero
48+
denominator = up_avg + down_avg
49+
with np.errstate(divide='ignore', invalid='ignore'):
50+
result = np.where(denominator != 0, 100 * (up_avg / denominator), 50)
4851

4952
return result if sequential else result[-1]
5053

jesse/services/metrics.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,12 @@ def calmar_ratio(returns):
133133
if years == 0:
134134
return pd.Series([0.0])
135135

136-
cagr_ratio = (last_value / first_value) ** (1 / years) - 1
136+
# Prevent overflow by limiting the ratio
137+
ratio = last_value / first_value
138+
# Clip ratio to prevent overflow in power calculation
139+
ratio = np.clip(ratio, 1e-10, 1e10)
140+
with np.errstate(over='ignore', under='ignore'):
141+
cagr_ratio = ratio ** (1 / years) - 1
137142

138143
# Calculate Max Drawdown using cumulative returns
139144
cum_returns = (1 + returns).cumprod()
@@ -211,8 +216,13 @@ def cagr(returns, rf=0.0, compounded=True, periods=365):
211216
if years == 0:
212217
return pd.Series([0.0])
213218

219+
# Prevent overflow by limiting the ratio
220+
ratio = last_value / first_value
221+
# Clip ratio to prevent overflow in power calculation
222+
ratio = np.clip(ratio, 1e-10, 1e10)
214223
# Calculate CAGR using quantstats formula
215-
result = (last_value / first_value) ** (1 / years) - 1
224+
with np.errstate(over='ignore', under='ignore'):
225+
result = ratio ** (1 / years) - 1
216226

217227
return pd.Series([result])
218228

jesse/services/web.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from fastapi.middleware.cors import CORSMiddleware
55
from pydantic import BaseModel
66

7+
78
fastapi_app = FastAPI()
89

910
origins = [

0 commit comments

Comments
 (0)