Repository: mandarons/icloud-drive-docker
Pull request #159 (2023-10-07 08:53:15)

According to README `download_all` should ignore filtered albums.
I missed it in preparing pull requests


Patch:
diff --git a/README.md b/README.md
index afbd9869..f88aa18a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-# iCloud-docker 
+# iCloud-docker
+
 [![CI - Main](https://github.com/mandarons/icloud-drive-docker/actions/workflows/ci-main-test-coverage-deploy.yml/badge.svg?branch=main)](https://github.com/mandarons/icloud-drive-docker/actions/workflows/ci-main-test-coverage-deploy.yml)
 [![Tests](https://mandarons.github.io/icloud-drive-docker/badges/tests.svg)](https://mandarons.github.io/icloud-drive-docker/test-results/)
 [![Coverage](https://mandarons.github.io/icloud-drive-docker/badges/coverage.svg)](https://mandarons.github.io/icloud-drive-docker/test-coverage/index.html)
@@ -8,7 +9,7 @@
 [![GitHub Sponsors][github-sponsors-badge]][github-sponsors]
 <a href="https://www.buymeacoffee.com/mandarons" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 150px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
 
-🤟 __Please star this repository if you end up using this project. If it has improved your life in any way, consider donating to my mission using 'Sponsor' or 'Buy Me a Coffee' button. It will help me to continue supporting this product.__ :pray:
+🤟 **Please star this repository if you end up using this project. If it has improved your life in any way, consider donating to my mission using 'Sponsor' or 'Buy Me a Coffee' button. It will help me to continue supporting this product.** :pray:
 
 iCloud-docker (previously known as iCloud-drive-docker) is a simple iCloud client in Docker environment. It uses [iCloudPy](https://github.com/mandarons/icloudpy) python library to interact with iCloud server.
 
@@ -115,8 +116,8 @@ photos:
   all_albums: false # Optional, default false. If true preserve album structure. If same photo is in multpile albums creates duplicates on filesystem
   folder_format: "%Y/%m" # optional, if set put photos in subfolders according to format. Format cheatsheet - https://strftime.org
   filters:
-    # if all_albums is false list of albums to download, if all_albums is true list of ignored albums
-    # if empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
+    # if all_albums is false - albums list is used as filter-in, if all_albums is true - albums list is used as filter-out
+    # if albums list is empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
     albums:
       - "album 1"
       - "album2"
@@ -124,14 +125,16 @@ photos:
       - "original"
       # - "medium"
       # - "thumb"
-    extensions: # Optional, media extensions to be included in syncing iCloud Photos content
+    extensions:# Optional, media extensions to be included in syncing iCloud Photos content
       # - jpg
       # - heic
       # - png
 ```
 
 **_Note: On every sync, this client iterates all the files. Depending on number of files in your iCloud (drive + photos), syncing can take longer._**
+
 ## Usage Policy
+
 As mentioned in [USAGE.md](https://github.com/mandarons/icloud-drive-docker/blob/main/USAGE.md)
 
 [github-sponsors]: https://github.com/sponsors/mandarons
diff --git a/config.yaml b/config.yaml
index a360111e..290d1228 100644
--- a/config.yaml
+++ b/config.yaml
@@ -48,8 +48,8 @@ photos:
   all_albums: false # Optional, default false. If true preserve album structure. If same photo is in multpile albums creates duplicates on filesystem
   # folder_format: "%Y/%m" # optional, if set put photos in subfolders according to format. Format cheatsheet - https://strftime.org
   filters:
-    # if all_albums is false list of albums to download, if all_albums is true list of ignored albums
-    # if empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
+    # if all_albums is false - albums list is used as filter-in, if all_albums is true - albums list is used as filter-out
+    # if albums list is empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
     albums:
       - "album 1"
       - "album2"
diff --git a/src/sync_photos.py b/src/sync_photos.py
index da9de171..5dd72043 100644
--- a/src/sync_photos.py
+++ b/src/sync_photos.py
@@ -165,6 +165,8 @@ def sync_photos(config, photos):
     folder_format = config_parser.get_photos_folder_format(config=config)
     if download_all:
         for album in photos.albums.keys():
+            if filters["albums"] and album in iter(filters["albums"]):
+                continue
             sync_album(
                 album=photos.albums[album],
                 destination_path=os.path.join(destination_path, album),


Test patch:
diff --git a/tests/data/test_config.yaml b/tests/data/test_config.yaml
index b3873f34..89112e28 100644
--- a/tests/data/test_config.yaml
+++ b/tests/data/test_config.yaml
@@ -56,8 +56,8 @@ photos:
   all_albums: false # Optional, default false. If true preserve album structure. If same photo is in multpile albums creates duplicates on filesystem
   # folder_format: "%Y/%m" # optional, if set put photos in subfolders according to format. Format cheatsheet - https://strftime.org
   filters:
-    # if all_albums is false list of albums to download, if all_albums is true list of ignored albums
-    # if empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
+    # if all_albums is false - albums list is used as filter-in, if all_albums is true - albums list is used as filter-out
+    # if albums list is empty and all_albums is false download all photos to "all" folder. if empty and all_albums is true download all folders
     albums:
       - "album 2"
       - album-1
diff --git a/tests/test_sync_photos.py b/tests/test_sync_photos.py
index e2483b8d..329b2033 100644
--- a/tests/test_sync_photos.py
+++ b/tests/test_sync_photos.py
@@ -31,6 +31,8 @@ class TestSyncPhotos(unittest.TestCase):
     def tearDown(self) -> None:
         """Remove temp directory."""
         shutil.rmtree(tests.TEMP_DIR)
+        if os.path.exists(tests.PHOTOS_DIR):
+            shutil.rmtree(tests.PHOTOS_DIR)
 
     @patch(target="keyring.get_password", return_value=data.VALID_PASSWORD)
     @patch(
@@ -65,7 +67,7 @@ class TestSyncPhotos(unittest.TestCase):
     )
     @patch("icloudpy.ICloudPyService")
     @patch("src.read_config")
-    def test_sync_photos_all_albums(
+    def test_sync_photos_all_albums_filtered(
         self, mock_read_config, mock_service, mock_get_username, mock_get_password
     ):
         """Test for successful original photo size download."""
@@ -84,6 +86,35 @@ class TestSyncPhotos(unittest.TestCase):
         album_1_path = os.path.join(
             self.destination_path, config["photos"]["filters"]["albums"][1]
         )
+        self.assertFalse(os.path.isdir(album_0_path))
+        self.assertFalse(os.path.isdir(album_1_path))
+
+    @patch(target="keyring.get_password", return_value=data.VALID_PASSWORD)
+    @patch(
+        target="src.config_parser.get_username", return_value=data.AUTHENTICATED_USER
+    )
+    @patch("icloudpy.ICloudPyService")
+    @patch("src.read_config")
+    def test_sync_photos_all_albums_not_filtered(
+        self, mock_read_config, mock_service, mock_get_username, mock_get_password
+    ):
+        """Test for successful original photo size download."""
+        mock_service = self.service
+        config = self.config.copy()
+        config["photos"]["destination"] = self.destination_path
+        config["photos"]["all_albums"] = True
+        mock_read_config.return_value = config
+        album_0_path = os.path.join(
+            self.destination_path, config["photos"]["filters"]["albums"][0]
+        )
+        album_1_path = os.path.join(
+            self.destination_path, config["photos"]["filters"]["albums"][1]
+        )
+        config["photos"]["filters"]["albums"] = None
+        # Sync original photos
+        self.assertIsNone(
+            sync_photos.sync_photos(config=config, photos=mock_service.photos)
+        )
         self.assertTrue(os.path.isdir(album_0_path))
         self.assertTrue(os.path.isdir(album_1_path))
         self.assertTrue(len(os.listdir(album_0_path)) > 1)