permissions and time

Tonights zmugfs update is permissions and time are now shown correctly. I defaulted the user and group to that of the user running the program (in this case me) :) And I now show the date and time correctly from the api.

Update: by “in this case me” it doesn’t mean I hardcoded my uid and gid. I used os.getuid() and os.getgid()

By the way, disregard the drew and foo entries. Those are debug strings which will be removed.

perms and time

zmugfs shows image data

Success. I got zmugfs to show image data in nautilus. It is a horribly inefficient algorithm but it works. I do the following:

  • login to smugmug
  • getUrls for imageid
  • httpget image from above url
  • return imgdata

I know EWW! :) But it worked!

img data

That’s cool and all, but I bet what would be really cool is to open the file up in GIMP.

gimp

How’s that for coolness! It’s 12:18am EDT, I need to get to bed because I have to get up at 6:30am to get the kiddies ready for school. If all goes well, I should be able to get zmugfs 0.1 released by next week.

zmugfs shows image listings

Yesterday I started implementing the image listings for the albums. I finished it up today. Here are the latest screenshots.

First up is an ls listing of the Album which appears on the filesystem as a directory (click the image to see a larger view, and yes that is Obi-wan in the background). The permissions aren’t quite right for the images, but that’s a minor change to the stat structure.

zmugfs shows ls listing of images

Next up is a subcategory containing albums. If you recall before I didn’t show the image counts, now the image counts appear.

zmugfs shows image counts now

Finally, you can see an album with the list of images and their file sizes. Since this only returns the filename information nautilus can’t render the previews. Still this is cool stuff, well in my opinion it’s cool stuff :)

zmugfs image list

zmugfs via nautilus (part 2)

Almost a month ago I posted a screenshot of zmugfs via nautilus. Back then I was returning a hardcoded list of strings with no inode information. Last week, I got the read-only listing of categories and subcategories to work, see the ls output here.

I thought to myself, I bet folks would love to see the new read-only functionality through nautilus. Well, prepare to be amazed and bedazzled. :) First up is a screenshot of a category showing all of the subcategories contained within. Notice all but one says “0 items”, that’s because I haven’t figured out how to get the image count for the albums contained within yet.

zmugfs category

The Birthday subcategory contains 9 items (all albums). So if you double click on that folder you are presented with a window showing all 9 albums in the subcategory.

zmugfs subcat

Isn’t that cool? You may be asking, “how do I know he’s not just returning some random list of strings?” Well, let’s look at smugmug to see what’s actually there:

actual smugmg subcategory

Next step is to get Albums to show their images and their image counts. Once that is done, I will release zmugfs 0.1 out in the wild. The following releases will add write support and possible performance enhancements.

zmugfs shows readonly (sub)categories

I kept fighting fuse.Direntry. When I tried:

for n in node.get_nodes():
     yield fuse.Direntry(n.path)

I would get NOTHING! but if I created a simple test list it would work:

f = ['foo', 'bar', 'path', 'cheese']
for i in f:
    yield fuse.Direntry(i)

It was confusing until I notice the only difference was that n.path was a unicode string while my test list were ascii stings. I thought to myself, “nah, that can’t be it”. But what do you know! I made this change:

yield fuse.Direntry(n.path.string('/').encode('ascii'))

Not sure if that will be the final code, IMO fuse.Direntry should work with unicode strings. But none the less, the result is a magnificent readonly view using ls and ls -l.

zmugfs shows ls

python’s default argument values

I’ve been trying to track down a bug for a couple days now with zmugfs. I’m caching the tree structure returned by smugmug.users.getTree. Here’s my Node class:

class Node(object):
    def __init__(self, path, inode=MyStat(), children=[]):
        self.path = path
        self.inode = inode
        self.children = children

To a newbie like me, this looks perfectly fine. If no inode is passed in create an instance of MyStat(), if no children are passed in create an empty list. Well guess what! That’s not how python works with lists. If you do what I did above the children list is shared! Imagine my horror when each Node has a reference to ALL of the children of the other Nodes. EEK! A few minutes of googling and I found this page:
4.7.1 Default Argument Values.

I changed the constructor of the Node class to be as follows:

def __init__(self, path, inode=MyStat(), children=None):
    self.path = path
    self.inode = inode
    if children is None:
        self.children = []
    else:
        self.children = children

This fixed my problem.

selfless isn’t always good

Last night I posted a little blurb about python’s self. My bud dgoodwin agreed with me, but after reading the reason it exists we both felt much better about having to use it. According to the General Python FAQ there’s a pretty good reason to have it:

The idea was borrowed from Modula-3. It turns out to be very useful, for a variety of reasons.

First, it’s more obvious that you are using a method or instance attribute instead of a local variable. Reading self.x or self.meth() makes it absolutely clear that an instance variable or method is used even if you don’t know the class definition by heart. In C++, you can sort of tell by the lack of a local variable declaration (assuming globals are rare or easily recognizable) — but in Python, there are no local variable declarations, so you’d have to look up the class definition to be sure. Some C++ and Java coding standards call for instance attributes to have an m_ prefix, so this explicitness is still useful in those languages, too.

Second, it means that no special syntax is necessary if you want to explicitly reference or call the method from a particular class. In C++, if you want to use a method from a base class which is overridden in a derived class, you have to use the :: operator — in Python you can write baseclass.methodname(self, ). This is particularly useful for __init__() methods, and in general in cases where a derived class method wants to extend the base class method of the same name and thus has to call the base class method somehow.

Finally, for instance variables it solves a syntactic problem with assignment: since local variables in Python are (by definition!) those variables to which a value assigned in a function body (and that aren’t explicitly declared global), there has to be some way to tell the interpreter that an assignment was meant to assign to an instance variable instead of to a local variable, and it should preferably be syntactic (for efficiency reasons). C++ does this through declarations, but Python doesn’t have declarations and it would be a pity having to introduce them just for this purpose. Using the explicit “self.var” solves this nicely. Similarly, for using instance variables, having to write “self.var” means that references to unqualified names inside a method don’t have to search the instance’s directories. To put it another way, local variables and instance variables live in two different namespaces, and you need to tell Python which namespace to use.

Hopefully you won’t curse python for being selfish next time.

zmugfs through the eyes of nautilus

zmugfs is moving along slowly, but I’m pretty happy with the progress I’ve made so far. Learning FUSE and about filesystem calls has been extremely interesting. I started out trying to get mkdir to work and realized I’m better off getting the read only part done first :)

Tonight I asked myself “I wonder what it looks like through nautilus?” So here is what it looks like. I’ve got a few inode issues (as you can tell by the …) but still it’s cool that I can actually see things :)

zmugfs via nautilus