diff --git a/gphotos/GoogleAlbumsSync.py b/gphotos/GoogleAlbumsSync.py index 5720a352..e422c565 100644 --- a/gphotos/GoogleAlbumsSync.py +++ b/gphotos/GoogleAlbumsSync.py @@ -38,6 +38,7 @@ def __init__(self, api: RestClient, root_folder: Path, db: LocalData, self._db: LocalData = db self._api: RestClient = api self.flush = flush + self.album = None @classmethod def make_search_parameters(cls, album_id: str, @@ -101,11 +102,12 @@ def fetch_album_contents(self, album_id: str, return first_date, last_date def index_album_media(self): + index_all_contents = self.album is not None self.index_albums_type(self._api.sharedAlbums.list.execute, 'sharedAlbums', "Shared (titled) Albums", False, True) self.index_albums_type(self._api.albums.list.execute, - 'albums', "Albums", True, False) + 'albums', "Albums", True, index_all_contents) def index_albums_type(self, api_function: Callable, item_key: str, description: str, allow_null_title: bool, @@ -131,7 +133,11 @@ def index_albums_type(self, api_function: Callable, item_key: str, already_indexed = indexed_album.size == album.size if \ indexed_album else False - if not allow_null_title and album.description == 'none': + if self.album and self.album != album.orig_name: + log.debug('Skipping Album: %s, photos: %d ' + '(does not match --album)', album.filename, + album.size) + elif not allow_null_title and album.description == 'none': log.debug('Skipping no-title album, photos: %d', album.size) elif already_indexed and not self.flush: diff --git a/gphotos/Main.py b/gphotos/Main.py index 421f48ec..7c8e5324 100644 --- a/gphotos/Main.py +++ b/gphotos/Main.py @@ -47,6 +47,11 @@ def __init__(self): parser.add_argument( "root_folder", help="root of the local folders to download into") + parser.add_argument( + "--album", + action='store', + help="only synchronize the contents of a single album." + "use quotes e.g. \"album name\" for album names with spaces") parser.add_argument( "--logfile", action='store', @@ -180,6 +185,7 @@ def setup(self, args: Namespace, db_path: Path): self.google_photos_idx.include_video = not args.skip_video self.google_photos_idx.rescan = args.rescan self.google_photos_down.retry_download = args.retry_download + self.google_albums_sync.album = args.album @classmethod def logging(cls, args: Namespace, folder: Path): @@ -229,12 +235,12 @@ def do_sync(self, args: Namespace): new_files = True with self.data_store: if not args.skip_index: - if not args.skip_files: + if not args.skip_files and not args.album: new_files = self.google_photos_idx.index_photos_media() # if there are no new files and no arguments that specify specific # scan requirements, then we have done all we need to do if new_files or args.rescan or args.retry_download or \ - args.start_date: + args.start_date or args.album: if not args.skip_albums and not args.skip_index: self.google_albums_sync.index_album_media() if not args.index_only: diff --git a/gphotos/restclient.py b/gphotos/restclient.py index dacbb1d9..23ba9bec 100644 --- a/gphotos/restclient.py +++ b/gphotos/restclient.py @@ -19,6 +19,12 @@ ''' +# a dummy decorator to suppress unresolved references on this dynamic class +def dynamic_attrs(cls): + return cls + + +@dynamic_attrs class RestClient: """ To create a callable client to a REST API, instantiate this class. For details of the discovery API see: