Spaces:
Running
Running
Update src/services/utils.py
Browse files- src/services/utils.py +7 -12
src/services/utils.py
CHANGED
|
@@ -13,7 +13,7 @@ from ..state import get_user_temp_dir
|
|
| 13 |
# --- Shared Utilities ---
|
| 14 |
|
| 15 |
def create_session(retries: int = 3, backoff_factor: float = 0.5, status_forcelist=(429, 500, 502, 503, 504)) -> requests.Session:
|
| 16 |
-
|
| 17 |
session = requests.Session()
|
| 18 |
retry = Retry(
|
| 19 |
total=retries,
|
|
@@ -29,7 +29,7 @@ def create_session(retries: int = 3, backoff_factor: float = 0.5, status_forceli
|
|
| 29 |
SESSION = create_session()
|
| 30 |
|
| 31 |
def short_num(n: float | int) -> str:
|
| 32 |
-
|
| 33 |
try:
|
| 34 |
n = float(n)
|
| 35 |
except Exception:
|
|
@@ -43,34 +43,29 @@ def short_num(n: float | int) -> str:
|
|
| 43 |
return str(round(n))
|
| 44 |
|
| 45 |
def now_str(fmt: str = "%d-%m-%Y %H:%M:%S") -> str:
|
|
|
|
| 46 |
return datetime.datetime.now().strftime(fmt)
|
| 47 |
|
| 48 |
# --- PDF Generation ---
|
| 49 |
|
| 50 |
def convert_html_to_pdf(html_content: str, user_id: str) -> Optional[Path]:
|
| 51 |
-
|
| 52 |
-
Uses Playwright (Local Chromium) to convert HTML to PDF.
|
| 53 |
-
Renders exactly as defined in CSS (Scale 1.0) on US Letter paper.
|
| 54 |
-
"""
|
| 55 |
print("\n Converting to PDF (Using Playwright)...")
|
| 56 |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
| 57 |
pdf_name = f"{timestamp}-crypto-analysis.pdf"
|
| 58 |
|
| 59 |
-
# Use user isolated directory
|
| 60 |
user_dir = get_user_temp_dir(user_id)
|
| 61 |
pdf_path = user_dir / pdf_name
|
| 62 |
|
| 63 |
try:
|
| 64 |
with sync_playwright() as p:
|
| 65 |
-
# 1. Launch Browser
|
| 66 |
browser = p.chromium.launch()
|
| 67 |
page = browser.new_page()
|
| 68 |
|
| 69 |
-
#
|
| 70 |
-
# wait_until="load" is safer to ensure styles load
|
| 71 |
page.set_content(html_content, wait_until="load")
|
| 72 |
|
| 73 |
-
#
|
| 74 |
page.pdf(
|
| 75 |
path=pdf_path,
|
| 76 |
format="Letter",
|
|
@@ -94,7 +89,7 @@ def convert_html_to_pdf(html_content: str, user_id: str) -> Optional[Path]:
|
|
| 94 |
# --- File Cleanup ---
|
| 95 |
|
| 96 |
def cleanup_after_analysis(spot_file: Optional[Path], futures_file: Optional[Path]) -> int:
|
| 97 |
-
|
| 98 |
files_cleaned = 0
|
| 99 |
now_date = datetime.datetime.now().date()
|
| 100 |
|
|
|
|
| 13 |
# --- Shared Utilities ---
|
| 14 |
|
| 15 |
def create_session(retries: int = 3, backoff_factor: float = 0.5, status_forcelist=(429, 500, 502, 503, 504)) -> requests.Session:
|
| 16 |
+
# Initialize requests session with exponential backoff and retry logic
|
| 17 |
session = requests.Session()
|
| 18 |
retry = Retry(
|
| 19 |
total=retries,
|
|
|
|
| 29 |
SESSION = create_session()
|
| 30 |
|
| 31 |
def short_num(n: float | int) -> str:
|
| 32 |
+
# Scale large integers into abbreviated strings (K, M, B)
|
| 33 |
try:
|
| 34 |
n = float(n)
|
| 35 |
except Exception:
|
|
|
|
| 43 |
return str(round(n))
|
| 44 |
|
| 45 |
def now_str(fmt: str = "%d-%m-%Y %H:%M:%S") -> str:
|
| 46 |
+
# Return current local system time in specified format
|
| 47 |
return datetime.datetime.now().strftime(fmt)
|
| 48 |
|
| 49 |
# --- PDF Generation ---
|
| 50 |
|
| 51 |
def convert_html_to_pdf(html_content: str, user_id: str) -> Optional[Path]:
|
| 52 |
+
# Render HTML string to PDF file using headless Chromium
|
|
|
|
|
|
|
|
|
|
| 53 |
print("\n Converting to PDF (Using Playwright)...")
|
| 54 |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
| 55 |
pdf_name = f"{timestamp}-crypto-analysis.pdf"
|
| 56 |
|
|
|
|
| 57 |
user_dir = get_user_temp_dir(user_id)
|
| 58 |
pdf_path = user_dir / pdf_name
|
| 59 |
|
| 60 |
try:
|
| 61 |
with sync_playwright() as p:
|
|
|
|
| 62 |
browser = p.chromium.launch()
|
| 63 |
page = browser.new_page()
|
| 64 |
|
| 65 |
+
# Ensure styles/assets are fully loaded before printing
|
|
|
|
| 66 |
page.set_content(html_content, wait_until="load")
|
| 67 |
|
| 68 |
+
# Export to US Letter with full background rendering and 0 margins
|
| 69 |
page.pdf(
|
| 70 |
path=pdf_path,
|
| 71 |
format="Letter",
|
|
|
|
| 89 |
# --- File Cleanup ---
|
| 90 |
|
| 91 |
def cleanup_after_analysis(spot_file: Optional[Path], futures_file: Optional[Path]) -> int:
|
| 92 |
+
# Delete temporary analysis files if they were modified on the current date
|
| 93 |
files_cleaned = 0
|
| 94 |
now_date = datetime.datetime.now().date()
|
| 95 |
|