meetteem: tech addict

software development, etc.

Tagging

I've added tagging to this site. As most of my avid readers know, this blog is made in Django.

A little background how I did it and why I choose to do it that way.

I had two options on how to implement tagging: generic relations using the contenttypes framework and many-to-many relations.

I went with the many-to-many relationship primarily because I had the impression that Contenttypes API isn't stable atm:

Generic relations will most likely be moved out of core and into the content-types contrib package to avoid core dependencies on optional components.

Well, as far as I can see, the django trunk has already made this change.

The second reason I went with the ManyToMany relationship was because I didn't need or want the Generic relations. I just needed to tag posts.

So there.

File Tambayan: My Storage in GAE

Beer caused this.

I had some bottles of beer last night. I definitely felt the alcohol circulating in my brain. I tried to stay awake but at around 12 midnight, I fell asleep. I woke up at 4 in the morning when my roommate turned the light off and having remembered that I forgot to send an sms to my dear ahem, I turned back the light on and searched for my phone. I found it on the floor, on top of my left rubber shoe. I was more awake now than when I had stood up from my bed. I got my MacBook and I remembered I was checking out my S3 account information right before I fell asleep. Four cents. Less than 20 pesos. Still, it's money I'm gonna have to pay everytime someone downloads a file from my S3 account. So I set myself a deadline: 10 A.M. By 10 in the morning, around 6 hours from that time, I must deploy a personal online storage app in Google App Engine.

So here it is. The beer's effect. My File Tambayan. I described it in teemlabs as

A simple file storage app ala s3. It's minimal (no thumbnail processing, has no css, etc), just plain file uploading and downloading.

It resides in teemlabs. It is written in Python, with the Django framework. Writing it as a small Django app will make it easier to install in other appengine applications. Somekinda drop-and-load of the module. Easy. Well, I think it's easy.

Here's the link to the first file uploaded to the Tambayan: rspec-1.1.3-tmBundle_patch.diff

I want to open its source, but only if there is interest in it. Like if you want to learn a little bit of Google App Engine, or just want to have an online storage, just like me. Having coded this so early in the morning, and being the n00b that I am, I'm not sure if you'd want to take a look at its source. Just send me an email if you want to look at the code, or just roll out your own.

Some Python Notes

I spent the last two days studying (and relearning) advanced Python and Smalltalk.

Here are some of my Python notes.

Disclaimer: I'm not a Python master, though I want to be one.

Classes and Objects

I thought that when you create a class without specifying a parent class, it sets object as the parent class, ala Ruby. I was wrong. Classes that inherit from object are new style classes.

Check this out:

>>> class A: pass
... 
>>> class B(object): pass
...
>>> dir(A)
['__doc__', '__module__']
>>> dir(B)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__']

And you can easily add attributes to objects (instances of a class).

>>> class Cat: pass
... 
>>> felix = Cat()
>>> felix.name = 'Felix'
>>> felix.name
'Felix'
>>> def meow(self):
...   if hasattr(self, 'name'):
...     print "%s: meowwww" % self.name
...   else:
...     print "purrrrr"
... 
>>> Cat.meow = meow
>>> dir(felix)
['__doc__', '__module__', 'meow', 'name']
>>> felix.meow()
Felix: meowwww
>>> sylvester = Cat()
>>> sylvester.meow()
purrrrr

I'm thinking of metaprogramming in Python right now. Like, how can I dynamically add a dynamically named method to a class? setattr maybe? And the last time I checked, decorators and descriptors are the most common metaprogramming techniques used in Python.

Descriptors

Here's a guide to Python descriptors.

Descriptors allow you to create attributes of an object that can do some magic when those attributes are read, written, or deleted.

Here's my example:

class EncryptionKey(object):
  def __set__(self, inst, value):
    self.key = value
    if hasattr(inst, 'encrypt'):
      inst.encrypt(value)
    else:
      pass

  def __get__(self, inst, objtype):
    return self.key

class EncryptableString(str):
  key = EncryptionKey()
  def encrypt(self, key):
    self.encrypted = __import__('string').join([chr(ord(c)^key) for c in self], '')

s = EncryptableString("hello")
s.key = 67
print s.encrypted

# output
+&//,

When s.key is set to 67, encrypt is called by the EncryptableString object, which encrypts the current object and the result is saved in the object's encryted attribute. The descriptor protocol allows this callback method to be called. Nice.

Note that for descriptors to work in a class, the class must be a new style class, i.e. a class that inherits from object or type.

Mixin Classes

Got this from here.

You can create mixin classes using multiple inheritance.

class EatingMixin(object):
  def eat(self, food="5 gallons of ice cream"):
    print "I'm now eating %s." % food
    return self


class WalkingMixin(object):
  def walk(self, distance=5):
    print "I'm now walking %d miles."
    return self


class Person(EatingMixin, WalkingMixin):
  def __init__(self, name):
    super(Person, self).__init__(self)
    self.name = name
    print "Hi! I'm %s." % self.name


tim = Person('Tim')
tim.walk()
tim.eat()
tim.eat('lots of vegetables')


# Output:
Hi! I'm Tim
I'm now walking 5 miles.
I'm now eating 5 gallons of ice cream.
I'm now eating lots of vegetables.

Another way is to modify the __bases__ of the class. Using the mixin example above:

class DressupMixin:
  def dressup(self, dress="red evening gown"):
    print "Do I look cute in this %s?" % dress
    return self

class Woman(Person):
  pass

Woman.__bases__ += (DressupMixin,)

Woman('Eve').walk().eat().dressup()


# Output
Hi! I'm Eve.
I'm now walking 5 miles.
I'm now eating 5 gallons of ice cream.
Do I look cute in this red evening gown?

Note that you can modify the __bases__ of the classes on the fly. How's that for power! You can do this:

new_bases = list(Woman.__bases__)
new_bases.remove(DressupMixin)
Woman.__bases__ = tuple(new_bases)

Now, the Woman class and its instances won't have the dressup method anymore. This makes Python classes pluggable.

The only problem I encountered was when I set the __bases__ to () or None. This causes a TypeError to be raised.

More to Come

So, there.

I also played with __metaclass__. And I'll also add my notes on decorators.

w00t! desyd is Up

Yup! I've just deployed my first Google App Engine app. Dubbed desyd, this app can be used to tabulate the pros and cons of anything. You can share the pros and cons of making a specific decision to the world. You can quantify each pro and con to help you decide much better.

If I can spare some more time, I plan to make it Ajaxxy. And I hope to add some stuff like commenting, and even adding notes to a pro or con.

It's simple really, and I wonder if it's going to useful. So, why don't you go ahead and try it, then tell me what you think?

This release in the pre-alpha stage. Haha! So, I'd really appreciate comments and stuff. :D

Putting teemlabs Under Git

Yesterday, I blogged about my adventure with Google App Engine and the 'launch' of teemlabs.

I knew that I had to maintain the source code of this app, and that meant creating a Git repository. The thing was, I didn't know, and still don't, if the .git directory will be uploaded to the Google servers when I deploy the application. (I have an update at the end of this post regarding this.) I don't want that. I thought of putting the main application directory inside another directory which would contain the .git directory, making the parent directory the root of the Git repository.

|--teemlabs.git
   |--.git
   |--teemlabs       <-- the app

I thought I knew what to do, but I encountered a problem creating the git repository.

Here's what happened.

~/dev/projects/appengine/teemlabs$ git init
Initialized empty Git repository in .git/
~/dev/projects/appengine/teemlabs$ mate .gitignore
~/dev/projects/appengine/teemlabs$ gst
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       .gitignore
#       teemlabs/
nothing added to commit but untracked files present (use "git add" to track)
~/dev/projects/appengine/teemlabs$ git add .
~/dev/projects/appengine/teemlabs$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file: .gitignore
#       new file: teemlabs
#
~/dev/projects/appengine/teemlabs$ git commit -m "Initial commit."
Created initial commit 25936f1: Initial commit.
 2 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
 create mode 160000 teemlabs
~/dev/projects/appengine/teemlabs$

I then copied teemlabs to my slice, and git cloned the new repository. Yup, it was cloned... except that the files under teemlabs/teemlabs weren't there.

Why? Didn't git add . add the teemlabs directory? Well, yes. It did add the teemlabs directory-- but only the directory. The files inside weren't added.

So I added them.

~/dev/projects/appengine/teemlabs$ git add teemlabs/*
~/dev/projects/appengine/teemlabs$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       deleted:    teemlabs
#       new file:   teemlabs/app.yaml
#       new file:   teemlabs/templates/index.html
...
~/dev/projects/appengine/teemlabs$ git commit -m "Add the teemlabs files."
Created commit 3c493b6: Add the teemlabs files.
 14 files changed, 177 insertions(+), 1 deletions(-)
 delete mode 160000 teemlabs
 create mode 100644 teemlabs/app.yaml
 create mode 100644 teemlabs/index.yaml
 ...

Now, all is well and good. Cloning the repo included the files.

But it took two commits just to add a single directory. This shouldn't be the case. Adding a new directory and the files it contains can simply be done with the following steps.

git add directory
git add directory/*
git commit

I'm confused, though, why sometimes just a simple git add . and git commit works, but this time, it doesn't.

Oh, well.

Update:

After reading more of the docs, I found out that app.yaml has a skip_files element which allows you to skip uploading of files. And Unix hidden files are, by default, not uploaded. I didn't have to create a parent directory, which acts as the root of the git repo, for teemlabs. I could simply run git init in the teemlabs directory itself.

<< Older Posts | Newer Posts >>