def test_get_username_given(self): config = read_config(config_path=tests.CONFIG_PATH) # Given username self.assertEqual( config["app"]["credentials"]["username"], config_parser.get_username(config=config), )
def test_get_retry_login_interval(self): # Given interval config = read_config(config_path=tests.CONFIG_PATH) self.assertEqual( config["app"]["credentials"]["retry_login_interval"], config_parser.get_retry_login_interval(config=config), )
def setUp(self) -> None: self.config = read_config(config_path=tests.CONFIG_PATH) self.root_dir = tests.TEMP_DIR self.config["app"]["root"] = self.root_dir os.makedirs(tests.TEMP_DIR, exist_ok=True) self.service = data.ICloudPyServiceMock(data.AUTHENTICATED_USER, data.VALID_PASSWORD)
def test_get_remove_obsolete(self): config = read_config(config_path=tests.CONFIG_PATH) config["drive"]["remove_obsolete"] = True self.assertTrue(config_parser.get_drive_remove_obsolete(config=config)) del config["drive"]["remove_obsolete"] self.assertFalse( config_parser.get_drive_remove_obsolete(config=config))
def test_get_photos_sync_interval(self): # Given sync interval config = read_config(config_path=tests.CONFIG_PATH) self.assertEqual( config["photos"]["sync_interval"], config_parser.get_photos_sync_interval(config=config), )
def test_get_photos_sync_interval_default(self): # Default sync interval config = read_config(config_path=tests.CONFIG_PATH) del config["photos"]["sync_interval"] self.assertEqual( DEFAULT_SYNC_INTERVAL_SEC, config_parser.get_photos_sync_interval(config=config), )
def test_get_retry_login_interval_default(self): # Default interval config = read_config(config_path=tests.CONFIG_PATH) del (config["app"]["credentials"]["retry_login_interval"], ) self.assertEqual( DEFAULT_RETRY_LOGIN_INTERVAL_SEC, config_parser.get_retry_login_interval(config=config), )
def setUp(self) -> None: self.config = read_config(config_path=tests.CONFIG_PATH) self.root = tests.PHOTOS_DIR self.destination_path = self.root os.makedirs(self.destination_path, exist_ok=True) self.service = data.ICloudPyServiceMock(data.AUTHENTICATED_USER, data.VALID_PASSWORD)
def test_get_photos_filters(self): config = read_config(config_path=tests.CONFIG_PATH) expected_albums = ["Screenshots", "Selfies"] expected_file_sizes = ["original", "medium", "thumb"] config["photos"]["filters"]["albums"] = expected_albums config["photos"]["filters"]["file_sizes"] = expected_file_sizes actual = config_parser.get_photos_filters(config=config) self.assertIsNotNone(actual) self.assertListEqual(actual["albums"], expected_albums) self.assertListEqual(actual["file_sizes"], expected_file_sizes)
def test_prepare_photos_destination(self): config = read_config(config_path=tests.CONFIG_PATH) # Given destination actual = config_parser.prepare_photos_destination(config=config) self.assertEqual( os.path.abspath( os.path.join(config["app"]["root"], config["photos"]["destination"])), actual, ) self.assertTrue(os.path.exists(actual)) self.assertTrue(os.path.isdir(actual)) os.rmdir(actual)
def setUp(self) -> None: self.config = read_config(config_path=tests.CONFIG_PATH) self.filters = self.config["drive"]["filters"] self.root = tests.DRIVE_DIR self.destination_path = self.root os.makedirs(self.destination_path, exist_ok=True) self.service = data.ICloudPyServiceMock( data.AUTHENTICATED_USER, data.VALID_PASSWORD ) self.drive = self.service.drive self.items = self.drive.dir() self.file_item = self.drive[self.items[4]]["Test"]["Scanned document 1.pdf"] self.file_name = "Scanned document 1.pdf" self.local_file_path = os.path.join(self.destination_path, self.file_name)
def test_prepare_drive_destination_default(self): config = read_config(config_path=tests.CONFIG_PATH) # Default destination del config["drive"]["destination"] actual = config_parser.prepare_drive_destination(config=config) self.assertEqual( os.path.abspath( os.path.join( DEFAULT_ROOT_DESTINATION, DEFAULT_DRIVE_DESTINATION, )), actual, ) self.assertTrue(os.path.exists(actual)) self.assertTrue(os.path.isdir(actual)) os.rmdir(actual)
def test_prepare_photos_destination_default(self): config = read_config(config_path=tests.CONFIG_PATH) # Default destination del config["photos"]["destination"] actual = config_parser.prepare_photos_destination(config=config) self.assertEqual( os.path.abspath( os.path.join( DEFAULT_ROOT_DESTINATION, DEFAULT_PHOTOS_DESTINATION, )), actual, ) self.assertTrue(os.path.exists(actual)) self.assertTrue(os.path.isdir(actual)) shutil.rmtree(actual)
def test_read_config_overridden_config_path(self): # Overridden config path self.assertIsNotNone(read_config(config_path=tests.CONFIG_PATH))
def test_read_config_none_config_path(self): # None config path self.assertIsNone(read_config(config_path=None))
def test_get_photos_filters_no_file_sizes(self): config = read_config(config_path=tests.CONFIG_PATH) del config["photos"]["filters"]["file_sizes"] actual = config_parser.get_photos_filters(config=config) self.assertEqual(actual["file_sizes"][0], "original")
def test_get_photos_filters_invalid_file_size(self): config = read_config(config_path=tests.CONFIG_PATH) config["photos"] = {"filters": {"file_sizes": ["invalid"]}} actual = config_parser.get_photos_filters(config=config) self.assertEqual(actual["file_sizes"][0], "original")
def test_read_config_invalid_config_path(self): # Invalid config path self.assertIsNone(read_config(config_path="invalid/path"))
def test_get_photos_remove_obsolete_missing(self): config = read_config(config_path=tests.CONFIG_PATH) del config["photos"]["remove_obsolete"] self.assertFalse( config_parser.get_photos_remove_obsolete(config=config))
def sync(): last_send = None enable_sync_drive = True enable_sync_photos = True drive_sync_interval = 0 photos_sync_interval = 0 sleep_for = 10 while True: config = read_config() username = config_parser.get_username(config=config) if username: try: if ENV_ICLOUD_PASSWORD_KEY in os.environ: password = os.environ.get(ENV_ICLOUD_PASSWORD_KEY) utils.store_password_in_keyring(username=username, password=password) else: password = utils.get_password_from_keyring( username=username) api = ICloudPyService( apple_id=username, password=password, cookie_directory=DEFAULT_COOKIE_DIRECTORY, ) if not api.requires_2sa: if "drive" in config and enable_sync_drive: sync_drive.sync_drive(config=config, drive=api.drive) drive_sync_interval = config_parser.get_drive_sync_interval( config=config) if "photos" in config and enable_sync_photos: sync_photos.sync_photos(config=config, photos=api.photos) photos_sync_interval = config_parser.get_photos_sync_interval( config=config) if "drive" not in config and "photos" not in config: LOGGER.warning( "Nothing to sync. Please add drive: and/or photos: section in config.yaml file." ) else: 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") LOGGER.info(f"Retrying login at {next_sync} ...") last_send = notify.send(config, last_send) sleep(sleep_for) continue except exceptions.ICloudPyNoStoredPasswordAvailableException: LOGGER.error( "Password is not stored in keyring. Please save the password in keyring." ) sleep_for = config_parser.get_retry_login_interval( config=config) 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, last_send) sleep(sleep_for) continue if "drive" not in config and "photos" in config: sleep_for = photos_sync_interval enable_sync_drive = False enable_sync_photos = True elif "drive" in config and "photos" not in config: sleep_for = drive_sync_interval enable_sync_drive = True enable_sync_photos = False elif ("drive" in config and "photos" in config and drive_sync_interval <= photos_sync_interval): sleep_for = photos_sync_interval - drive_sync_interval photos_sync_interval -= drive_sync_interval enable_sync_drive = True enable_sync_photos = False else: sleep_for = drive_sync_interval - photos_sync_interval drive_sync_interval -= photos_sync_interval enable_sync_drive = False enable_sync_photos = True next_sync = (datetime.datetime.now() + datetime.timedelta(seconds=sleep_for)).strftime("%c") LOGGER.info(f"Resyncing at {next_sync} ...") if (config_parser.get_drive_sync_interval(config=config) < 0 if "drive" in config else True and config_parser.get_photos_sync_interval( config=config) < 0 if "photos" in config else True): break sleep(sleep_for)
def test_get_username_empty(self): # Empty username config = read_config(config_path=tests.CONFIG_PATH) config["app"]["credentials"]["username"] = "" self.assertIsNone(config_parser.get_username(config=config))
def test_read_config_default_config_path(self): # Default config path self.assertIsNotNone(read_config(config_path=tests.CONFIG_PATH))
def setUp(self) -> None: self.config = read_config(config_path=tests.CONFIG_PATH) return super().setUp()
def test_get_photos_remove_obsolete(self): config = read_config(config_path=tests.CONFIG_PATH) config["photos"]["remove_obsolete"] = True self.assertTrue( config_parser.get_photos_remove_obsolete(config=config))