pytagsfs team mailing list archive
-
pytagsfs team
-
Mailing list archive
-
Message #00068
xattr metastore: an initial attempt
Hi,
You'll find attached an initial attempt to create an xattr metastore for
pytagsfs.
It's far from perfect but basically working.
I'm really in need of advices about the _right_ way to implement bases
classes from pytagsfs.
I would also appreciate clarification about "cp -r" / "mv" support.
Finally it would be nice if we can go ahead on the following thread:
https://lists.launchpad.net/pytagsfs/msg00061.html
Thank you in advance.
Raph
# coding: utf-8
# Copyright (c) 2011 Raphaël Droz.
# This file is part of the pytagsfs software package.
#
# pytagsfs is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License version 2 as published by the Free
# Software Foundation.
#
# A copy of the license has been included in the COPYING file.
import os.path
# for debugging purpose
import inspect, traceback, sys, re
import xattr
from pytagsfs.metastore import MetaStore
# todo: implement this ?
from pytagsfs.values import Values
# TODO:
# $ mv mnt/tag1/filename.avi mnt/tag2/filename2.avi
# should fail as 'filename.avi' will be kept (tag will change though)
# TODO: the following fails
# $ mkdir mnt/tag2
# $ cp mnt/tag1/file.avi mnt/tag2/
# as is:
# $ cp -a mnt/tag1 mnt/tag2
def __function__ ():
caller = inspect.stack()[1]
return caller[3]
# TODO:
# sync or async...
# with update() we have to (re)set all tags
# (and remove obsolete ones) !
# TODO:
# two consecutive --add for the same key failed
# TODO: inherit from Values if possible !
class SimpleXAttrFile(dict):
# dictionary containing all attributes and their value
d = {}
# filename
f = None
def __init__(self,filename):
print "IMPL:", __function__()
# test the file is regular/exists/...
if not os.path.exists(filename):
print "failed to find", filename
# todo: how to return (raise ?) a failure here ?
self.d = None
return None
# todo: test the filesystem supports xattr
# or, todo: simply test pyxattr supports it
self.f = filename
self.d = dict ( xattr.get_all(filename, namespace=xattr.NS_USER) )
print "__init__ => d = ", self.d
# needed when one extends the dict class
self.update(self.d.keys(), self.d.values())
# needed (print SimpleXAttrFile)
def __repr__(self):
return repr(self.d)
# used by pytags --add
def get(self, key, failobj=None):
print "IMPL:", __function__()
if key not in self.d:
return failobj
return self.d[key]
# needed (by, eg, update and others)
def __setitem__(self, key, value):
print "IMPL:", __function__()
self.d[key] = value
return
# needed by pytags --remove
def __delitem__(self, key):
print "IMPL:", __function__()
self.d.pop(key)
# needed when initialization happens in __init__
def update(self, args, kwargs):
print "IMPL:", __function__()
for k, v in dict(zip(args, kwargs)).iteritems():
self.d[k] = v
# needed by ... pytags, why ?
def save(self):
print "IMPL:", __function__()
for k, v in self.d.iteritems():
# todo:
# with pytags --set, v = [ value ] so we need v[0]
# with pytags --add, v = value so we need v
print "save", k, "=", v
if isinstance(v, (list, tuple)):
xattr.set(self.f, k, v[0], namespace=xattr.NS_USER)
else:
xattr.set(self.f, k, v, namespace=xattr.NS_USER)
# needed by all *.items(), Values.from_flat_dict(), ... in the _XattrMetaStore class below
def items(self):
print "IMPL:", __function__()
return self.d.items()
# followings uneeded ?
def keys(self):
print "IMPL:", __function__()
return self.d.keys()
def values(self):
print "IMPL:", __function__()
return self.d.values()
def __getitem__(self, key):
print "IMPL:", __function__()
return self.d[key]
def iteritems(self):
print "IMPL:", __function__()
return self.d.iteritems()
def __iteritems__(self):
print "IMPL:", __function__()
return self.d.__iteritems__()
def viewitems(self):
print "IMPL:", __function__()
return self.d.viewitems()
def __contains__(self, key):
print "IMPL:", __function__()
return key in self.d
class _XattrMetaStore(MetaStore):
# needed by pytagsfs --format
# called by sourcetreerep/__init__.py: add_source_file()
# through the DelegateMultiMetaStore:get() function
def get(self, path):
#traceback.print_stack()
# todo, how is it merged if one do, eg, attr -s extension=X file.avi ?
d = dict ( xattr.get_all(path, namespace=xattr.NS_USER ) )
for k in d:
d[k] = d[k].split(',')
values = Values(d)
return values
# called by a move on the destination filesystem
def set(self, path, values):
print "IMPL:", self.__class__.__name__, __function__()
#print path
#print values
for k,v in values.iteritems():
# concatenate the elements in a string with ',' as separator
xattr.set(path, k, ','.join(v), namespace=xattr.NS_USER)
return values.keys()
def save(self):
print "IMPL:", self.__class__.__name__, __function__()
# needed by pytags --format
@classmethod
def extract(self, tags):
print "IMPL:", self.__class__.__name__, __function__()
values = Values()
print tags, values
return tags
# needed: used by pytags --set
@classmethod
def inject(cls, tags, values):
print "IMPL:", self.__class__.__name__, __function__()
# values always seems empty, return
return
class XattrMetaStore(_XattrMetaStore):
error_class = Exception
def tags_class(self, filename):
return SimpleXAttrFile(filename)
# PYTHONPATH=modules ./pytags --metastores=pytagsfs.metastore.xattr_.XattrMetaStore --set subject=eco ~/tagsfs/sources/Into_Eternity.avi
# PYTHONPATH=modules ./pytags --metastores=pytagsfs.metastore.xattr_.XattrMetaStore --format='/%{title}.%{extension}' ~/tagsfs/sources/Into_Eternity.avi
# pytagsfs.metastore.path.PathMetaStore is needed to "inherit" %f, %p and %e !
# (in the last position to override potential conflicting attributes from XattrMetaStore)
# PYTHONPATH=modules ./pytagsfs -ds -o metastores='pytagsfs.metastore.xattr_.XattrMetaStore;pytagsfs.metastore.path.PathMetaStore' -o format='/%{subject}/%f' ~/tagsfs/sources ~/tagsfs/mnt
# PYTHONPATH=modules ./pytagsfs -ds -o metastores='pytagsfs.metastore.maildir.MaildirMetaStore;pytagsfs.metastore.path.PathMetaStore' -o format='/%{maildir_tag}/%f' ~/tagsfs/sources/mail/cur/ ~/tagsfs/mnt/
# ===
# PYTHONPATH=modules ./pymailtagsfs -ds -o format='/%{maildir_tag}/%f' ~/tagsfs/sources/mail/cur/ ~/tagsfs/mnt/
Follow ups