Commits

Anonymous committed 441ea02

added support for multiple generic option fields in one model by a addident number
added Path class for easier handling of paths
more tests and bugfixes
use one RootDirectory instance throuout the api
started implementing write support
allow recrusive option lookups, this way preferences travel down the tree

  • Participants
  • Parent commits 2df032f

Comments (0)

Files changed (8)

genericoptions/fields.py

     fields.
     """
 
-    #def __init__(self, ct_field="content_type", fk_field="object_id"):
+    def __init__(self, ct_field="content_type", fk_field="object_id", instance=None, addident=0, parent=None):
+        self.addident = addident
+        self.instance = instance
+        self.parentname = parent
+
     #    self.ct_field = ct_field
     #    self.fk_field = fk_field
 
         # Handle initalizing an object with the generic FK instaed of
         # content-type/object-id fields.
         if self.name in kwargs:
-            value = kwargs.pop(self.name)
-            kwargs[self.ct_field] = self.get_content_type(value)
-            kwargs[self.fk_field] = value._get_pk_val()
+            #print "metas passed"
+            raise ValueError, "passing meta attributes in constructor is not supported"
+
+            #value = kwargs.pop(self.name)
+            #kwargs[self.ct_field] = self.get_content_type(value)
+            #kwargs[self.fk_field] = value._get_pk_val()
 
     #def get_content_type(self, obj):
     #    # Convenience function using get_model avoids a circular import when using this model
         if instance is None:
             raise AttributeError, u"%s must be accessed via instance" % self.name
 
-        return OptionWrapper(instance=instance)
+        # fixme hack: this shouldn't be here when makeing it generic
+        #if isinstance(instance, RootDirectory):
+        #    return OptionWrapper(instance=None)
+        #if
+        key = None
+        for k,n in instance.__class__.__dict__.items():
+            if n == self:
+                key = k
+                break
+        def parent_lookup(model_instance, instance, name):
+            m = model_instance
+            while True:
+                c = getattr(m, key)
+                try:
+                    o = getattr(c, name)
+                    return o
+                except (KeyError, AttributeError):
+                    if not self.parentname:
+                        raise
+                    m2 = getattr(m, self.parentname)
+                    if m == m2 or m2 == None:
+                        raise KeyError, "Option not found in recrusive lookup"
+                    m = m2
+                    #getattr(o,
+
+
+        if self.instance == -1:
+            return OptionWrapper(instance=self.instance, addident=self.addident, parent_lookup=parent_lookup)
+        return OptionWrapper(instance=instance, addident=self.addident, parent_lookup=parent_lookup)
         #try:
         #    return getattr(instance, self.cache_attr)
         #except AttributeError:

genericoptions/models.py

 
 class Option(models.Model):
     """Used to save options for a mount or specific object"""
-    key = models.CharField(max_length=255, null=False, blank=False, editable=False, unique=True)
+    key = models.CharField(max_length=255, null=False, blank=False, editable=False)
     typ = models.IntegerField(null=False, choices=OPTION_TYPES, default=0)
 
     instance_type = models.ForeignKey(genmodels.ContentType, null=True)
     instance_id = models.PositiveIntegerField(null=True)
     #target = generic.GenericForeignKey()
     instance = generic.GenericForeignKey(ct_field=instance_type, fk_field=instance_id)
+    addident = models.IntegerField(default=0)
+
     value = models.TextField(null=True, blank=True)
 
     def set(self, value):
 
     def __repr__(self):
         if self.instance_id:
-            return '<Option %.10s:%.10s... for %s:%s>' %(self.key, self.get(), self.instance_type, self.instance_id)
-        return '<Option %(key).10s:%(value).10s...>' %self.__dict__
+            return '<Option %.10s:%.10s... (idnt:%s) for %s:%s>' %(self.key, self.get(), self.addident, self.instance_type, self.instance_id)
+        return '<Option %(key).10s:%(value).10s... (idnt:%(addident)s)>' %self.__dict__
 
 DEFAULT_NOT_GIVEN="_DEFAULT_NOT_GIVEN_"
 
-def option_get(name, default_value=DEFAULT_NOT_GIVEN, instance=None):
+def option_get(name, default_value=DEFAULT_NOT_GIVEN, instance=None, addident=0):
     if not isinstance(name, basestring):
         raise KeyError, "Key must be a string"
 
-    if instance is not None:
+
+    if instance != None:
         ContentType = get_model("contenttypes", "contenttype")
         ct = ContentType.objects.get_for_model(instance)
+
+        #print Option.objects.all()
+        #print name, default_value, instance, addident
+        #print Option.objects.filter(
+        #key__exact=name, instance_id=instance.pk, instance_type=ct, addident=addident)
+        #print "||"
+
         try:
             o = Option.objects.get(
-                    key=name, instance_id=instance.pk, instance_type=ct)
+                    key=name, instance_id=instance.pk, instance_type=ct, addident=addident)
+            return o.get()
         except Option.DoesNotExist:
             if default_value != DEFAULT_NOT_GIVEN:
                 return default_value
-            raise KeyError, "Option with key %s not found" %name
+            raise KeyError, "Option with key '%s' not found" %name
 
     try:
-        o = Option.objects.get(key__exact=name)
+        o = Option.objects.get(key__exact=name, instance_id__isnull=True, instance_type__isnull=True, addident__exact=addident)
         return o.get()
     except Option.DoesNotExist:
-        if default_value != DEFAULT_NOT_GIVEN:
+        if id(default_value) != id(DEFAULT_NOT_GIVEN):
             return default_value
         raise KeyError, "Option with key %s not found" %name
 
-def option_set(name, value, instance=None):
+def option_set(name, value, instance=None, addident=0):
     if not isinstance(name, basestring):
         raise KeyError, "Key must be a string"
 
         ContentType = get_model("contenttypes", "contenttype")
         ct = ContentType.objects.get_for_model(instance)
         (o, c) = Option.objects.get_or_create(
-                key=name, instance_id=instance.pk, instance_type=ct,
-                defaults={'key':name, 'value': None, 'instance_id':instance.pk, 'instance_type':ct}
+                key=name, instance_id=instance.pk, instance_type=ct, addident=addident,
+                defaults={'key':name, 'value': None, 'instance_id':instance.pk, 'instance_type':ct, 'addident':addident}
                 )
     else:
-        (o, c) = Option.objects.get_or_create(key=name, instance_id__isnull=True, instance_type__isnull=True, defaults={'key':name, 'value':value})
+        (o, c) = Option.objects.get_or_create( \
+                        key=name, instance_id__isnull=True, \
+                        instance_type__isnull=True, addident=addident, \
+                        defaults={'key':name, 'value':None, 'addident':addident})
     o.set(value)
     o.save()
 
-def option_has(name, instance=None):
+def option_has(name, instance=None, addident=0):
     if instance is not None:
         ContentType = get_model("contenttypes", "contenttype")
         ct = ContentType.objects.get_for_model(instance)
         return Option.objects.filter(
-                key=name, instance_id=instance.pk, instance_type=ct).count() == 1
+                key=name, instance_id=instance.pk, instance_type=ct, addident=addident).count() == 1
 
     return Option.objects.filter(key=name, instance_id__isnull=True, instance_type__isnull=True).count() == 1
 
 class OptionWrapper(object):
-    def __init__(self, instance=None, options=None):
+    def __init__(self, instance=None, options=None, addident=0, parent_lookup=None):
         self.options = options
         self.instance = instance
+        self.addident = addident
+        self.parent_lookup = parent_lookup
 
     def __getitem__(self, name):
-        rv = option_get(name, instance=self.instance)
+        rv = option_get(name, instance=self.instance, addident=self.addident)
         return rv
 
+    def __getattr__(self, name):
+        try:
+            return self.__getitem__(name)
+        except KeyError, e:
+            raise AttributeError, e
+
+    def get_recrusive(self, name):
+        if self.parent_lookup:
+            return self.parent_lookup(self.instance, self, name)
+        else:
+            raise KeyError, "No option found"
+
     def __setitem__(self, name, value):
-        return option_set(name, value, instance=self.instance)
+        return option_set(name, value, instance=self.instance, addident=self.addident)
 
     def filter(self, *args, **kwargs):
-        if self.instance:
+        self.all().filter(*args, **kwargs)
+
+    def all(self):
+        if self.instance is not None:
             ContentType = get_model("contenttypes", "contenttype")
-            ct = ContentType.objects.get_for_model(instance)
-            return Options.objects.filter(key=name,
-                instance_id=instance.pk, instance_type=ct).filter(*args, **kwargs)
-        return Option.objects.filter(key=name,
-                instance_id__isnull=True, instance_type__isnull=True).filter(*args, **kwargs)
+            ct = ContentType.objects.get_for_model(self.instance)
+            return Option.objects.filter(
+                instance_id=self.instance.pk, instance_type=ct, addident=self.addident)
+        return Option.objects.filter(
+                instance_id__isnull=True, instance_type__isnull=True, addident=self.addident)
+
+    def get(self, *args, **kwargs):
+        self.all().get(*args, **kwargs)
+
+    def has_key(self, name):
+        try:
+            self.__getitem__(name)
+            return True
+        except:
+            return False
 
     def __iter__(self):
-        for i in self.filter():
+        for i in self.all():
             yield i
 
     def keys(self):
         rv = []
-        for i in self.filter():
+        for i in self.all():
             rv.append(i.key)
 
     def iteritems(self):
-        for i in self.filter():
+        for i in self.all():
             yield (i.key, i.get())
 
     def iterkeys(self):
-        for i in self.filter():
+        for i in self.all():
             yield i.key
 
+    def __str__(self):
+        return 'OptionWrapper%s' %dict(self.iteritems()).__str__()
+
+    def __repr__(self):
+        return 'OptionWrapper%s' %dict(self.iteritems()).__repr__()
+
     #def iter
     # fixme: make more complete api here
 

genericoptions/tests.py

     threestr = "3"
     uniquad = u"4"
 
+    def __cmp__(self, other):
+        if self.uno != other.uno or \
+            self.duofloat != other.duofloat or \
+            self.threestr != other.threestr or \
+            self.uniquad != other.uniquad:
+            return -1
+        return 0
+
 class TestModel(models.Model):
     test = models.CharField(max_length=10)
     options = fields.GenericOptions()
+    metas = fields.GenericOptions(addident=99)
+
+    def __repr__(self):
+        return '<TestModel %s "%s">' %(self.id, self.test)
+
+    def __str__(self):
+        return '<TestModel %s "%s">' %(self.id, self.test)
+
+class TestRecrModel(models.Model):
+    parent = models.ForeignKey('self', null=True)
+    options = fields.GenericOptions(parent='parent')
+
+    def __repr__(self):
+        return '<TestRecr %s "%s">' %(self.id, self.parent_id)
+
+    def __str__(self):
+        return '<TestRecr %s "%s">' %(self.id, self.parent_id)
+
+
+class TestRecr(TestCase):
+    def setUp(self):
+        self.t1 = TestRecrModel()
+        self.t1.save()
+        self.t2 = TestRecrModel(parent=self.t1)
+        self.t2.save()
+        self.t3 = TestRecrModel(parent=self.t2)
+        self.t3.save()
+        self.s1 = TestRecrModel()
+        self.s1.save()
+        self.t4 = TestRecrModel(parent=self.t1)
+        self.t4.save()
+
+    def geto(self, mod, key):
+        return mod.options[key]
+
+
+    def test_recrmeta(self):
+        self.t1.options['rootset'] = 'test'
+        self.assertEqual(self.t1.options.get_recrusive('rootset'), 'test')
+        self.assertEqual(self.t2.options.get_recrusive('rootset'), 'test')
+        self.assertEqual(self.t3.options.get_recrusive('rootset'), 'test')
+        self.assertEqual(self.t4.options.get_recrusive('rootset'), 'test')
+        self.assertRaises(KeyError, self.geto, self.s1, 'rootset')
+        self.assertRaises(KeyError, self.geto, self.t1, 'rootset2')
+        self.t2.options['rootset'] = 'test2'
+        self.assertEqual(self.t1.options.get_recrusive('rootset'), 'test')
+        self.assertEqual(self.t2.options.get_recrusive('rootset'), 'test2')
+        self.assertEqual(self.t3.options.get_recrusive('rootset'), 'test2')
+        self.assertEqual(self.t4.options.get_recrusive('rootset'), 'test')
+        self.t4.options['rootset'] = 'test3'
+        self.assertEqual(self.t1.options.get_recrusive('rootset'), 'test')
+        self.assertEqual(self.t2.options.get_recrusive('rootset'), 'test2')
+        self.assertEqual(self.t3.options.get_recrusive('rootset'), 'test2')
+        self.assertEqual(self.t4.options.get_recrusive('rootset'), 'test3')
+
+
+
+
+
 
 class TestFields(TestCase):
     def setUp(self):
         
     def test_fields(self):
         #print self.t1.options
-
         self.t1.options['test'] = 1
         self.t1.options['test2'] = 2
+        #print self.t1.options
         self.assertEqual(self.t1.options['test'], 1)
         self.assertEqual(self.t1.options['test2'], 2)
+        self.assertEqual(self.t1.options.has_key('test'), True)
+        self.assertEqual(self.t1.options.has_key('test2'), True)
+        self.assertEqual(self.t1.options.has_key('test3'), False)
+        self.assertEqual(self.t2.options.has_key('test'), False)
+        self.assertEqual(self.t2.options.has_key('test2'), False)
 
+        
     def geto(self, mod, key):
         return mod.options[key]
 
+
+    def getm(self, mod, key):
+        return mod.metas[key]
+
     def test_existing(self):
         self.t1.options['test'] = 1001
         self.assertRaises(KeyError, self.geto, self.t2, 'test')
         self.t2.options['test2'] = 2002
         self.assertRaises(KeyError, self.geto, self.t1, 'test2')
 
-        self.assertEqual(getattr(self.t2.options,'test2',None), None)
-        self.assertEqual(getattr(self.t2.options,'test2',-120), -120)
+        self.assertEqual(getattr(self.t2.options,'test2',None), 2002)
 
+        self.assertEqual(getattr(self.t2.options,'test3',None), None)
+        self.assertEqual(getattr(self.t2.options,'test3',-120), -120)
+
+    def test_second(self):
+        # test that second optionsfield doesn't have values
+
+        self.t1.options['test'] = 99
+        self.assertRaises(KeyError, self.getm, self.t1, 'test')
+        self.assertRaises(KeyError, self.getm, self.t2, 'test')
+
+        self.t1.metas['testm'] = 99
+        self.assertRaises(KeyError, self.geto, self.t1, 'testm')
+        self.assertRaises(KeyError, self.geto, self.t2, 'testm')
 
 
 class TestOptions(TestCase):
     def test_complex(self):
         o = options
         o['comp1'] = Complex()
-        print o['comp1']
         self.assertEqual(o['comp1'], Complex())
 
+        # default complex python types
+        o['k1'] = {'a':1, 'b':2}
+        self.assertEqual(o['k1'], {'a':1, 'b':2})
+        o['k2'] = None
+        self.assertEqual(o['k2'], None)
+        o['k3'] = [1,2,3]
+        self.assertEqual(o['k3'], [1 ,2 ,3 ])
+        self.assertEqual(o['k3'], [1,2,3])
+        self.assertNotEqual(o['k3'], [1,2,3,4])
+        self.assertNotEqual(o['k3'], (1,2,3))
+
+        o['k4'] = (1,2,3)
+        self.assertEqual(o['k4'], (1,2,3))
+        self.assertNotEqual(o['k4'], [1 ,2 ,3])
+
+
+
 
 
     def test_lowlevel(self):

vaultdb/models.py

 from django.db import models
 from django.contrib.contenttypes import generic
 import django.contrib.contenttypes.models as genmodels
+from vaultfs.genericoptions.fields import GenericOptions
+from vaultfs.genericoptions.models import OptionWrapper
 
 
 import os
     media_type = fields.MediaField("Type of Media", choices=(), max_length=30)
     mountpoint = models.CharField("Current Mountpoint of media", max_length=255)
     mounted = models.BooleanField("Is medium mounted", default=False)
+    options = GenericOptions()
 
     def _get_backend(self):
         from backends import get_backend
 
 class BaseOperations(object):
 
+    def _get_optionr(self, name):
+        pass
+
     def get_absolute_path(self):
         na = []
         st = self
             return False
 
     def _get_children(self):
-        for i in self.directory_set:
+        for i in self.directory_set.filter():
             yield i
 
-        for i in self.file_set:
+        for i in self.file_set.filter():
             yield i
 
-        for i in self.symlink_set:
+        for i in self.symlink_set.filter():
             yield i
 
     children = property(_get_children)
     real_directory = None
     absolute_path = None
     id = None
+    options = GenericOptions(instance=None)
 
     def _dirset(self):
+        print
         return Directory.objects.filter(parent__isnull=True)
     directory_set = property(_dirset)
 
     real_directory = models.ForeignKey(RealDirectory, null=True)
     mtime  = models.DateTimeField(auto_now=True, editable=False)
     ctime  = models.DateTimeField(auto_now_add=True, editable=False)
+    options = GenericOptions()
 
 
     objects = DirectoryManager()
     media = models.ForeignKey(Media)
     media_path = models.TextField('path of file on media')
     parent = models.ForeignKey(RealDirectory, null=False)
+    options = GenericOptions()
+    # contains meta information parsed out of the data part of file
+    metadata = GenericOptions()
+
+    def __init__(self, create=False, *args, **kwargs):
+        models.Model.__init__(*args, **kwargs)
+        if create:
+            
+            if not os.exists(media_path):
+                #r = getattr(OPTIONS, '
+                #fp = open(
+                pass
+
+            if not os.isfile(media_path):
+                raise EnvironmentError, "Error creating new File"
+
 
     def _aliases_get(self):
         return RealFile.objects.filter(file_size=self.file_size, hash=self.hash, hash__isnull=False)
     _name = models.CharField("Relative Name", max_length=255, db_index=True)
     parent = models.ForeignKey(Directory, null=True, db_index=True)
     real_file = models.ForeignKey(RealFile, null=True)
-    is_file = True
     mtime  = models.DateTimeField(auto_now=True, editable=False)
     ctime  = models.DateTimeField(auto_now_add=True, editable=False)
+    options = GenericOptions()
+
+    is_file = True
 
     def __init__(self, *args, **kwargs):
         if kwargs.has_key('name'):
     parent = models.ForeignKey(Directory, null=True, db_index=True)
 
     target = models.TextField(null=False)
+
+    options = GenericOptions()
+
     #target_type = models.ForeignKey(genmodels.ContentType)
     #target_id = models.PositiveIntegerField()
     #target = generic.GenericForeignKey()
 
 
 ROOTDIRECTORY = RootDirectory()
+OPTIONS = OptionWrapper(instance=None)
 
 
 

vaultdb/tests/basic.py

 
     def test_directory_api(self):
         root = Directory.objects.resolve_complete("")
+        self.assertEqual(root, ROOTDIRECTORY)
+        self.assertEqual(str(root), "/")
+
+        
 
 
 class TestOptions(TestBasic):
     """ Test option interface """
     def test_options(self):
-        o = options
+        o = OPTIONS
         o.assign1 = 0
         o['test'] = 1
         o['test2'] = 2
         self.assertNotEqual(o['str1'], o['uni1'])
 
 
+from vaultfs.vaultdb.tools import Path
 
+class TestPath(TestCase):
+    def test_init(self):
+        p1 = Path("/test/bla")
+        p2 = Path("/test/bla2")
+        p3 = Path("test")
+        p4 = Path("test/bla")
+        p5 = Path("")
+        p6 = Path("/")
+        p7 = Path(".")
+        p8 = Path("./")
+        p9 = Path("/.")
+        p10 = Path("/.bla")
+        p11 = Path("/./bla")
+
+
+        self.assertEqual(str(p1), "/test/bla")
+        self.assertEqual(str(p2), "/test/bla2")
+        self.assertEqual(str(p3), "test")
+        self.assertEqual(str(p4), "test/bla")
+        self.assertEqual(str(p5), "./")
+        self.assertEqual(str(p6), "/")
+        self.assertEqual(str(p7), "./")
+        self.assertEqual(str(p8), "./")
+        self.assertEqual(str(p9), "/")
+        self.assertEqual(str(p10), "/.bla")
+        self.assertEqual(str(p11), "/bla")
+
+
+        # absolute test
+        self.assertEqual(p1.is_absolute(), True)
+        self.assertEqual(p2.is_absolute(), True)
+        self.assertEqual(p3.is_absolute(), False)
+        self.assertEqual(p4.is_absolute(), False)
+        self.assertEqual(p5.is_absolute(), False)
+        self.assertEqual(p6.is_absolute(), True)
+        self.assertEqual(p7.is_absolute(), False)
+        self.assertEqual(p8.is_absolute(), False)
+        self.assertEqual(p9.is_absolute(), True)
+        self.assertEqual(p10.is_absolute(), True)
+        self.assertEqual(p11.is_absolute(), True)
+
+        self.assertEqual(len(p1), 3)
+        self.assertEqual(len(p2), 3)
+        self.assertEqual(len(p3), 1)
+        self.assertEqual(len(p4), 2)
+        self.assertEqual(len(p5), 2)
+        self.assertEqual(len(p6), 2)
+        self.assertEqual(len(p7), 2)
+        self.assertEqual(len(p8), 2)
+        self.assertEqual(len(p9), 2)
+        self.assertEqual(len(p10), 2)
+        self.assertEqual(len(p11), 2)
+
+
+
+
+    def test_cmp(self):
+        pl = [
+          Path("/test/bla"), Path("/test/bla"),
+          Path("/test/cla"), Path("/a"), Path("/b/bla"),
+          Path("/b"), Path("/z"), Path("/b/"), Path("/b/b"), Path("/b/c")
+          ]
+
+        ps = [
+          Path("/a"), Path("/b/"), Path("/b"), Path("/b/b"), Path("/b/bla"), Path("/b/c"),
+          Path("/test/bla"), Path("/test/bla"),
+          Path("/test/cla"), Path("/z")
+          ]
+        
+        pl.sort()
+        self.assertEqual(pl, ps)
+
+    def test_len(self):
+        p1 = Path("/test/blubb")
+        p2 = Path("/")
+
+        self.assertEqual(len(p1), 3)
+        self.assertEqual(len(p2), 2)
+
+import os.path
+
+class Path(object):
+    """Path object represents a filesystem path"""
+    def __init__(self, path):
+        if isinstance(path, basestring):
+            if path == "":
+                self.chunks = ['.','']
+            elif path == ".":
+                self.chunks = ['.','']
+            else:
+                #rv = os.path.split(os.path.normpath(path))
+                self.chunks = os.path.normpath(path).split(os.sep)
+                if len(self.chunks) == 1 and self.chunks[0] == ".":
+                    self.chunks.append('')
+                #if self.chunks[-1] == '':
+                #    del self.chunks[-1]
+
+        elif isinstance(path, list):
+            self.chunks = path
+        elif isinstance(path, tuple):
+            self.chunks = list(path)
+        else:
+            raise ValueError, "unsupported path type"
+
+    def __getitem__(self, num):
+        return self.chunks[num]
+
+    def __str__(self):
+        return os.path.sep.join(self.chunks)
+
+    def __repr__(self):
+        return "<Path %s>" %self.chunks
+
+    def __cmp__(self, other):
+        rv = 0
+        if isinstance(other, Path):
+            for i in xrange(min(len(self.chunks), len(other.chunks))):
+                rv = cmp(self[i], other[i])
+                if rv:
+                    break
+            if not rv:
+                rv = cmp(len(self.chunks), len(other.chunks))
+            return rv
+        return rv
+
+    def __len__(self):
+        return len(self.chunks)
+        #rv = 0
+        #for i in self.chunks:
+        #    rv += len(i) + len(os.path.sep)
+        #return rv
+
+    def is_absolute(self):
+        if len(self) and self[0] == '':
+            return True
+        return False
+        
+
+
+        
 #!/usr/bin/env python2.5
 # simple wrapper to call vaultfs
-#from django.core.management import setup_environ
+from django.core.management import setup_environ
 
-#try:
-#import settings # Assumed to be in the same directory.
-#setup_environ(settings)
-#except ImportError:
+try:
+    import settings # Assumed to be in the same directory.
+    setup_environ(settings)
+except ImportError:
     # don't do anything, maybe its defined somewhere
-#    pass
+    pass
     #import sys
     #sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
     #sys.exit(1)

vaultfuse/vault_fuse.py

 import time
 import re
 import posix
+import thread
 
 from vaultfs.vaultdb import models
 from vaultfs.vaultdb.vaulterrors import *
         """returns a os.stat compatible object"""
         # fixme: handle uid/guid better ???
         add = 0
-        print parent, parent
+        #print parent, parent
         if parent is None or parent == models.ROOTDIRECTORY:
             add = S_IRWXU | S_IROTH | S_IRGRP | S_IXOTH |  S_IXGRP
         elif parent:
            return True
         return False
 
-    def readdir_meta(self, path, offset):
+    def readdir_meta(self, parent, pchunks, offset):
+        print "readdir_meta", parent, pchunks, offset
         pass
 
-    def readdir_mount(self, path, offset):
+    def readdir_mount(self, parent, pchunks, offset):
         pass
 
-    def readdir_media(self, path, offset):
+    def readdir_media(self, parent, pchunks, offset):
         pass
 
 
             yield fuse.Direntry(i)
         #yield fuse.Direntry("..")
         #for i in xrange(len(pchunks)):
-        for chn in pchunks:
+        for n,chn in enumerate(pchunks):
             #chn = pchunks[i]
             if VaultFS.is_meta(chn):
                 rdn = "readdir_%s" %chn.lower()[len(META_PREFIX):]
                 if self.__class__.__dict__.has_key(rdn):
-                    v = self.__class__.__dict__[rdn](self, path, offset)
+                    parent = models.Directory.objects.resolve_complete(pchunks[0:n-1])
+                    v = self.__class__.__dict__[rdn](self, parent, pchunks[n:], offset)
                     if v is None:
                         return
                     for x in v:
             for i in TOP_METAS + ALL_METAS:
                 yield fuse.Direntry(META_PREFIX + i)
 
-            for de in models.ROOTDIRECTORY.children:#models.Directory.objects.filter(parent__isnull=True):
+            for de in models.ROOTDIRECTORY.children: #models.Directory.objects.filter(parent__isnull=True):
                 if de.name:
                     yield fuse.Direntry(de.name.encode("utf-8"))
 
 
     def create(self, path, flags, mode):
         print "create ", path, flags, oct(mode)
-        (par, left) = models.Directory.resolve_parent(path)
+        (par, left) = models.Directory.objects.resolve_parent(path)
 
         if par.has_child(left[0]):
             if flags & os.O_CREAT: