From 2834058d0d1450e9346717da70cbecf2dbf4a96c Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Sep 2026 22:34:37 +0000 Subject: [PATCH 1/6] ci: only run the release workflow on the upstream repository The Release workflow triggers on every push to master. On a fork that means semantic-release rewrites the version in pyproject.toml, commits the change to the default branch, tags it and then tries to publish the result to PyPI under the upstream package name. Gate the job on the repository name so forks keep a clean master. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PjZRpyoEfSCLjTx5ctzQmJ --- .github/workflows/publish.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8df3ca7f..2119bfad 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,6 +11,10 @@ permissions: jobs: release: + # Releases are cut from the upstream repository only. Without this guard the + # workflow also runs on forks, where semantic-release rewrites the version in + # pyproject.toml, commits to the default branch and attempts a PyPI upload. + if: github.repository == 'appium/python-client' runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 From 6be356bf4a3d1939b35ca5e5b971f2715afdad3b Mon Sep 17 00:00:00 2001 From: Dor-bl <59066376+Dor-bl@users.noreply.github.com> Date: Sun, 11 Oct 2026 22:18:33 +0000 Subject: [PATCH 2/6] test: add unit tests for setup_logger function --- test/unit/common/logger_test.py | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/unit/common/logger_test.py diff --git a/test/unit/common/logger_test.py b/test/unit/common/logger_test.py new file mode 100644 index 00000000..44d6ef88 --- /dev/null +++ b/test/unit/common/logger_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import sys + +from appium.common.logger import logger, setup_logger + + +def test_setup_logger_default(): + # Store initial state / handlers + handlers_before = list(logger.handlers) + + setup_logger() + + assert logger.propagate is False + assert logger.level == logging.NOTSET + assert len(logger.handlers) > len(handlers_before) + + new_handler = logger.handlers[-1] + assert isinstance(new_handler, logging.StreamHandler) + assert new_handler.stream == sys.stderr + + +def test_setup_logger_custom_level(): + setup_logger(level=logging.DEBUG) + + assert logger.propagate is False + assert logger.level == logging.DEBUG + assert len(logger.handlers) > 0 + + new_handler = logger.handlers[-1] + assert isinstance(new_handler, logging.StreamHandler) + assert new_handler.stream == sys.stderr From c581508c19879b0adeed908a2150b8c7a6b93090 Mon Sep 17 00:00:00 2001 From: Dor-bl <59066376+Dor-bl@users.noreply.github.com> Date: Sun, 11 Oct 2026 22:52:15 +0000 Subject: [PATCH 3/6] test: add unit tests for setup_logger function From e6e477f00793f7483a692d0749b3a4bb5b4c8d99 Mon Sep 17 00:00:00 2001 From: Dor-bl <59066376+Dor-bl@users.noreply.github.com> Date: Sun, 11 Oct 2026 23:34:35 +0000 Subject: [PATCH 4/6] test: add unit tests for setup_logger function From 34c5b1c29a1ff7bc8d4ec189ed5eb3fbfc82b5dd Mon Sep 17 00:00:00 2001 From: Dor-bl <59066376+Dor-bl@users.noreply.github.com> Date: Mon, 12 Oct 2026 00:33:12 +0000 Subject: [PATCH 5/6] test: add unit tests for setup_logger function From 8c9f9713a9cb4b1d9ab0f99f8641d99d260ae0b0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 8 Nov 2026 08:00:51 +0000 Subject: [PATCH 6/6] test: restore the shared logger after each setup_logger test setup_logger adds a stderr handler to the module-level appium logger on every call, so the tests left extra handlers and a DEBUG level behind for the rest of the suite. Snapshot and restore the logger in an autouse fixture, and assert exactly one handler is added. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012HCUdSWNJMojXCjBoxhg41 --- test/unit/common/logger_test.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/test/unit/common/logger_test.py b/test/unit/common/logger_test.py index 44d6ef88..6c53af12 100644 --- a/test/unit/common/logger_test.py +++ b/test/unit/common/logger_test.py @@ -14,31 +14,47 @@ import logging import sys +from collections.abc import Iterator + +import pytest from appium.common.logger import logger, setup_logger -def test_setup_logger_default(): - # Store initial state / handlers +@pytest.fixture(autouse=True) +def restore_logger() -> Iterator[None]: + # setup_logger mutates the shared module logger, so put it back after each test. + handlers = list(logger.handlers) + level = logger.level + propagate = logger.propagate + yield + logger.handlers[:] = handlers + logger.setLevel(level) + logger.propagate = propagate + + +def test_setup_logger_default() -> None: handlers_before = list(logger.handlers) setup_logger() assert logger.propagate is False assert logger.level == logging.NOTSET - assert len(logger.handlers) > len(handlers_before) + assert len(logger.handlers) == len(handlers_before) + 1 new_handler = logger.handlers[-1] assert isinstance(new_handler, logging.StreamHandler) assert new_handler.stream == sys.stderr -def test_setup_logger_custom_level(): +def test_setup_logger_custom_level() -> None: + handlers_before = list(logger.handlers) + setup_logger(level=logging.DEBUG) assert logger.propagate is False assert logger.level == logging.DEBUG - assert len(logger.handlers) > 0 + assert len(logger.handlers) == len(handlers_before) + 1 new_handler = logger.handlers[-1] assert isinstance(new_handler, logging.StreamHandler)