From 62a60401c628ea43ee260c71793418f694a8eac2 Mon Sep 17 00:00:00 2001 From: Jaisen Mathai Date: Tue, 7 May 2019 22:36:57 -0700 Subject: [PATCH 1/4] Add timezone from location with tests - not complete --- elodie/media/base.py | 27 +++++++++++ elodie/tests/media/photo_test.py | 80 +++++++++++++++++++++++++++++++- requirements.txt | 3 ++ 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/elodie/media/base.py b/elodie/media/base.py index 83f29c5a..52388bfd 100644 --- a/elodie/media/base.py +++ b/elodie/media/base.py @@ -10,8 +10,13 @@ .. moduleauthor:: Jaisen Mathai """ +import datetime import mimetypes import os +import pytz +from tzwhere.tzwhere import tzwhere + +from elodie.config import load_config try: # Py3k compatibility basestring @@ -39,6 +44,28 @@ def format_metadata(self, **kwargs): :returns: dict """ + def get_adjusted_date_taken(self): + """Returns date taken and adjust based on time zone if needed. + Time zone conversion is based on a configurable value from config.ini. + + :returns: int + """ + config = load_config() + metadata = self.get_metadata() + if( + 'Timezone' in config and + 'use_location' in config['Timezone'] and + config['Timezone'].getboolean('use_location') is True and + metadata['latitude'] is not None and + metadata['longitude'] is not None + ): + timezone_string = tzwhere().tzNameAt( + metadata['latitude'], + metadata['longitude'] + ) + return timezone_string + return metadata['date_taken'] + def get_album(self): """Base method for getting an album diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index d2141895..ec4dd409 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -1,20 +1,22 @@ # -*- coding: utf-8 # Project imports from __future__ import unicode_literals +import mock import os import sys from datetime import datetime import shutil -import tempfile import time from nose.plugins.skip import SkipTest +from tempfile import gettempdir 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.config import load_config from elodie.media.media import Media from elodie.media.photo import Photo @@ -57,6 +59,82 @@ def test_is_not_valid(): assert not photo.is_valid() +@mock.patch('elodie.config.config_file', '%s/config.ini-no-config' % gettempdir()) +def test_get_adjusted_date_taken_no_config(): + with open('%s/config.ini-no-config' % gettempdir(), 'w') as f: + f.write(""" + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + date_taken = photo.get_adjusted_date_taken() + + if hasattr(load_config, 'config'): + del load_config.config + +@mock.patch('elodie.config.config_file', '%s/config.ini-do-not-use-location' % gettempdir()) +def test_get_adjusted_date_taken_do_not_use_location(): + with open('%s/config.ini-do-not-use-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=False + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + date_taken = photo.get_adjusted_date_taken() + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken + +@mock.patch('elodie.config.config_file', '%s/config.ini-without-exif-location' % gettempdir()) +def test_get_adjusted_date_taken_without_exif_location(): + with open('%s/config.ini-without-exif-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=True + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('plain.jpg')) + date_taken = photo.get_adjusted_date_taken() + print(photo.get_metadata()) + print(date_taken) + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken + +@mock.patch('elodie.config.config_file', '%s/config.ini-use-location' % gettempdir()) +def test_get_adjusted_date_taken_use_location(): + with open('%s/config.ini-use-location' % gettempdir(), 'w') as f: + f.write(""" +[Timezone] +use_location=True + """) + + if hasattr(load_config, 'config'): + del load_config.config + + photo = Photo(helper.get_file('with-location.jpg')) + date_taken = photo.get_adjusted_date_taken() + print(photo.get_metadata()) + print(date_taken) + + if hasattr(load_config, 'config'): + del load_config.config + + assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 1)), date_taken + def test_get_metadata_of_invalid_photo(): photo = Photo(helper.get_file('invalid.jpg')) metadata = photo.get_metadata() diff --git a/requirements.txt b/requirements.txt index 2c8fccbd..45537143 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,6 @@ Send2Trash==1.3.0 future==0.16.0 configparser==3.5.0 tabulate==0.7.7 +pytz==2019.1 +tzwhere==3.0.3 +numpy==1.16.3 From 56af78e612f3dd1ed6ad13b53573bdb1143153be Mon Sep 17 00:00:00 2001 From: Jaisen Mathai Date: Wed, 8 May 2019 01:02:49 -0700 Subject: [PATCH 2/4] Add additional metadata attribute and pass tests --- elodie/media/base.py | 72 +++++++++++++++++++------------- elodie/tests/media/photo_test.py | 31 +++++++------- 2 files changed, 59 insertions(+), 44 deletions(-) diff --git a/elodie/media/base.py b/elodie/media/base.py index 52388bfd..dd2ecf09 100644 --- a/elodie/media/base.py +++ b/elodie/media/base.py @@ -10,10 +10,11 @@ .. moduleauthor:: Jaisen Mathai """ -import datetime import mimetypes import os -import pytz +from datetime import datetime, timedelta +from pytz import timezone +from time import mktime from tzwhere.tzwhere import tzwhere from elodie.config import load_config @@ -44,42 +45,48 @@ def format_metadata(self, **kwargs): :returns: dict """ - def get_adjusted_date_taken(self): + + def get_album(self): + """Base method for getting an album + + :returns: None + """ + return None + + def get_camera_make(self): + return None + + def get_camera_model(self): + return None + + def get_date_taken_adjusted(self, date_taken, latitude, longitude): """Returns date taken and adjust based on time zone if needed. Time zone conversion is based on a configurable value from config.ini. :returns: int """ config = load_config() - metadata = self.get_metadata() + + # Check if use_location config is true and file has lat/lon + # Else default to returning date_taken directly from file if( 'Timezone' in config and 'use_location' in config['Timezone'] and config['Timezone'].getboolean('use_location') is True and - metadata['latitude'] is not None and - metadata['longitude'] is not None + latitude is not None and + longitude is not None ): timezone_string = tzwhere().tzNameAt( - metadata['latitude'], - metadata['longitude'] - ) - return timezone_string - return metadata['date_taken'] - - - def get_album(self): - """Base method for getting an album + latitude, + longitude + ) + date_taken_as_time = datetime.fromtimestamp(mktime(date_taken)) + now_in_timezone = datetime.now(timezone(timezone_string)) + seconds_offset = now_in_timezone.utcoffset().total_seconds() + adjusted_date_taken = date_taken_as_time - timedelta(seconds = seconds_offset) + return adjusted_date_taken.timetuple() - :returns: None - """ - return None - - def get_file_path(self): - """Get the full path to the video. - - :returns: string - """ - return self.source + return date_taken def get_coordinate(self, type): return None @@ -95,11 +102,12 @@ def get_extension(self): source = self.source return os.path.splitext(source)[1][1:].lower() - def get_camera_make(self): - return None + def get_file_path(self): + """Get the full path to the video. - def get_camera_model(self): - return None + :returns: string + """ + return self.source def get_metadata(self, update_cache=False): """Get a dictionary of metadata for any file. @@ -130,7 +138,11 @@ def get_metadata(self, update_cache=False): 'extension': self.get_extension(), 'directory_path': os.path.dirname(source) } - + self.metadata['date_taken_adjusted'] = self.get_date_taken_adjusted( + self.metadata['date_taken'], + self.metadata['latitude'], + self.metadata['longitude'] + ) return self.metadata def get_mimetype(self): diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index ec4dd409..e9dfbf79 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -69,13 +69,14 @@ def test_get_adjusted_date_taken_no_config(): del load_config.config photo = Photo(helper.get_file('plain.jpg')) - date_taken = photo.get_adjusted_date_taken() + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) if hasattr(load_config, 'config'): del load_config.config @mock.patch('elodie.config.config_file', '%s/config.ini-do-not-use-location' % gettempdir()) -def test_get_adjusted_date_taken_do_not_use_location(): +def test_get_date_taken_adjusted_do_not_use_location(): with open('%s/config.ini-do-not-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] @@ -86,15 +87,16 @@ def test_get_adjusted_date_taken_do_not_use_location(): del load_config.config photo = Photo(helper.get_file('plain.jpg')) - date_taken = photo.get_adjusted_date_taken() + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) if hasattr(load_config, 'config'): del load_config.config - assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken + assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj @mock.patch('elodie.config.config_file', '%s/config.ini-without-exif-location' % gettempdir()) -def test_get_adjusted_date_taken_without_exif_location(): +def test_get_date_taken_adjusted_without_exif_location(): with open('%s/config.ini-without-exif-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] @@ -105,17 +107,16 @@ def test_get_adjusted_date_taken_without_exif_location(): del load_config.config photo = Photo(helper.get_file('plain.jpg')) - date_taken = photo.get_adjusted_date_taken() - print(photo.get_metadata()) - print(date_taken) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) if hasattr(load_config, 'config'): del load_config.config - assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken + assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj @mock.patch('elodie.config.config_file', '%s/config.ini-use-location' % gettempdir()) -def test_get_adjusted_date_taken_use_location(): +def test_get_date_taken_adjusted_use_location(): with open('%s/config.ini-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] @@ -126,14 +127,16 @@ def test_get_adjusted_date_taken_use_location(): del load_config.config photo = Photo(helper.get_file('with-location.jpg')) - date_taken = photo.get_adjusted_date_taken() - print(photo.get_metadata()) - print(date_taken) + metadata = photo.get_metadata() + date_taken_adj = photo.get_date_taken_adjusted(metadata['date_taken'], metadata['latitude'], metadata['longitude']) + date_taken_adj_from_metadata = photo.get_metadata()['date_taken_adjusted'] + is_dst = date_taken_adj.tm_isdst if hasattr(load_config, 'config'): del load_config.config - assert date_taken == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 1)), date_taken + assert date_taken_adj == date_taken_adj_from_metadata, (date_taken_adj, date_taken_adj_from_metadata) + assert date_taken_adj == helper.time_convert((2015, 12, 5, 7, 59, 26, 5, 339, is_dst)), date_taken_adj def test_get_metadata_of_invalid_photo(): photo = Photo(helper.get_file('invalid.jpg')) From 4c1b423248b5706b7616f6a037691205d841ea8e Mon Sep 17 00:00:00 2001 From: Jaisen Mathai Date: Tue, 14 May 2019 21:08:46 -0700 Subject: [PATCH 3/4] Trying to fix tests --- elodie/tests/media/photo_test.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index e9dfbf79..087c8768 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -59,9 +59,9 @@ def test_is_not_valid(): assert not photo.is_valid() -@mock.patch('elodie.config.config_file', '%s/config.ini-no-config' % gettempdir()) -def test_get_adjusted_date_taken_no_config(): - with open('%s/config.ini-no-config' % gettempdir(), 'w') as f: +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-no-config' % gettempdir()) +def test_get_date_taken_adjusted_no_config(): + with open('%s/config.ini-date-taken-adjusted-no-config' % gettempdir(), 'w') as f: f.write(""" """) @@ -75,9 +75,9 @@ def test_get_adjusted_date_taken_no_config(): if hasattr(load_config, 'config'): del load_config.config -@mock.patch('elodie.config.config_file', '%s/config.ini-do-not-use-location' % gettempdir()) +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir()) def test_get_date_taken_adjusted_do_not_use_location(): - with open('%s/config.ini-do-not-use-location' % gettempdir(), 'w') as f: + with open('%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] use_location=False @@ -95,9 +95,9 @@ def test_get_date_taken_adjusted_do_not_use_location(): assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj -@mock.patch('elodie.config.config_file', '%s/config.ini-without-exif-location' % gettempdir()) +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir()) def test_get_date_taken_adjusted_without_exif_location(): - with open('%s/config.ini-without-exif-location' % gettempdir(), 'w') as f: + with open('%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] use_location=True @@ -115,9 +115,9 @@ def test_get_date_taken_adjusted_without_exif_location(): assert date_taken_adj == helper.time_convert((2015, 12, 5, 0, 59, 26, 5, 339, 0)), date_taken_adj -@mock.patch('elodie.config.config_file', '%s/config.ini-use-location' % gettempdir()) -def test_get_date_taken_adjusted_use_location(): - with open('%s/config.ini-use-location' % gettempdir(), 'w') as f: +@mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir()) +def test_get_date_taken_adjusted_for_timestamp_use_location(): + with open('%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] use_location=True From 18e86c86fbede2659a6c4da01f11843f472de613 Mon Sep 17 00:00:00 2001 From: Jaisen Mathai Date: Sun, 12 Jan 2020 20:50:03 -0800 Subject: [PATCH 4/4] some commit --- elodie/tests/config_test.py | 3 ++- elodie/tests/media/photo_test.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/elodie/tests/config_test.py b/elodie/tests/config_test.py index ee073f73..23919d28 100644 --- a/elodie/tests/config_test.py +++ b/elodie/tests/config_test.py @@ -10,12 +10,12 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))) from elodie import constants -from elodie.config import load_config BASE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) @patch('elodie.config.config_file', '%s/config.ini-sample' % BASE_PATH) def test_load_config_singleton_success(): + from elodie.config import load_config config = load_config() assert config['MapQuest']['key'] == 'your-api-key-goes-here', config.get('MapQuest', 'key') config.set('MapQuest', 'key', 'new-value') @@ -27,5 +27,6 @@ def test_load_config_singleton_success(): @patch('elodie.config.config_file', '%s/config.ini-does-not-exist' % BASE_PATH) def test_load_config_singleton_no_file(): + from elodie.config import load_config config = load_config() assert config == {}, config diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index 087c8768..bb15b547 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -16,7 +16,6 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) import helper -from elodie.config import load_config from elodie.media.media import Media from elodie.media.photo import Photo @@ -61,6 +60,7 @@ def test_is_not_valid(): @mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-no-config' % gettempdir()) def test_get_date_taken_adjusted_no_config(): + from elodie.config import load_config with open('%s/config.ini-date-taken-adjusted-no-config' % gettempdir(), 'w') as f: f.write(""" """) @@ -77,6 +77,7 @@ def test_get_date_taken_adjusted_no_config(): @mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir()) def test_get_date_taken_adjusted_do_not_use_location(): + from elodie.config import load_config with open('%s/config.ini-date-taken-adjusted-do-not-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] @@ -97,6 +98,7 @@ def test_get_date_taken_adjusted_do_not_use_location(): @mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir()) def test_get_date_taken_adjusted_without_exif_location(): + from elodie.config import load_config with open('%s/config.ini-date-taken-adjusted-without-exif-location' % gettempdir(), 'w') as f: f.write(""" [Timezone] @@ -117,6 +119,7 @@ def test_get_date_taken_adjusted_without_exif_location(): @mock.patch('elodie.config.config_file', '%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir()) def test_get_date_taken_adjusted_for_timestamp_use_location(): + from elodie.config import load_config with open('%s/config.ini-date-taken-adjusted-for-timestamp-use-location' % gettempdir(), 'w') as f: f.write(""" [Timezone]