From 5c255093e3991e3758b52a6db440c404abb20909 Mon Sep 17 00:00:00 2001 From: Cedric Leporcq Date: Sun, 17 Oct 2021 12:33:14 +0200 Subject: [PATCH] Add FPath class --- ordigi/collection.py | 147 ++++++++++++++++++++++----------------- tests/test_collection.py | 40 +++++++---- 2 files changed, 109 insertions(+), 78 deletions(-) diff --git a/ordigi/collection.py b/ordigi/collection.py index 53fddd1..e252bcf 100644 --- a/ordigi/collection.py +++ b/ordigi/collection.py @@ -24,69 +24,16 @@ from ordigi.summary import Summary from ordigi import utils -class Collection: - """Class of the media collection.""" +class FPath: + """Featured path object""" - def __init__( - self, - root, - path_format, - album_from_folder=False, - cache=False, - day_begins=0, - dry_run=False, - exclude=set(), - filter_by_ext=set(), - glob='**/*', - interactive=False, - logger=logging.getLogger(), - max_deep=None, - mode='copy', - use_date_filename=False, - use_file_dates=False, - ): - - # Attributes - self.root = Path(root).expanduser().absolute() - if not self.root.exists(): - logger.error(f'Directory {self.root} does not exist') - sys.exit(1) - - self.path_format = path_format - self.db = Sqlite(self.root) - - # Options - self.album_from_folder = album_from_folder - self.cache = cache + def __init__(self, path_format, day_begins=0, logger=logging.getLogger()): self.day_begins = day_begins - self.dry_run = dry_run - self.exclude = exclude - - if '%media' in filter_by_ext: - filter_by_ext.remove('%media') - self.filter_by_ext = filter_by_ext.union(media.extensions) - else: - self.filter_by_ext = filter_by_ext - - self.glob = glob self.items = self.get_items() - self.interactive = interactive - self.logger = logger.getChild(self.__class__.__name__) - self.max_deep = max_deep - self.mode = mode - # List to store media metadata - self.medias = [] - self.summary = Summary() - self.use_date_filename = use_date_filename - self.use_file_dates = use_file_dates + self.logger = logger + self.path_format = path_format self.whitespace_regex = '[ \t\n\r\f\v]+' - self.src_list = [] - self.dest_list = [] - - # Constants - self.theme = request.load_theme() - def get_items(self): return { 'album': '{album}', @@ -96,7 +43,7 @@ class Collection: 'city': '{city}', 'custom': '{".*"}', 'country': '{country}', - # 'folder': '{folder[<>]?[-+]?[1-9]?}', + 'date': '{(%[a-zA-Z][^a-zA-Z]*){1,8}}', # search for date format string 'ext': '{ext}', 'folder': '{folder}', 'folders': r'{folders(\[[0-9:]{0,3}\])?}', @@ -105,19 +52,25 @@ class Collection: 'original_name': '{original_name}', 'state': '{state}', 'title': '{title}', - 'date': '{(%[a-zA-Z][^a-zA-Z]*){1,8}}', # search for date format string } - def _check_for_early_morning_photos(self, date): + def get_early_morning_photos_date(self, date, mask): """check for early hour photos to be grouped with previous day""" + + for m in '%H', '%M', '%S','%I', '%p', '%f': + if m in mask: + # D'ont change date format if datestring contain hour, minutes or seconds... + return date.strftime(mask) + if date.hour < self.day_begins: self.logger.info( "moving this photo to the previous day for classification purposes" ) + # push it to the day before for classification purposes date = date - timedelta(hours=date.hour + 1) - return date + return date.strftime(mask) def _get_folders(self, folders, mask): """ @@ -186,8 +139,7 @@ class Collection: date = metadata['date_media'] # early morning photos can be grouped with previous day if date is not None: - date = self._check_for_early_morning_photos(date) - part = date.strftime(mask) + part = self.get_early_morning_photos_date(date, mask) elif item == 'folder': part = os.path.basename(metadata['subdirs']) @@ -295,6 +247,68 @@ class Collection: return None + +class Collection: + """Class of the media collection.""" + + def __init__( + self, + root, + path_format, + album_from_folder=False, + cache=False, + day_begins=0, + dry_run=False, + exclude=set(), + filter_by_ext=set(), + glob='**/*', + interactive=False, + logger=logging.getLogger(), + max_deep=None, + mode='copy', + use_date_filename=False, + use_file_dates=False, + ): + + # Attributes + self.root = Path(root).expanduser().absolute() + if not self.root.exists(): + logger.error(f'Directory {self.root} does not exist') + sys.exit(1) + + self.path_format = path_format + self.db = Sqlite(self.root) + + # Options + self.album_from_folder = album_from_folder + self.cache = cache + self.day_begins = day_begins + self.dry_run = dry_run + self.exclude = exclude + + if '%media' in filter_by_ext: + filter_by_ext.remove('%media') + self.filter_by_ext = filter_by_ext.union(media.extensions) + else: + self.filter_by_ext = filter_by_ext + + self.glob = glob + self.interactive = interactive + self.logger = logger.getChild(self.__class__.__name__) + self.max_deep = max_deep + self.mode = mode + # List to store media metadata + self.medias = [] + self.summary = Summary() + self.use_date_filename = use_date_filename + self.use_file_dates = use_file_dates + + self.src_list = [] + self.dest_list = [] + + # Constants + self.theme = request.load_theme() + def _checkcomp(self, dest_path, src_checksum): """Check file.""" if self.dry_run: @@ -845,7 +859,8 @@ class Collection: ) metadata = media.get_metadata(self.root, loc, self.db, self.cache) # Get the destination path according to metadata - relpath = Path(self.get_path(metadata)) + fpath = FPath(self.path_format, self.day_begins, self.logger) + relpath = Path(fpath.get_path(metadata)) files_data.append((copy(media), relpath)) @@ -1031,3 +1046,5 @@ class Collection: result = self.check_db() return self.summary, result + + diff --git a/tests/test_collection.py b/tests/test_collection.py index 66cb143..8f6d104 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -11,7 +11,7 @@ from time import sleep from .conftest import randomize_files, randomize_db from ordigi import constants -from ordigi.collection import Collection +from ordigi.collection import Collection, FPath from ordigi.database import Sqlite from ordigi.exiftool import ExifToolCaching, exiftool_is_running, terminate_exiftool from ordigi.geolocation import GeoLocation @@ -20,7 +20,7 @@ from ordigi.media import Media from ordigi import utils -class TestCollection: +class TestFPath: @pytest.fixture(autouse=True) def setup_class(cls, sample_files_paths): @@ -28,18 +28,13 @@ class TestCollection: cls.path_format = constants.default_path + '/' + constants.default_name cls.logger = log.get_logger(level=10) - def teardown_class(self): - terminate_exiftool() - assert not exiftool_is_running() - def test_get_part(self, tmp_path): """ Test all parts """ + fpath = FPath(self.path_format, 4, self.logger) # Item to search for: - collection = Collection(tmp_path, self.path_format, - use_date_filename=True, use_file_dates=True) - items = collection.get_items() + items = fpath.get_items() masks = [ '{album}', '{basename}', @@ -77,7 +72,7 @@ class TestCollection: for mask in masks: matched = re.search(regex, mask) if matched: - part = collection.get_part(item, mask[1:-1], metadata) + part = fpath.get_part(item, mask[1:-1], metadata) # check if part is correct assert isinstance(part, str), file_path if item == 'basename': @@ -113,6 +108,28 @@ class TestCollection: else: assert part == '', file_path + def test_get_early_morning_photos_date(self): + date = datetime(2021, 10, 16, 2, 20, 40) + fpath = FPath(self.path_format, 4, self.logger) + part = fpath.get_early_morning_photos_date(date, '%Y-%m-%d') + assert part == '2021-10-15' + + part = fpath.get_early_morning_photos_date(date, '%Y%m%d-%H%M%S') + assert part == '20211016-022040' + + +class TestCollection: + + @pytest.fixture(autouse=True) + def setup_class(cls, sample_files_paths): + cls.src_path, cls.file_paths = sample_files_paths + cls.path_format = constants.default_path + '/' + constants.default_name + cls.logger = log.get_logger(level=10) + + def teardown_class(self): + terminate_exiftool() + assert not exiftool_is_running() + def test_sort_files(self, tmp_path): collection = Collection(tmp_path, self.path_format, album_from_folder=True, logger=self.logger) @@ -182,9 +199,6 @@ class TestCollection: # TODO check for conflicts - - # TODO check date - def test__get_files_in_path(self, tmp_path): collection = Collection(tmp_path, self.path_format, exclude={'**/*.dng',},