Monday, August 24, 2009

Fixing a mistake after commiting in Git

So, I ran into an interesting issue while coding today. I made a lot of changes and committed code to my Git repository. Just after committing, I realized that I still had to make some changes to a file and those changes should also have gone in with the previous commit.

Fixing a commit mistake can be done in two ways. Revert the commit, make the changes and then recommit them. This is the preferred way if we have already made the changes public (and thus someone may already have pulled them). However, in my case I am the only one working on this project right now and I had not pushed the changes to GitHub, so I could try the other method.

So here's what I did. I made changes to the file, added it to the index, and committed it thus:

$git commit --amend


Committing code with the --amend switch will cause the index to be committed as part of the previous commit. Git also brings up the editor window, in case we want to change the commit message. This method can also be used to change the commit message without adding any files to the commit.

Reference:

Sunday, August 23, 2009

Lack of design patterns in Python

While searching for PyCon videos, I came across Joe Gregorio's very good video on (lack of) design patterns in Python. I have also added the video timeline along with some notes I made for myself and my takeaway. Enjoy the video.




Timeline:
[00:00] - Start
[00:15] - People pick tools based on a mythology and not necessarily facts
[02:35] - Python isn't just Java without the compiler
[03:34] - Design patterns are also a sign of weakness in a language
[04:06] - Lack of design patterns in Python (proof of lack)
[06:10] - Patterns are built into Python
[07:00] - Strategy pattern in Python the wrong and right way
[07:36] - The strategy pattern is invisible in languages with first-class functions
[08:07] - Some other language features in Python (first class functions, metaprogramming, iterators, closures)
[09:17] - The iterator pattern (iterators) is also built into Python
[09:36] - The observer pattern is also built into Python
[10:17] - Factory method pattern in Python (
[10:34] - Abstract Factory Pattern
[10:40] - Strategy pattern goes away becaise of first class functions
[11:08] - Drawing some useful conslusions
[12:20] - Drawing light on Python from the perspective of patterns
[12:31] - Thread Pool and Concurrency patterns (should we be talking about language features in Python for concurrency patterns???)
[13:49] - Channels (a model for concurrent processes)
[15:12] - PyCSP (implmentation of csp on top of Python)
[18:42] - Conclusions, summary, and questions
[19:17] - end (video goes on for a few more seconds waiting for questions)



Notes:
There are very few references to design patterns in Python mailing lists and discussions around Python... design patterns could be a sign of weakness in a language... patterns are built into Python (hence very little discussion)...strategy pattern is invisible in languages with first class functions...



Takeaway:
If you have to implement a design pattern, first look at language features and try to determine if any can be used instead of the pattern or at least assist in the implementation of the pattern while programming in that language.

Ask yourself if a language feature would make that pattern part of the language itself.

Concurrency patterns are a rich area to look at.



References:


Monday, August 17, 2009

iAccelerator

iAccelerator

I took a sabbatical from my consulting work this summer to participate in the iAccelerator program. This is a program for early stage software startups, similar to YCombinator, but the first of it's kind (I believe) in India.

I enjoy teaching programming, I have taught programming classes at a college, done corporate workshops, and more recently have been working on a website for participatory learning. This time I was looking for a different kind of mentoring experience, something which would be free form and fun. After a discussion with Freeman, I decided to go spend the summer at iAccelerator.

In the first few days of the program we had introductions by all the teams where they spoke about their product and vision. This was followed by a session on team building and thinking out of the box, a few legal sessions, sessions on accounting and company law, and several other mentoring sessions. All this is very useful for early stage software stratups, especially when they are founded by techies who are excelent hackers but need some help with legal and business stuff.

iAccelerator had ten very motivated and talented teams. I split my time helping them with technical stuff and working on my participatory learning project.

We worked out of a large hall, converted very tastefully into a working area. Each team had their own space towards the walls, and the centre was furnished with couches, projector, a large whiteboard (where we had presentations and brainstorming sessions) and a wii for fun and entertainment.

Even though everyone had their own work areas, many people chose to work on the couches. Working from the couches was a lot more fun and it gave opportunities for discussions, knowledge exchange, and friendly bantering. The couch culture (as I call this) in retrospect has been a very important part of the cameredierie and the excellent environment we had among us.

A good, positive, and helpful environment is one of the best things in such a program. Whenever anyone was stuck with a problem, or needed help with something new, they would always find someone who had that knowledge and was willing to share it. Everyone had their unique strengths, and collectively we all had a lot of talent which flowed freely. Entrepreneurship is also often a journey of highs and lows. There are times when you feel like your product will take over the world, and then there are times which can be described as not so pleasant. Being in a good environment with friends, means that you are not in this alone. If someone is down he can be sure that his buddies will pull him up.

One team found their first few customers within the group itself, and another team made a kick-ass software for internal communication which had passionate users from day one.

Ever so often we would have mentors, and successful entrepreneurs come talk to us about various things related to business and startups. Many guests spoke about their journey as entrepreneurs, their successes, failures, and lessons learned. Besides these sessions, we were also invited for many talks given by various mentors to the IIM students. This was a benefit of being on the IIM-A campus. Several mentors also worked one on one with the teams to help them with their vision and business plans.

Since we all had technical skills, internally we did several TechTalks on topics such as security, Amazon EC2 & cloud computing, designing with GIMP, JQuery, version control with SVN and Git, and many more. Sometimes we played tech videos from the Internet and had discussions around them. These sessions were a lot of fun and we all learned from them.

Since Freeman has successfully created and exited a startup in the past, he had many insights about how to run a startup. He shared his knowledge and insights with everyone, helping with business plans, vision, fund raising pitches, and many other nitty gritties of creating startups.

However, it was not just work all the time. We had a great time watching MTV while eating breakfast in the college mess. I can now tell you that watching MTV is far better than reading the morning newspaper. We played ping pong (Freeman and me had some really fun and intense ping pong sessions) ... we played cricket... on weekends we watched movies on the office projector. We also had a lot of diverse talent in the group. Jeevan Ram rocked everyone with his dancing and Ghazal made us laugh with his mimicry.

It's amazing how well we all got to know each other in just a few months. Thinking back, this was the best time I have had after graduating. Most importantly, I cannot stress enough the fact that I made really good friends, and I am very grateful for the wonderful time we all spent together.

This year's iA program will end in a few weeks. I wish all the teams lot of success and good luck.

Friday, August 07, 2009

Custom JSON Encoder in Django

I have been messing around with how to display date formats (in questions and answers) for my web based learning site from the past couple days. After trying various things, I settled for what seems to be a web 2.0 standard for displaying dates - displaying dates as '2 days 4 hours ago' instead of the actual date and time '4th August, 2009 5:50 PM'. I like this because I do not have to deal with any browser localization issues. Everything is a delta between the UTC time a question was asked and the current UTC time (btw if you are working with datetime in Python, do read this blog post).

In my Django based application, I use JQuery to get questions and answers for forums on every topic page. The application sends back JSON to the Javascript functions which display the questions and answers from the JSON objects.

The DjangoJSONEncoder (scroll to the end of this module) provided by Django serializes dates in a specific format. I wanted to change this so that a date would be serialized as '2 days ago'.

A bit of Googling bought me to Jessy's very nice blog post, which explained very nicely how to create a custom Encoder to be used for serializing objects in Python. This seemed like a good idea, so I wrote my custom encoder to change the way dates are displayed;


class Web20DatesEncoder(DjangoJSONEncoder):
SECONDS_IN_HR = 60 * 60
SECONDS_IN_MIN = 60
def default(self, object):
if isinstance(object, datetime.datetime):
delta = datetime.datetime.now() - object
return self.get_delta_as_string(delta)
else:
return super(Web20DatesEncoder, self).default(object)

def get_delta_as_string(self, delta):
days = delta.days
seconds = delta.seconds
hours = 0
minutes = 0
hours = seconds / self.SECONDS_IN_HR
seconds = seconds % self.SECONDS_IN_HR
minutes = seconds / self.SECONDS_IN_MIN
seconds = seconds % self.SECONDS_IN_MIN
delta_str = ''
if days > 0:
delta_str += str(days) + ' days, '
if hours > 0:
delta_str += str(hours) + ' hours, '
if days <= 0 and seconds > 0:
delta_str += str(seconds) + ' secs, '
return delta_str


However, I could not figure out how to hook this class into the call chain so that it is used when my QuerySet is serialized as such;


res = serializers.serialize(”json”, questions)


One solution which came up was to use the 'cls' parameter in the call to serialize.


res = serializers.serialize(”json”, questions, cls=Web20DatesEncoder)


However, when I ran my code, there was an error:

dump() got multiple values for keyword argument ‘cls’

Why do we get this error? Maybe (I still do understand Python well enough to be sure) because, the end_serialization method in django.core.Serializers.json.Serializer has the following line:

simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)

As you can see it specifically passes cls=DjangoJSONEncoder to simplejson.dump(...), and this is the reason why we get the above error message.

Now I do not know what is the right way to resolve this issue, but here's how I did it. I created a subclass of JSONSerializer, such that my subclass used my custom encoder.


from django.core.serializers.json import Serializer as JSONSerializer

class DateModifyingJSONSerializer(JSONSerializer):
def end_serialization(self):
self.options.pop('stream', None)
self.options.pop('fields', None)
simplejson.dump(self.objects, self.stream, cls=Web20DatesEncoder, **self.options)

and the client code which earlier instantiated JSONSerializer now uses DateModifyingJSONSerializer.


#Here is the code snippet which uses the above class
json_serializer = DateModifyingJSONSerializer()
res = json_serializer.serialize(query_set)

#instead of old code shown below
#serializers.get_serializer("json")()
#res = json_serializer.serialize(query_set)


I hope you find this solution useful. Please leave a comment if it helped you, or if you know a better way to perform this task.