diff --git a/.actrc b/.actrc index 9f0f6f5..6db524e 100644 --- a/.actrc +++ b/.actrc @@ -6,4 +6,4 @@ -W .github/workflows/build.yml -j build --matrix os:ubuntu-latest ---matrix PYTHON_VERSION:3.13.5 +--matrix PYTHON_VERSION:3.14 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 19fce0a..8d59020 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,16 +74,16 @@ jobs: PYTHON_VERSION: "3.10" PUBLISH_RELEASE: false - os: macos-13 # X86 - PYTHON_VERSION: "3.13.5" + PYTHON_VERSION: "3.14" PUBLISH_RELEASE: true - os: macos-latest # ARM - PYTHON_VERSION: "3.13.5" + PYTHON_VERSION: "3.14" PUBLISH_RELEASE: true - os: ubuntu-latest - PYTHON_VERSION: "3.13.5" + PYTHON_VERSION: "3.14" PUBLISH_RELEASE: true - os: windows-latest - PYTHON_VERSION: "3.13.5" + PYTHON_VERSION: "3.14" PUBLISH_RELEASE: true runs-on: ${{ matrix.os }} # https://github.com/actions/runner-images#available-images diff --git a/docker/image/Dockerfile b/docker/image/Dockerfile index e580016..182b3db 100644 --- a/docker/image/Dockerfile +++ b/docker/image/Dockerfile @@ -48,7 +48,7 @@ EOF ###################### # https://hub.docker.com/_/python/tags?name=3-slim -FROM python:3.13-slim AS build-image +FROM python:3.14-slim AS build-image ARG DEBIAN_FRONTEND=noninteractive ARG LC_ALL=C diff --git a/pdm.lock b/pdm.lock index 331c718..5bb5ade 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,10 +5,10 @@ groups = ["default", "dev"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:eecf66c65d3597b333bec94ec2b8efa5fba4f96d772c466ab6023550b8d7dd3a" +content_hash = "sha256:76ff52a743ae07eb656f450998dd67f0bc441ce4e1c73d550c4b63434eca6541" [[metadata.targets]] -requires_python = ">=3.10,<3.14" +requires_python = ">=3.10,<3.15" [[package]] name = "altgraph" @@ -754,6 +754,12 @@ files = [ {file = "mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d"}, {file = "mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba"}, {file = "mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544"}, + {file = "mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce"}, + {file = "mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d"}, + {file = "mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c"}, + {file = "mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb"}, + {file = "mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075"}, + {file = "mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf"}, {file = "mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e"}, {file = "mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b"}, ] diff --git a/pyproject.toml b/pyproject.toml index 9207389..4e2cbec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ classifiers = [ # https://pypi.org/classifiers/ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10" ] -requires-python = ">=3.10,<3.14" +requires-python = ">=3.10,<3.15" dependencies = [ "certifi", "colorama", diff --git a/src/kleinanzeigen_bot/utils/web_scraping_mixin.py b/src/kleinanzeigen_bot/utils/web_scraping_mixin.py index 9a6641f..e9fa50d 100644 --- a/src/kleinanzeigen_bot/utils/web_scraping_mixin.py +++ b/src/kleinanzeigen_bot/utils/web_scraping_mixin.py @@ -249,6 +249,9 @@ class WebScrapingMixin: self.browser = await nodriver.start(cfg) LOG.info("New Browser session is %s", self.browser.websocket_url) except Exception as e: + # Clean up any resources that were created during setup + self._cleanup_session_resources() + error_msg = str(e) if "root" in error_msg.lower(): LOG.error("Failed to start browser. This error often occurs when:") @@ -418,6 +421,12 @@ class WebScrapingMixin: p.kill() # terminate orphaned browser processes self.browser = None # pyright: ignore[reportAttributeAccessIssue] + def _cleanup_session_resources(self) -> None: + """Clean up any resources that were created during session setup.""" + # Reset browser and page references + self.browser = None # pyright: ignore[reportAttributeAccessIssue] + self.page = None # pyright: ignore[reportAttributeAccessIssue] + def get_compatible_browser(self) -> str: match platform.system(): case "Linux": diff --git a/tests/unit/test_web_scraping_mixin.py b/tests/unit/test_web_scraping_mixin.py index 5183b6d..fbdc61d 100644 --- a/tests/unit/test_web_scraping_mixin.py +++ b/tests/unit/test_web_scraping_mixin.py @@ -787,7 +787,7 @@ class TestWebScrapingBrowserConfiguration: monkeypatch.setattr(nodriver, "start", mock_start_fail) monkeypatch.setattr(nodriver.core.config, "Config", DummyConfig) # type: ignore[unused-ignore,reportAttributeAccessIssue] - monkeypatch.setattr(os.path, "exists", lambda p: True) + # Don't mock os.path.exists globally - let the file operations work normally # Attempt to create a session scraper = WebScrapingMixin()