From c0a2ff00ad7811401bbbc42d9eb0b8fd08180d21 Mon Sep 17 00:00:00 2001 From: Mandar Patil Date: Wed, 7 Aug 2024 10:30:00 -0700 Subject: [PATCH] Fixed retry_login_interval < 0 for empty keyring (#251) --- src/sync.py | 9 +++++--- tests/test_sync.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/sync.py b/src/sync.py index 2bc7d03f..3e00a0a5 100644 --- a/src/sync.py +++ b/src/sync.py @@ -100,12 +100,12 @@ def sync(): LOGGER.error("Error: 2FA is required. Please log in.") # Retry again sleep_for = config_parser.get_retry_login_interval(config=config) - next_sync = ( - datetime.datetime.now() + datetime.timedelta(seconds=sleep_for) - ).strftime("%c") if sleep_for < 0: LOGGER.info("retry_login_interval is < 0, exiting ...") break + next_sync = ( + datetime.datetime.now() + datetime.timedelta(seconds=sleep_for) + ).strftime("%c") LOGGER.info(f"Retrying login at {next_sync} ...") last_send = notify.send( config=config, username=username, last_send=last_send @@ -117,6 +117,9 @@ def sync(): "Password is not stored in keyring. Please save the password in keyring." ) sleep_for = config_parser.get_retry_login_interval(config=config) + if sleep_for < 0: + LOGGER.info("retry_login_interval is < 0, exiting ...") + break next_sync = ( datetime.datetime.now() + datetime.timedelta(seconds=sleep_for) ).strftime("%c") diff --git a/tests/test_sync.py b/tests/test_sync.py index bcee6016..2e01c493 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -7,6 +7,8 @@ from io import StringIO from unittest.mock import patch +from icloudpy import exceptions + import tests from src import ENV_ICLOUD_PASSWORD_KEY, read_config, sync from tests import data @@ -417,3 +419,52 @@ def test_sync_negative_retry_login_interval( ) > 0 ) + + @patch("src.sync.sleep") + @patch( + target="keyring.get_password", + side_effect=exceptions.ICloudPyNoStoredPasswordAvailableException, + ) + @patch( + target="src.config_parser.get_username", return_value=data.AUTHENTICATED_USER + ) + @patch("icloudpy.ICloudPyService") + @patch("src.sync.read_config") + @patch("requests.post", side_effect=tests.mocked_usage_post) + def test_sync_negative_retry_login_interval_without_keyring_password( + self, + mock_usage_post, + mock_read_config, + mock_service, + mock_get_username, + mock_get_password, + mock_sleep, + ): + """Test for negative retry login interval.""" + config = self.config.copy() + config["app"]["credentials"]["retry_login_interval"] = -1 + mock_read_config.return_value = config + if ENV_ICLOUD_PASSWORD_KEY in os.environ: + del os.environ[ENV_ICLOUD_PASSWORD_KEY] + + with self.assertLogs() as captured: + mock_get_username.return_value = data.REQUIRES_2FA_USER + mock_sleep.side_effect = [ + None, + ] + sync.sync() + self.assertTrue(len(captured.records) > 1) + self.assertTrue( + len([e for e in captured[1] if "Password is not stored in keyring." in e]) + > 0 + ) + self.assertTrue( + len( + [ + e + for e in captured[1] + if "retry_login_interval is < 0, exiting ..." in e + ] + ) + > 0 + )