Project Mouse http://projectmouse.org/ Hello and thank you for grabbing my really simple syndication (RSS) feed for Project Mouse. en-us Built with Django http://media.projectmouse.org/img/bloggies.100px.jpg Project Mouse http://projectmouse.org/ Really simple syndication (RSS) feed icon for Project Mouse. http://projectmouse.org/symboliclinker+-+a+symbolic+link+service+for+the+finder.html SymbolicLinker - A Symbolic Link Service for the Finder Thu, 03 Dec 2009 07:42:46 MST http://projectmouse.org/symboliclinker+-+a+symbolic+link+service+for+the+finder.html ~ link: http://seiryu.home.comcast.net/~seiryu/symboliclinker.html

SymbolicLinker is a tiny contextual menu plugin (for Puma through Leopard users) and software service (for Snow Leopard and later users) that, once installed, allows any user to create symbolic links to files inside the Finder.

SymbolicLinker does this by adding a contextual menu item to the Finder that generates symbolic links to the selected files. The goal of this product is to decrease users' trips to the Terminal in order to use the "ln -s" command. SymbolicLinker is available in English, Finnish, French, German, Italian, Japanese, Spanish, Swedish, and Turkish.

- via Nick Zitzmann description on his low bandwidth software site. ]]> http://projectmouse.org/the+complete+guide+to+google+wave.html The Complete Guide to Google Wave Fri, 06 Nov 2009 11:00:59 MST http://projectmouse.org/the+complete+guide+to+google+wave.html ~ link: http://completewaveguide.com/

Gina Trapani launched her self-published book called "The Complete Guide to Google Wave" on This Week in Google (TWiG #14). The book is mirrored on the official website at http://completewaveguide.com/ where the book can be read for free. Both the website and the book will be updated as changes are made to Google Wave and the system becomes more prevalent.

]]>
http://projectmouse.org/tracking+memory+consumption.html Tracking Memory Consumption Sat, 31 Oct 2009 21:06:07 MST http://projectmouse.org/tracking+memory+consumption.html I wanted a way to track the memory used by the Django applications on my WebFaction account so I could get a better sense of the memory consumption over time as well as the peaks and valleys for the applications. I have a shell script in place that sums up the current memory usage for the command prompt so I can log into the server and check the current usage but nothing was setup for logging that number or plotting it on a graph. This is the solution I came up with to measure, log and display the memory usage over a twenty four hour period.

1) Measuring:

WebFaction has a simple how-to for measuring the current memory usage for an account. Users have tweaked this command and I took their tweaks and added a final change so the script would output a single line of text that looks like this: [!] Current Memory Usage: 130.871 MB [ 134012 KB ]. I also added an alias to my ~/.bash_profile so at any point I can type memory at the command prompt and get the current memory usage.


#!/usr/bin/env sh
ps -u <username> -o pid,rss,command | awk '{sum+=$2} END {print "[!] Current Memory Usage:",(sum/1024),"MB [",sum,"KB ]"}'
$ memory
[!] Current Memory Usage: 130.871 MB [ 134012 KB ]

2) Logging:

I wrote a Python script that uses the shell script and records the value to a specific log file for later use if needed. The script also reads a second file which is used as the data source for the graph. The record function updates a "current usage" data set as well as averaging the memory total into another data set for a base line total. The Python script is run by a cron every fifteen minutes.


#!/usr/bin/env python

from subprocess import Popen, PIPE
import datetime, time, sys

def memory():
	memory = Popen('/path/to/.get_total_memory', shell=True, stdout=PIPE).communicate()[0]
	memory = float(memory.split('[!] Current Memory Usage:')[1].split('MB [')[0].strip())
	return memory


def record(total,timestamp):
	now = datetime.datetime.now()
	stats = open('/path/to/memory_stats.txt', 'r')
	try:
		graph = stats.readlines()
		stats = open('/path/to/memory_stats.txt', 'w')
		# Update averages
		average = graph[0].strip('\n').split(',')
		average[(now.hour - 1)] = int(round(total))
		line = ""
		for number in average:
			line += '%s,' % number
		graph[0] = line.rsplit(',',1)[0]
		# Update current usage
		current = graph[1].strip('\n').split(',')
		current[(now.hour - 1)] = (int(current[(now.hour - 1)]) + int(round(total))) / 2
		line = ""
		for number in current:
			line += '%s,' % number
		graph[1] = line.rsplit(',',1)[0]
		graph[2] = timestamp
		# Save new data
		for line in graph[:3]:
			stats.write('%s\n' % (line))
	finally:
		stats.close()


def log(message,timestamp):
	log = open('/path/to/memory.log', 'r')
	try:
		past_log = log.readlines()
		log = open('/path/to/memory.log', 'w')
		for line in past_log:
			log.write(line)
		log.write('[%s] %s\n' % (timestamp, message))
	finally:
	    log.close()


if __name__ == '__main__':
	total = memory()
	record(total,timestamp=time.ctime())
	log("Current memory total: %s MB" % total,timestamp=time.ctime())

3) Display:

I am using the Google Graphing API and a little JavaScript in a HTML file to read the memory_stats.txt text file produced by the Python script. The JavaScript does some minor parsing of the lines in the text file but is only responsible for piecing all the graph configuration URL parameters together with the data to produce a readable graph. The HTML file is served as a static file on the media server making it viewable in just about any browser that supports JavaScript and images including the iPhone.

Super Awesome Memory Statistics for Django using the Google Graphing API

Is this the best way to do this? This is probably not the most stable or easiest to implement but it does have the desired effect: A) this solution does measures, logs and displays the memory usage, B) the methods used to produce and display the data has a negligible processing/memory/storage cost and C) the graph is pretty and easy to access.

]]>
http://projectmouse.org/mozilla+jetpack+for+learning+design+challenge.html Mozilla Jetpack for Learning Design Challenge Fri, 30 Oct 2009 06:22:09 MST http://projectmouse.org/mozilla+jetpack+for+learning+design+challenge.html ~ link: http://design-challenge.mozillalabs.com/jetpack-for-learning/ Mozilla Jetpack for Learning Design Challenge

Mozilla is looking for designers, educators, and software developers who want to use Jetpack (or other Firefox add-on technologies) to unlock new opportunities for digital learning. You don't need to be a computer geek, but participants are expected to implement their ideas as Firefox add-ons, which will require writing some software code.

Jetpack is a newly formed experiment in using open Web technologies to enhance the browser, with the goal of allowing anyone who can build a Web site to participate in making the Web a better place to work, communicate and play.

]]>
http://projectmouse.org/couchdb+and+wsgi.html CouchDB and WSGI Thu, 29 Oct 2009 06:32:43 MST http://projectmouse.org/couchdb+and+wsgi.html ~ link: http://www.mikealrogers.com/archives/664 via Mikeal Rogers (http://www.mikealrogers.com/)

Django Application Example:


#!/usr/bin/python
import os, sys
import couchdb_wsgi
 
django_project = os.path.join(os.path.dirname(__file__), 'mysite')
sys.path.append(django_project)
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
 
import django.core.handlers.wsgi
 
application = django.core.handlers.wsgi.WSGIHandler()
 
couchdb_wsgi.CouchDBWSGIHandler(application).run()

All the code is up on github and [he's] written up some solid Sphinx docs that are up on gh-pages. [He's] also pushed an initial release to PyPI.

]]>
http://projectmouse.org/automatic+thumbnail+image+creation+for+django.html Automatic Thumbnail Image Creation for Django Fri, 16 Oct 2009 11:19:20 MST http://projectmouse.org/automatic+thumbnail+image+creation+for+django.html Django comes with a lot of batteries included in the core code including an admin interface that is incredibly easy to use as well as being easily extensible. One of the missing batteries is a method to automatically create thumbnail images for media being uploaded through the application. This is my current solution for the thumbnail creation which I use on a couple of sites. This allows me to upload an image with or without a thumbnail file and have the system create a thumbnail when needed.

This solution requires the Python Image Library (PIL) for the image processing. The PIL library may not be available automatically for you hosting package. You will then add the create_thumb definition either in the models.py file directly or through an import statement. The final requirement is to adjust your "media" model to override for the default save() method used by all models so the function will run when a new media file is saved.

create_thumb() definition

def create_thumb(media, width, height):
	from django.conf import settings
	import Image, os
	ALLOWED_EXTS = {'JPG':'JPEG','JPEG':'JPEG','PNG':'PNG','GIF':'GIF','TIF':'TIFF','TIFF':'TIFF'}
	EXT = str(media.name).rsplit('.',1)[1].upper()
	if EXT in ALLOWED_EXTS:
		CREATE_THUMBNAIL = True
		thumb = '%s' % ('T.'.join(str(media.name).rsplit('.',1)))
	else:
		CREATE_THUMBNAIL = False
		thumb = 'img/default.%s.png' % (EXT.lower())
	if CREATE_THUMBNAIL:
		path = settings.MEDIA_ROOT
		t = Image.open(media.path)
		w, h = t.size
		if float(w)/h < float(width)/height:
			t = t.resize((width, h*width/w), Image.ANTIALIAS)
		else:
			t = t.resize((w*height/h, height), Image.ANTIALIAS)
		w, h = t.size
		t = t.crop( ((w-width)/2, (h-height)/4, (w-width)/2+width, (h-height)/4+height))
		t.save(path + thumb, ALLOWED_EXTS[EXT])
		os.chmod(path + thumb, 0644)
	return thumb

create_thumb() used in a Model class definition

class Media(models.Model):
	...
	media = models.FileField(upload_to="%Y/%m")
	thumb = models.FileField(upload_to="%Y/%m", blank=True, null=True)
	...
	# ++++++++ ++++++++ ++++++++ ++++++++
	def save(self):
		if self.media and not self.thumb:
			super(Media, self).save()
			self.thumb = create_thumb(self.media, 125, 125)
			super(Media, self).save()
		else:
			super(Media, self).save()

Stepping through the code:

First the Media model uses two FileFields. One for the main media and one for the thumb. The thumb field is optional (blank=True, null=True) to allow the main media to be saved without an error. I choose the FileField instead of the ImageField because I also wanted to be able to upload more than images to the media server.

class Media(models.Model):
	...
	media = models.FileField(upload_to="%Y/%m")
	thumb = models.FileField(upload_to="%Y/%m", blank=True, null=True)
	...

The next part overrides or extends the save() method used by Django model classes. The create_thumb() is only called when a thumbnail image is not provided (and not self.thumb:). The first super().save() is needed because the create_thumb() function uses the file object created when the media file is saved. This also has the benefit of saving the main media file before attempting to create the thumbnail so if the thumbnail process encounters an error, the original media has already been saved to the server.

The create_thumb() then runs creating and saving a new file as well as returning a portion of file's media path which is saved by the second super().save() line. It is important to note that a full file object is not saved for the thumbnail. If one deletes the record for the Media object through the admin, Django will only delete the media file and not the thumb file because the full file path is not saved.

I am looking for a better method to all this madness but I have yet to tinker with this any further since it meets my needs.

class Media(models.Model):
	...
	def save(self):
		if self.media and not self.thumb:
			super(Media, self).save()
			self.thumb = create_thumb(self.media, 125, 125)
			super(Media, self).save()
		else:
			super(Media, self).save()

The dictionary at the beginning of the create_thumb() definition is used for translating the correct library function PIL uses for saving the thumbnail file as the same media type as the original. JPEG and TIFF files can have three and four letter file extensions but the Image library uses the four letter description to save the file in the correct format.

def create_thumb(media, width, height):
	ALLOWED_EXTS = {'JPG':'JPEG','JPEG':'JPEG','PNG':'PNG','GIF':'GIF','TIF':'TIFF','TIFF':'TIFF'}
	...
	t.save(path + thumb, ALLOWED_EXTS[EXT])

I defined the media field as a FileField so more than images could be added to the media library. The create_thumb() definition will default to a file path when the media file does not have a matching file extension. I have pre-saved thumbnail images for some of the common files extensions so the system can use default.tgz.png for tar guzip archives or default.pdf.png for PDF files.

else:
	CREATE_THUMBNAIL = False
	thumb = 'img/default.%s.png' % (EXT.lower())

The create_thumb() definition will use the file system path set in MEDIA_ROOT as the base path for the thumbnail image.


	path = settings.MEDIA_ROOT

The final step should not be needed as the creation mask for the web server should not be 777 but just incase this is true, after saving the thumbnail image create_thumb() will set the permissions to 644 (-rw-r--r--) for the file.


	os.chmod(path + thumb, 0644)

I only needed one thumbnail size 125x125px but you could loop through a couple of blocks of code to create a few sizes the way Flickr does for on their service. Any number of modifications can be made including changing the storage system, meta data changes, what ever your needs may be. The last thing you'll want to do is test-test-test. You can make your own test files or you can download the test files I used at: http://media.projectmouse.org/2009/10/djangoTestImgs.bz2

]]>
http://projectmouse.org/django+thumbnail+test+files.html Django Thumbnail Test Files [MEDIA FILE] Fri, 16 Oct 2009 11:12:21 MST http://projectmouse.org/django+thumbnail+test+files.html ~ link: http://projectmouse.org/r/1792/ ]]> http://projectmouse.org/nap+time.html Nap Time [MEDIA FILE] Thu, 15 Oct 2009 09:05:50 MST http://projectmouse.org/nap+time.html ]]> http://projectmouse.org/xerophyte+drawing+(2008).html Xerophyte Drawing (2008) [MEDIA FILE] Thu, 15 Oct 2009 09:05:50 MST http://projectmouse.org/xerophyte+drawing+(2008).html ]]> http://projectmouse.org/pretty+lady+(ss140b).html Pretty Lady (SS140B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/pretty+lady+(ss140b).html ]]> http://projectmouse.org/food+chain+(ss141b).html Food Chain (SS141B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/food+chain+(ss141b).html ]]> http://projectmouse.org/locked+in+(ss142a).html Locked In (SS142A) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/locked+in+(ss142a).html ]]> http://projectmouse.org/firewall+port+configuration+(ss142b).html Firewall Port Configuration (SS142B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/firewall+port+configuration+(ss142b).html ]]> http://projectmouse.org/_nix+box+plus+wefe+(ss142b).html _nix Box Plus WeFe (SS142B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/_nix+box+plus+wefe+(ss142b).html ]]> http://projectmouse.org/turtle+(ss142b).html Turtle (SS142B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:49 MST http://projectmouse.org/turtle+(ss142b).html ]]> http://projectmouse.org/chicago+(ss137b).html Chicago (SS137B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/chicago+(ss137b).html ]]> http://projectmouse.org/london+(ss137b).html London (SS137B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/london+(ss137b).html ]]> http://projectmouse.org/san+francisco+bay+(ss137b).html San Francisco Bay (SS137B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/san+francisco+bay+(ss137b).html ]]> http://projectmouse.org/atari+bunnies+(ss138b).html Atari Bunnies (SS138B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/atari+bunnies+(ss138b).html ]]> http://projectmouse.org/march+of+a+botnet+(ss138b).html March of a Botnet (SS138B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/march+of+a+botnet+(ss138b).html ]]> http://projectmouse.org/system+halt+(ss138b).html System Halt (SS138B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/system+halt+(ss138b).html ]]> http://projectmouse.org/timbuk2+girl+(ss138b).html Timbuk2 Girl (SS138B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/timbuk2+girl+(ss138b).html ]]> http://projectmouse.org/distracted+(ss139a).html Distracted (SS139A) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/distracted+(ss139a).html ]]> http://projectmouse.org/armored+bear+(ss139b).html Armored Bear (SS139B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:48 MST http://projectmouse.org/armored+bear+(ss139b).html ]]> http://projectmouse.org/starving+(ss135b).html Starving (SS135B) [MEDIA FILE] Thu, 15 Oct 2009 09:05:47 MST http://projectmouse.org/starving+(ss135b).html ]]>