diff --git a/config.ini-sample b/config.ini-sample index efd3d77..d3733ce 100644 --- a/config.ini-sample +++ b/config.ini-sample @@ -1,5 +1,19 @@ +[Directory] +# day_begins: what hour of the day you want the day to begin (only for +# classification purposes). Defaults at 0 as midnight. Can be +# used to group early morning photos with the previous day. Must +# be a number between 0-23') +day_begins=4 + +location=%city, %state +year=%Y +month=%B +# date=%Y +# custom=%date %album +full_path=%year/%month/%location + [Geolocation] -; geocoder: Nominatim or MapQuest +# geocoder: Nominatim or MapQuest geocoder=Nominatim mapquest_key=None prefer_english_names=False diff --git a/elodie.py b/elodie.py index 928c19a..c3fd29f 100755 --- a/elodie.py +++ b/elodie.py @@ -177,11 +177,6 @@ def _import(destination, source, file, album_from_folder, trash, @click.option('--copy', '-c', default=False, is_flag=True, help='True if you want files to be copied over from src_dir to\ dest_dir rather than moved') -@click.option('--day-begins', '-b', default=0, - help='What hour of the day you want the day to begin (only for\ - classification purposes). Defaults at 0 as midnight. Can be\ - used to group early morning photos with the previous day. Must\ - be a number between 0-23') @click.option('--exclude-regex', '-e', default=set(), multiple=True, help='Regular expression for directories or files to exclude.') @click.option('--filter-by-ext', '-f', default=False, help='''Use filename @@ -197,7 +192,7 @@ def _import(destination, source, file, album_from_folder, trash, @click.option('--verbose', '-v', default=False, is_flag=True, help='True if you want to see details of file processing') @click.argument('paths', required=True, nargs=-1, type=click.Path()) -def _sort(debug, dry_run, destination, copy, day_begins, exclude_regex, filter_by_ext, ignore_tags, +def _sort(debug, dry_run, destination, copy, exclude_regex, filter_by_ext, ignore_tags, remove_duplicates, verbose, paths): """Sort files or directories by reading their EXIF and organizing them according to config.ini preferences. @@ -241,9 +236,17 @@ def _sort(debug, dry_run, destination, copy, day_begins, exclude_regex, filter_b # Initialize Db db = Db(destination) - filesystem = FileSystem(mode, dry_run, exclude_regex_list, logger) - summary, has_errors = filesystem.sort_files(paths, destination, db, remove_duplicates) + if 'Directory' in config and 'day_begins' in config['Directory']: + config_directory = config['Directory'] + day_begins = config_directory['day_begins'] + else: + day_begins = 0 + filesystem = FileSystem(mode, dry_run, exclude_regex_list, logger, + day_begins) + + summary, has_errors = filesystem.sort_files(paths, destination, db, + remove_duplicates) if verbose or debug: summary.write() diff --git a/elodie/filesystem.py b/elodie/filesystem.py index 4ae8665..0ad61f5 100644 --- a/elodie/filesystem.py +++ b/elodie/filesystem.py @@ -12,7 +12,7 @@ import os import re import shutil import time -from datetime import datetime +from datetime import datetime, timedelta from elodie import geolocation from elodie import log @@ -29,7 +29,7 @@ class FileSystem(object): """A class for interacting with the file system.""" def __init__(self, mode='copy', dry_run=False, exclude_regex_list=set(), - logger=logging.getLogger()): + logger=logging.getLogger(), day_begins=0): # The default folder path is along the lines of 2017-06-17_01-04-14-dsc_1234-some-title.jpg self.default_file_name_definition = { 'date': '%Y-%m-%d_%H-%M-%S', @@ -56,6 +56,7 @@ class FileSystem(object): self.mode = mode self.logger = logger self.summary = Summary() + self.day_begins = day_begins # Instantiate a plugins object self.plugins = Plugins() @@ -137,6 +138,18 @@ class FileSystem(object): """ return os.getcwd() + + def check_for_early_morning_photos(self, date): + """check for early hour photos to be grouped with previous day""" + + if date.hour < self.day_begins: + self.logger.info('moving this photo to the previous day for\ + classification purposes (day_begins=' + str(self.day_begins) + ')') + date = date - timedelta(hours=date.hour+1) # push it to the day before for classificiation purposes + + return date + + def get_file_name(self, metadata): """Generate file name for a photo or video using its metadata. @@ -336,8 +349,9 @@ class FileSystem(object): # 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'] + if 'Directory' in config: + if 'full_path' in config['Directory']: + config_directory = config['Directory'] # Find all subpatterns of full_path that map to directories. # I.e. %foo/%bar => ['foo', 'bar'] @@ -502,7 +516,8 @@ class FileSystem(object): config_directory = self.default_folder_path_definition config = load_config(constants.CONFIG_FILE) if('Directory' in config): - config_directory = config['Directory'] + if 'full_path' in config['Directory']: + config_directory = config['Directory'] # Get date mask from config mask = '' if 'date' in config_directory: @@ -518,6 +533,8 @@ class FileSystem(object): return folder elif part in ('date', 'day', 'month', 'year'): date = self.get_date_taken(metadata) + # early morning photos can be grouped with previous day + date = self.check_for_early_morning_photos(date) if date is not None: return date.strftime(mask) else: @@ -620,6 +637,7 @@ class FileSystem(object): # If we find a checksum match but the file doesn't exist where we # believe it to be then we write a debug log and proceed to import. checksum_file = db.get_hash(checksum) + # BUG: inconsistency if file removed manually without update db if(allow_duplicate is False and checksum_file is not None): if(os.path.isfile(checksum_file)): log.info('%s already at %s.' % ( diff --git a/tests/test_filesystem.py b/tests/test_filesystem.py index 57cecfe..289a14f 100644 --- a/tests/test_filesystem.py +++ b/tests/test_filesystem.py @@ -730,6 +730,14 @@ def test_checkcomp(): assert valid_checksum assert not invalid_checksum + +def test_check_for_early_morning_photos(): + date_origin = datetime(1985, 1, 1, 3, 5) + filesystem = FileSystem(day_begins=4) + date = filesystem.check_for_early_morning_photos(date_origin) + assert date.date() == datetime(1984, 12, 31).date() + + def test_sort_file(): filesystem = FileSystem() temporary_folder, folder = helper.create_working_folder()