Esempio n. 1
0
    def get_folder_path(self, metadata):
        """Given a media's metadata this function returns the folder path as a string.

        :param metadata dict: Metadata dictionary.
        :returns: str
        """
        path_parts = self.get_folder_path_definition()
        path = []
        for path_part in path_parts:
            # We support fallback values so that
            #  'album|city|"Unknown Location"
            #  %album|%city|"Unknown Location" results in
            #  My Album - when an album exists
            #  Sunnyvale - when no album exists but a city exists
            #  Unknown Location - when neither an album nor location exist
            for this_part in path_part:
                part, mask = this_part
                if part in ('date', 'day', 'month', 'year'):
                    path.append(time.strftime(mask, metadata['date_taken']))
                    break
                elif part in ('location', 'city', 'state', 'country'):
                    place_name = geolocation.place_name(
                        metadata['latitude'], metadata['longitude'])

                    location_parts = re.findall('(%[^%]+)', mask)
                    parsed_folder_name = self.parse_mask_for_location(
                        mask,
                        location_parts,
                        place_name,
                    )
                    path.append(parsed_folder_name)
                    break
                elif part == 'dbcomplex':
                    maskT, maskL = mask.split('~')
                    tcomp = time.strftime(maskT, metadata['date_taken'])

                    place_name = geolocation.place_name(
                        metadata['latitude'], metadata['longitude'])

                    location_parts = re.findall('(%[^%]+)', maskL)
                    parsed_folder_name = self.parse_mask_for_location(
                        maskL,
                        location_parts,
                        place_name,
                    )
                    path.append(tcomp + ' ' + parsed_folder_name)
                    break
                elif part in ('album'):
                    if metadata['album']:
                        path.append(metadata['album'])
                        break
                elif part.startswith('"') and part.endswith('"'):
                    path.append(part[1:-1])

        return os.path.join(*path)
Esempio n. 2
0
def test_place_name_no_default():
    # See gh-160 for backwards compatability needed when a string is stored instead of a dict
    helper.reset_dbs()
    place_name = geolocation.place_name(123456.000, 123456.000)
    helper.restore_dbs()

    assert place_name['default'] == 'Unknown Location', place_name
Esempio n. 3
0
    def get_folder_path(self, metadata):
        """Get folder path by various parameters.

        :param time time_obj: Time object to be used to determine folder name.
        :returns: str
        """
        path = []
        if(metadata['date_taken'] is not None):
            path.append(time.strftime('%Y-%m-%b', metadata['date_taken']))

        if(metadata['album'] is not None):
            path.append(metadata['album'])
        elif(
            metadata['latitude'] is not None and
            metadata['longitude'] is not None
        ):
            place_name = geolocation.place_name(
                metadata['latitude'],
                metadata['longitude']
            )
            if(place_name is not None):
                path.append(place_name)

        # if we don't have a 2nd level directory we use 'Unknown Location'
        if(len(path) < 2):
            path.append('Unknown Location')

        # return '/'.join(path[::-1])
        return os.path.join(*path)
Esempio n. 4
0
    def get_folder_path(self, metadata):
        """Get folder path by various parameters.

        :param time time_obj: Time object to be used to determine folder name.
        :returns: str
        """
        path = []
        if (metadata['date_taken'] is not None):
            path.append(time.strftime('%Y-%m-%b', metadata['date_taken']))

        if (metadata['album'] is not None):
            path.append(metadata['album'])
        elif (metadata['latitude'] is not None
              and metadata['longitude'] is not None):
            place_name = geolocation.place_name(metadata['latitude'],
                                                metadata['longitude'])
            if (place_name is not None):
                path.append(place_name)

        # if we don't have a 2nd level directory we use 'Unknown Location'
        if (len(path) < 2):
            path.append('Unknown Location')

        # return '/'.join(path[::-1])
        return os.path.join(*path)
Esempio n. 5
0
def main(argv):
    args = arguments.parse(
        argv, None, ['file=', 'type='],
        './import.py --type=<photo or video> --file=<path to file>')

    if ('file' not in args):
        print 'No file specified'
        sys.exit(1)

    media = Media.get_class_by_file(args['file'], [Photo, Video])

    if (media is None):
        print 'Not a valid file'
        sys.exit(1)

    metadata = media.get_metadata()

    place_name = geolocation.place_name(metadata['latitude'],
                                        metadata['longitude'])

    output = {
        'latitude': metadata['latitude'],
        'longitude': metadata['longitude'],
        'place_name': place_name
    }
    print '%r' % output
Esempio n. 6
0
    def get_folder_path(self, metadata, path_parts=None):
        """Given a media's metadata this function returns the folder path as a string.

        :param metadata dict: Metadata dictionary.
        :optional param path_parts list of tuples: Pre-defined path definition (for unit test)
        :returns: str
        """

        # Stitch in the extended folder_path handler
        config = Destination_path_pattern()
        config_ini = os.path.join(os.getcwd(), 'elodie', 'tests', 'files',
                                  'config_extended_1.ini')
        config.read_config_file(config_file)
        raw_full_path = config.get_raw_full_path()
        if raw_full_path != '':
            fpconfig = Destination_actual_path(
                raw_full_path,
                '')  # Don't need the filepath as we'll fake the metadata
            fpconfig._set_metadata(metadata)
            full_path = fpconfig.get_full_path()
            return full_path
        # else extended folder_path handler is not specified in config.ini

        if not path_parts:
            path_parts = self.get_folder_path_definition()
        path = []
        for path_part in path_parts:
            # We support fallback values so that
            #  'album|city|"Unknown Location"
            #  %album|%city|"Unknown Location" results in
            #  My Album - when an album exists
            #  Sunnyvale - when no album exists but a city exists
            #  Unknown Location - when neither an album nor location exist
            for this_part in path_part:
                part, mask = this_part
                if part in ('date', 'day', 'month', 'year'):
                    path.append(time.strftime(mask, metadata['date_taken']))
                    break
                elif part in ('location', 'hamlet', 'village', 'town', 'city',
                              'state', 'country'):
                    place_name = geolocation.place_name(
                        metadata['latitude'], metadata['longitude'])

                    # TBD _x = self._parseFallbacks(metadata, mask)
                    location_parts = re.findall('(%[^%]+)', mask)
                    parsed_folder_name = self.parse_mask_for_location(
                        mask,
                        location_parts,
                        place_name,
                    )
                    path.append(parsed_folder_name)
                    break
                elif part in ('album', 'camera_make', 'camera_model'):
                    if metadata[part]:
                        path.append(metadata[part])
                        break
                elif part.startswith('"') and part.endswith('"'):
                    path.append(part[1:-1])

        return os.path.join(*path)
Esempio n. 7
0
def test_place_name_cached():
    helper.reset_dbs()
    with open('%s/location.json-cached' % gettempdir(), 'w') as f:
        f.write("""
[{"lat": 37.3667027222222, "long": -122.033383611111, "name": {"city": "UNITTEST"}}]
""")
    place_name = geolocation.place_name(37.3667027222222, -122.033383611111)
    helper.restore_dbs()

    assert place_name['city'] == 'UNITTEST', place_name
Esempio n. 8
0
    def get_dynamic_path(self, part, mask, metadata):
        """Parse a specific folder's name given a mask and metadata.

        :param part: Name of the part as defined in the path (i.e. date from %date)
        :param mask: Mask representing the template for the path (i.e. %city %state
        :param metadata: Metadata dictionary.
        :returns: str
        """

        # Each part has its own custom logic and we evaluate a single part and return
        #  the evaluated string.
        if part in ('custom'):
            custom_parts = re.findall('(%[a-z_]+)', mask)
            folder = mask
            for i in custom_parts:
                folder = folder.replace(
                    i,
                    self.get_dynamic_path(i[1:], i, metadata)
                )
            return folder
        elif part in ('date'):
            config = load_config()
            # If Directory is in the config we assume full_path and its
            #  corresponding values (date, location) are also present
            config_directory = self.default_folder_path_definition
            if('Directory' in config):
                config_directory = config['Directory']
            date_mask = ''
            if 'date' in config_directory:
                date_mask = config_directory['date']
            return time.strftime(date_mask, metadata['date_taken'])
        elif part in ('day', 'month', 'year'):
            return time.strftime(mask, metadata['date_taken'])
        elif part in ('location', 'city', 'state', 'country'):
            place_name = geolocation.place_name(
                metadata['latitude'],
                metadata['longitude']
            )

            location_parts = re.findall('(%[^%]+)', mask)
            parsed_folder_name = self.parse_mask_for_location(
                mask,
                location_parts,
                place_name,
            )
            return parsed_folder_name
        elif part in ('album', 'camera_make', 'camera_model'):
            if metadata[part]:
                return metadata[part]
        elif part.startswith('"') and part.endswith('"'):
            # Fallback string
            return part[1:-1]

        return ''
Esempio n. 9
0
def test_place_name_deprecated_string_cached():
    # See gh-160 for backwards compatability needed when a string is stored instead of a dict
    helper.reset_dbs()
    with open('%s/location.json-cached' % gettempdir(), 'w') as f:
        f.write("""
[{"lat": 37.3667027222222, "long": -122.033383611111, "name": "OLDVALUE"}]
""")
    place_name = geolocation.place_name(37.3667027222222, -122.033383611111)
    helper.restore_dbs()

    assert place_name['city'] == 'Sunnyvale', place_name
Esempio n. 10
0
    def get_folder_path(self, metadata):
        path = []
        if(metadata['date_taken'] is not None):
            path.append(time.strftime('%Y-%m-%b', metadata['date_taken']))

        if(metadata['album'] is not None):
            path.append(metadata['album'])
        elif(metadata['latitude'] is not None and metadata['longitude'] is not None):
            place_name = geolocation.place_name(metadata['latitude'], metadata['longitude'])
            if(place_name is not None):
                path.append(place_name)

        # if we don't have a 2nd level directory we use 'Unknown Location'
        if(len(path) < 2):
            path.append('Unknown Location')

        #return '/'.join(path[::-1])
        return '/'.join(path)
Esempio n. 11
0
def main(argv):
    args = arguments.parse(argv, None, ['file=','type='], './import.py --type=<photo or video> --file=<path to file>')

    if('file' not in args):
        print 'No file specified'
        sys.exit(1)

    media = Media.get_class_by_file(args['file'], [Photo, Video])

    if(media is None):
        print 'Not a valid file'
        sys.exit(1)

    metadata = media.get_metadata()

    place_name = geolocation.place_name(metadata['latitude'], metadata['longitude'])

    output = {'latitude': metadata['latitude'], 'longitude': metadata['longitude'], 'place_name': place_name}
    print '%r' % output
Esempio n. 12
0
    def get_folder_path(self, metadata):
        """Get folder path by various parameters.

        :param metadata dict: Metadata dictionary.
        :returns: str
        """
        path_parts = self.get_folder_path_definition()
        path = []
        for path_part in path_parts:
            part, mask = path_part
            if part == 'date':
                path.append(time.strftime(mask, metadata['date_taken']))
            elif part == 'location':
                if (metadata['latitude'] is not None
                        and metadata['longitude'] is not None):
                    place_name = geolocation.place_name(
                        metadata['latitude'], metadata['longitude'])
                    if (place_name is not None):
                        location_parts = re.findall('(%[^%]+)', mask)
                        parsed_folder_name = self.parse_mask_for_location(
                            mask,
                            location_parts,
                            place_name,
                        )
                        path.append(parsed_folder_name)

        # For now we always make the leaf folder an album if it's in the EXIF.
        # This is to preserve backwards compatability until we figure out how
        # to include %album in the config.ini syntax.
        if (metadata['album'] is not None):
            if (len(path) == 1):
                path.append(metadata['album'])
            elif (len(path) == 2):
                path[1] = metadata['album']

        # if we don't have a 2nd level directory we use 'Unknown Location'
        if (len(path) < 2):
            path.append('Unknown Location')

        # return '/'.join(path[::-1])
        return os.path.join(*path)
Esempio n. 13
0
    def get_file_name(self, metadata):
        """Generate file name for a photo or video using its metadata.

        Originally we hardcoded the file name to include an ISO date format.
        We use an ISO8601-like format for the file name prefix. Instead of
        colons as the separator for hours, minutes and seconds we use a hyphen.
        https://en.wikipedia.org/wiki/ISO_8601#General_principles

        PR #225 made the file name customizable and fixed issues #107 #110 #111.
        https://github.com/jmathai/elodie/pull/225

        :param media: A Photo or Video instance
        :type media: :class:`~elodie.media.photo.Photo` or
            :class:`~elodie.media.video.Video`
        :returns: str or None for non-photo or non-videos
        """
        if(metadata is None):
            return None

        # Get the name template and definition.
        # Name template is in the form %date-%original_name-%title.%extension
        # Definition is in the form
        #  [
        #    [('date', '%Y-%m-%d_%H-%M-%S')],
        #    [('original_name', '')], [('title', '')], // contains a fallback
        #    [('extension', '')]
        #  ]
        name_template, definition = self.get_file_name_definition()

        name = name_template
        for parts in definition:
            this_value = None
            for this_part in parts:
                part, mask = this_part
                if part in ('date', 'day', 'month', 'year'):
                    this_value = time.strftime(mask, metadata['date_taken'])
                    break
                elif part in ('location', 'city', 'state', 'country'):
                    place_name = geolocation.place_name(
                        metadata['latitude'],
                        metadata['longitude']
                    )

                    location_parts = re.findall('(%[^%]+)', mask)
                    this_value = self.parse_mask_for_location(
                        mask,
                        location_parts,
                        place_name,
                    )
                    break
                elif part in ('album', 'extension', 'title'):
                    if metadata[part]:
                        this_value = re.sub(self.whitespace_regex, '-', metadata[part].strip())
                        break
                elif part in ('original_name'):
                    # First we check if we have metadata['original_name'].
                    # We have to do this for backwards compatibility because
                    #   we original did not store this back into EXIF.
                    if metadata[part]:
                        this_value = os.path.splitext(metadata['original_name'])[0]
                    else:
                        # We didn't always store original_name so this is
                        #  for backwards compatability.
                        # We want to remove the hardcoded date prefix we used
                        #  to add to the name.
                        # This helps when re-running the program on file
                        #  which were already processed.
                        this_value = re.sub(
                            '^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}-',
                            '',
                            metadata['base_name']
                        )
                        if(len(this_value) == 0):
                            this_value = metadata['base_name']

                    # Lastly we want to sanitize the name
                    this_value = re.sub(self.whitespace_regex, '-', this_value.strip())
                elif part.startswith('"') and part.endswith('"'):
                    this_value = part[1:-1]
                    break

            # Here we replace the placeholder with it's corresponding value.
            # Check if this_value was not set so that the placeholder
            #  can be removed completely.
            # For example, %title- will be replaced with ''
            # Else replace the placeholder (i.e. %title) with the value.
            if this_value is None:
                name = re.sub(
                    #'[^a-z_]+%{}'.format(part),
                    '[^a-zA-Z0-9_]+%{}'.format(part),
                    '',
                    name,
                )
            else:
                name = re.sub(
                    '%{}'.format(part),
                    this_value,
                    name,
                )

        config = load_config()

        if('File' in config and 'capitalization' in config['File'] and config['File']['capitalization'] == 'upper'):
            return name.upper()
        else:
            return name.lower()
Esempio n. 14
0
    def get_file_name(self, media):
        """Generate file name for a photo or video using its metadata.

        We use an ISO8601-like format for the file name prefix. Instead of
        colons as the separator for hours, minutes and seconds we use a hyphen.
        https://en.wikipedia.org/wiki/ISO_8601#General_principles

        :param media: A Photo or Video instance
        :type media: :class:`~elodie.media.photo.Photo` or
            :class:`~elodie.media.video.Video`
        :returns: str or None for non-photo or non-videos
        """
        if (not media.is_valid()):
            return None

        metadata = media.get_metadata()
        if (metadata is None):
            return None

        name_template, definition = self.get_file_name_definition()

        name = name_template
        for parts in definition:
            this_value = None
            for this_part in parts:
                part, mask = this_part
                if part in ('date', 'day', 'month', 'year'):
                    this_value = time.strftime(mask, metadata['date_taken'])
                    break
                elif part in ('location', 'city', 'state', 'country'):
                    place_name = geolocation.place_name(
                        metadata['latitude'], metadata['longitude'])

                    location_parts = re.findall('(%[^%]+)', mask)
                    this_value = self.parse_mask_for_location(
                        mask,
                        location_parts,
                        place_name,
                    )
                    break
                elif part in ('album', 'base_name', 'extension',
                              'original_name', 'title'):
                    if metadata[part]:
                        this_value = metadata[part]
                        break
                elif part.startswith('"') and part.endswith('"'):
                    this_value = part[1:-1]
                    break

            if this_value is None:
                name = re.sub(
                    '[^a-z_]+%{}'.format(part),
                    '',
                    name,
                )
            else:
                name = re.sub(
                    '%{}'.format(part),
                    this_value,
                    name,
                )

        return name

        # DELETE ME ..

        # First we check if we have metadata['original_name'].
        # We have to do this for backwards compatibility because
        #   we original did not store this back into EXIF.
        if ('original_name' in metadata and metadata['original_name']):
            base_name = os.path.splitext(metadata['original_name'])[0]
        else:
            # If the file has EXIF title we use that in the file name
            #   (i.e. my-favorite-photo-img_1234.jpg)
            # We want to remove the date prefix we add to the name.
            # This helps when re-running the program on file which were already
            #   processed.
            base_name = re.sub('^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}-', '',
                               metadata['base_name'])
            if (len(base_name) == 0):
                base_name = metadata['base_name']

        if ('title' in metadata and metadata['title'] is not None
                and len(metadata['title']) > 0):
            title_sanitized = re.sub('\W+', '-', metadata['title'].strip())
            base_name = base_name.replace('-%s' % title_sanitized, '')
            base_name = '%s-%s' % (base_name, title_sanitized)

        file_name = '%s-%s.%s' % (time.strftime(
            '%Y-%m-%d_%H-%M-%S',
            metadata['date_taken']), base_name, metadata['extension'])
        return file_name.lower()