Coder Social home page Coder Social logo

jmathai / elodie Goto Github PK

View Code? Open in Web Editor NEW
1.2K 37.0 138.0 10.28 MB

An EXIF-based photo assistant, organizer and workflow automation tool.

Home Page: https://bit.ly/introducing-elodie

License: Apache License 2.0

Python 87.63% JavaScript 5.35% CSS 3.85% HTML 2.77% Shell 0.03% Dockerfile 0.38%
organize-photos photo-organizer exif elodie photo-manager photography synology synology-nas exiftool automation

elodie's People

Contributors

adamantike avatar adamcandy avatar amaleki avatar arikfr avatar auenkind avatar benmccann avatar clach04 avatar davisonio avatar dzamataev avatar edent avatar evanjt avatar gti96 avatar ibizaman avatar jmathai avatar kraymer avatar mattca avatar misterpipine avatar noonat avatar ostavnaas avatar patricksan avatar pbuyle avatar petertiedemann avatar phifogg avatar qasimk avatar ramblurr avatar rkoster avatar srynot4sale avatar vkuptcov avatar zingo avatar zserg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elodie's Issues

Hazel script

I am new with Hazel script stuff. Do you mind to describe the rule you made in Hazel to notify Elodie to do this:
"to set up a Hazel rule to notify me when photos arrive in ~/Downloads so I can import them."

Thanks

Import/update script exits when it encounters an invalid file

The import/update script recursively gets a listing of files and checks the extension against a list of supported extensions. If a file has a supported extension but does not contain valid data (i.e. is not a picture or movie) then the script exits.

Traceback (most recent call last):
  File "<string>", line 150, in <module>
  File "<string>", line 44, in _import
  File "/......../filesystem.py", line 137, in process_file
  File "/......../media.py", line 243, in get_metadata
  File "/......../media.py", line 143, in get_date_taken
  File "/......../media.py", line 175, in get_exif
  File "/usr/local/Cellar/pyexiv2/0.3.2_1/lib/python2.7/site-packages/pyexiv2/metadata.py", line 107, in read
    self.__image = self._instantiate_image(self.filename)
  File "/usr/local/Cellar/pyexiv2/0.3.2_1/lib/python2.7/site-packages/pyexiv2/metadata.py", line 79, in _instantiate_image
    return libexiv2python._Image(filename)
IOError: /......../Photos/._2012-04-21 17.59.46.jpg: The file contains data of an unknown image type
elodie returned -1

AttributeError: type object 'Media' has no attribute 'photo_extensions'

When running a simple import, I get the following error:

Traceback (most recent call last):
  File "./elodie.py", line 157, in <module>
    _import(params)
  File "./elodie.py", line 37, in _import
    media = Media.get_class_by_file(current_file, [Photo, Video])
  File "./elodie/elodie/media/media.py", line 298, in get_class_by_file
    if(extension in Media.photo_extensions):
AttributeError: type object 'Media' has no attribute 'photo_extensions'

I'm on master - 5818978 and all tests seem to pass fine:

nosetests -s
..............S.S....S...********************.S********************.S......................
----------------------------------------------------------------------
Ran 51 tests in 10.250s

OK (SKIP=5)

I outputted some values if that can help:

>>> Media.__class__
<class 'elodie.media.media.Media'>

>>> dir(Media)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'get_album', 'get_class_by_file', 'get_exif', 'get_exiftool',
'get_exiftool_attributes', 'get_extension', 'get_file_path', 'get_metadata',
'get_mimetype', 'get_title', 'is_valid', 'set_album', 'set_album_from_folder',
'set_metadata', 'set_metadata_basename']

Command not present

I couldn't find the command ./elodie.py in the root, as suggested in the README.
To test I used the import.py

After installing pip

I am at this stage:
pip install LatLon
I am at the root of my Mac, but have this error:
running install_lib
creating /Library/Python/2.7/site-packages/pyproj
error: could not create '/Library/Python/2.7/site-packages/pyproj': Permission denied

Thanks for your help :)

Johan

Deduce geolocation from photos taken the same day

Hi, discovered your project on HN, looks like something I could use :)

Regarding the problem of photos with unknown location, the current solution consist to run the update subcommand on them.
But say I have this folder tree :

├── 2015-06-Jun
│   ├── California
│   │   ├── 2015-06-29_16-34-14-img_3900.jpg

and an unknown location photo named 2015-06-29_17-07-06-img_3901.jpg
I think it would make the workflow even more painless, if I could ./elodie.py import --propagate ... or something that would deduce that the photo has been taken in Cali since one half hour I took another one in this place.
A little magic/dangerous so should probably be turned off by default but does it make sense to you ?

Regards

Use of '~' in folder doesn't work

I tried to run this command and it didn't work:

$ ./elodie.py import --source="~/Desktop/chris" --destination="/Volumes/Data/Pictures/elodie-photos"

I had to convert to:

$ ./elodie.py import --source="/Users/patrick/Desktop/chris" --destination="/Volumes/Data/Pictures/elodie-photos"

Video test for get_date_taken fails on Travis but not locally

FAIL: elodie.tests.media.video_test.test_get_date_taken
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/virtualenv/python2.7_with_system_site_packages/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/travis/build/jmathai/elodie/elodie/tests/media/video_test.py", line 58, in test_get_date_taken
    assert date_taken == (2015, 1, 19, 12, 45, 11, 0, 19, 0), date_taken
AssertionError: time.struct_time(tm_year=2015, tm_mon=12, tm_mday=12, tm_hour=8, tm_min=59, tm_sec=26, tm_wday=5, tm_yday=346, tm_isdst=0)

Cache coordinates and place names for geolocation lookups

When looking up a geolocation coordinate we can cache the value to limit the number of lookups needed. A few considerations to make...

  • Store location name (i.e. Sunnyvale, CA) to a lat/lon pair
  • Store a lat/lon pair (i.e. extracted from EXIF)

lat/lon pairs within a certain radius of a pair that's already stored should return the stored location name. (see gelocation.place_name). When a pair is not within a certain radius of a stored lat/lon pair it should be looked up against an API and stored.

// cc @zingo

README not updated

I just tried to run the commands but they don't exist anymore. I guess it was renamed to ./elodie

Address pep8 related issues

So far this is the list of pep8 issues.

# pep8 elodie
elodie/arguments.py:3:11: E401 multiple imports on one line
elodie/arguments.py:6:1: E302 expected 2 blank lines, found 1
elodie/arguments.py:12:1: W293 blank line contains whitespace
elodie/filesystem.py:17:1: E302 expected 2 blank lines, found 0
elodie/filesystem.py:21:80: E501 line too long (86 > 79 characters)
elodie/filesystem.py:38:80: E501 line too long (93 > 79 characters)
elodie/filesystem.py:38:94: W291 trailing whitespace
elodie/filesystem.py:41:80: E501 line too long (86 > 79 characters)
elodie/filesystem.py:63:31: E711 comparison to None should be 'if cond is None:'
elodie/filesystem.py:63:80: E501 line too long (80 > 79 characters)
elodie/filesystem.py:78:80: E501 line too long (86 > 79 characters)
elodie/filesystem.py:89:21: E711 comparison to None should be 'if cond is None:'
elodie/filesystem.py:92:80: E501 line too long (103 > 79 characters)
elodie/filesystem.py:94:80: E501 line too long (86 > 79 characters)
elodie/filesystem.py:94:87: W291 trailing whitespace
elodie/filesystem.py:95:80: E501 line too long (94 > 79 characters)
elodie/filesystem.py:98:80: E501 line too long (97 > 79 characters)
elodie/filesystem.py:103:80: E501 line too long (127 > 79 characters)
elodie/filesystem.py:128:80: E501 line too long (85 > 79 characters)
elodie/filesystem.py:129:80: E501 line too long (92 > 79 characters)
elodie/filesystem.py:137:9: E265 block comment should start with '# '
elodie/filesystem.py:159:21: E711 comparison to None should be 'if cond is None:'
elodie/filesystem.py:160:32: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/filesystem.py:164:80: E501 line too long (85 > 79 characters)
elodie/filesystem.py:165:27: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
elodie/filesystem.py:166:32: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/filesystem.py:167:80: E501 line too long (93 > 79 characters)
elodie/filesystem.py:172:17: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/filesystem.py:194:80: E501 line too long (117 > 79 characters)
elodie/filesystem.py:197:80: E501 line too long (84 > 79 characters)
elodie/filesystem.py:201:80: E501 line too long (82 > 79 characters)
elodie/filesystem.py:205:80: E501 line too long (97 > 79 characters)
elodie/filesystem.py:208:80: E501 line too long (91 > 79 characters)
elodie/filesystem.py:210:80: E501 line too long (80 > 79 characters)
elodie/filesystem.py:211:1: W293 blank line contains whitespace
elodie/geolocation.py:14:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:25:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:39:80: E501 line too long (86 > 79 characters)
elodie/geolocation.py:39:87: W291 trailing whitespace
elodie/geolocation.py:40:80: E501 line too long (121 > 79 characters)
elodie/geolocation.py:42:80: E501 line too long (92 > 79 characters)
elodie/geolocation.py:43:80: E501 line too long (83 > 79 characters)
elodie/geolocation.py:44:80: E501 line too long (86 > 79 characters)
elodie/geolocation.py:47:80: E501 line too long (154 > 79 characters)
elodie/geolocation.py:50:1: W293 blank line contains whitespace
elodie/geolocation.py:55:1: W293 blank line contains whitespace
elodie/geolocation.py:58:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:59:80: E501 line too long (82 > 79 characters)
elodie/geolocation.py:71:15: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
elodie/geolocation.py:76:80: E501 line too long (153 > 79 characters)
elodie/geolocation.py:78:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:80:23: E221 multiple spaces before operator
elodie/geolocation.py:81:28: E221 multiple spaces before operator
elodie/geolocation.py:85:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:89:1: W293 blank line contains whitespace
elodie/geolocation.py:97:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:102:54: E231 missing whitespace after ','
elodie/geolocation.py:106:29: E703 statement ends with a semicolon
elodie/geolocation.py:133:80: E501 line too long (110 > 79 characters)
elodie/geolocation.py:136:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/geolocation.py:140:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/geolocation.py:145:1: E302 expected 2 blank lines, found 1
elodie/geolocation.py:153:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/geolocation.py:154:80: E501 line too long (98 > 79 characters)
elodie/geolocation.py:155:80: E501 line too long (106 > 79 characters)
elodie/geolocation.py:158:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/geolocation.py:162:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/localstorage.py:9:1: E302 expected 2 blank lines, found 1
elodie/localstorage.py:11:80: E501 line too long (82 > 79 characters)
elodie/localstorage.py:23:80: E501 line too long (82 > 79 characters)
elodie/localstorage.py:38:80: E501 line too long (82 > 79 characters)
elodie/localstorage.py:47:18: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/localstorage.py:91:18: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/localstorage.py:94:52: E231 missing whitespace after ','
elodie/localstorage.py:99:80: E501 line too long (140 > 79 characters)
elodie/localstorage.py:102:80: E501 line too long (99 > 79 characters)
elodie/localstorage.py:105:37: E201 whitespace after '('
elodie/localstorage.py:105:53: E202 whitespace before ')'
elodie/localstorage.py:107:26: E201 whitespace after '('
elodie/localstorage.py:107:36: E202 whitespace before ')'
elodie/localstorage.py:110:17: E265 block comment should start with '# '
elodie/localstorage.py:111:36: E703 statement ends with a semicolon
elodie/plist_parser.py:15:1: E302 expected 2 blank lines, found 0
elodie/media/media.py:23:1: E302 expected 2 blank lines, found 0
elodie/media/media.py:33:80: E501 line too long (106 > 79 characters)
elodie/media/media.py:33:82: E261 at least two spaces before inline comment
elodie/media/media.py:33:83: E262 inline comment should start with '# '
elodie/media/media.py:54:1: W293 blank line contains whitespace
elodie/media/media.py:68:80: E501 line too long (81 > 79 characters)
elodie/media/media.py:74:5: E303 too many blank lines (2)
elodie/media/media.py:91:80: E501 line too long (108 > 79 characters)
elodie/media/media.py:98:1: W293 blank line contains whitespace
elodie/media/media.py:117:80: E501 line too long (111 > 79 characters)
elodie/media/media.py:134:26: E703 statement ends with a semicolon
elodie/media/media.py:144:5: E303 too many blank lines (2)
elodie/media/media.py:166:55: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
elodie/media/media.py:184:1: W293 blank line contains whitespace
elodie/media/media.py:196:21: E711 comparison to None should be 'if cond is None:'
elodie/media/media.py:200:1: W293 blank line contains whitespace
elodie/media/media.py:235:28: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/media.py:236:80: E501 line too long (107 > 79 characters)
elodie/media/media.py:237:80: E501 line too long (170 > 79 characters)
elodie/media/media.py:270:5: E303 too many blank lines (2)
elodie/media/media.py:271:80: E501 line too long (92 > 79 characters)
elodie/media/media.py:273:80: E501 line too long (121 > 79 characters)
elodie/media/media.py:276:80: E501 line too long (82 > 79 characters)
elodie/media/photo.py:26:1: E302 expected 2 blank lines, found 0
elodie/media/photo.py:38:1: W293 blank line contains whitespace
elodie/media/photo.py:51:13: E128 continuation line under-indented for visual indent
elodie/media/photo.py:51:19: E251 unexpected spaces around keyword / parameter equals
elodie/media/photo.py:51:21: E251 unexpected spaces around keyword / parameter equals
elodie/media/photo.py:51:45: E251 unexpected spaces around keyword / parameter equals
elodie/media/photo.py:51:47: E251 unexpected spaces around keyword / parameter equals
elodie/media/photo.py:54:80: E501 line too long (87 > 79 characters)
elodie/media/photo.py:66:80: E501 line too long (94 > 79 characters)
elodie/media/photo.py:73:80: E501 line too long (91 > 79 characters)
elodie/media/photo.py:75:80: E501 line too long (93 > 79 characters)
elodie/media/photo.py:78:23: E225 missing whitespace around operator
elodie/media/photo.py:78:80: E501 line too long (94 > 79 characters)
elodie/media/photo.py:83:80: E501 line too long (113 > 79 characters)
elodie/media/photo.py:85:80: E501 line too long (114 > 79 characters)
elodie/media/photo.py:100:80: E501 line too long (85 > 79 characters)
elodie/media/photo.py:102:80: E501 line too long (93 > 79 characters)
elodie/media/photo.py:103:80: E501 line too long (102 > 79 characters)
elodie/media/photo.py:105:80: E501 line too long (104 > 79 characters)
elodie/media/photo.py:110:80: E501 line too long (96 > 79 characters)
elodie/media/photo.py:111:80: E501 line too long (86 > 79 characters)
elodie/media/photo.py:112:30: E703 statement ends with a semicolon
elodie/media/photo.py:114:36: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/photo.py:124:80: E501 line too long (89 > 79 characters)
elodie/media/photo.py:125:1: W293 blank line contains whitespace
elodie/media/photo.py:134:25: E703 statement ends with a semicolon
elodie/media/photo.py:175:80: E501 line too long (95 > 79 characters)
elodie/media/photo.py:176:80: E501 line too long (132 > 79 characters)
elodie/media/photo.py:177:80: E501 line too long (97 > 79 characters)
elodie/media/photo.py:178:80: E501 line too long (135 > 79 characters)
elodie/media/video.py:26:1: E302 expected 2 blank lines, found 0
elodie/media/video.py:28:24: E231 missing whitespace after ','
elodie/media/video.py:28:30: E231 missing whitespace after ','
elodie/media/video.py:28:36: E231 missing whitespace after ','
elodie/media/video.py:28:42: E231 missing whitespace after ','
elodie/media/video.py:46:80: E501 line too long (95 > 79 characters)
elodie/media/video.py:52:5: E303 too many blank lines (2)
elodie/media/video.py:74:80: E501 line too long (100 > 79 characters)
elodie/media/video.py:92:80: E501 line too long (102 > 79 characters)
elodie/media/video.py:94:80: E501 line too long (85 > 79 characters)
elodie/media/video.py:102:80: E501 line too long (123 > 79 characters)
elodie/media/video.py:114:1: W293 blank line contains whitespace
elodie/media/video.py:127:13: E128 continuation line under-indented for visual indent
elodie/media/video.py:127:19: E251 unexpected spaces around keyword / parameter equals
elodie/media/video.py:127:21: E251 unexpected spaces around keyword / parameter equals
elodie/media/video.py:127:45: E251 unexpected spaces around keyword / parameter equals
elodie/media/video.py:127:47: E251 unexpected spaces around keyword / parameter equals
elodie/media/video.py:130:80: E501 line too long (87 > 79 characters)
elodie/media/video.py:135:80: E501 line too long (87 > 79 characters)
elodie/media/video.py:145:80: E501 line too long (111 > 79 characters)
elodie/media/video.py:149:80: E501 line too long (89 > 79 characters)
elodie/media/video.py:150:1: W293 blank line contains whitespace
elodie/media/video.py:171:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:172:80: E501 line too long (97 > 79 characters)
elodie/media/video.py:188:80: E501 line too long (82 > 79 characters)
elodie/media/video.py:213:80: E501 line too long (89 > 79 characters)
elodie/media/video.py:215:80: E501 line too long (84 > 79 characters)
elodie/media/video.py:224:80: E501 line too long (118 > 79 characters)
elodie/media/video.py:225:32: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:231:32: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:237:80: E501 line too long (87 > 79 characters)
elodie/media/video.py:239:80: E501 line too long (102 > 79 characters)
elodie/media/video.py:241:80: E501 line too long (115 > 79 characters)
elodie/media/video.py:242:80: E501 line too long (122 > 79 characters)
elodie/media/video.py:245:36: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:250:80: E501 line too long (106 > 79 characters)
elodie/media/video.py:261:80: E501 line too long (92 > 79 characters)
elodie/media/video.py:263:80: E501 line too long (82 > 79 characters)
elodie/media/video.py:264:80: E501 line too long (88 > 79 characters)
elodie/media/video.py:280:80: E501 line too long (84 > 79 characters)
elodie/media/video.py:285:80: E501 line too long (82 > 79 characters)
elodie/media/video.py:286:21: E265 block comment should start with '# '
elodie/media/video.py:299:36: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:304:80: E501 line too long (81 > 79 characters)
elodie/media/video.py:305:80: E501 line too long (82 > 79 characters)
elodie/media/video.py:313:80: E501 line too long (111 > 79 characters)
elodie/media/video.py:314:80: E501 line too long (108 > 79 characters)
elodie/media/video.py:317:36: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:318:80: E501 line too long (86 > 79 characters)
elodie/media/video.py:321:80: E501 line too long (84 > 79 characters)
elodie/media/video.py:324:80: E501 line too long (207 > 79 characters)
elodie/media/video.py:325:36: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/media/video.py:329:80: E501 line too long (99 > 79 characters)
elodie/media/video.py:346:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:8:80: E501 line too long (114 > 79 characters)
elodie/tests/filesystem_test.py:10:1: E402 module level import not at top of file
elodie/tests/filesystem_test.py:11:1: E402 module level import not at top of file
elodie/tests/filesystem_test.py:12:1: E402 module level import not at top of file
elodie/tests/filesystem_test.py:13:1: E402 module level import not at top of file
elodie/tests/filesystem_test.py:14:1: E402 module level import not at top of file
elodie/tests/filesystem_test.py:27:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/filesystem_test.py:30:1: W293 blank line contains whitespace
elodie/tests/filesystem_test.py:37:80: E501 line too long (97 > 79 characters)
elodie/tests/filesystem_test.py:43:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/filesystem_test.py:49:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:51:80: E501 line too long (92 > 79 characters)
elodie/tests/filesystem_test.py:53:19: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
elodie/tests/filesystem_test.py:55:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:68:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:70:80: E501 line too long (97 > 79 characters)
elodie/tests/filesystem_test.py:88:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:120:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:124:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:131:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:136:80: E501 line too long (82 > 79 characters)
elodie/tests/filesystem_test.py:138:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:150:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:157:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:164:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:171:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:178:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:186:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:196:80: E501 line too long (99 > 79 characters)
elodie/tests/filesystem_test.py:198:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:206:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:216:80: E501 line too long (110 > 79 characters)
elodie/tests/filesystem_test.py:218:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:226:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:236:80: E501 line too long (92 > 79 characters)
elodie/tests/filesystem_test.py:238:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:246:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:256:80: E501 line too long (103 > 79 characters)
elodie/tests/filesystem_test.py:258:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:266:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:276:80: E501 line too long (93 > 79 characters)
elodie/tests/filesystem_test.py:278:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:286:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:296:80: E501 line too long (104 > 79 characters)
elodie/tests/filesystem_test.py:298:1: E302 expected 2 blank lines, found 1
elodie/tests/filesystem_test.py:303:80: E501 line too long (85 > 79 characters)
elodie/tests/filesystem_test.py:306:80: E501 line too long (95 > 79 characters)
elodie/tests/filesystem_test.py:316:80: E501 line too long (104 > 79 characters)
elodie/tests/geolocation_test.py:7:80: E501 line too long (114 > 79 characters)
elodie/tests/geolocation_test.py:9:1: E402 module level import not at top of file
elodie/tests/geolocation_test.py:10:1: E402 module level import not at top of file
elodie/tests/geolocation_test.py:14:1: E302 expected 2 blank lines, found 1
elodie/tests/geolocation_test.py:20:1: W293 blank line contains whitespace
elodie/tests/geolocation_test.py:22:80: E501 line too long (91 > 79 characters)
elodie/tests/geolocation_test.py:27:80: E501 line too long (112 > 79 characters)
elodie/tests/geolocation_test.py:29:1: E302 expected 2 blank lines, found 1
elodie/tests/geolocation_test.py:33:1: W293 blank line contains whitespace
elodie/tests/geolocation_test.py:35:80: E501 line too long (91 > 79 characters)
elodie/tests/geolocation_test.py:42:80: E501 line too long (120 > 79 characters)
elodie/tests/helper.py:8:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:19:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:21:80: E501 line too long (82 > 79 characters)
elodie/tests/helper.py:26:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:30:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:33:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:45:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:46:80: E501 line too long (111 > 79 characters)
elodie/tests/helper.py:48:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:51:1: E302 expected 2 blank lines, found 1
elodie/tests/helper.py:55:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:5:80: E501 line too long (114 > 79 characters)
elodie/tests/localstorage_test.py:7:1: E402 module level import not at top of file
elodie/tests/localstorage_test.py:8:1: E402 module level import not at top of file
elodie/tests/localstorage_test.py:9:1: E402 module level import not at top of file
elodie/tests/localstorage_test.py:13:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:19:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:28:80: E501 line too long (83 > 79 characters)
elodie/tests/localstorage_test.py:33:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:34:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:43:80: E501 line too long (83 > 79 characters)
elodie/tests/localstorage_test.py:48:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:49:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:58:80: E501 line too long (83 > 79 characters)
elodie/tests/localstorage_test.py:63:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:64:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:73:80: E501 line too long (83 > 79 characters)
elodie/tests/localstorage_test.py:74:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:75:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:80:80: E501 line too long (100 > 79 characters)
elodie/tests/localstorage_test.py:82:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:91:80: E501 line too long (102 > 79 characters)
elodie/tests/localstorage_test.py:92:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:93:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:98:80: E501 line too long (103 > 79 characters)
elodie/tests/localstorage_test.py:100:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:109:80: E501 line too long (83 > 79 characters)
elodie/tests/localstorage_test.py:121:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:127:80: E501 line too long (129 > 79 characters)
elodie/tests/localstorage_test.py:129:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:139:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:145:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:146:5: E303 too many blank lines (2)
elodie/tests/localstorage_test.py:151:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:165:80: E501 line too long (105 > 79 characters)
elodie/tests/localstorage_test.py:167:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:181:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:183:1: W293 blank line contains whitespace
elodie/tests/localstorage_test.py:198:1: E302 expected 2 blank lines, found 1
elodie/tests/localstorage_test.py:200:1: W293 blank line contains whitespace
elodie/tests/media/media_test.py:13:80: E501 line too long (131 > 79 characters)
elodie/tests/media/media_test.py:14:80: E501 line too long (97 > 79 characters)
elodie/tests/media/media_test.py:16:1: E402 module level import not at top of file
elodie/tests/media/media_test.py:17:1: E402 module level import not at top of file
elodie/tests/media/media_test.py:18:1: E402 module level import not at top of file
elodie/tests/media/media_test.py:19:1: E402 module level import not at top of file
elodie/tests/media/media_test.py:23:1: E302 expected 2 blank lines, found 1
elodie/tests/media/media_test.py:29:1: E302 expected 2 blank lines, found 1
elodie/tests/media/media_test.py:35:1: E302 expected 2 blank lines, found 1
elodie/tests/media/media_test.py:36:80: E501 line too long (81 > 79 characters)
elodie/tests/media/media_test.py:40:1: E302 expected 2 blank lines, found 1
elodie/tests/media/media_test.py:41:80: E501 line too long (81 > 79 characters)
elodie/tests/media/media_test.py:45:1: E302 expected 2 blank lines, found 1
elodie/tests/media/media_test.py:46:80: E501 line too long (80 > 79 characters)
elodie/tests/media/media_test.py:50:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:13:80: E501 line too long (131 > 79 characters)
elodie/tests/media/photo_test.py:14:80: E501 line too long (97 > 79 characters)
elodie/tests/media/photo_test.py:16:1: E402 module level import not at top of file
elodie/tests/media/photo_test.py:17:1: E402 module level import not at top of file
elodie/tests/media/photo_test.py:18:1: E402 module level import not at top of file
elodie/tests/media/photo_test.py:22:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:36:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:40:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:46:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:51:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:56:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:62:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:68:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:74:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:80:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:86:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:94:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:100:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:105:80: E501 line too long (95 > 79 characters)
elodie/tests/media/photo_test.py:109:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:114:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:119:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:128:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/photo_test.py:137:80: E501 line too long (82 > 79 characters)
elodie/tests/media/photo_test.py:139:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:140:80: E501 line too long (80 > 79 characters)
elodie/tests/media/photo_test.py:155:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/photo_test.py:166:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:177:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/photo_test.py:186:1: E302 expected 2 blank lines, found 1
elodie/tests/media/photo_test.py:198:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/video_test.py:13:80: E501 line too long (131 > 79 characters)
elodie/tests/media/video_test.py:14:80: E501 line too long (97 > 79 characters)
elodie/tests/media/video_test.py:16:1: E402 module level import not at top of file
elodie/tests/media/video_test.py:17:1: E402 module level import not at top of file
elodie/tests/media/video_test.py:18:1: E402 module level import not at top of file
elodie/tests/media/video_test.py:22:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:36:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:42:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:48:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:54:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:61:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:67:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:72:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:77:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:89:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/video_test.py:98:80: E501 line too long (82 > 79 characters)
elodie/tests/media/video_test.py:100:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:104:80: E501 line too long (80 > 79 characters)
elodie/tests/media/video_test.py:114:5: E265 block comment should start with '# '
elodie/tests/media/video_test.py:115:5: E265 block comment should start with '# '
elodie/tests/media/video_test.py:119:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/video_test.py:130:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:144:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/video_test.py:153:1: E302 expected 2 blank lines, found 1
elodie/tests/media/video_test.py:168:19: E712 comparison to True should be 'if cond is True:' or 'if cond:'
elodie/tests/media/video_test.py:177:1: E302 expected 2 blank lines, found 1

Folder created with update command get misnamed

Some UTC problem ?

./elodie.py update --time="2010-05-01" /Users/flap/Pictures/elodie/2004-12-Dec/Unknown\ Location/2004-12-31_23-0*
{"source":"/Users/flap/Pictures/elodie/2004-12-Dec/Unknown Location/2004-12-31_23-01-39-imgp4530.jpg", 
"destination":"/Users/flap/Pictures/elodie/2010-04-Apr/Unknown Location/2010-04-30_22-00-00-imgp4530.jpg"}

destination folder should be 2010-05-May, not 2010-04-Apr

API KEY for Map Quest

Which API should I use to put in the configuration?
Consumer key or secret or other?

I tried the consumer key and it didn't work.

screen shot 2015-12-02 at 22 34 30

The import continue appears as "Unknown location"

Cache location names and return them when looking up coordinates

gh-47 by @zingo added caching for location coordinates. We can leverage the same cache to lookup a name and return its corresponding name.

In addition to a performance boost this lets us further customize location labels and folders as a result. If the location db contains a name, lat, long set you can update a set of photos with that name. That means you can explicitly set labels and use ./elodie.py update --location="Home" /path/to/file.jpg which would assign it the exact location from the cache and place the photo(s) into a folder named Home instead of the normal "city name".

{"lat": 39.387227, "name": "Home", "long": -115.026129}

TODO: We need to come up with a way to backup/store the databases/caches that we're storing.

--album doesn't work in the import

I tried to execute this command:

./elodie.py import --source="~/Desktop/chris" --destination="/Volumes/Data/Pictures/elodie-photos" --album="Aniversario Chris" 

but it always return Usage message:

Usage: main.py import --source=<s> --destination=<d>
       main.py import --file=<f> --destination=<d>
       main.py update [--time=<t>] [--location=<l>] [--album=<a>] [--title=<t>] INPUT ...

If I remove the --album it does work.

EXIF title only supports ascii characters when updating

Marking a test as skipped for this by adding # -*- coding: utf-8 to the top of the file.

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/jmathai/elodie/elodie/tests/media/photo.py", line 168, in test_set_title_non_ascii
    status = photo.set_title('形声字 / 形聲字')
  File "/Users/jmathai/elodie/elodie/media/photo.py", line 165, in set_title
    exif_metadata['Xmp.dc.title'] = title
  File "/usr/local/lib/python2.7/site-packages/pyexiv2/metadata.py", line 271, in __setitem__
    return getattr(self, '_set_%s_tag' % family)(key, tag_or_value)
  File "/usr/local/lib/python2.7/site-packages/pyexiv2/metadata.py", line 244, in _set_xmp_tag
    tag = XmpTag(key, tag_or_value)
  File "/usr/local/lib/python2.7/site-packages/pyexiv2/xmp.py", line 114, in __init__
    self._set_value(value)
  File "/usr/local/lib/python2.7/site-packages/pyexiv2/xmp.py", line 235, in _set_value
    raw_value[k.encode('utf-8')] = v.encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

Sync EXIF and filesystem without issuing commands

TL;DR: what would you think about using fuse?

First of all THANK YOU. This is the project I always wanted to do - in the exact same way.

So for now, the only way to update pictures is to run the elodie.py command. I would propose to make importing and updating even more intuitive by adding fuse into the mix. This way, making a modification on the filesystem - renaming a directory, moving a file, etc. - would trigger elodie.py and automatically change the EXIF information.

The UI could then be very inuitive. Assuming:

├── 2015-06-Jun
│   ├── California
│   │   ├── 2015-06-29_16-34-14-img_3900.jpg
│   │   └── 2015-06-29_17-07-06-img_3901.jpg
│   └── Paris
│       └── 2015-06-30_02-40-43-img_3903.jpg
├── 2015-07-Jul
│   ├── Mountain View
│   │   ├── 2015-07-19_17-16-37-img_9426.jpg
│   │   └── 2015-07-24_19-06-33-img_9432.jpg

Renaming California to Silicon Valley would trigger:

./elodie.py update --location="Silicon Valley" \
    2015-06-Jun/California/2015-06-29_16-34-14-img_3900.jpg \
    2015-06-Jun/California/2015-06-29_16-34-14-img_3901.jpg

Renaming 2015-07-Jul to 2015-08 would trigger, with a bit of magick:

./elodie.py update --time="2015-08-19" 2015-07-Jul/Mountain View/2015-07-19_17-16-37-img_9426.jpg
./elodie.py update --time="2015-08-24" 2015-07-Jul/Mountain View/2015-07-24_19-06-33-img_9432.jpg

And of course, editing the EXIF information directly would also trigger corresponding ./elodie.py commands.

Python bindings for fuse can be installed with pip too: pip install fuse-python.

What do you think of this?

Error in media/photo.py

It seems like error in photo.py line 82:

 if(key == 'latitude'):

should be:

if(type == 'latitude'):

Folder respect when no data or gps are found

I already have this kind of organisation in my photos:
screen shot 2015-12-03 at 00 00 14

if I import, probably I will loose all information as years ago we didn't embedded dates/gps on photos.

How could we solve this problem?

import pyexiv2

Hi again,

I have this error:
./elodie.py", line 4, in
import pyexiv2
ImportError: No module named pyexiv2

But everything is well installed.(pyexiv2-0.3.2_1 already installed)

Thanks

Read-only source fails on exiftool trying to create a file in source directory

When importing from a read-only source, I get the following error:

$ ./elodie.py import --source=~/Pictures/source --destination=~/Pictures/organized --album-from-folder
/usr/local/bin/exiftool -config "./elodie/configs/ExifTool_config" -xmp-elodie:Album="2015-08 MyEvent" "~/Pictures/source/2015/2015-08 MyEvent/P8242306.JPG"
Error: Error creating file: ~/Pictures/source/2015/2015-08 MyEvent/P8242306.JPG_exiftool_tmp - ~/Pictures/source/2015/2015-08 MyEvent/P8242306.JPG

And nothing is imported in the destination folder.

No status at Elodie app

  1. open app
  2. put folder A and folder B
  3. Click Start Organising
  4. Click in another window. At this moment the app disappear (minimised)
  5. Open the app again, there is no status

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.