Archive for the ‘Projects’ Category.

Alive and Well (Just Busy)!

It has been ages since I last posted, and for that I am sorry, but I have kept up with my twitter and identica accounts. Things have been moving really fast for me of late and as a result my blogging has slipped. So whats new in the world of earobinson?

  1. I am now working for CAE, more precisely CAE PS out of Toronto, and I am loving every moment of it. They have a very open culture and encourage the use of open source tools when appropriate. I have been able to use Ubuntu to host some of the websites I have developed in Django. This has kept me very happy. I can honestly say that I think that my Ubuntu, and Open Source knowledge set me apart.
  2. I have been getting more and more into photography with my new Canon EOS Rebel T1i, you can follow me on flickr.
  3. I have been ramping up my fitness (and Brazilian Jiu-Jitsu skills) at Toronto BJJ.

This brings me to my goals for the future, I am falling in love with Django and as a result I want to play with it more and more, now my current hosting provider 1and1 has served me very well up to now. But now that I want to start playing with Django more I need to get a hosting provider that can support Django (because I want to show off my work of course). I would hope that any new hosting provider I use could support both Django, and ruby on rails (as I may want to play with it in the future). So dear lazy web what do you recommend? And I know I could use Google app engein but I like the idea of pure Django, not some hack, I have also looked at djangohosting.org but would love some recommendations from actual users of hosting plans.

Any advise lazyweb?

DeadlineExceededError on Google App Engine

A while back I wrote a post about using Google docs as an expense tracker. The post received a lot of great feedback and so when I wanted to learn about Google App Engine I decided the best way was to create a Google app that connects to my Google docs to let the user easily add expenses. This would solve the problem I had with the original Google expense tracker that anyone could add an expense to my spreadsheet. The result of this is eyecost released under the gpl (I had wanted to use the agpl but I don’t think that that is an option since it connects to Google servers) you can download eyecost here. The problem I am having is that if I do a lot of spreadsheet editing the Google App Engine times out.

Anyone know how I can get around this?

Mapping Wikipedia

I was reading reddit the other day and stumbled upon the fact that wikipedia has an API. Neat I thought, and having some free time since my exams are now over I figured I would play around a bit with it. When I browse wikipedia I often click from link to link, and have come to the conclusion that all articles are 6 degrees of separation. For example I can go from Ubuntu to Tesco to Japan to G8 to United States to George W. Bush bet you never knew Ubuntu was connected to George W. Bush. I once wrote a map of the internet program that people seemed to like to download and modify so in that spirit I wrote wikimap.py to map wikipedia. wikimap.py Requires pygraphviz (Install using sudo aptitude install python-pygraphviz). To use the program simply run the program and give it the wiki page name for example “python wikimap.py Norman_Graham” Note that Ubuntu is Ubuntu_(Linux_distribution) and you can find the full name in the address bar of your browser. For more complicated maps use wikimap.py –help for full usage info.

Here are a few examples that I created with wikimap.py


And a really large one being viewed in inkscape.

More examples including the dot files can be found at http://www.files.earobinson.org/wiki/. But there are a few features I would like to add:

  1. Generating the graph using python-pygraphviz currently takes a really long time and I would like to be able to do it faster
  2. Page links currently include templates, I would like to only use links in the body of the text
  3. It would be nice if the software cached previously seen connections. (But then I need to detect updates to that page)

If anyone has a nice simple soultion to any of those problems leave a comment. Also if you are able to generate any neat images I would love to see them.

OLPC Spy Cam

So now that I have my XO OLPC computer I wanted to find something to do with it. As I said before its the web cam that really impressed me and so I decided to start playing with that. After jumping onto the #OLPC freenode irc room and asking them a few questions I was quickly able to write this python program.

Set it up as a cron job and upload pictures from outside my apartment window every hour. I’m not sure how long ill be keeping it running and if I play with the laptop and dont turn off the script I guess it will upload pictures of me.

Well for anyone interested the important code to take a picture is: [sourcecode language="python"]os.system(‘gst-launch-0.10 v4l2src ! ffmpegcolorspace ! pngenc ! filesink location=’ + filename)[/sourcecode] and I would love to hear what you have been doing with your XO.

Map of The Internet

The other day I stumbled upon Chris Harrison’s internet map, the only problem I found with his map is that I wanted to know exactly which country each network connection was in. So using the DIMES public data repository, and 1site1moment’s country boarders I have mapped the internet for myself.

From Public

Feel free to download the source code and come up with your own internet map, I would love to see what other people can come up with.

UPDATE 01: Image is back up, If the source code link wont work for you email me and I will send you a copy. Feel free to host this anywhere you like just post a link back to this site.

UPDATE 02: Source code can now also be found here.

UPDATE 03: Would love to see what other people can do with this.

Propensity v0.1.2.1906 — Now With an Icon! (shameless repost)

Due to an issue with wordpress I have been forced to repost this.

It has been about a week since I released Propensity into the wild for your feedback, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 well version 0.1.1.xxxx was released as a limited demo but I have pushed forward to release version 0.1.2.190.

New to this version we have:

  • The ability to add your own programs to propensity (you can import them or manually add them)
  • A Propensity Icon
  • Cleaned up and much prettier terminal
  • And many other little features.

As always feedback is wanted and bugs can be emailed to earobinson+propensity@gmail.com.

Download Propensity Here
Download Propensity Source Here

Ubuntu forums propensity post can be found here

Screenshots below

From Propensity
From Propensity
From Propensity

Propensity v0.1.2.1906 — Now With an Icon!

It has been about a week since I released Propensity into the wild for your feedback, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 well version 0.1.1.xxxx was released as a limited demo but I have pushed forward to release version 0.1.2.190.

New to this version we have:

  • The ability to add your own programs to propensity (you can import them or manually add them)
  • A Propensity Icon
  • Cleaned up and much prettier terminal
  • And many other little features.

As always feedback is wanted and bugs can be emailed to earobinson+propensity@gmail.com.

Download Propensity Here
Download Propensity Source Here

Ubuntu forums propensity post can be found here

Screenshots below

From Propensity
From Propensity
From Propensity

Python vte.Terminal example

About a week ago while working on propensity, I was trying to add an impeded terminal into the program instead of just sending commands to an xterm. I quickly found out about the VTE Terminal Widget, this is the same widget used by the gnome-terminal. Now while I was able to find a great API, I was working in python not C and while I love API’s when I’m using a new feature I also find examples to be one of the best ways for me to learn, but even with all my google searching I found it really hard to find a simple python example of the VTE Terminal Widget. The good news is I now have a simple working example, its a basic gui that lets you enter a command and then that command will be run in a separate terminal window (I’m not exactly sure why I used two windows now that I think of it.)


An so without further ado here is the code (all GPL). Hope this helps someone in the future. You can download the code here, or view it below.

VirtualTerminal.py (This code could be used in your program)
[sourcecode language="python"]#!/usr/bin/env python
#
# VirtualTerminal.py
#
# Copyright 2007 Edward Andrew Robinson <earobinson@gmail>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#

# Imports
import os
import vte
import gtk
import time

class VirtualTerminal(vte.Terminal):
def __init__(self, log_file = None, history_length = 5, prompt_watch = {}, prompt_auto_reply = True, icon = None):
# Set up terminal
vte.Terminal.__init__(self)

self.history = []
self.history_length = history_length
self.icon = icon
self.last_row_logged = 0
self.log_file = log_file
self.prompt_auto_reply = prompt_auto_reply
self.prompt_watch = prompt_watch

self.connect(‘eof’, self.run_command_done_callback)
self.connect(‘child-exited’, self.run_command_done_callback)
self.connect(‘cursor-moved’, self.contents_changed_callback)

if False:
self.connect(‘char-size-changed’, self.activate_action, ‘char-size-changed’)
#self.connect(‘child-exited’, self.activate_action, ‘child-exited’)
self.connect(‘commit’, self.activate_action, ‘commit’)
self.connect(‘contents-changed’, self.activate_action, ‘contents-changed’)
#self.connect(‘cursor-moved’, self.activate_action, ‘cursor-moved’)
self.connect(‘decrease-font-size’, self.activate_action, ‘decrease-font-size’)
self.connect(‘deiconify-window’, self.activate_action, ‘deiconify-window’)
self.connect(‘emulation-changed’, self.activate_action, ‘emulation-changed’)
self.connect(‘encoding-changed’, self.activate_action, ‘encoding-changed’)
#self.connect(‘eof’, self.activate_action, ‘eof’)
self.connect(‘icon-title-changed’, self.activate_action, ‘icon-title-changed’)
self.connect(‘iconify-window’, self.activate_action, ‘iconify-window’)
self.connect(‘increase-font-size’, self.activate_action, ‘increase-font-size’)
self.connect(‘lower-window’, self.activate_action, ‘lower-window’)
self.connect(‘maximize-window’, self.activate_action, ‘maximize-window’)
self.connect(‘move-window’, self.activate_action, ‘move-window’)
self.connect(‘raise-window’, self.activate_action, ‘raise-window’)
self.connect(‘refresh-window’, self.activate_action, ‘refresh-window’)
self.connect(‘resize-window’, self.activate_action, ‘resize-window’)
self.connect(‘restore-window’, self.activate_action, ‘restore-window’)
self.connect(’selection-changed’, self.activate_action, ’selection-changed’)
self.connect(’status-line-changed’, self.activate_action, ’status-line-changed’)
self.connect(‘text-deleted’, self.activate_action, ‘text-deleted’)
self.connect(‘text-inserted’, self.activate_action, ‘text-inserted’)
self.connect(‘text-modified’, self.activate_action, ‘text-modified’)
self.connect(‘text-scrolled’, self.activate_action, ‘text-scrolled’)
self.connect(‘window-title-changed’, self.activate_action, ‘window-title-changed’)

def activate_action(self, action, string):
print ‘Action ‘ + action.get_name() + ‘ activated ‘ + str(string)

def capture_text(self,text,text2,text3,text4):
return True

def contents_changed_callback(self, terminal):
”’Gets the last line printed to the terminal, it will log
this line using self.log() (if the logger is on, and it will
also prompt this line using self.prompt() if the line needs
prompting”’
column,row = self.get_cursor_position()
if self.last_row_logged != row:
off = row-self.last_row_logged
text = self.get_text_range(row-off,0,row-1,-1,self.capture_text)
self.last_row_logged=row
text = text.strip()

# Log
self.log(text)

# Prompter
self.prompter()

def get_last_line(self):
terminal_text = self.get_text(self.capture_text)
terminal_text = terminal_text.split(‘\\\\n’)
ii = len(terminal_text) – 1
while terminal_text[ii] == ”:
ii = ii – 1
terminal_text = terminal_text[ii]

return terminal_text

def log(self, text):
”’if self.log_file is not None the the line will be logged to
self.log_file. This function also stors the info in self.histoy
if self.history_lenght > 0”’
if self.log_file != None:
date_string = time.strftime(‘[%d %b %Y %H:%M:%S] ‘, time.localtime())
file = open(self.log_file, ‘a’)
file.write(date_string + text + ‘\\\\n’)
file.close

# Append to internal history
if self.history_length != 0:
if len(self.history) >= self.history_length:
self.history.pop(0)
self.history.append(text)

def prompter(self):
last_line = self.get_last_line()
if last_line in self.prompt_watch:
if self.prompt_auto_reply == False:
message = ”
for ii in self.prompt_watch[last_line]:
message = message + self.history[self.history_length - 1 - ii]
if self.yes_no_question(message):
self.feed_child(‘Yes\\\\n’)
# TODO not sure why this is needed twice
self.feed_child(‘Yes\\\\n’)
else:
self.feed_child(‘No\\\\n’)
else:
self.feed_child(‘Yes\\\\n’)

def run_command(self, command_string):
”’run_command runs the command_string in the terminal. This
function will only return when self.thred_running is set to
True, this is done by run_command_done_callback”’
self.thread_running = True
spaces = ”
for ii in range(80 – len(command_string) – 2):
spaces = spaces + ‘ ‘
self.feed(‘$ ‘ + str(command_string) + spaces)
self.log(‘$ ‘ + str(command_string) + spaces)

command = command_string.split(‘ ‘)
pid = self.fork_command(command=command[0], argv=command, directory=os.getcwd())

while self.thread_running:
#time.sleep(.01)
gtk.main_iteration()

def run_command_done_callback(self, terminal):
”’When called this function sets the thread as done allowing
the run_command function to exit”’
#print ‘child done’
self.thread_running = False

def yes_no_question(self, message):
message = message.replace(‘\\\\n\\\\n’, ‘[NEWLINE][NEWLINE]‘).replace(‘\\\\n’, ”).replace(‘[NEWLINE]‘, ‘\\\\n’)

if message.find(‘?’) == -1:
message = message + ‘\\\\n\\\\nDo you want to continue?’

type=gtk.MESSAGE_QUESTION
if message.lower().find(‘warning’) != -1:
type=gtk.MESSAGE_WARNING

dialog = gtk.MessageDialog(parent=None, flags=0, type=type, buttons=gtk.BUTTONS_YES_NO, message_format=message)
dialog.set_icon(self.icon)
dialog.show_all()
responce = dialog.run()
dialog.destroy()

# Responce == yes
return responce == -8
[/sourcecode]

TestVirtualTerminal.py Used to actually make the GUIs, this is the program you should run.
[sourcecode language="python"]#!/usr/bin/env python
#
# TestVirtualTerminal.py
#
# Copyright 2007 Edward Andrew Robinson <earobinson@gmail>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#

import gtk

from VirtualTerminal import VirtualTerminal

class mainWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect(‘destroy’, lambda w: gtk.main_quit())
self.set_default_size(400, 400)

self.button = gtk.Button(‘press me’)
self.button.connect(“clicked”, self.pressed_callback)

self.command_entry = gtk.Entry()
self.command_entry.set_text(‘python count.py’)
#self.command_entry.set_text(’sudo aptitude install gaim-encryption’)

vbox = gtk.VBox()

self.r = 0

self.add(vbox)

vbox.pack_start(self.command_entry, False)
vbox.pack_start(self.button, True)

self.myTerminal = terminal()

self.show_all()

gtk.main()

def pressed_callback(self, button):
print ‘presed’
column,row = self.myTerminal.terminal.get_cursor_position()
if self.r != row:
off = row-self.r
text = self.myTerminal.terminal.get_text_range(row-off,0,row-1,-1,self.capture_text)
self.r=row
text = text.strip()
print text
self.button.set_sensitive(False)
self.myTerminal.terminal.run_command(self.command_entry.get_text())
self.button.set_sensitive(True)
print ‘done’

def capture_text(self,text,text2,text3,text4):
return True

class terminal(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
#self.set_title(self.settings.application_name)
self.connect(‘destroy’, lambda w: gtk.main_quit())

self.terminal = VirtualTerminal()

#self.child_pid = self.terminal.fork_command()

self.add(self.terminal)
self.show_all()

mainWindow()[/sourcecode]

count.py A little test program but you can run any command you want
[sourcecode language="python"]#!/usr/bin/python

import time

print ‘0′

for ii in range (10):
time.sleep(1)
print ii + 1[/sourcecode]

A special thanks to Alberto Milone for all the help he provided me with for this.

Propensity – feedback wanted

I have been using ubuntu for quite some time, and I have ubuntu installed on 20+ computers at one time. I find myself always installing ubuntu on a different computer. One of the things that I always do is install some programs that don’t come stock with ubuntu like geany, or miro. At first I had a simple shell script that I ran that aptituded (lol) all the programs I wanted to install. But soon that was not enough because different computers had different uses and installing miro or gaim guifications on a work computer, or a computer that will be going back to a client is out of the question. Another thing I wanted was to updated the source.list file with new repositories cleanly. And so eventually that shell script involved into a python program.

I have spent a bit of my summer cleaning up that python program and the result is propensity (I looked for synonyms for aptitude) and now I figure its almost ready to be released into the public. I have uploaded both a deb file and the source to my website, and would love some feedback.

Some features that I would like to add before I release it are:

  • I would like propensity to generate a standalone shell script that could be used to standalone install the package
  • Icon
  • Splash screen
  • Ability to add your own programs and save them (so you can load them from a file at a later date) Thanks Ed
  • Documentation

To sum up you can get the deb file here, and the source here. Thanks for any feedback you have.

Update 01: I made a post to the ubuntu forums and posted a screenshot
Update 02: I have been dugg.
Update 03: Propensity has only been tested on feisty.