From 7169975d2aeb77b89d4b800d89aa748d4494371d Mon Sep 17 00:00:00 2001 From: sebthom Date: Sun, 9 Feb 2025 04:23:24 +0100 Subject: [PATCH] fix: logging file handler not closed on bot shutdown. Fixes #405 --- src/kleinanzeigen_bot/__init__.py | 3 ++- tests/unit/test_bot.py | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/kleinanzeigen_bot/__init__.py b/src/kleinanzeigen_bot/__init__.py index 0037c8d..ecc9c69 100644 --- a/src/kleinanzeigen_bot/__init__.py +++ b/src/kleinanzeigen_bot/__init__.py @@ -60,6 +60,7 @@ class KleinanzeigenBot(WebScrapingMixin): def __del__(self) -> None: if self.file_log: LOG_ROOT.removeHandler(self.file_log) + self.file_log.close() self.close_browser_session() def get_version(self) -> str: @@ -707,7 +708,7 @@ class KleinanzeigenBot(WebScrapingMixin): await self.web_sleep(1) # Wait for city dropdown to populate options = await self.web_find_all(By.CSS_SELECTOR, "#pstad-citychsr option") for option in options: - option_text = await self.web_text(By.CSS_SELECTOR, "option", parent=option) + option_text = await self.web_text(By.CSS_SELECTOR, "option", parent = option) if option_text == ad_cfg["contact"]["location"]: await self.web_select(By.ID, "pstad-citychsr", option_text) break diff --git a/tests/unit/test_bot.py b/tests/unit/test_bot.py index 2eb6fb0..79f1809 100644 --- a/tests/unit/test_bot.py +++ b/tests/unit/test_bot.py @@ -3,11 +3,12 @@ SPDX-FileCopyrightText: © Sebastian Thomschke and contributors SPDX-License-Identifier: AGPL-3.0-or-later SPDX-ArtifactOfProjectHomePage: https://github.com/Second-Hand-Friends/kleinanzeigen-bot/ """ -import pytest +import gc, pytest from kleinanzeigen_bot import KleinanzeigenBot class TestKleinanzeigenBot: + @pytest.fixture def bot(self) -> KleinanzeigenBot: return KleinanzeigenBot() @@ -31,3 +32,19 @@ class TestKleinanzeigenBot: version = bot.get_version() assert isinstance(version, str) assert len(version) > 0 + + def test_file_log_closed_after_bot_shutdown(self) -> None: + """Ensure the file log handler is properly closed after the bot is deleted""" + + # Directly instantiate the bot to control its lifecycle within the test + bot = KleinanzeigenBot() + + bot.configure_file_logging() + file_log = bot.file_log + assert not file_log.stream.closed # type: ignore[union-attr] + + # Delete and garbage collect the bot instance to ensure the destructor (__del__) is called + del bot + gc.collect() + + assert file_log.stream is None # type: ignore[union-attr]