diff --git a/ordigi/cli.py b/ordigi/cli.py index 90a5b62..78962b7 100755 --- a/ordigi/cli.py +++ b/ordigi/cli.py @@ -346,6 +346,87 @@ def _compare(**kwargs): sys.exit(1) +@cli.command('edit') +@add_options(_logger_options) +@add_options(_filter_options) +@click.option( + '--key', + '-k', + default=None, + multiple=True, + # TODO Allow edit all values + required=True, + help="Select exif tags groups to edit", +) +@click.argument('subdirs', required=False, nargs=-1, type=click.Path()) +@click.argument('path', required=True, nargs=1, type=click.Path()) +def _edit(**kwargs): + """Edit EXIF metadata in files or directories""" + + log_level = log.get_level(kwargs['verbose']) + log.console(LOG, level=log_level) + + paths, root = _get_paths(kwargs['subdirs'], kwargs['path']) + + collection = Collection( + root, + { + 'cache': True, + 'ignore_tags': kwargs['ignore_tags'], + 'exclude': kwargs['exclude'], + 'extensions': kwargs['ext'], + 'glob': kwargs['glob'], + } + ) + + location = False + keys = set() + for key in kwargs['key']: + if key not in ( + 'album', + 'camera_make', + 'camera_model', + 'coordinates', + 'date_original', + 'date_created', + 'date_modified', + 'latitude', + 'longitude', + 'latitude_ref', + 'longitude_ref', + 'original_name', + 'title', + ): + LOG.error(f"key '{key}' is not valid") + sys.exit(1) + + if key in ( + 'latitude', + 'longitude', + 'latitude_ref', + 'longitude_ref', + ): + location = True + + if key == 'coordinates': + keys.update(['latitude', 'longitude']) + else: + keys.add(key) + + if location: + loc = _cli_get_location(collection) + else: + loc = None + + summary = collection.edit_metadata(paths, keys, loc, overwrite=True) + + if log_level < 30: + summary.print() + + if summary.errors: + sys.exit(1) + + @cli.command('init') @add_options(_logger_options) @click.argument('path', required=True, nargs=1, type=click.Path()) @@ -366,6 +447,9 @@ def _init(**kwargs): if log_level < 30: summary.print() + if summary.errors: + sys.exit(1) + @cli.command('import') @add_options(_logger_options) diff --git a/ordigi/collection.py b/ordigi/collection.py index 046ad0d..6ffdef5 100644 --- a/ordigi/collection.py +++ b/ordigi/collection.py @@ -543,6 +543,7 @@ class SortMedias: def sort_file(self, src_path, dest_path, metadata, imp=False): """Sort file and register it to db""" + if imp == 'copy': self.fileio.copy(src_path, dest_path) else: @@ -1130,69 +1131,50 @@ class Collection(SortMedias): return self.summary - def edit_metadata(self, path, key, loc=None, overwrite=False): - """Fill metadata and exif data for given key""" + def edit_metadata(self, paths, keys, loc=None, overwrite=False): + """Edit metadata and exif data for given key""" self._init_check_db() - if key in ( - 'latitude', - 'longitude', - 'latitude_ref', - 'longitude_ref', - ): - print(f"Set {key} alone is not allowed") - return None - - if overwrite: - print(f"Edit {key} values:") - else: - print(f"Fill empty {key} values:") - - paths = self.paths.get_paths_list(path) - - for file_path in paths: - media = self.medias.get_media(file_path, self.root) - media.get_metadata( - self.root, loc, self.db.sqlite, False - ) + for file_path, media in self.medias.get_medias_datas(paths, loc=loc): media.metadata['file_path'] = os.path.relpath(file_path, self.root) - print() - value = media.metadata[key] - if overwrite or not value: - print(f"FILE: '{file_path}'") - if overwrite: - print(f"{key}: '{value}'") - if overwrite or not value: - # Prompt value for given key for file_path - # utils.open_file() - prompt = [ - inquirer.Text('value', message=key), - ] - answer = inquirer.prompt(prompt, theme=self.theme) - # Validate value - if key in ('date_original', 'date_created', 'date_modified'): - # Check date format - value = media.get_date_format(answer['value']) - else: - if not answer[key].isalnum(): - print("Invalid entry, use alphanumeric chars") - value = inquirer.prompt(prompt, theme=self.theme) + for key in keys: + print() + value = media.metadata[key] + if overwrite or not value: + print(f"FILE: '{file_path}'") + if overwrite: + print(f"{key}: '{value}'") + if overwrite or not value: + # Prompt value for given key for file_path + prompt = [ + inquirer.Text('value', message=key), + ] + answer = inquirer.prompt(prompt, theme=self.theme) + # answer = {'value': '03-12-2021 08:12:35'} + # Validate value + if key in ('date_original', 'date_created', 'date_modified'): + # Check date format + value = media.get_date_format(answer['value']) + else: + if not answer[key].isalnum(): + print("Invalid entry, use alphanumeric chars") + value = inquirer.prompt(prompt, theme=self.theme) - result = False - if value: - media.metadata[key] = value - # Update database - self.db.add_file_data(media.metadata) - # Update exif data - exif = WriteExif( - file_path, - media.metadata, - ignore_tags=self.opt['Exif']['ignore_tags'], - ) - result = exif.set_key_values(key, value) - if result: - self.summary.append('update', True, file_path) - else: - self.summary.append('update', False, file_path) + result = False + if value: + media.metadata[key] = value + # Update database + self.db.add_file_data(media.metadata) + # Update exif data + exif = WriteExif( + file_path, + media.metadata, + ignore_tags=self.opt['Exif']['ignore_tags'], + ) + result = exif.set_key_values(key, value) + if result: + self.summary.append('update', True, file_path) + else: + self.summary.append('update', False, file_path) return self.summary diff --git a/ordigi/media.py b/ordigi/media.py index 208fc47..5f5e443 100644 --- a/ordigi/media.py +++ b/ordigi/media.py @@ -665,16 +665,20 @@ class Medias: return media - def get_metadata(self, file_path, src_dir, loc=None): + def get_media_data(self, file_path, src_dir, loc=None): media = self.get_media(file_path, src_dir) media.get_metadata( self.root, loc, self.db.sqlite, self.exif_opt['cache'] ) - return media.metadata + return media - def get_metadatas(self, src_dirs, imp=False, loc=None): - """Get medias data""" + def get_metadata(self, src_path, src_dir, loc=None): + """Get metadata""" + return self.get_media_data(src_path, src_dir, loc).metadata + + def get_paths(self, src_dirs, imp=False): + """Get paths""" for src_dir in src_dirs: src_dir = self.paths.check(src_dir) paths = self.paths.get_paths_list(src_dir) @@ -687,10 +691,23 @@ class Medias: collection, use `ordigi import`""") sys.exit(1) - # Get file metadata - metadata = self.get_metadata(src_path, src_dir, loc) + yield src_dir, src_path - yield src_path, metadata + def get_medias_datas(self, src_dirs, imp=False, loc=None): + """Get medias datas""" + for src_dir, src_path in self.get_paths(src_dirs, imp=imp): + # Get file metadata + media = self.get_media_data(src_path, src_dir, loc) + + yield src_path, media + + def get_metadatas(self, src_dirs, imp=False, loc=None): + """Get medias data""" + for src_dir, src_path in self.get_paths(src_dirs, imp=imp): + # Get file metadata + metadata = self.get_metadata(src_path, src_dir, loc) + + yield src_path, metadata def update_exif_data(self, metadata): diff --git a/tests/test_cli.py b/tests/test_cli.py index 024d4ed..45dc2ce 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,6 +2,7 @@ import shutil from click.testing import CliRunner from pathlib import Path import pytest +import inquirer from ordigi import cli @@ -62,6 +63,7 @@ class TestOrdigi: cli._check, cli._clean, cli._compare, + cli._edit, cli._import, cli._init, cli._sort, @@ -76,6 +78,32 @@ class TestOrdigi: self.assert_cli(cli._clone, ['not_exist'], state=2) + def test_edit(self, monkeypatch): + + bool_options = () + + arg_options = ( + *self.logger_options, + *self.filter_options, + ) + + def mockreturn(prompt, theme): + return {'value': '03-12-2021 08:12:35'} + + monkeypatch.setattr(inquirer, 'prompt', mockreturn) + + args = ( + '--key', + 'date_original', + str(self.src_path.joinpath('test_exif/photo.png')), + str(self.src_path), + ) + + self.assert_cli(cli._edit, args) + + # self.assert_options(cli._edit, bool_options, arg_options, args) + # self.assert_all_options(cli._edit, bool_options, arg_options, args) + def test_sort(self): bool_options = ( # '--interactive', diff --git a/tests/test_collection.py b/tests/test_collection.py index 288c69c..0d3b6ef 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -251,7 +251,6 @@ class TestCollection: # Summary is created and there is no errors assert not summary.errors - # @pytest.mark.skip() def test_edit_metadata(self, tmp_path, monkeypatch): path = tmp_path / 'collection' shutil.copytree(self.src_path, path) @@ -263,7 +262,7 @@ class TestCollection: monkeypatch.setattr(inquirer, 'prompt', mockreturn) - collection.edit_metadata(path, 'date_original', overwrite=True) + collection.edit_metadata({path}, {'date_original'}, overwrite=True) # check if db value is set date = collection.db.sqlite.get_metadata_data('test_exif/photo.rw2', 'DateOriginal')