Skip to content

Commit

Permalink
ratings: Add import and saving of ratings
Browse files Browse the repository at this point in the history
Saving requires a mediagoblin that has the needed hook
  • Loading branch information
odinho committed Aug 17, 2014
1 parent b71fe42 commit 602e96d
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 1 deletion.
2 changes: 2 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from mediagoblin import processing

from . import ratings
from .storage import _is_cachefile, _ensure_in_cache_dir


Expand Down Expand Up @@ -64,4 +65,5 @@ def setup_plugin():

hooks = {
'setup': setup_plugin,
'add_media_to_collection': ratings.media_added_to_collection,
}
5 changes: 5 additions & 0 deletions import_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from mediagoblin.tools.text import convert_to_tag_list_of_dicts
from mediagoblin.user_pages.lib import add_media_to_collection

from . import ratings


CACHE_DIR = 'mg_cache'
Expand Down Expand Up @@ -142,6 +143,10 @@ def handle(self):
if not entry:
continue
added_entries.append(entry)
rating = ratings.get_rating(path)
if rating:
self.add_to_collection('rating:{}'.format(rating),
[entry])
self.add_to_collection(u'roll:{}'.format(folder_path),
added_entries)

Expand Down
65 changes: 65 additions & 0 deletions metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import os

import pyexiv2


class Metadata(object):
lookups = {
'rating': ('Xmp.xmp.Rating', ),
}

def __init__(self, path):
self.path = path
self.md = pyexiv2.ImageMetadata(path)
self.dirty = False

self.read()

def read(self):
self.md.read()

def save(self):
if self.dirty:
self.md.write()
self.dirty = False

def _get_metadata_item(self, lookup):
existing_keys = self.md.keys()
for key in self.lookups[lookup]:
if key in existing_keys:
return self.md.get(key)

@property
def rating(self):
tag = self._get_metadata_item('rating')
return tag.value if tag else None

@rating.setter
def rating(self, value):
tag = self._get_metadata_item('rating')
if tag is None:
tag_key = self.lookups['rating'][0]
tag = pyexiv2.XmpTag(tag_key, value)
self.md[tag_key] = tag
else:
tag.value = value
self.dirty = True

@classmethod
def from_potential_sidecar(self, filepath):
xmp_filepath = u'{}.xmp'.format(filepath)
if os.path.exists(xmp_filepath):
return Metadata(xmp_filepath)
return Metadata(filepath)


if __name__ == '__main__':
import sys
path = sys.argv[1].decode('utf8')
md = Metadata.from_potential_sidecar(path)
print md.path
print u" rating:", md.rating
if len(sys.argv) > 2:
md.rating = int(sys.argv[2])
md.save()
print u" set rating to:", md.rating
41 changes: 41 additions & 0 deletions ratings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#from sqlalchemy import event
#
#from mediagoblin.db.models import MediaEntry
#
#@event.listens_for(MediaEntry.collections, 'append')
#def test(target, value, initiator):
# print "RECV event"
# import ipdb; ipdb.set_trace()

import re

from mediagoblin import mg_globals as mgg

from .metadata import Metadata


def media_added_to_collection(collection, media_entry, note):
m = re.match(r'rating:(\d+)', collection.title)
if not m:
return
rating_number = int(m.group(1))
set_rating_from_media_entry(media_entry, rating_number)


def set_rating_from_media_entry(media_entry, rating):
filepath = (mgg.public_store
._cachefile_to_original_filepath(
media_entry.media_files['original']))
path = mgg.public_store._resolve_filepath(filepath)
set_rating(path)


def set_rating(path, rating):
md = Metadata.from_potential_sidecar(path)
md.rating = rating
md.save()


def get_rating(path):
md = Metadata.from_potential_sidecar(path)
return md.rating
12 changes: 11 additions & 1 deletion storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ class PersistentFileStorage(BasicFileStorage):
Local filesystem implementation of storage API that doesn't delete files
"""

def _cachefile_to_original_filepath(self, filepath):
"""
Custom function taking a cache file and returns original filepath.
"""
if CACHE_DIR == filepath[0]:
filepath = filepath[1:]
filename = self._re_raw_from_preview.sub(r'\1.\2', filepath[-1])
return list(filepath[:-1]) + [filename]
_re_raw_from_preview = re.compile(r'^(.*)\.(nef|cr2)(\.jpg)$', re.I)

def _resolve_filepath(self, filepath):
"""
Transform the given filepath into a local filesystem path.
Expand Down Expand Up @@ -108,7 +118,7 @@ def get_file(self, filepath, mode='r'):
mode = mode.replace("w", "r")
# Grab and return the file in the mode specified
return PersistentStorageObjectWrapper(
open(self._resolve_filepath(filepath), mode))
open(self._resolve_filepath(filepath), mode))

def delete_file(self, filepath):
_log.info(u'Not removing {0} as requested.'.format(
Expand Down

0 comments on commit 602e96d

Please sign in to comment.