Using Arguments in a Shell Script

Within 5 seconds of looking at a shell script I’m usually opening a new file in my text editor to re-write the ugliness into something that makes more visual sense.  To me at least python is highly preferable.

Still I use shell scripts all the time to batch a group of commonly used sequential executions, or to abbreviate a commonly used but lengthy commands.

Today I looked into going one step further into the complexities of shell scripts, probably my last step for a while, and discovered how to handle arguments.

The inspiring work case was in using Django manager to run tests for the different apps

./manage.py test --settings test_settings <optional app names>

The following script will check if an argument exists and if it does it will use the argument in the tests command.

if [ -n "$1" ]
# Test whether command-line argument is present (non-empty).
then
 ./manage.py test --settings test_settings $1
else
 ./manage.py test --settings test_settings
fi

Notice that $1 refers to the first argument ($0 refers to the name of the executable and $5 refers to the 5th argument).

Save the file as ‘test’ and then modify it as an executable

chmod +x test

And now I can run the tests on their own

./test

or with an argument app

./test auth_user
Expanding

Note that the above example has a limitation of only dealing with the first argument and seems a bit redundant.  The entire script can indeed be shortened to

./manage.py test --settings test_settings $@

As $@ represents all arguments after $0.

‘drop’ Database Command for Django Manager

The Django manager is a really handy tool.  I wrote earlier about making your own custom managers and there is a lot of other great documentation on it.

Django comes with a bunch of helpful management commands like ‘flush’, ‘syncdb’, ‘test’, etc.

I’ve created a generic ‘drop’ command as I felt it was missing.  I often found myself going into mysql to drop and re-create a database.  This is needed whenever you significantly change your models and need to start over.  The ‘drop’ command does that automatically using the database information in your settings file.

The following code is from ‘drop.py’

from django.conf import settingsfrom django.conf import settings

from django.core.management.base import NoArgsCommand

class Command(NoArgsCommand):
 help = "Drop and re-create the database"
 def handle_noargs(self, **options):

 import MySQLdb

 print "Connecting..."
 db=MySQLdb.connect(host=settings.DATABASE_HOST or "localhost" ,user=settings.DATABASE_USER,
 passwd=settings.DATABASE_PASSWORD, port=int(settings.DATABASE_PORT or 3306))

 cursor = db.cursor()
 print "Dropping database %s" % settings.DATABASE_NAME
 cursor.execute("drop database %s; create database %s;" % (settings.DATABASE_NAME, settings.DATABASE_NAME))
 print "Dropped"

To install simply place this code in a file called ‘drop.py’ and add it to a management comands folder.  If you don’t have a management command folder yet you simply need to create the following file structure in one of your app directories (MY-APP-DIR).

MY-APP-DIR/
  management/
    __init__.py
    commands/
      __init__.py
      drop.py

Now, whenever you’ need to whipe your database and start fresh you can simply run:

./manage.py drop

Testing AJAX Requests in Django

Django has a really handy function on the request object that will determine if the request was an AJAX request (an XMLHttpRequest).

request.is_ajax()

It simply checks whether the HTTP_X_REQUESTED_WITH header is equal to ‘XMLHttpRequest’, a standard that’s supported by most javascript libraries. You can read more about it and see the list of supporting frameworks here.

It’d be great if the Django client had a simple client.ajax request in addition to its client.post and client.get requests, but alas it doesn’t.  The tests can still be done however by changing the HTTP_X_REQUESTED_WITH header when sending  your test requests.

>>> from django.test.client import Client
>>> client = Client()

>>> client.post(“http://example.com”, {“foo”: “bar”}, **{‘HTTP_X_REQUESTED_WITH’: ‘XMLHttpRequest’})

From there its fairly straight forward to create your own .ajax wrapper if you’d like.

Now you have no excuse for not having complete tests for all of your XMLHttpRequests :) .

Some Notes and Requests on Django Signals

I’ve finally gotten around to playing with the Django Signals.  I’ve been pleased so far but I feel its currently missing a few key features.

Some background: Django Signals allows developers to more easily break up their code into separate components which allows much greater freedom and organization.  Often as a web application expands you add more an more functionality to each of the events.  When a new user is created for example the program might need to spin off a few emails, maybe search for whether any of their friends are the site, store an extra statistic, etc…

When adding or removing these features developers would previously have to paste more code into their create_new_user function.  Now however developers can creaet a Django Signal in creaet_new_user function and then build other functions (sending email, storing stats, etc) as seperate listeners for that signal.

It makes everything more modular.  Lots of other languages have this.  If you’re a hardware developer its similar to interupts, if you’re a javascript developer its similar to events.

So reading about them I’ve been excited about the possibilities and have been looking forward to putting them to use.  I’ve got to say its incredibly simple, works great and I’m going to start using them all the time.

That said there is a lot of growth yet to be done in this area.  With that in mind I’m going to make two requests fully aware of the fact that most people will say “add it yourself” or “just use the patch” or “roll your own”.  Some of which I will ofcourse do, still I continue to blog…

Request: ManyToMany Signals

A great feature is that django automatically has signals set up for many of the common tasks.  There are signals fired when objects are saved and deleted and when requests are made and finished.  Currently there is no signals for ManyToMany relationships.  There is a ticket and a patch on the issue but it has not been released in the trunk of yet.

A simple example with Socialbrowse is in following other people in the network.  In Django following someone is easy:

userprofile.following.add( other_userprofile )

Man it’d be great if there was a signal on that!  Unfortunately I had to make a wrapper funtion in UserProfile.

import django.dispatch
followed_signal = django.dispatch.Signal(providing_args=["followed", ])
def follow(self, dude_to_follow):
  """ follow the input <dude_to_follow> """
  self.following.add( dude_to_follow )

  # Send out a django signal
  followed_signal.send(sender = self, followed = dude_to_follow)

I know, its not a big deal, I’m a big baby, but that stuff does add up eventually.  Hopefully Ticket #5390 will be merged shortly.  The comments seem to suggest that its ready.

Request: Asynchronous Signals

It seems that I’m not the only one to assume that Django Signals created Asynchronous tasks.  If you come from a Javascript or Hardware world you would assume asycronous signals, as both JS events and hardware interrupts are asyncronous.

Unfortunately Django Signals are not.  That’s great in many cases, but I think it should support both. Sending emails for example tends to take a sigificant amount of time, mostly spent waiting around.  It would be great if the request could continue on and return, independant of the email task, instead of having to wait for it to complete.

The result would be a much faster experience for the user, and I think Django Signals is the place to put that type of functionality in.   The ideal interface would be specifying an extra input ‘async’ when registering a listener.  If true the process calling the signal would not wait for the listener to finish.

Continuing with the follow example above the code would look something like this:

def email_follow_notification(sender, **kwargs):
...    # do some emailing here
followed_signal.connect(email_follow_notification, async = True)

The email_follow_notification function would then be run in a seperate process, allowing everything else to continue on without waiting.

Those are my notes for now.  I’m sure I’ll have more and maybe some contributions in the form of real code.

Simple MySQLdb Example

MySQLdb is a python interface to MySQL.  I wrote the following simple script for some database tests and thought it might be handy to others looking for tutorials or examples.

It simply connects to MySQL, drops and creates a database called ‘testdb’, makes a table called ‘waves’ with columns ‘sin’, ‘cos’, ‘tan’, and ‘date’ and fills the table with a thousand data points of the trig functions performed on the date in 5 minute intervals leading up to the current date.

The code and comments I think are fairly straight forward, so I will just paste and link to the text version.

DATABASE_HOST = "localhost"
DATABASE_USER = "root"
DATABASE_NAME = "testdb"
DATABASE_PASSWD = "YOUR PASSWORD HERE"
DATABASE_PORT = 3306

import MySQLdb

# Connect to the Database
db=MySQLdb.connect(host=DATABASE_HOST,user=DATABASE_USER,
 passwd=DATABASE_PASSWD, port=int(DATABASE_PORT))

# Make the database cursor
cursor = db.cursor()

# Drop and create the database
cursor.execute("drop database %s; create database %s;" % (DATABASE_NAME, DATABASE_NAME))

# Re connect to database using db=DATABASE_NAME
db=MySQLdb.connect(host=DATABASE_HOST,user=DATABASE_USER,
 passwd=DATABASE_PASSWD, db=DATABASE_NAME, port=int(DATABASE_PORT))
cursor = db.cursor()

# Create the table for the wave data
from math import sin, cos, tan
cursor.execute("""CREATE TABLE waves (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
sin FLOAT,
cos FLOAT,
tan FLOAT,
date INT);
""")

# Insert the sine wave data
from datetime import datetime

def STAMP( dt ):
 """ turns a python datetime object into a unix time stamp (seconds) """
 import time
 return int(time.mktime( dt.timetuple() ))

now = STAMP( datetime.now() )
five_mins = 60*5

sql = "INSERT INTO waves (sin, cos, tan, date) VALUES (%s, %s, %s, %s);"

# Insert the data into the table
for i in range(1000):
 s = now - i*five_mins
 cursor.execute(sql % ( sin(s), cos(s), tan(s), s ))

I really need to get some syntax highlighting…  More documentation on MySQLdb can be found here.  If you have any questions leave them in the comments.

Road Bikes are Waaaay Better than Target Bikes

Recently I bought a junky Road bike to hold me over for a while in Minnesota while I build my return to my beautiful road bike in California. I’m leaving it there for now for several reasons. It costs a lot to ship, I’m never sure how much longer I’ll be in Minnesota, and I think its happier being periodically peddled around the Stanford Campus in beautiful Palo Alto than sitting in a garage most of the time here, even if its being peddled by legs that are not my own.

But anyway, this new bike reminds me of why until last year I never really enjoyed biking.  I used to think it was because I didn’t have good places to bike to, and that with the exception of a few extremists bicycling is a highly seasonal activity in Minnesota.

old-rusty-bike1But I was wrong.  Sure those things contribute but the main factor was the bike.  I always had cheap generic bikes from Target, Walmart, or some such place.  These bikes change gears horribly, are overweight, slow, and just ruin the overall biking experience.

A road bike is lightweight, designed for going fast, and gears change with ease.  All of the gears are helpful, not just the highest and lowest.  There’s no struggling painfully up heavy inclines or excessive pedaling due to gears not shifting. 

On a road bike I’ve never hopped off to walked up a hill because it was just a lot easier.  On my new crappy mountain bike I feel like doing that all the time.

For these reasons I feel angry at Target and other similar stores.  Why do they make and sell such poorly designed bikes?  Why do you only sell mountain bikes and a few ‘hybrids’?  Shouldn’t the large tires cost more?  How many people actually bike dirttrains anymore?  Is it that tough to get the whole shifting gears thing down?  Can I have those years of not enjoying biking back?

At the same time I feel upset with the bike shops.  Why do road bikes have to be so expensive?  Why are they exclusive to your niche stores?  Can’t you keep it under $300?

I will probably never get an answer to those questions…

I never would have bought a road bike had it not been my only means of transportation for a year and had I not run into such an amazing deal on a used one.  It angers me that I so closely missed out because bicycling is now one of my favorite hobbies and my preferred method of transportation assuming painful weather conditions and a reasonable distance.

I wish there were reasonably priced ($200) road bikes for casual biking.  Around here I see garages full of bikes all the time and they’re always big framed mountain bikes with fat tires.  I don’t get it.  I think there’s a missing market there.

Socialbrowse On The News

It happened a few weeks ago and we mentioned it on the Socialbrowse Blog but I feel like mentioning it here as well. Socialbrowse was covered on the News!  Zack and I were interviewed by Ali Lucia and were really pleased with the coverage.  Unfortunately I can’t embed the video in this wordpress blog so you’ll have to follow the link:

Watch The Socialbrowse News Coverage

So what did I learn from being on the news?  A few things:

  1. It doesn’t bring much traffic to a web site
  2. It brings substantial clout among friends/family who wonder what I’m doing with my life
  3. You get some temporary local fame/recognition
  4. Its best to be prepared (our site was going down during our interview :)
  5. 95% of what you say in an interview isn’t used
  6. So speaking in small poignant sentences helps

Uninstalling the easy_install(ed)

Today I was switching from the Python Cheese Shop’s version of the Twisted Web Framework to the trunk version.  I’d previously installed Twisted with the handy

easy_install PackageName

Worked great!  Unfortunately its not so obvious on how to uninstall…  After some research I found it and am sharing it here so I wont’ forget.

Simply use easy_install with the -m option

easy_install -m PackageName

Which will remove the installed dependencies.  Then you can delete the PackageName.egg file that easy_install left behind.  You may have to do some “locate”ing to find where it put the package as its different on every system.

Another hint is that easy_install creates a file easy-install.pth in your site-packages directory.  That file lists the path to the various eggs you’ve installed with easy_install.  In some cases you may simply be able to delete the path of your package in that file.

Wanted: Generous Blog Designer

I’m currently doing a lot of research and experimenting in Marketing as its my weakest skill as a startup founder.  I want to make it one of my strengths, or at least become moderately good at it.  One of the marketing tools I’m going to be experimenting with is this blog.  To do that I really think it needs some sort of re-design, or rather a first-design as almost no design went into it in the first place.

Lately I get between 30 and 80 views per day, numbers I hope to increase significantly.  I have various distribution methods in mind and am confident I can accomplish the task.

So here’s the deal

I’m a bootstrapping startup founder, so I have no money to spend on this.  I’m hoping there’s someone generous enough to design it for the experience and the portfolio builder.  Everyone starts somewhere.  Hairstylists give out a lot of free haircuts before they get paid.  Writers write a lot of free stories, and even engineers write a lot of software before someone ever pays us.

Though I can’t offer money,

Here is what I can offer

  1. Name and link of designer’s site at the bottom of each page.
  2. A blog article thanking, complimenting, and recommending the designer
  3. Possible paid work on sites in the future

I make a lot of websites and have alot of projects.  I won’t always be poor.  I also know a lot of people who make a lot of web sites and are looking for good designers.  If I like your work, I’m not shy to recomend people.

Here’s what I want

This blog is about the Things I Learn, and most of that tends to be about technical stuff (but not all).  It should be modern, stylish, and clean.

Here are some blogs, who’s designs I really like.

I’d like a large RSS icon on a sidebar as well as some space to put the Socialbrowse Blog Widget and other widgets that my hacker friends have made.  I’d like a great font so that the post is fun to read on its own, without always needing a picture to support it.

I’d also like to keep the blog hosted on wordpress, which means the design is constrained to using one of the currently available themes (formats) and updating the css.  Here is more information about the Custom CSS feature and a FAQ.

If you’re interested or want more information contact me at dave [at] socialbrowse.com

Paper or Plastic?

I’m probably the last person to look this up but I’ve often wondered what the best answer to “Paper or Plastic?” really is.  The best answer ofcourse is neither.  I should bring my own bags, but I rarely preform ideally so that aside what’s the best?

It seems like paper would be more environmentally friendly because its renewable and degrades much faster.  Also its brown and reminds you of nature, so that has to be better environmentally right? Plastic bags use up a lot of oil, which we know is not nonrenewable.  But then how much oil is used to make paper bags?  Cutting down all those trees, shipping them, printing, gluing, etc.  The more extensive manufacturing process must take a considerable amount of oil right?

This article gives some quick facts on the costs of each:

To make all the bags we use each year, it takes 14 million trees for paper and 12 million barrels of oil for plastic. The production of paper bags creates 70 percent more air pollution than plastic, but plastic bags create four times the solid waste — enough to fill the Empire State Building two and a half times. And they can last up to a thousand years.

Another great article suggests further proves that there is no consensus on the issue:

Both paper and plastic bags consume large amounts of natural resources and the majority will eventually end up in the landfill. Both bags can be recycled to some extent and can be utilized around the house. I’ve read several studies comparing the two choices and none of them agree.

Drats!  I hate issues with no clear answer.  The first article suggests that there are bio-degradable plastic bags that take only a few weeks to break down.  That would be the ideal solution, but they’re rarely a choice.

For now I think I’m going to go with plastic on this one but with the intent to save the bags and recycle them.  The plastic uses less resources and polutes less.  Recycling them should reduce their significant impact which is in all the garbage they produce.  I’m also going to continue to not take a bag when one is not required.  Too often I see people check out with one or two small items and walk off with them in a bag.  If you don’t need the bag, don’t use it.

Update: My friend Natalie recently shared this clever video promoting careful use of your plastic bags.

Follow

Get every new post delivered to your Inbox.