Test edit metadata

This commit is contained in:
Cédric Leporcq 2022-04-23 13:01:55 +02:00
parent be4cf38377
commit fd35963994
7 changed files with 125 additions and 59 deletions

View File

@ -353,8 +353,6 @@ def _compare(**kwargs):
'-k', '-k',
default=None, default=None,
multiple=True, multiple=True,
# TODO Allow edit all values
required=True,
help="Select exif tags groups to edit", help="Select exif tags groups to edit",
) )
@click.argument('subdirs', required=False, nargs=-1, type=click.Path()) @click.argument('subdirs', required=False, nargs=-1, type=click.Path())
@ -378,40 +376,53 @@ def _edit(**kwargs):
} }
) )
editable_keys = (
'album',
'camera_make',
'camera_model',
'city',
'coordinates',
'country',
# 'date_created',
'date_media',
# 'date_modified',
'date_original',
'default',
'latitude',
'location',
'longitude',
'latitude_ref',
'longitude_ref',
'original_name',
'state',
'title',
)
if not kwargs['key']:
keys = set(editable_keys)
else:
keys = set(kwargs['key'])
location = False location = False
keys = set() for key in keys:
for key in kwargs['key']: if key not in editable_keys:
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") LOG.error(f"key '{key}' is not valid")
sys.exit(1) sys.exit(1)
if key == 'coordinates':
keys.remove('coordinates')
keys.update(['latitude', 'longitude'])
if key in ( if key in (
'city',
'latitude', 'latitude',
'location',
'longitude', 'longitude',
'latitude_ref', 'latitude_ref',
'longitude_ref', 'longitude_ref',
): ):
location = True location = True
if key == 'coordinates':
keys.update(['latitude', 'longitude'])
else:
keys.add(key)
if location: if location:
loc = _cli_get_location(collection) loc = _cli_get_location(collection)
else: else:

View File

@ -169,9 +169,6 @@ class FPath:
'state', 'state',
'title', 'title',
): ):
if item == 'location':
mask = 'default'
if metadata[mask]: if metadata[mask]:
part = str(metadata[mask]) part = str(metadata[mask])
elif item in 'custom': elif item in 'custom':
@ -1168,22 +1165,48 @@ class Collection(SortMedias):
# Check date format # Check date format
value = media.get_date_format(answer['value']) value = media.get_date_format(answer['value'])
else: else:
if not answer[key].isalnum(): value = answer['value']
if not value.isalnum():
print("Invalid entry, use alphanumeric chars") print("Invalid entry, use alphanumeric chars")
value = inquirer.prompt(prompt, theme=self.theme) value = inquirer.prompt(prompt, theme=self.theme)
result = False result = False
if value: if value:
media.metadata[key] = value media.metadata[key] = value
if key == 'location':
coordinates = loc.coordinates_by_name(value)
if coordinates:
media.metadata['latitude'] = coordinates['latitude']
media.metadata['longitude'] = coordinates['longitude']
media.set_location_from_coordinates(loc)
# Update database # Update database
self.db.add_file_data(media.metadata) self.db.add_file_data(media.metadata)
# Update exif data # Update exif data
exif = WriteExif( if key in (
file_path, 'date_original',
media.metadata, 'album',
ignore_tags=self.opt['Exif']['ignore_tags'], 'title',
) 'latitude',
result = exif.set_key_values(key, value) 'location',
'longitude',
'latitude_ref',
'longitude_ref',
):
exif = WriteExif(
file_path,
media.metadata,
ignore_tags=self.opt['Exif']['ignore_tags'],
)
if key == 'location':
result = exif.set_key_values(
'latitude', media.metadata['latitude']
)
result = exif.set_key_values(
'longitude', media.metadata['longitude']
)
else:
result = exif.set_key_values(key, value)
if result: if result:
self.summary.append('update', True, file_path) self.summary.append('update', True, file_path)
else: else:

View File

@ -59,7 +59,7 @@ class Sqlite:
'City': 'text', 'City': 'text',
'State': 'text', 'State': 'text',
'Country': 'text', 'Country': 'text',
'Default': 'text', 'Location': 'text',
} }
self.tables = { self.tables = {

View File

@ -98,5 +98,4 @@ class GeoLocation:
if locator_reverse is not None: if locator_reverse is not None:
return locator_reverse.raw return locator_reverse.raw
return None return None

View File

@ -303,12 +303,12 @@ class Media(ReadExif):
self.loc_keys = ( self.loc_keys = (
'latitude', 'latitude',
'longitude', 'longitude',
'location',
'latitude_ref', 'latitude_ref',
'longitude_ref', 'longitude_ref',
'city', 'city',
'state', 'state',
'country', 'country',
'default',
) )
def get_mimetype(self): def get_mimetype(self):
@ -510,7 +510,7 @@ class Media(ReadExif):
continue continue
label = utils.snake2camel(key) label = utils.snake2camel(key)
value = db.get_metadata_data(relpath, label) value = db.get_metadata(relpath, label)
if 'date' in key: if 'date' in key:
formated_data = self.get_date_format(value) formated_data = self.get_date_format(value)
else: else:
@ -518,10 +518,10 @@ class Media(ReadExif):
self.metadata[key] = formated_data self.metadata[key] = formated_data
for key in 'src_dir', 'subdirs', 'filename': for key in 'src_dir', 'subdirs', 'filename':
label = utils.snake2camel(key) label = utils.snake2camel(key)
formated_data = db.get_metadata_data(relpath, label) formated_data = db.get_metadata(relpath, label)
self.metadata[key] = formated_data self.metadata[key] = formated_data
return db.get_metadata_data(relpath, 'LocationId') return db.get_metadata(relpath, 'LocationId')
def _check_file(self, db, root): def _check_file(self, db, root):
"""Check if file_path is a subpath of root""" """Check if file_path is a subpath of root"""
@ -548,7 +548,7 @@ class Media(ReadExif):
return None, None return None, None
def _set_location_from_db(self, location_id, db): def set_location_from_db(self, location_id, db):
self.metadata['location_id'] = location_id self.metadata['location_id'] = location_id
@ -563,7 +563,7 @@ class Media(ReadExif):
for key in self.loc_keys: for key in self.loc_keys:
self.metadata[key] = None self.metadata[key] = None
def _set_location_from_coordinates(self, loc): def set_location_from_coordinates(self, loc):
self.metadata['location_id'] = None self.metadata['location_id'] = None
@ -572,11 +572,13 @@ class Media(ReadExif):
self.metadata['latitude'], self.metadata['longitude'] self.metadata['latitude'], self.metadata['longitude']
) )
self.log.debug("location: {place_name['default']}") self.log.debug("location: {place_name['default']}")
for key in ('city', 'state', 'country', 'default'): for key in ('city', 'state', 'country', 'location'):
# mask = 'city' # mask = 'city'
# place_name = {'default': u'Sunnyvale', 'city-random': u'Sunnyvale'} # place_name = {'default': u'Sunnyvale', 'city-random': u'Sunnyvale'}
if key in place_name: if key in place_name:
self.metadata[key] = place_name[key] self.metadata[key] = place_name[key]
elif key == 'location':
self.metadata[key] = place_name['default']
else: else:
self.metadata[key] = None self.metadata[key] = None
else: else:
@ -613,7 +615,7 @@ class Media(ReadExif):
relpath, db_checksum = self._check_file(db, root) relpath, db_checksum = self._check_file(db, root)
if db_checksum: if db_checksum:
location_id = self._set_metadata_from_db(db, relpath) location_id = self._set_metadata_from_db(db, relpath)
self._set_location_from_db(location_id, db) self.set_location_from_db(location_id, db)
else: else:
# file not in db # file not in db
self.metadata['src_dir'] = str(self.src_dir) self.metadata['src_dir'] = str(self.src_dir)
@ -623,7 +625,7 @@ class Media(ReadExif):
self.metadata['filename'] = self.file_path.name self.metadata['filename'] = self.file_path.name
self._set_metadata_from_exif() self._set_metadata_from_exif()
self._set_location_from_coordinates(loc) self.set_location_from_coordinates(loc)
self.metadata['date_media'] = self.get_date_media() self.metadata['date_media'] = self.get_date_media()
self.metadata['location_id'] = location_id self.metadata['location_id'] = location_id

View File

@ -251,11 +251,10 @@ class TestCollection:
# Summary is created and there is no errors # Summary is created and there is no errors
assert not summary.errors assert not summary.errors
def test_edit_metadata(self, tmp_path, monkeypatch): def test_edit_date_metadata(self, tmp_path, monkeypatch):
path = tmp_path / 'collection' path = tmp_path / 'collection'
shutil.copytree(self.src_path, path) shutil.copytree(self.src_path, path)
collection = Collection(path, {'cache': False}) collection = Collection(path, {'cache': False})
# loc = GeoLocation()
def mockreturn(prompt, theme): def mockreturn(prompt, theme):
return {'value': '03-12-2021 08:12:35'} return {'value': '03-12-2021 08:12:35'}
@ -264,10 +263,34 @@ class TestCollection:
collection.edit_metadata({path}, {'date_original'}, overwrite=True) collection.edit_metadata({path}, {'date_original'}, overwrite=True)
# check if db value is set # check if db value is set
date = collection.db.sqlite.get_metadata_data('test_exif/photo.rw2', file_path = 'test_exif/photo.rw2'
'DateOriginal') date = collection.db.sqlite.get_metadata(file_path, 'DateOriginal')
assert date == '2021-03-12 08:12:35' assert date == '2021-03-12 08:12:35'
# Check if exif value is set # Check if exif value is set
file_path = path.joinpath('test_exif/photo.rw2') path_file = path.joinpath(file_path)
date = ExifTool(file_path).asdict()['EXIF:DateTimeOriginal'] date = ExifTool(path_file).asdict()['EXIF:DateTimeOriginal']
assert date == '2021-03-12 08:12:35' assert date == '2021-03-12 08:12:35'
def test_edit_location_metadata(self, tmp_path, monkeypatch):
path = tmp_path / 'collection'
shutil.copytree(self.src_path, path)
collection = Collection(path, {'cache': False})
loc = GeoLocation()
def mockreturn(prompt, theme):
return {'value': 'lyon'}
monkeypatch.setattr(inquirer, 'prompt', mockreturn)
collection.edit_metadata({path}, {'location'}, loc, True)
# check if db value is set
file_path = 'test_exif/photo.rw2'
location_id = collection.db.sqlite.get_metadata(file_path, 'LocationId')
location = collection.db.sqlite.get_location_data(location_id, 'Location')
assert location_id, location == 'Lyon'
# Check if exif value is set
path_file = path.joinpath(file_path)
latitude = ExifTool(path_file).asdict()['EXIF:GPSLatitude']
longitude = ExifTool(path_file).asdict()['EXIF:GPSLongitude']
assert latitude == 45.7578136999889
assert longitude == 4.83201140001667

View File

@ -41,13 +41,13 @@ class TestSqlite:
'City': 'city', 'City': 'city',
'State': 'state', 'State': 'state',
'Country': 'country', 'Country': 'country',
'Default': 'default' 'Location': 'location'
} }
cls.sqlite.add_row('metadata', row_data) cls.sqlite.add_row('metadata', row_data)
cls.sqlite.add_row('location', location_data) cls.sqlite.add_row('location', location_data)
# cls.sqlite.add_metadata_data('filename', 'ksinslsdosic', 'original_name', 'date_original', 'album', 1) # cls.sqlite.add_metadata_data('filename', 'ksinslsdosic', 'original_name', 'date_original', 'album', 1)
# cls.sqlite.add_location(24.2, 7.3, 'city', 'state', 'country', 'default') # cls.sqlite.add_location(24.2, 7.3, 'city', 'state', 'country', 'location')
yield yield
@ -88,14 +88,22 @@ class TestSqlite:
assert not self.sqlite.get_checksum('invalid') assert not self.sqlite.get_checksum('invalid')
assert self.sqlite.get_checksum('file_path') == 'checksum' assert self.sqlite.get_checksum('file_path') == 'checksum'
def test_get_metadata_data(self): def test_get_metadata(self):
assert not self.sqlite.get_metadata_data('invalid', 'DateOriginal') assert not self.sqlite.get_metadata('invalid', 'DateOriginal')
assert self.sqlite.get_metadata_data('file_path', 'Album') == 'album' assert self.sqlite.get_metadata('file_path', 'Album') == 'album'
def test_add_location(self): def test_add_location(self):
result = tuple(self.sqlite.cur.execute("""select * from location where result = tuple(self.sqlite.cur.execute("""select * from location where
rowid=1""").fetchone()) rowid=1""").fetchone())
assert result == (24.2, 7.3, 'latitude_ref', 'longitude_ref', 'city', 'state', 'country', 'default') assert result == (
24.2, 7.3,
'latitude_ref',
'longitude_ref',
'city',
'state',
'country',
'location',
)
@pytest.mark.skip('TODO') @pytest.mark.skip('TODO')
def test_get_location_data(self, LocationId, data): def test_get_location_data(self, LocationId, data):
@ -106,8 +114,8 @@ class TestSqlite:
pass pass
def test_get_location_nearby(self): def test_get_location_nearby(self):
value = self.sqlite.get_location_nearby(24.2005, 7.3004, 'Default') value = self.sqlite.get_location_nearby(24.2005, 7.3004, 'Location')
assert value == 'default' assert value == 'location'
@pytest.mark.skip('TODO') @pytest.mark.skip('TODO')
def test_delete_row(self, table, id): def test_delete_row(self, table, id):