From 7f7cbfe65ef83ceec605c05fed3be56cdd56457c Mon Sep 17 00:00:00 2001 From: Edward Betts <edward@4angle.com> Date: Fri, 21 Feb 2025 17:00:44 -0500 Subject: [PATCH] feat: add logging to control output based on TTY context - Replaced print() with logging.info() and logging.error() - Added logging configuration to output INFO messages only in TTY - Ensured ERROR messages are always logged to stdout, including cron runs - Used sys.stdout.isatty() to detect terminal context - Maintained existing functionality with updated config and SMTP setup --- check.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/check.py b/check.py index 2eba7ea..7dd2d34 100755 --- a/check.py +++ b/check.py @@ -2,7 +2,9 @@ import configparser import json +import logging import smtplib +import sys from datetime import date from email.mime.text import MIMEText from pathlib import Path @@ -33,6 +35,22 @@ DATA_DIR = Path.home() / "lib" / "data" DATA_FILE = DATA_DIR / "ferrocarril_dates.json" URL = "https://ferrocarrilcentral.com.pe/appfcca/" +# Configure logging +logger = logging.getLogger("FerrocarrilMonitor") +logger.setLevel(logging.INFO) + +# Handler for stdout +handler = logging.StreamHandler(sys.stdout) +formatter = logging.Formatter("%(levelname)s: %(message)s") +handler.setFormatter(formatter) + +# Only log INFO when in TTY, always log ERROR +if sys.stdout.isatty(): + logger.addHandler(handler) +else: + handler.setLevel(logging.ERROR) + logger.addHandler(handler) + def parse_dates(html_content: str) -> list[date]: doc = lxml.html.fromstring(html_content) @@ -57,7 +75,7 @@ def parse_dates(html_content: str) -> list[date]: dates.append(date(year, month, day)) except (IndexError, ValueError) as e: - print(f"Error parsing date: {e}") + logger.error(f"Error parsing date: {e}") continue return dates @@ -87,7 +105,7 @@ def load_config() -> configparser.ConfigParser: config = configparser.ConfigParser() config.read(CONFIG_FILE) if "mail" not in config: - raise ValueError(f"Config file {CONFIG_FILE} must have an [email] section") + raise ValueError(f"Config file {CONFIG_FILE} must have an [mail] section") return config @@ -105,9 +123,10 @@ def send_email(new_dates: list[date], config: configparser.ConfigParser) -> None try: with smtplib.SMTP(email_config["smtp_host"]) as server: server.send_message(msg) - print("Email sent successfully") + logger.info("Email sent successfully") except Exception as e: - print(f"Failed to send email: {e}") + logger.error(f"Failed to send email: {e}") + raise # Re-raise to prevent saving dates if email fails def main() -> None: @@ -121,13 +140,13 @@ def main() -> None: response.raise_for_status() html_content = response.text except requests.RequestException as e: - print(f"Failed to fetch webpage: {e}") + logger.error(f"Failed to fetch webpage: {e}") return # Parse current dates current_dates = set(parse_dates(html_content)) if not current_dates: - print("No dates found on webpage") + logger.info("No dates found on webpage") return # Load previous dates @@ -137,7 +156,7 @@ def main() -> None: new_dates = [d for d in current_dates if d.isoformat() not in previous_dates] if new_dates: - print(f"New dates found: {new_dates}") + logger.info(f"New dates found: {new_dates}") try: config = load_config() send_email(new_dates, config) @@ -145,11 +164,11 @@ def main() -> None: list(current_dates) ) # Update stored dates only if email succeeds except FileNotFoundError as e: - print(e) + logger.error(str(e)) except Exception as e: - print(f"Error in processing: {e}") + logger.error(f"Error in processing: {e}") else: - print("No new dates found") + logger.info("No new dates found") if __name__ == "__main__":