From 8bc8b6c5c40413f87dbb6d8305eeef4af4ca66f8 Mon Sep 17 00:00:00 2001 From: Cedric Leporcq Date: Sat, 19 Jun 2021 15:42:28 +0200 Subject: [PATCH] Drop textfile support --- elodie.py | 1 - elodie/media/base.py | 3 +- elodie/media/text.py | 203 ----------- elodie/tests/elodie_test.py | 50 --- elodie/tests/files/text.txt | 0 .../tests/files/valid-with-numeric-header.txt | 4 - elodie/tests/files/valid-without-header.txt | 1 - elodie/tests/files/valid.txt | 3 - elodie/tests/files/with-original-name.txt | 3 - elodie/tests/filesystem_test.py | 1 - elodie/tests/media/base_test.py | 5 +- elodie/tests/media/text_test.py | 318 ------------------ elodie/tools/add_original_name.py | 1 - 13 files changed, 3 insertions(+), 590 deletions(-) delete mode 100644 elodie/media/text.py delete mode 100644 elodie/tests/files/text.txt delete mode 100644 elodie/tests/files/valid-with-numeric-header.txt delete mode 100644 elodie/tests/files/valid-without-header.txt delete mode 100644 elodie/tests/files/valid.txt delete mode 100644 elodie/tests/files/with-original-name.txt delete mode 100644 elodie/tests/media/text_test.py diff --git a/elodie.py b/elodie.py index b0206b5..63b5fc6 100755 --- a/elodie.py +++ b/elodie.py @@ -24,7 +24,6 @@ from elodie.filesystem import FileSystem from elodie.localstorage import Db from elodie.media.base import Base, get_all_subclasses from elodie.media.media import Media -from elodie.media.text import Text from elodie.media.audio import Audio from elodie.media.photo import Photo from elodie.media.video import Video diff --git a/elodie/media/base.py b/elodie/media/base.py index 3eae82d..5e66b4c 100644 --- a/elodie/media/base.py +++ b/elodie/media/base.py @@ -3,8 +3,7 @@ The base module provides a base :class:`Base` class for all objects that are tracked by Elodie. The Base class provides some base functionality used by all the media types, but isn't itself used to represent anything. Its sub-classes (:class:`~elodie.media.audio.Audio`, -:class:`~elodie.media.photo.Photo`, :class:`~elodie.media.video.Video`, and -:class:`~elodie.media.text.Text`) +:class:`~elodie.media.photo.Photo`, :class:`~elodie.media.video.Video`) are used to represent the actual files. .. moduleauthor:: Jaisen Mathai diff --git a/elodie/media/text.py b/elodie/media/text.py deleted file mode 100644 index 4e3c6bb..0000000 --- a/elodie/media/text.py +++ /dev/null @@ -1,203 +0,0 @@ -""" -The text module provides a base :class:`Text` class for text files that -are tracked by Elodie. - -.. moduleauthor:: Jaisen Mathai -""" - -from json import dumps, loads -import os -from shutil import copy2, copyfileobj -import time - -# load modules -from elodie import log -from elodie.media.base import Base - - -class Text(Base): - - """The class for all text files. - - :param str source: The fully qualified path to the text file. - """ - - __name__ = 'Text' - - #: Valid extensions for text files. - extensions = ('txt',) - - def __init__(self, source=None): - super(Text, self).__init__(source) - self.reset_cache() - - def get_album(self): - self.parse_metadata_line() - if(not isinstance(self.metadata_line, dict) or - 'album' not in self.metadata_line): - return None - - return self.metadata_line['album'] - - def get_coordinate(self, type='latitude'): - self.parse_metadata_line() - if not self.metadata_line: - return None - elif type in self.metadata_line: - if type == 'latitude': - return self.metadata_line['latitude'] or None - elif type == 'longitude': - return self.metadata_line['longitude'] or None - - return None - - def get_date_taken(self): - source = self.source - self.parse_metadata_line() - - # We return the value if found in metadata - if(isinstance(self.metadata_line, dict) and - 'date_taken' in self.metadata_line): - return time.gmtime(self.metadata_line['date_taken']) - - # If there's no date_taken in the metadata we return - # from the filesystem - seconds_since_epoch = min( - os.path.getmtime(source), - os.path.getctime(source) - ) - return time.gmtime(seconds_since_epoch) - - def get_metadata(self): - self.parse_metadata_line() - return super(Text, self).get_metadata() - - def get_original_name(self): - self.parse_metadata_line() - - # We return the value if found in metadata - if(isinstance(self.metadata_line, dict) and - 'original_name' in self.metadata_line): - return self.metadata_line['original_name'] - - return super(Text, self).get_original_name() - - def get_title(self): - self.parse_metadata_line() - - if(not isinstance(self.metadata_line, dict) or - 'title' not in self.metadata_line): - return None - - return self.metadata_line['title'] - - def reset_cache(self): - """Resets any internal cache - """ - self.metadata_line = None - super(Text, self).reset_cache() - - def set_album(self, name): - status = self.write_metadata(album=name) - self.reset_cache() - return status - - def set_date_taken(self, passed_in_time): - if(time is None): - return False - - seconds_since_epoch = time.mktime(passed_in_time.timetuple()) - status = self.write_metadata(date_taken=seconds_since_epoch) - self.reset_cache() - return status - - def set_original_name(self, name=None): - """Sets the original name if not already set. - - :returns: True, False, None - """ - if(not self.is_valid()): - return None - - # If EXIF original name tag is set then we return. - if self.get_original_name() is not None: - return None - - source = self.source - - if not name: - name = os.path.basename(source) - - status = self.write_metadata(original_name=name) - self.reset_cache() - return status - - def set_location(self, latitude, longitude): - status = self.write_metadata(latitude=latitude, longitude=longitude) - self.reset_cache() - return status - - def parse_metadata_line(self): - if isinstance(self.metadata_line, dict): - return self.metadata_line - - source = self.source - if source is None: - return None - - with open(source, 'r') as f: - first_line = f.readline().strip() - - try: - parsed_json = loads(first_line) - if isinstance(parsed_json, dict): - self.metadata_line = parsed_json - except ValueError: - log.error('Could not parse JSON from first line: %s' % first_line) - pass - - def write_metadata(self, **kwargs): - if len(kwargs) == 0: - return False - - source = self.source - - self.parse_metadata_line() - - # Set defaults for a file without metadata - # Check if self.metadata_line is set and use that instead - metadata_line = {} - has_metadata = False - if isinstance(self.metadata_line, dict): - metadata_line = self.metadata_line - has_metadata = True - - for name in kwargs: - metadata_line[name] = kwargs[name] - - metadata_as_json = dumps(metadata_line) - - # Create an _original copy just as we do with exiftool - # This is to keep all file processing logic in line with exiftool - copy2(source, source + '_original') - - if has_metadata: - # Update the first line of this file in place - # http://stackoverflow.com/a/14947384 - with open(source, 'r') as f_read: - f_read.readline() - with open(source, 'w') as f_write: - f_write.write("{}\n".format(metadata_as_json)) - copyfileobj(f_read, f_write) - else: - # Prepend the metadata to the file - with open(source, 'r') as f_read: - original_contents = f_read.read() - with open(source, 'w') as f_write: - f_write.write("{}\n{}".format( - metadata_as_json, - original_contents) - ) - - self.reset_cache() - return True diff --git a/elodie/tests/elodie_test.py b/elodie/tests/elodie_test.py index e90edf9..ac055c0 100644 --- a/elodie/tests/elodie_test.py +++ b/elodie/tests/elodie_test.py @@ -21,7 +21,6 @@ from elodie.config import load_config from elodie.localstorage import Db from elodie.media.audio import Audio from elodie.media.photo import Photo -from elodie.media.text import Text from elodie.media.video import Video from elodie.plugins.plugins import Plugins from elodie.plugins.googlephotos.googlephotos import GooglePhotos @@ -460,31 +459,6 @@ def test_update_location_on_photo(): assert helper.isclose(metadata_processed['latitude'], 37.36883), metadata_processed['latitude'] assert helper.isclose(metadata_processed['longitude'], -122.03635), metadata_processed['longitude'] -def test_update_location_on_text(): - temporary_folder, folder = helper.create_working_folder() - temporary_folder_destination, folder_destination = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('text.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - helper.reset_dbs() - status = elodie.update_location(text, origin, 'Sunnyvale, CA') - helper.restore_dbs() - - text_processed = Text(origin) - metadata_processed = text_processed.get_metadata() - - shutil.rmtree(folder) - shutil.rmtree(folder_destination) - - assert status == True, status - assert metadata['latitude'] != metadata_processed['latitude'] - assert helper.isclose(metadata_processed['latitude'], 37.36883), metadata_processed['latitude'] - assert helper.isclose(metadata_processed['longitude'], -122.03635), metadata_processed['longitude'] - def test_update_location_on_video(): temporary_folder, folder = helper.create_working_folder() temporary_folder_destination, folder_destination = helper.create_working_folder() @@ -558,30 +532,6 @@ def test_update_time_on_photo(): assert metadata['date_taken'] != metadata_processed['date_taken'] assert metadata_processed['date_taken'] == helper.time_convert((2000, 1, 1, 12, 0, 0, 5, 1, 0)), metadata_processed['date_taken'] -def test_update_time_on_text(): - temporary_folder, folder = helper.create_working_folder() - temporary_folder_destination, folder_destination = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('text.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - helper.reset_dbs() - status = elodie.update_time(text, origin, '2000-01-01 12:00:00') - helper.restore_dbs() - - text_processed = Text(origin) - metadata_processed = text_processed.get_metadata() - - shutil.rmtree(folder) - shutil.rmtree(folder_destination) - - assert status == True, status - assert metadata['date_taken'] != metadata_processed['date_taken'] - assert metadata_processed['date_taken'] == helper.time_convert((2000, 1, 1, 12, 0, 0, 5, 1, 0)), metadata_processed['date_taken'] - def test_update_time_on_video(): temporary_folder, folder = helper.create_working_folder() temporary_folder_destination, folder_destination = helper.create_working_folder() diff --git a/elodie/tests/files/text.txt b/elodie/tests/files/text.txt deleted file mode 100644 index e69de29..0000000 diff --git a/elodie/tests/files/valid-with-numeric-header.txt b/elodie/tests/files/valid-with-numeric-header.txt deleted file mode 100644 index a9f9d8b..0000000 --- a/elodie/tests/files/valid-with-numeric-header.txt +++ /dev/null @@ -1,4 +0,0 @@ -1234567890 - - -See gh-98 diff --git a/elodie/tests/files/valid-without-header.txt b/elodie/tests/files/valid-without-header.txt deleted file mode 100644 index 30d5d5a..0000000 --- a/elodie/tests/files/valid-without-header.txt +++ /dev/null @@ -1 +0,0 @@ -This file has no header. diff --git a/elodie/tests/files/valid.txt b/elodie/tests/files/valid.txt deleted file mode 100644 index 75c20ad..0000000 --- a/elodie/tests/files/valid.txt +++ /dev/null @@ -1,3 +0,0 @@ -{"date_taken":1460027726.0,"latitude":"51.521435","longitude":"0.162714","title":"sample title"} - -This file has a valid header. diff --git a/elodie/tests/files/with-original-name.txt b/elodie/tests/files/with-original-name.txt deleted file mode 100644 index c35b56a..0000000 --- a/elodie/tests/files/with-original-name.txt +++ /dev/null @@ -1,3 +0,0 @@ -{"date_taken":1460027726.0,"latitude":"51.521435","longitude":"0.162714","title":"sample title","original_name":"originalname.txt"} - -This file has a valid header. diff --git a/elodie/tests/filesystem_test.py b/elodie/tests/filesystem_test.py index 06575e1..fb6c7e5 100644 --- a/elodie/tests/filesystem_test.py +++ b/elodie/tests/filesystem_test.py @@ -15,7 +15,6 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirna from . import helper from elodie.config import load_config from elodie.filesystem import FileSystem -from elodie.media.text import Text from elodie.media.media import Media from elodie.media.photo import Photo from elodie.media.video import Video diff --git a/elodie/tests/media/base_test.py b/elodie/tests/media/base_test.py index 9838c80..88a66b0 100644 --- a/elodie/tests/media/base_test.py +++ b/elodie/tests/media/base_test.py @@ -17,7 +17,6 @@ import helper from elodie.media.base import Base, get_all_subclasses from elodie.media.media import Media from elodie.media.audio import Audio -from elodie.media.text import Text from elodie.media.photo import Photo from elodie.media.video import Video @@ -28,13 +27,13 @@ teardown_module = helper.teardown_module def test_get_all_subclasses(): subclasses = get_all_subclasses(Base) - expected = {Media, Base, Text, Photo, Video, Audio} + expected = {Media, Base, Photo, Video, Audio} assert subclasses == expected, subclasses def test_get_class_by_file_without_extension(): base_file = helper.get_file('withoutextension') - cls = Base.get_class_by_file(base_file, [Audio, Text, Photo, Video]) + cls = Base.get_class_by_file(base_file, [Audio, Photo, Video]) assert cls is None, cls diff --git a/elodie/tests/media/text_test.py b/elodie/tests/media/text_test.py deleted file mode 100644 index 6f0c9b2..0000000 --- a/elodie/tests/media/text_test.py +++ /dev/null @@ -1,318 +0,0 @@ -# -*- coding: utf-8 -# Project imports -import os -import sys - -from datetime import datetime -import shutil -import tempfile -import time - -from nose.plugins.skip import SkipTest - -sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))) -sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) - -import helper -from elodie.media.base import Base -from elodie.media.text import Text - -os.environ['TZ'] = 'GMT' - -def test_text_extensions(): - text = Text() - extensions = text.extensions - - assert 'txt' in extensions - - valid_extensions = Text.get_valid_extensions() - - assert extensions == valid_extensions, valid_extensions - -def test_get_original_name(): - media = Text(helper.get_file('with-original-name.txt')) - original_name = media.get_original_name() - - assert original_name == 'originalname.txt', original_name - -def test_get_original_name_when_does_not_exist(): - media = Text(helper.get_file('valid.txt')) - original_name = media.get_original_name() - - assert original_name is None, original_name - -def test_get_title(): - text = Text(helper.get_file('valid.txt')) - text.get_metadata() - assert text.get_title() == 'sample title', text.get_title() - -def test_get_default_coordinate(): - text = Text(helper.get_file('valid.txt')) - text.get_metadata() - assert text.get_coordinate() == '51.521435', text.get_coordinate() - -def test_get_coordinate_latitude(): - text = Text(helper.get_file('valid.txt')) - text.get_metadata() - assert text.get_coordinate('latitude') == '51.521435', text.get_coordinate('latitude') - -def test_get_coordinate_longitude(): - text = Text(helper.get_file('valid.txt')) - text.get_metadata() - assert text.get_coordinate('longitude') == '0.162714', text.get_coordinate('longitude') - -def test_get_date_taken(): - text = Text(helper.get_file('valid.txt')) - text.get_metadata() - - date_taken = text.get_date_taken() - - assert date_taken == helper.time_convert((2016, 4, 7, 11, 15, 26, 3, 98, 0)), date_taken - -def test_get_date_taken_from_invalid(): - origin = helper.get_file('valid-without-header.txt') - text = Text(origin) - text.get_metadata() - - date_taken = text.get_date_taken() - - seconds_since_epoch = min( - os.path.getmtime(origin), - os.path.getctime(origin) - ) - expected_date_taken = time.gmtime(seconds_since_epoch) - - assert date_taken == expected_date_taken, date_taken - -def test_get_metadata_with_numeric_header(): - # See gh-98 for details - text = Text(helper.get_file('valid-with-numeric-header.txt')) - - # Should not throw error - # TypeError: argument of type 'int' is not iterable - metadata = text.get_metadata() - - assert metadata['mime_type'] == 'text/plain' - -def test_set_album(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents = f.read() - - album_name = 'Test Album' - assert album_name != metadata['album'] - - status = text.set_album(album_name) - assert status == True, status - - text_new = Text(origin) - metadata_new = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert album_name == metadata_new['album'], metadata_new - -def test_set_date_taken(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents = f.read() - - assert helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)) != metadata['date_taken'], metadata['date_taken'] - - status = text.set_date_taken(datetime(2013, 9, 30, 7, 6, 5)) - assert status == True, status - - text_new = Text(origin) - metadata_new = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)) == metadata_new['date_taken'], metadata_new['date_taken'] - -def test_set_location(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid.txt'), origin) - - text = Text(origin) - origin_metadata = text.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents = f.read() - - # Verify that original photo has different location info that what we - # will be setting and checking - assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude'] - assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude'] - - status = text.set_location(11.1111111111, 99.9999999999) - - assert status == True, status - - text_new = Text(origin) - metadata = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude'] - -def test_set_album_without_header(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid-without-header.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - with open(origin, 'r') as f: - contents = f.read() - - album_name = 'Test Album' - assert album_name != metadata['album'] - - status = text.set_album(album_name) - assert status == True, status - - text_new = Text(origin) - metadata_new = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert album_name == metadata_new['album'], metadata_new - -def test_set_date_taken_without_header(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid-without-header.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - - with open(origin, 'r') as f: - contents = f.read() - - assert helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)) != metadata['date_taken'], metadata['date_taken'] - - status = text.set_date_taken(datetime(2013, 9, 30, 7, 6, 5)) - assert status == True, status - - text_new = Text(origin) - metadata_new = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert helper.time_convert((2013, 9, 30, 7, 6, 5, 0, 273, 0)) == metadata_new['date_taken'], metadata_new['date_taken'] - -def test_set_location_without_header(): - temporary_folder, folder = helper.create_working_folder() - - origin = '%s/text.txt' % folder - shutil.copyfile(helper.get_file('valid-without-header.txt'), origin) - - text = Text(origin) - origin_metadata = text.get_metadata() - - with open(origin, 'r') as f: - contents = f.read() - - # Verify that original photo has different location info that what we - # will be setting and checking - assert not helper.isclose(origin_metadata['latitude'], 11.1111111111), origin_metadata['latitude'] - assert not helper.isclose(origin_metadata['longitude'], 99.9999999999), origin_metadata['longitude'] - - status = text.set_location(11.1111111111, 99.9999999999) - - assert status == True, status - - text_new = Text(origin) - metadata = text_new.get_metadata() - - with open(origin, 'r') as f: - f.readline() - contents_new = f.read() - assert contents == contents_new, contents_new - - shutil.rmtree(folder) - - assert helper.isclose(metadata['latitude'], 11.1111111111), metadata['latitude'] - -def test_set_original_name(): - temporary_folder, folder = helper.create_working_folder() - - random_file_name = '%s.txt' % helper.random_string(10) - origin = '%s/%s' % (folder, random_file_name) - shutil.copyfile(helper.get_file('valid.txt'), origin) - - text = Text(origin) - metadata = text.get_metadata() - text.set_original_name() - metadata_updated = text.get_metadata() - - shutil.rmtree(folder) - - assert metadata['original_name'] is None, metadata['original_name'] - assert metadata_updated['original_name'] == random_file_name, metadata_updated['original_name'] - -def test_set_original_name_with_arg(): - temporary_folder, folder = helper.create_working_folder() - - random_file_name = '%s.txt' % helper.random_string(10) - origin = '%s/%s' % (folder, random_file_name) - shutil.copyfile(helper.get_file('valid.txt'), origin) - - new_name = helper.random_string(15) - - text = Text(origin) - metadata = text.get_metadata() - text.set_original_name(new_name) - metadata_updated = text.get_metadata() - - shutil.rmtree(folder) - - assert metadata['original_name'] is None, metadata['original_name'] - assert metadata_updated['original_name'] == new_name, metadata_updated['original_name'] diff --git a/elodie/tools/add_original_name.py b/elodie/tools/add_original_name.py index 2f39a2b..559de2a 100644 --- a/elodie/tools/add_original_name.py +++ b/elodie/tools/add_original_name.py @@ -12,7 +12,6 @@ from elodie.filesystem import FileSystem from elodie.localstorage import Db from elodie.media.base import Base, get_all_subclasses from elodie.media.media import Media -from elodie.media.text import Text from elodie.media.audio import Audio from elodie.media.photo import Photo from elodie.media.video import Video