diff --git a/screen_locker/screen_lock.py b/screen_locker/screen_lock.py index 3f376a3..ce06b47 100755 --- a/screen_locker/screen_lock.py +++ b/screen_locker/screen_lock.py @@ -19,7 +19,7 @@ if TYPE_CHECKING: from collections.abc import Callable from concurrent.futures import Future -from python_pkg.screen_locker._constants import ( # noqa: F401 +from python_pkg.screen_locker._constants import ( MAX_DISTANCE_KM, MAX_PACE_MIN_PER_KM, MAX_REPS, @@ -34,6 +34,23 @@ from python_pkg.screen_locker._constants import ( # noqa: F401 SUBMIT_DELAY_DEMO, SUBMIT_DELAY_PRODUCTION, ) + +__all__ = [ + "MAX_DISTANCE_KM", + "MAX_PACE_MIN_PER_KM", + "MAX_REPS", + "MAX_SETS", + "MAX_TIME_MINUTES", + "MAX_WEIGHT_KG", + "MIN_EXERCISE_NAME_LEN", + "PHONE_PENALTY_DELAY_DEMO", + "PHONE_PENALTY_DELAY_PRODUCTION", + "SICK_LOCKOUT_SECONDS", + "STRONGLIFTS_DB_REMOTE", + "SUBMIT_DELAY_DEMO", + "SUBMIT_DELAY_PRODUCTION", + "ScreenLocker", +] from python_pkg.screen_locker._phone_verification import PhoneVerificationMixin from python_pkg.screen_locker._shutdown import ShutdownMixin from python_pkg.screen_locker._ui_flows import UIFlowsMixin diff --git a/screen_locker/tests/test_adb_and_phone.py b/screen_locker/tests/test_adb_and_phone.py index 9c2b5e1..be60544 100644 --- a/screen_locker/tests/test_adb_and_phone.py +++ b/screen_locker/tests/test_adb_and_phone.py @@ -117,8 +117,12 @@ class TestAdbShell: ) -> None: """Test ADB shell without root.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(True, "output"), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(True, "output"), + ), ) success, output = locker._adb_shell("ls /sdcard") @@ -135,8 +139,12 @@ class TestAdbShell: ) -> None: """Test ADB shell with root.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(True, "output"), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(True, "output"), + ), ) success, _output = locker._adb_shell("ls /data", root=True) @@ -158,10 +166,14 @@ class TestIsPhoneConnected: ) -> None: """Test phone detected as connected.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=( - True, - "List of devices attached\nABC123\tdevice\n\n", + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=( + True, + "List of devices attached\nABC123\tdevice\n\n", + ), ), ) @@ -175,11 +187,19 @@ class TestIsPhoneConnected: ) -> None: """Test no phone connected.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(True, "List of devices attached\n\n"), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(True, "List of devices attached\n\n"), + ), ) - locker._try_wireless_reconnect = MagicMock( # type: ignore[method-assign] - return_value=False, + object.__setattr__( + locker, + "_try_wireless_reconnect", + MagicMock( + return_value=False, + ), ) assert locker._is_phone_connected() is False @@ -192,14 +212,22 @@ class TestIsPhoneConnected: ) -> None: """Test phone connected but offline.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=( - True, - "List of devices attached\nABC123\toffline\n\n", + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=( + True, + "List of devices attached\nABC123\toffline\n\n", + ), ), ) - locker._try_wireless_reconnect = MagicMock( # type: ignore[method-assign] - return_value=False, + object.__setattr__( + locker, + "_try_wireless_reconnect", + MagicMock( + return_value=False, + ), ) assert locker._is_phone_connected() is False @@ -212,11 +240,19 @@ class TestIsPhoneConnected: ) -> None: """Test ADB command failure.""" locker = create_locker(mock_tk, tmp_path) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(False, ""), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(False, ""), + ), ) - locker._try_wireless_reconnect = MagicMock( # type: ignore[method-assign] - return_value=False, + object.__setattr__( + locker, + "_try_wireless_reconnect", + MagicMock( + return_value=False, + ), ) assert locker._is_phone_connected() is False @@ -233,11 +269,19 @@ class TestFindHealthConnectDb: ) -> None: """Test StrongLifts DB pulled from device.""" locker = create_locker(mock_tk, tmp_path) - locker._adb_shell = MagicMock( # type: ignore[method-assign] - return_value=(True, ""), + object.__setattr__( + locker, + "_adb_shell", + MagicMock( + return_value=(True, ""), + ), ) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(True, ""), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(True, ""), + ), ) result = locker._pull_stronglifts_db() @@ -256,8 +300,12 @@ class TestFindHealthConnectDb: ) -> None: """Test returns None when cat command fails.""" locker = create_locker(mock_tk, tmp_path) - locker._adb_shell = MagicMock( # type: ignore[method-assign] - return_value=(False, ""), + object.__setattr__( + locker, + "_adb_shell", + MagicMock( + return_value=(False, ""), + ), ) assert locker._pull_stronglifts_db() is None @@ -270,11 +318,19 @@ class TestFindHealthConnectDb: ) -> None: """Test returns None when adb pull fails.""" locker = create_locker(mock_tk, tmp_path) - locker._adb_shell = MagicMock( # type: ignore[method-assign] - return_value=(True, ""), + object.__setattr__( + locker, + "_adb_shell", + MagicMock( + return_value=(True, ""), + ), ) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(False, ""), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(False, ""), + ), ) assert locker._pull_stronglifts_db() is None @@ -287,11 +343,19 @@ class TestFindHealthConnectDb: ) -> None: """Test uses the correct StrongLifts DB remote path.""" locker = create_locker(mock_tk, tmp_path) - locker._adb_shell = MagicMock( # type: ignore[method-assign] - return_value=(True, ""), + object.__setattr__( + locker, + "_adb_shell", + MagicMock( + return_value=(True, ""), + ), ) - locker._run_adb = MagicMock( # type: ignore[method-assign] - return_value=(True, ""), + object.__setattr__( + locker, + "_run_adb", + MagicMock( + return_value=(True, ""), + ), ) locker._pull_stronglifts_db() diff --git a/screen_locker/tests/test_init_and_log.py b/screen_locker/tests/test_init_and_log.py index feaa5c8..46095a3 100644 --- a/screen_locker/tests/test_init_and_log.py +++ b/screen_locker/tests/test_init_and_log.py @@ -263,7 +263,7 @@ class TestShowError: ) -> None: """Test show_error clears container and displays error.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker.show_error("Test error message") @@ -284,7 +284,7 @@ class TestRun: locker.run() - locker.root.mainloop.assert_called_once() # type: ignore[attr-defined] + locker.root.mainloop.assert_called_once() class TestMainEntry: @@ -324,11 +324,11 @@ class TestAdjustShutdownTimeLater: ) -> None: """Test _adjust_shutdown_time_later adds hours successfully.""" locker = create_locker(mock_tk, tmp_path) - locker._read_shutdown_config = MagicMock( # type: ignore[method-assign] - return_value=(21, 22, 8) + object.__setattr__( + locker, "_read_shutdown_config", MagicMock(return_value=(21, 22, 8)) ) - locker._write_shutdown_config = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_write_shutdown_config", MagicMock(return_value=True) ) result = locker._adjust_shutdown_time_later() @@ -344,11 +344,11 @@ class TestAdjustShutdownTimeLater: ) -> None: """Test _adjust_shutdown_time_later caps hours at 23.""" locker = create_locker(mock_tk, tmp_path) - locker._read_shutdown_config = MagicMock( # type: ignore[method-assign] - return_value=(22, 23, 8) + object.__setattr__( + locker, "_read_shutdown_config", MagicMock(return_value=(22, 23, 8)) ) - locker._write_shutdown_config = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_write_shutdown_config", MagicMock(return_value=True) ) result = locker._adjust_shutdown_time_later() @@ -365,8 +365,8 @@ class TestAdjustShutdownTimeLater: ) -> None: """Test _adjust_shutdown_time_later returns False if config missing.""" locker = create_locker(mock_tk, tmp_path) - locker._read_shutdown_config = MagicMock( # type: ignore[method-assign] - return_value=None + object.__setattr__( + locker, "_read_shutdown_config", MagicMock(return_value=None) ) result = locker._adjust_shutdown_time_later() @@ -381,8 +381,10 @@ class TestAdjustShutdownTimeLater: ) -> None: """Test _adjust_shutdown_time_later handles OSError.""" locker = create_locker(mock_tk, tmp_path) - locker._read_shutdown_config = MagicMock( # type: ignore[method-assign] - side_effect=OSError("permission denied") + object.__setattr__( + locker, + "_read_shutdown_config", + MagicMock(side_effect=OSError("permission denied")), ) result = locker._adjust_shutdown_time_later() diff --git a/screen_locker/tests/test_phone_check_unlock.py b/screen_locker/tests/test_phone_check_unlock.py index 599324d..dda7119 100644 --- a/screen_locker/tests/test_phone_check_unlock.py +++ b/screen_locker/tests/test_phone_check_unlock.py @@ -26,14 +26,26 @@ class TestVerifyPhoneWorkout: ) -> None: """Test workout verified on phone.""" locker = create_locker(mock_tk, tmp_path) - locker._is_phone_connected = MagicMock( # type: ignore[method-assign] - return_value=True, + object.__setattr__( + locker, + "_is_phone_connected", + MagicMock( + return_value=True, + ), ) - locker._pull_stronglifts_db = MagicMock( # type: ignore[method-assign] - return_value=tmp_path / "sl.db", + object.__setattr__( + locker, + "_pull_stronglifts_db", + MagicMock( + return_value=tmp_path / "sl.db", + ), ) - locker._count_today_workouts = MagicMock( # type: ignore[method-assign] - return_value=2, + object.__setattr__( + locker, + "_count_today_workouts", + MagicMock( + return_value=2, + ), ) status, message = locker._verify_phone_workout() @@ -49,14 +61,26 @@ class TestVerifyPhoneWorkout: ) -> None: """Test no workout found on phone.""" locker = create_locker(mock_tk, tmp_path) - locker._is_phone_connected = MagicMock( # type: ignore[method-assign] - return_value=True, + object.__setattr__( + locker, + "_is_phone_connected", + MagicMock( + return_value=True, + ), ) - locker._pull_stronglifts_db = MagicMock( # type: ignore[method-assign] - return_value=tmp_path / "sl.db", + object.__setattr__( + locker, + "_pull_stronglifts_db", + MagicMock( + return_value=tmp_path / "sl.db", + ), ) - locker._count_today_workouts = MagicMock( # type: ignore[method-assign] - return_value=0, + object.__setattr__( + locker, + "_count_today_workouts", + MagicMock( + return_value=0, + ), ) status, message = locker._verify_phone_workout() @@ -72,8 +96,12 @@ class TestVerifyPhoneWorkout: ) -> None: """Test no phone connected.""" locker = create_locker(mock_tk, tmp_path) - locker._is_phone_connected = MagicMock( # type: ignore[method-assign] - return_value=False, + object.__setattr__( + locker, + "_is_phone_connected", + MagicMock( + return_value=False, + ), ) status, _ = locker._verify_phone_workout() @@ -88,11 +116,19 @@ class TestVerifyPhoneWorkout: ) -> None: """Test error when StrongLifts DB cannot be pulled.""" locker = create_locker(mock_tk, tmp_path) - locker._is_phone_connected = MagicMock( # type: ignore[method-assign] - return_value=True, + object.__setattr__( + locker, + "_is_phone_connected", + MagicMock( + return_value=True, + ), ) - locker._pull_stronglifts_db = MagicMock( # type: ignore[method-assign] - return_value=None, + object.__setattr__( + locker, + "_pull_stronglifts_db", + MagicMock( + return_value=None, + ), ) status, message = locker._verify_phone_workout() @@ -112,11 +148,15 @@ class TestStartPhoneCheck: ) -> None: """Test _start_phone_check shows checking message and starts check.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker._verify_phone_workout = MagicMock( # type: ignore[method-assign] - return_value=("no_phone", "No phone"), + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__( + locker, + "_verify_phone_workout", + MagicMock( + return_value=("no_phone", "No phone"), + ), ) - locker._poll_phone_check = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_poll_phone_check", MagicMock()) locker._start_phone_check() @@ -132,8 +172,8 @@ class TestStartPhoneCheck: ) -> None: """Test verified result shows success screen then unlocks via after().""" locker = create_locker(mock_tk, tmp_path) - locker.unlock_screen = MagicMock() # type: ignore[method-assign] - locker.root.after = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "unlock_screen", MagicMock()) + object.__setattr__(locker.root, "after", MagicMock()) locker._handle_startup_phone_result("verified", "Workout verified! (1 session)") @@ -150,7 +190,7 @@ class TestStartPhoneCheck: ) -> None: """Test not_verified result shows blocking screen with buttons.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker._handle_startup_phone_result( "not_verified", "No workout found on phone today" ) @@ -165,7 +205,7 @@ class TestStartPhoneCheck: ) -> None: """Test no_phone result triggers penalty with ask_workout_done as callback.""" locker = create_locker(mock_tk, tmp_path) - locker._show_phone_penalty = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_show_phone_penalty", MagicMock()) locker._handle_startup_phone_result("no_phone", "No phone") @@ -181,7 +221,7 @@ class TestStartPhoneCheck: ) -> None: """Test error result triggers penalty with ask_workout_done as callback.""" locker = create_locker(mock_tk, tmp_path) - locker._show_phone_penalty = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_show_phone_penalty", MagicMock()) locker._handle_startup_phone_result("error", "DB not found") @@ -199,8 +239,8 @@ class TestStartPhoneCheck: locker = create_locker(mock_tk, tmp_path) mock_future: MagicMock = MagicMock() mock_future.done.return_value = False - locker._phone_future = mock_future # type: ignore[assignment] - locker.root.after = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_phone_future", mock_future) + object.__setattr__(locker.root, "after", MagicMock()) locker._poll_phone_check() @@ -217,8 +257,8 @@ class TestStartPhoneCheck: mock_future: MagicMock = MagicMock() mock_future.done.return_value = True mock_future.result.return_value = ("no_phone", "No phone") - locker._phone_future = mock_future # type: ignore[assignment] - locker._handle_startup_phone_result = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_phone_future", mock_future) + object.__setattr__(locker, "_handle_startup_phone_result", MagicMock()) locker._poll_phone_check() @@ -240,7 +280,7 @@ class TestAttemptUnlock: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "strength"} - locker.unlock_screen = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "unlock_screen", MagicMock()) locker._attempt_unlock() @@ -258,7 +298,7 @@ class TestShowPhonePenalty: ) -> None: """Test demo mode uses short penalty delay.""" locker = create_locker(mock_tk, tmp_path, demo_mode=True) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker._show_phone_penalty("test message") @@ -273,7 +313,7 @@ class TestShowPhonePenalty: ) -> None: """Test production mode uses long penalty delay.""" locker = create_locker(mock_tk, tmp_path, demo_mode=False) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker._show_phone_penalty("test message") @@ -294,7 +334,7 @@ class TestShowPhonePenalty: assert locker.phone_penalty_remaining == 4 locker.phone_penalty_label.config.assert_called_once_with(text="5") - locker.root.after.assert_called() # type: ignore[attr-defined] + locker.root.after.assert_called() def test_update_phone_penalty_at_zero( self, @@ -308,8 +348,8 @@ class TestShowPhonePenalty: locker.workout_data = {"type": "strength"} locker.phone_penalty_remaining = 0 locker.phone_penalty_label = MagicMock() - locker.unlock_screen = MagicMock() # type: ignore[method-assign] - locker._phone_penalty_done_fn = locker.unlock_screen # type: ignore[attr-defined] + object.__setattr__(locker, "unlock_screen", MagicMock()) + locker._phone_penalty_done_fn = locker.unlock_screen locker._update_phone_penalty() @@ -329,8 +369,8 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "running"} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=True) ) locker.unlock_screen() @@ -347,8 +387,8 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "strength"} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=True) ) locker.unlock_screen() @@ -365,8 +405,8 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "phone_verified"} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=True) ) locker.unlock_screen() @@ -383,8 +423,8 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "sick_day"} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=True) ) locker.unlock_screen() @@ -401,8 +441,8 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=True + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=True) ) locker.unlock_screen() @@ -419,12 +459,12 @@ class TestUnlockScreenShutdownAdjustment: locker = create_locker(mock_tk, tmp_path) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "running"} - locker._adjust_shutdown_time_later = MagicMock( # type: ignore[method-assign] - return_value=False + object.__setattr__( + locker, "_adjust_shutdown_time_later", MagicMock(return_value=False) ) # Should not raise, should continue with unlock locker.unlock_screen() locker._adjust_shutdown_time_later.assert_called_once() - locker.root.after.assert_called() # type: ignore[attr-defined] + locker.root.after.assert_called() diff --git a/screen_locker/tests/test_ui_and_timers.py b/screen_locker/tests/test_ui_and_timers.py index 209b104..cbad5bb 100644 --- a/screen_locker/tests/test_ui_and_timers.py +++ b/screen_locker/tests/test_ui_and_timers.py @@ -33,7 +33,7 @@ class TestUITransitions: # Set up mock children mock_child1 = MagicMock() mock_child2 = MagicMock() - locker.container.winfo_children.return_value = [ # type: ignore[attr-defined] + locker.container.winfo_children.return_value = [ mock_child1, mock_child2, ] @@ -57,7 +57,7 @@ class TestUITransitions: locker.unlock_screen() # Check that after() was called to schedule close - locker.root.after.assert_called() # type: ignore[attr-defined] + locker.root.after.assert_called() def test_lockout_starts_countdown( self, @@ -85,7 +85,7 @@ class TestUITransitions: locker.close() - locker.root.destroy.assert_called_once() # type: ignore[attr-defined] + locker.root.destroy.assert_called_once() mock_sys_exit.assert_called_with(0) @@ -106,9 +106,7 @@ class TestTimerLogic: locker.update_lockout_countdown() assert locker.remaining_time == 4 - locker.root.after.assert_called_with( # type: ignore[attr-defined] - 1000, locker.update_lockout_countdown - ) + locker.root.after.assert_called_with(1000, locker.update_lockout_countdown) def test_update_lockout_countdown_at_zero( self, @@ -120,7 +118,7 @@ class TestTimerLogic: locker = create_locker(mock_tk, tmp_path) locker.remaining_time = 0 locker.countdown_label = MagicMock() - locker.ask_workout_done = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "ask_workout_done", MagicMock()) locker.update_lockout_countdown() @@ -142,7 +140,7 @@ class TestTimerLogic: locker.update_submit_timer() assert locker.submit_unlock_time == 4 - locker.root.after.assert_called() # type: ignore[attr-defined] + locker.root.after.assert_called() def test_update_submit_timer_enables_when_filled( self, @@ -181,9 +179,7 @@ class TestTimerLogic: locker.update_submit_timer() - locker.root.after.assert_called_with( # type: ignore[attr-defined] - 1000, locker.check_entries_filled - ) + locker.root.after.assert_called_with(1000, locker.check_entries_filled) def test_update_submit_timer_handles_tcl_error( self, @@ -235,9 +231,7 @@ class TestTimerLogic: locker.check_entries_filled() - locker.root.after.assert_called_with( # type: ignore[attr-defined] - 1000, locker.check_entries_filled - ) + locker.root.after.assert_called_with(1000, locker.check_entries_filled) def test_check_entries_filled_handles_tcl_error( self, @@ -267,7 +261,7 @@ class TestAskWorkoutType: ) -> None: """Test ask_workout_type creates running and strength buttons.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker.ask_workout_type() @@ -288,8 +282,8 @@ class TestAskRunningDetails: ) -> None: """Test ask_running_details sets workout type to running.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_running_details() @@ -304,8 +298,8 @@ class TestAskRunningDetails: ) -> None: """Test ask_running_details creates entry fields.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_running_details() @@ -323,8 +317,8 @@ class TestAskRunningDetails: ) -> None: """Test ask_running_details initializes submit timer.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_running_details() @@ -343,8 +337,8 @@ class TestAskStrengthDetails: ) -> None: """Test ask_strength_details sets workout type to strength.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_strength_details() @@ -359,8 +353,8 @@ class TestAskStrengthDetails: ) -> None: """Test ask_strength_details creates entry fields.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_strength_details() @@ -380,8 +374,8 @@ class TestAskStrengthDetails: ) -> None: """Test ask_strength_details initializes submit timer.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_strength_details() @@ -396,8 +390,8 @@ class TestAskStrengthDetails: ) -> None: """Test production mode uses longer submit delay.""" locker = create_locker(mock_tk, tmp_path, demo_mode=False) - locker.clear_container = MagicMock() # type: ignore[method-assign] - locker.update_submit_timer = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) + object.__setattr__(locker, "update_submit_timer", MagicMock()) locker.ask_strength_details() @@ -415,7 +409,7 @@ class TestAskWorkoutDone: ) -> None: """Test ask_workout_done creates yes/no buttons.""" locker = create_locker(mock_tk, tmp_path) - locker.clear_container = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "clear_container", MagicMock()) locker.ask_workout_done() diff --git a/screen_locker/tests/test_verify_data.py b/screen_locker/tests/test_verify_data.py index 05a064b..978539c 100644 --- a/screen_locker/tests/test_verify_data.py +++ b/screen_locker/tests/test_verify_data.py @@ -31,7 +31,7 @@ class TestVerifyRunningData: setup_running_entries(locker, RunningData("5", "25", "5")) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "running"} - locker._attempt_unlock = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_attempt_unlock", MagicMock()) locker.verify_running_data() @@ -46,7 +46,7 @@ class TestVerifyRunningData: """Test zero distance is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("0", "25", "5")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -62,7 +62,7 @@ class TestVerifyRunningData: """Test distance over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("150", "600", "4")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -78,7 +78,7 @@ class TestVerifyRunningData: """Test zero time is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("5", "0", "5")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -94,7 +94,7 @@ class TestVerifyRunningData: """Test time over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("5", "700", "5")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -110,7 +110,7 @@ class TestVerifyRunningData: """Test zero pace is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("5", "25", "0")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -126,7 +126,7 @@ class TestVerifyRunningData: """Test pace over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("5", "25", "25")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -143,7 +143,7 @@ class TestVerifyRunningData: # 5km in 25 min should be 5 min/km, but we say 10 min/km locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("5", "25", "10")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -159,7 +159,7 @@ class TestVerifyRunningData: """Test non-numeric input is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_running_entries(locker, RunningData("abc", "25", "5")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_running_data() @@ -181,7 +181,7 @@ class TestVerifyStrengthData: setup_strength_entries(locker, StrengthData("Squat", "3", "10", "50", "1500")) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "strength"} - locker._attempt_unlock = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_attempt_unlock", MagicMock()) locker.verify_strength_data() @@ -201,7 +201,7 @@ class TestVerifyStrengthData: ) locker.log_file = tmp_path / "workout_log.json" locker.workout_data = {"type": "strength"} - locker._attempt_unlock = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "_attempt_unlock", MagicMock()) locker.verify_strength_data() @@ -219,7 +219,7 @@ class TestVerifyStrengthData: locker, StrengthData("Squat, Bench", "3", "10, 8", "50, 40", "2000"), ) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -235,7 +235,7 @@ class TestVerifyStrengthData: """Test short exercise names are rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Sq", "3", "10", "50", "1500")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -251,7 +251,7 @@ class TestVerifyStrengthData: """Test zero sets is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "0", "10", "50", "0")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -267,7 +267,7 @@ class TestVerifyStrengthData: """Test sets over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "25", "10", "50", "12500")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -283,7 +283,7 @@ class TestVerifyStrengthData: """Test zero reps is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "3", "0", "50", "0")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -299,7 +299,7 @@ class TestVerifyStrengthData: """Test reps over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "3", "150", "50", "22500")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -315,7 +315,7 @@ class TestVerifyStrengthData: """Test negative weight is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "3", "10", "-10", "-300")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -331,7 +331,7 @@ class TestVerifyStrengthData: """Test weight over max is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "3", "10", "600", "18000")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -347,7 +347,7 @@ class TestVerifyStrengthData: """Test total weight mismatch is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "3", "10", "50", "3000")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data() @@ -363,7 +363,7 @@ class TestVerifyStrengthData: """Test invalid format is rejected.""" locker = create_locker(mock_tk, tmp_path) setup_strength_entries(locker, StrengthData("Squat", "abc", "10", "50", "1500")) - locker.show_error = MagicMock() # type: ignore[method-assign] + object.__setattr__(locker, "show_error", MagicMock()) locker.verify_strength_data()