Example #1
0
    def scan_originals(self, folder, options):
        """Scan a folder of Original images, and delete obsolete ones."""
        file_list = os.listdir(folder)
        if not file_list:
            return

        for f in file_list:
            # We won't touch some files.
            if imageutils.is_ignore(f):
                continue

            originalfile = unicodedata.normalize("NFC",
                                                 os.path.join(folder, f))
            if os.path.isdir(originalfile):
                delete_album_file(originalfile, self.albumdirectory,
                                  "Obsolete export Originals directory",
                                  options)
                continue

            base_name = unicodedata.normalize("NFC",
                                              su.getfilebasename(originalfile))
            master_file = self.files.get(base_name)

            # everything else must have a master, or will have to go
            if (not master_file
                    or originalfile != master_file.original_export_file
                    or master_file.photo.rotation_is_only_edit):
                delete_album_file(originalfile, originalfile,
                                  "Obsolete Original", options)
Example #2
0
    def check_directories(self, directory, rel_path, album_directories,
                          options):
        """Checks an export directory for obsolete files."""
        if options.ignore:
            exclude_pattern = re.compile(su.fsdec(options.ignore))
            if exclude_pattern.match(os.path.split(directory)[1]):
                return True
        if not os.path.exists(directory):
            return True
        contains_albums = False
        for f in su.os_listdir_unicode(directory):
            if self._check_abort():
                return
            album_file = os.path.join(directory, f)
            if os.path.isdir(album_file):
                if f == "iPod Photo Cache":
                    su.pout("Skipping " + album_file)
                    continue
                rel_path_file = os.path.join(rel_path, f)
                if album_file in album_directories:
                    contains_albums = True
                elif not self.check_directories(album_file, rel_path_file,
                                                album_directories, options):
                    delete_album_file(album_file, directory,
                                      "Obsolete directory", options)
            else:
                # we won't touch some files
                if imageutils.is_ignore(f):
                    continue
                delete_album_file(album_file, directory, "Obsolete", options)

        return contains_albums
Example #3
0
    def check_directories(self, directory, rel_path, album_directories,
                          options):
        """Checks an export directory for obsolete files."""
        if options.ignore:
            exclude_pattern = re.compile(su.fsdec(options.ignore))
            if exclude_pattern.match(os.path.split(directory)[1]):
                return True
        if not os.path.exists(directory):
            return True
        contains_albums = False
        for f in su.os_listdir_unicode(directory):
            if self._check_abort():
                return
            album_file = os.path.join(directory, f)
            if os.path.isdir(album_file):
                if f == "iPod Photo Cache":
                    su.pout("Skipping " + album_file)
                    continue
                rel_path_file = os.path.join(rel_path, f)
                if album_file in album_directories:
                    contains_albums = True
                elif not self.check_directories(album_file, rel_path_file,
                                                album_directories, options):
                    delete_album_file(album_file, directory,
                                      "Obsolete directory", options)
                else:
                    contains_albums = True
            else:
                # we won't touch some files
                if imageutils.is_ignore(f):
                    continue
                delete_album_file(album_file, directory, "Obsolete",
                                  options)

        return contains_albums
Example #4
0
    def load_album(self, options):
        """Loads an existing album (export folder)."""
        online_albums = {}
        for album in self.client.gd_client.GetUserFeed().entry:
            if online_albums.has_key(album.title.text):
                self.delete_online_album(album, "duplicate album", options)
            else:
                online_albums[su.unicode_string(album.title.text)] = album

        album_directories = {}
        for folder_name in sorted(self.named_folders):
            folder = self.named_folders.get(folder_name)
            if self._check_abort():
                return
            album_directories[folder.name] = True
            folder.load_album(self.client, online_albums, options)

        ignore_pattern = None
        if options.ignore:
            ignore_pattern = re.compile(su.fsdec(options.ignore))
        for album_name in online_albums:
            if self._check_abort():
                return
            if album_name in album_directories:
                continue
            if ignore_pattern and ignore_pattern.match(album_name):
                continue
            # We won't touch some albums
            if imageutils.is_ignore(album_name):
                continue
            self.delete_online_album(online_albums[album_name],
                                     "obsolete album", options)
Example #5
0
    def scan_originals(self, folder, options):
        """Scan a folder of Original images, and delete obsolete ones."""
        file_list = os.listdir(folder)
        if not file_list:
            return

        for f in file_list:
            # We won't touch some files.
            if imageutils.is_ignore(f):
                continue

            originalfile = unicodedata.normalize("NFC", os.path.join(folder, f))
            if os.path.isdir(originalfile):
                delete_album_file(originalfile, self.albumdirectory,
                                  "Obsolete export Originals directory",
                                  options)
                continue

            base_name = unicodedata.normalize("NFC",
                                              su.getfilebasename(originalfile))
            master_file = self.files.get(base_name.lower())

            # everything else must have a master, or will have to go
            if (not master_file or
                originalfile != master_file.original_export_file or
                master_file.photo.rotation_is_only_edit):
                delete_album_file(originalfile, originalfile,
                                  "Obsolete Original", options)
Example #6
0
    def load_album(self, options):
        """Loads an existing album (export folder)."""
        online_albums = {}
        for album in self.client.gd_client.GetUserFeed().entry:
            if online_albums.has_key(album.title.text):
                self.delete_online_album(album, "duplicate album", options)
            else:
                online_albums[su.unicode_string(album.title.text)] = album

        album_directories = {}
        for folder_name in sorted(self.named_folders):
            folder = self.named_folders.get(folder_name)
            if self._check_abort():
                return
            album_directories[folder.name] = True
            folder.load_album(self.client, online_albums, options)

        ignore_pattern = None
        if options.ignore:
            ignore_pattern = re.compile(su.fsdec(options.ignore))
        for album_name in online_albums:
            if self._check_abort():
                return
            if album_name in album_directories:
                continue
            if ignore_pattern and ignore_pattern.match(album_name):
                continue
            # We won't touch some albums
            if imageutils.is_ignore(album_name):
                continue
            self.delete_online_album(online_albums[album_name], "obsolete album", options)
Example #7
0
    def load_album(self, options):
        """walks the album directory tree, and scans it for existing files."""
        if not os.path.exists(self.albumdirectory):
            su.pout("Creating folder " + self.albumdirectory)
            if not options.dryrun:
                os.makedirs(self.albumdirectory)
            else:
                return
        file_list = os.listdir(self.albumdirectory)
        if file_list is None:
            return

        for f in sorted(file_list):
            # we won't touch some files
            if imageutils.is_ignore(f):
                continue

            album_file = unicodedata.normalize("NFC",
                                               os.path.join(self.albumdirectory,
                                                            f))
            if os.path.isdir(album_file):
                if (options.originals and
                    (f == "Originals" or (options.picasa and
                                          f == ".picasaoriginals"))):
                    self.scan_originals(album_file, options)
                    continue
                else:
                    delete_album_file(album_file, self.albumdirectory,
                                      "Obsolete export directory", options)
                    continue

            base_name = unicodedata.normalize("NFC",
                                              su.getfilebasename(album_file))
            master_file = self.files.get(base_name.lower())

            # everything else must have a master, or will have to go
            if master_file is None or not master_file.is_part_of(album_file):
                delete_album_file(album_file, self.albumdirectory,
                                  "Obsolete exported file", options)
Example #8
0
    def load_album(self, options):
        """walks the album directory tree, and scans it for existing files."""
        if not os.path.exists(self.albumdirectory):
            su.pout("Creating folder " + self.albumdirectory)
            if not options.dryrun:
                os.makedirs(self.albumdirectory)
            else:
                return
        file_list = os.listdir(self.albumdirectory)
        if file_list is None:
            return

        for f in sorted(file_list):
            # we won't touch some files
            if imageutils.is_ignore(f):
                continue

            album_file = unicodedata.normalize("NFC",
                                               os.path.join(self.albumdirectory,
                                                            f))
            if os.path.isdir(album_file):
                if (options.originals and
                    (f == "Originals" or (options.picasa and
                                          f == ".picasaoriginals"))):
                    self.scan_originals(album_file, options)
                    continue
                else:
                    delete_album_file(album_file, self.albumdirectory,
                                      "Obsolete export directory", options)
                    continue

            base_name = unicodedata.normalize("NFC",
                                              su.getfilebasename(album_file))
            master_file = self.files.get(base_name.lower())

            # everything else must have a master, or will have to go
            if master_file is None or not master_file.is_part_of(album_file):
                delete_album_file(album_file, self.albumdirectory,
                                  "Obsolete exported file", options)
Example #9
0
class PicasaAlbum(object):
    """Tracks an album folder in the export location."""
    def __init__(self, name, iphoto_container):
        self.name = name
        self.iphoto_container = iphoto_container
        self.files = {}  # name -> PicasaFile
        self.online_album = None
        self.image_suffix = re.compile(
            r'\.(jpeg|jpg|mpg|mpeg|mov|png|tif|tiff)$', re.IGNORECASE)

    def add_iphoto_images(self, images, options):
        """Works through an image folder tree, and builds data for exporting."""
        entries = 0
        template = options.nametemplate

        if images is not None:
            entry_digits = len(str(len(images)))
            for image in images:
                if image.ismovie() and not options.movies:
                    continue
                if _NOUPLOAD_KEYWORD in image.keywords:
                    continue
                entries += 1
                image_basename = self.make_album_basename(
                    image, entries,
                    str(entries).zfill(entry_digits), template)
                picture_file = PicasaFile(image, self.name, image_basename,
                                          options)
                self.files[image_basename] = picture_file
        return len(self.files)

    def make_album_basename(self, photo, index, padded_index, name_template):
        """creates unique file name."""
        base_name = imageutils.format_photo_name(photo,
                                                 self.iphoto_container.name,
                                                 index, padded_index,
                                                 name_template)
        index = 0
        while True:
            album_basename = base_name
            if index > 0:
                album_basename += "_%d" % (index)
            if self.files.get(album_basename) is None:
                return album_basename
            index += 1
        return base_name

    def load_album(self, client, online_albums, options):
        """Walks the album directory tree, and scans it for existing files."""

        if options.verbose:
            print 'Reading online album ' + self.name
        comments = self.iphoto_container.getcommentwithouthints().strip()
        timestamp = get_picasaweb_date(self.iphoto_container.date)
        self.online_album = online_albums.get(self.name)
        if not self.online_album:
            print "Creating album: " + su.fsenc(self.name)
            if not options.dryrun:
                client.throttle()
                self.online_album = client.gd_client.InsertAlbum(
                    title=self.name,
                    summary=comments,
                    access='private',
                    timestamp=timestamp)
                online_albums[self.name] = self.online_album
            return

        # Check the properties of the online album
        changed = False
        online_album_summary_text = su.unicode_string(
            self.online_album.summary.text)
        if online_album_summary_text != comments:
            print 'Updating summary for online album %s (%s vs. %s)' % (
                su.fsenc(self.name), su.fsenc(online_album_summary_text),
                su.fsenc(comments))
            self.online_album.summary.text = comments
            changed = True

        if (timestamp and timestamp != self.online_album.timestamp.text):
            print 'Updating timestamp for online album %s (%s/%s)' % (
                su.fsenc(self.name), self.online_album.timestamp.datetime(),
                self.iphoto_container.date)
            self.online_album.timestamp.text = timestamp
            changed = True

        if changed and not options.dryrun:
            client.throttle()
            try:
                self.online_album = client.gd_client.Put(
                    self.online_album,
                    self.online_album.GetEditLink().href,
                    converter=gdata.photos.AlbumEntryFromString)
            except gdata.photos.service.GooglePhotosException, e:
                print 'Failed to update data for online album %s: %s' % (
                    self.name, str(e))

        # Check the pictures in the online album
        try:
            photos = client.gd_client.GetFeed(
                '/data/feed/api/user/%s/albumid/%s?kind=photo' %
                ('default', self.online_album.gphoto_id.text))
            for photo in photos.entry:
                # we won't touch some files
                if imageutils.is_ignore(photo.title.text):
                    continue

                photo_name = su.unicode_string(photo.title.text)
                base_name = su.getfilebasename(photo_name)
                master_file = self.files.get(base_name)

                # everything else must have a master, or will have to go
                if master_file is None:
                    delete_online_photo(client, photo, self.name,
                                        "Obsolete online photo", options)
                elif master_file.picasa_photo:
                    delete_online_photo(client, photo, self.name,
                                        "Duplicate online photo", options)
                else:
                    master_file.picasa_photo = photo
        except gdata.photos.service.GooglePhotosException, e:
            print 'Failed to load pictures for online album %s: %s' % (
                self.name, str(e))