tags:

views:

220

answers:

1

I have a python fuse project based on the Xmp example in the fuse documentation. I have included a small piece of the code to show how this works. For some reason get_file does get called and the class gets created, but instead of fuse calling .read() on the class from get_file (file_class) fuse keeps calling Dstorage.read() which defeats the purpose in moving the read function out of that class.

class Dstorage(Fuse, Distributor):
    def get_file(self, server, path, flags, *mode):
        pass
        # This does some work and passes back an instance of
        # a class very similar to XmpFile

    def main(self, *a, **kw):
        self.file_class = self.get_file
        return Fuse.main(self, *a, **kw)

I have my code hosted on launchpad, you can download it with this command.
bzr co https://code.launchpad.net/~asa-ayers/+junk/dstorage
bzr branch lp:~asa-ayers/dstorage/trunk

solution:
I used a proxy class that subclasses the one I needed and in the constructor I get the instance of the class I need and overwrite all of the proxy's methods to simply call the instance methods.

+1  A: 

Looking at the code of the Fuse class (which is a maze of twisty little passages creating method proxies), I see this bit (which is a closure used to create a setter inside Fuse.MethodProxy._add_class_type, line 865):

        def setter(self, xcls):

            setattr(self, type + '_class', xcls)

            for m in inits:
                self.mdic[m] = xcls

            for m in proxied:
                if hasattr(xcls, m):
                    self.mdic[m] = self.proxyclass(m)

When you do self.file_class = self.get_file, this gets called with self.get_file, which is a bound method. The loop over proxied attributes is expecting to be able to get the attributes off the class you set, to put them into its mdic proxy dictionary after wrapping them, but they aren't there, because it's a bound method, rather than a class. Since it can't find them, it reverts to calling them on Dstorage.

So, long story short, you can't use a callable that returns an instance (kind of a pseudo-class) instead of a class here, because Fuse is introspecting the object that you set to find the methods it should call.

You need to assign a class to file_class - if you need to refer back to the parent instance, you can use the nested class trick they show in the docs.

wilberforce