<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5236867476487043111</id><updated>2026-02-27T19:07:34.467-05:00</updated><category term="python"/><category term="testing"/><category term="Canonical"/><category term="ubuntu"/><category term="selenium"/><category term="Linux"/><category term="audio"/><category term="unittest"/><category term="G6"/><category term="Gource"/><category term="LG"/><category term="NAS"/><category term="QC 3.0"/><category term="UDS"/><category term="backup"/><category term="bandwidth"/><category term="boot"/><category term="chrome"/><category term="conky"/><category term="java"/><category term="latency"/><category term="mobile"/><category term="monitoring"/><category term="music"/><category term="network"/><category term="perl"/><category term="phantomjs"/><category term="rsync"/><category term="splash"/><category term="squeezebox"/><category term="tools"/><category term="visualization"/><category term="web"/><category term="webdriver"/><title type='text'>Corey Goldberg</title><subtitle type='html'>Blog - Technology, Programming</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/-/python'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/search/label/python'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/-/python/-/python?start-index=26&amp;max-results=25'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>119</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-6485344598637497715</id><published>2018-09-07T12:07:00.001-04:00</published><updated>2018-09-07T12:07:16.986-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chrome"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="selenium"/><category scheme="http://www.blogger.com/atom/ns#" term="webdriver"/><title type='text'>Python - Using Chrome Extensions With Selenium WebDriver</title><content type='html'>&lt;div&gt;
When you launch a Chrome browser from Selenium, a fresh temporary profile is created for the browser session. This means that by default, Chrome extensions are not loaded. To use an extension during a Selenium test, you must install the extension each time you launch a new browser.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;u style=&quot;background-color: #f5f5f5;&quot;&gt;Example 1: Installing a packed extension&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A packed extension comes in the form of a single .crx file.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
You can install a packed extension like this:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;script src=&quot;https://gist.github.com/cgoldberg/e2983e0d0db89c6d46d40547bc148415.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;u style=&quot;background-color: #f5f5f5;&quot;&gt;Example 2: Installing an unpacked extension&lt;/u&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
An unpacked extension is a directory containing extension code.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
You can install an unpacked extension like this:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;script src=&quot;https://gist.github.com/cgoldberg/e6e2a1ef3535f8d614462cc42c935f33.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;i&gt;examples tested with: chromium 68, chromedriver 2.41, selenium 3.14&lt;/i&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6485344598637497715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6485344598637497715'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2018/09/python-using-chrome-extensions-with.html' title='Python - Using Chrome Extensions With Selenium WebDriver'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-692610443445149338</id><published>2014-01-11T11:02:00.000-05:00</published><updated>2014-01-11T11:02:16.645-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - Fixing My Photo Library Dates (Exif Metadata)</title><content type='html'>&lt;p&gt;
I have a large image library of photos I&#39;ve taken or downloaded over the years.  They are from various cameras and sources, many with missing or incomplete &lt;a href=&quot;http://en.wikipedia.org/wiki/Exchangeable_image_file_format&quot;&gt;Exif&lt;/a&gt; metadata.
&lt;/p&gt;

&lt;p&gt;
This is problematic because some image viewing programs and galleries use metadata to sort images into timelines.  For example, when I view my library in &lt;a href=&quot;https://www.dropbox.com/features/photos&quot;&gt;Dropbox Photos&lt;/a&gt; timeline, images with missing Exif date tags are not displayed.
&lt;/p&gt;

&lt;p&gt;
To remedy this, I wrote a Python script to fix the dates in my photo library.  It uses &lt;a href=&quot;https://wiki.gnome.org/Projects/gexiv2&quot;&gt;gexiv2&lt;/a&gt;, which is a wrapper around the &lt;a href=&quot;http://www.exiv2.org/&quot;&gt;Exiv2&lt;/a&gt; photo metadata library.
&lt;/p&gt;

&lt;p&gt;
The scipt will:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;recursively scan a directory tree for jpg and png files&lt;/li&gt;
  &lt;li&gt;get each file&#39;s creation time&lt;/li&gt;
  &lt;li&gt;convert it to a timestamp string&lt;/li&gt;
  &lt;li&gt;set Exif.Image.DateTime tag to timestamp&lt;/li&gt;
  &lt;li&gt;set Exif.Photo.DateTimeDigitized tag to timestamp&lt;/li&gt;
  &lt;li&gt;set Exif.Photo.DateTimeOriginal tag to timestamp&lt;/li&gt;
  &lt;li&gt;save file with modified metadata&lt;/li&gt;
  &lt;li&gt;set file access and modified times to file creation time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
* Note: it does modifications in-place.
&lt;/p&gt;

&lt;p&gt;
The &lt;a href=&quot;https://gist.github.com/cgoldberg/8372494&quot;&gt;Code&lt;/a&gt;:
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/cgoldberg/8372494.js&quot;&gt;&lt;/script&gt;



</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/692610443445149338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/692610443445149338' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/692610443445149338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/692610443445149338'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2014/01/python-fixing-my-photo-library-dates.html' title='Python - Fixing My Photo Library Dates (Exif Metadata)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>Boston, MA, USA</georss:featurename><georss:point>42.3584308 -71.0597732</georss:point><georss:box>42.3584308 -71.0597732 42.3584308 -71.0597732</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-1423650560786645012</id><published>2013-10-22T10:38:00.000-04:00</published><updated>2013-10-22T10:38:00.827-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu"/><title type='text'>deadsnakes - Using Old Versions of Python on Ubuntu</title><content type='html'>&lt;p&gt;How do you install an older version of Python on Ubuntu without building it yourself?&lt;/p&gt;
    
&lt;p&gt;The Python packages in the official Ubuntu archives generally don&#39;t go back all that far, but people might still need to develop and test against these old Python interpreters.  Felix Krull maintains a PPA (package archive) of older Python versions that are easy to install on Ubuntu.&lt;/p&gt;

&lt;p&gt;
see: &lt;a href=&quot;https://launchpad.net/~fkrull/+archive/deadsnakes&quot;&gt;https://launchpad.net/~fkrull/+archive/deadsnakes&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Currently supported Python releases: &lt;strong&gt;2.4, 2.5, 2.6, 2.7, 3.1, 3.2, 3.3&lt;/strong&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
&lt;strong&gt;Instructions:&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
Add the deadsnakes repository:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;$ sudo add-apt-repository ppa:fkrull/deadsnakes&lt;/pre&gt;

&lt;p&gt;
Run Update:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;$ sudo apt-get update&lt;/pre&gt;

&lt;p&gt;
Install an older version of Python:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;$ sudo apt-get install python2.6 python2.6-dev&lt;/pre&gt;

&lt;hr /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/1423650560786645012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/1423650560786645012' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1423650560786645012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1423650560786645012'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/10/deadsnakes-using-old-versions-of-python.html' title='deadsnakes - Using Old Versions of Python on Ubuntu'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-633607069233803984</id><published>2013-06-22T15:44:00.000-04:00</published><updated>2013-06-22T15:44:52.329-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="audio"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Generating Audio Spectrograms in Python</title><content type='html'>&lt;p&gt;
A &lt;strong&gt;spectrogram&lt;/strong&gt; is a visual representation of the spectrum of frequencies in a sound sample.
&lt;/p&gt;

&lt;p&gt;
more info: &lt;a href=&quot;http://en.wikipedia.org/wiki/Spectrogram&quot;&gt;wikipedia spectrogram&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
Spectrogram code in Python, using Matplotlib:&lt;/br&gt;
(source on &lt;a href=&quot;https://github.com/cgoldberg/audioscripts/blob/master/visualization/spectrogram_matplotlib.py&quot;&gt;GitHub&lt;/a&gt;)
&lt;/p&gt;

&lt;pre style=&quot;font-size:11px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
&quot;&quot;&quot;Generate a Spectrogram image for a given WAV audio sample.

A spectrogram, or sonogram, is a visual representation of the spectrum
of frequencies in a sound.  Horizontal axis represents time, Vertical axis
represents frequency, and color represents amplitude.
&quot;&quot;&quot;


import os
import wave

import pylab


def graph_spectrogram(wav_file):
    sound_info, frame_rate = get_wav_info(wav_file)
    pylab.figure(num=None, figsize=(19, 12))
    pylab.subplot(111)
    pylab.title(&#39;spectrogram of %r&#39; % wav_file)
    pylab.specgram(sound_info, Fs=frame_rate)
    pylab.savefig(&#39;spectrogram.png&#39;)


def get_wav_info(wav_file):
    wav = wave.open(wav_file, &#39;r&#39;)
    frames = wav.readframes(-1)
    sound_info = pylab.fromstring(frames, &#39;Int16&#39;)
    frame_rate = wav.getframerate()
    wav.close()
    return sound_info, frame_rate


if __name__ == &#39;__main__&#39;:
    wav_file = &#39;sample.wav&#39;
    graph_spectrogram(wav_file)
&lt;/pre&gt;

&lt;p&gt;
Spectrogram code in Python, using &lt;a href=&quot;https://code.google.com/p/timeside/&quot;&gt;timeside&lt;/a&gt;:&lt;br /&gt;
(source on &lt;a href=&quot;https://github.com/cgoldberg/audioscripts/blob/master/visualization/spectrogram_timeside.py&quot;&gt;GitHub&lt;/a&gt;)
&lt;/p&gt;

&lt;pre style=&quot;font-size:11px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
&quot;&quot;&quot;Generate a Spectrogram image for a given audio sample.

Compatible with several audio formats: wav, flac, mp3, etc.
Requires: https://code.google.com/p/timeside/

A spectrogram, or sonogram, is a visual representation of the spectrum
of frequencies in a sound.  Horizontal axis represents time, Vertical axis
represents frequency, and color represents amplitude.
&quot;&quot;&quot;


import timeside


audio_file = &#39;sample.wav&#39;

decoder = timeside.decoder.FileDecoder(audio_file)
grapher = timeside.grapher.Spectrogram(width=1920, height=1080)
(decoder | grapher).run()
grapher.render(&#39;spectrogram.png&#39;)
&lt;/pre&gt;

&lt;p&gt;
happy audio hacking.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/633607069233803984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/633607069233803984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/633607069233803984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/633607069233803984'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/06/generating-audio-spectrograms-in-python.html' title='Generating Audio Spectrograms in Python'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>Boston, MA 02116, USA</georss:featurename><georss:point>42.353068 -71.076518800000031</georss:point><georss:box>42.306118 -71.157199800000029 42.400018 -70.995837800000032</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-5687740226732278197</id><published>2013-06-10T09:27:00.000-04:00</published><updated>2013-06-10T09:27:58.329-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Python - concurrencytest: Running Concurrent Tests</title><content type='html'>&lt;p&gt;
Add parallel testing to your unit test framework.
&lt;/p&gt;

&lt;p&gt;
In my &lt;a href=&quot;http://coreygoldberg.blogspot.com/2013/06/python-nose-running-concurrent-tests.html&quot;&gt;previous post&lt;/a&gt;, I described running concurrent tests using &lt;a href=&quot;http://nose.readthedocs.org/&quot;&gt;nose&lt;/a&gt; as a loader and runner.
&lt;/p&gt;

&lt;p&gt;
On a similar note, let&#39;s look at building concurrency into your own test framework built on Python&#39;s &lt;a href=&quot;http://docs.python.org/3/library/unittest.html&quot;&gt;unittest&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Have a look at this module: &lt;a href=&quot;https://github.com/cgoldberg/concurrencytest&quot;&gt;concurrencytest&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;i&gt;(Thanks to bits and concepts taken from &lt;a href=&quot;http://testtools.readthedocs.org&quot;&gt;testtools&lt;/a&gt; and &lt;a href=&quot;http://bazaar.canonical.com&quot;&gt;bzrlib&lt;/a&gt;)&lt;/i&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
&lt;b&gt;An Example:&lt;/b&gt;
&lt;/p&gt;

&lt;p&gt;
Say you have a &#39;TestSuite&#39; of tests loaded.  You could run them with the standard &#39;TextTestRunner&#39; like this:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
runner = unittest.TextTestRunner()
runner.run(suite)
&lt;/pre&gt;

&lt;p&gt;
That would run the tests in your suite sequentially in a single process.
&lt;/p&gt;

&lt;p&gt;
By adding the &lt;a href=&quot;https://github.com/cgoldberg/concurrencytest&quot;&gt;concurrencytest&lt;/a&gt; module, you can use a &#39;ConcurrentTestSuite&#39; instead, by adding:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
from concurrencytest import ConcurrentTestSuite, fork_for_tests

concurrent_suite = ConcurrentTestSuite(suite, fork_for_tests(4))
runner.run(concurrent_suite)
&lt;/pre&gt;

&lt;p&gt;
That would run the same tests split across 4 processes (workers).
&lt;/p&gt;

&lt;p&gt;
Note: this relies on &#39;os.fork()&#39; which only works on Unix systems.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
There&#39;s no way to understand this better than looking at some contrived examples!
&lt;/p&gt;

&lt;p&gt;
This first example is totally unrealistic, but shows off concurrency perfectly.  The test cases it loads each sleep for 0.5 seconds and then exit.
&lt;/p&gt;

&lt;p&gt;
The Code:
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/cgoldberg/5744573.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Output:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
Loaded 50 test cases...

Run tests sequentially:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 25.031s

OK

Run same tests across 50 processes:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 0.525s

OK
&lt;/pre&gt;

&lt;p&gt;
nice!
&lt;/p&gt;

&lt;p&gt;
Now another example that shows concurrency with CPU-bound test cases.  The test cases it loads each calculate fibonacci of 31 (recursively!) and then exit.  We can see how it performs on my 8-core machine (Core2 i7 quad, hyperthreaded).
&lt;/p&gt;

&lt;p&gt;
The Code:
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/cgoldberg/5744574.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Output:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
Loaded 50 test cases...

Run tests sequentially:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 21.941s

OK

Run same tests with 2 processes:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 11.081s

OK

Run same tests with 4 processes:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 5.862s

OK

Run same tests with 8 processes:
..................................................
----------------------------------------------------------------------
Ran 50 tests in 4.743s

OK
&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;
happy hacking.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/5687740226732278197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/5687740226732278197' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5687740226732278197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5687740226732278197'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/06/python-concurrencytest-running.html' title='Python - concurrencytest: Running Concurrent Tests'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>Boston, MA 02116, USA</georss:featurename><georss:point>42.353068 -71.076518800000031</georss:point><georss:box>42.306118 -71.157199800000029 42.400018 -70.995837800000032</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-6513481021993200742</id><published>2013-06-09T19:17:00.000-04:00</published><updated>2013-06-09T19:17:01.138-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><category scheme="http://www.blogger.com/atom/ns#" term="unittest"/><title type='text'>Python - Nose: Running Concurrent Tests</title><content type='html'>&lt;p&gt;
&lt;b&gt;TLDR&lt;/b&gt;:&lt;br /&gt;
To enable multiprocessing with &lt;i&gt;N&lt;/i&gt; workers,&lt;br /&gt;
run &lt;a href=&quot;https://nose.readthedocs.org&quot;&gt;nose&lt;/a&gt; with:
&lt;p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
$ nosetests --processes=N
&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;
When writing tests in Python, I start with TestCase&#39;s derived from &lt;a href=&quot;http://docs.python.org/2/library/unittest.html#test-cases&quot;&gt;unittest.TestCase&lt;/a&gt;, and standard &lt;a href=&quot;http://docs.python.org/2/library/unittest.html#test-discovery&quot;&gt;test discovery&lt;/a&gt;.  When I need more complex test discovery/loading or output reports, I often use &lt;a href=&quot;https://nose.readthedocs.org&quot;&gt;nose&lt;/a&gt; and its assortment of plugins as my test loader/runner.
&lt;/p&gt;

&lt;p&gt;
One nice feature of nose is the &lt;a href=&quot;http://nose.readthedocs.org/en/latest/plugins/multiprocess.html&quot;&gt;multiprocess plugin&lt;/a&gt;.  It allows you to run your tests suites concurrently rather than sequentially, spread across a number of worker processes.  Running tests in parallel like this can potentially give you a large speedup in your test run times.
&lt;/p&gt;

&lt;p&gt;
from the nose multiprocess docs:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;i&gt;&quot;You can parallelize a test run across a configurable number of worker processes. While this can speed up CPU-bound test runs, it is mainly useful for IO-bound tests that spend most of their time waiting for data to arrive from someplace else and can benefit from parallelization.&quot;&lt;/i&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Normally, you run tests from nose with:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
$ nosetests
&lt;/pre&gt;

&lt;p&gt;
To run the same tests split across 4 processes (workers), you would just do:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
$ nosetests --processes=4
&lt;/pre&gt;

&lt;p&gt;
Assuming your tests are properly isolated, everything should run normally, and you can benefit from a speedup on a multiprocessor machine.
&lt;/p&gt;

&lt;p&gt;
However, &lt;b&gt;Beware&lt;/b&gt;.
&lt;/p&gt;

&lt;blockquote&gt;
&lt;i&gt;&quot;Not all test suites will benefit from, or even operate correctly using, this plugin. For example, CPU-bound tests will run more slowly if you don&#39;t have multiple processors.&quot;&lt;/i&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;i&gt;&quot;But the biggest issue you will face is probably concurrency. Unless you have kept your tests as religiously pure unit tests, with no side-effects, no ordering issues, and no external dependencies, chances are you will experience odd, intermittent and unexplainable failures and errors when using this plugin. This doesn&#39;t necessarily mean the plugin is broken; it may mean that your test suite is not safe for concurrency.&quot;&lt;/i&gt;
&lt;/blockquote&gt;
</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/6513481021993200742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/6513481021993200742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6513481021993200742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6513481021993200742'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/06/python-nose-running-concurrent-tests.html' title='Python - Nose: Running Concurrent Tests'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>Boston, MA 02116, USA</georss:featurename><georss:point>42.353068 -71.076518800000031</georss:point><georss:box>42.306118 -71.157199800000029 42.400018 -70.995837800000032</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-2367345880276503522</id><published>2013-03-28T18:35:00.000-04:00</published><updated>2013-04-02T12:16:44.224-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - Re-tag FLAC Audio Files (Update Metadata)</title><content type='html'>&lt;p&gt;
I had a bunch of &lt;a href=&quot;http://en.wikipedia.org/wiki/FLAC&quot;&gt;FLAC&lt;/a&gt; (.flac) audio files together in a directory.  They are from various sources and their metadata (tags) were somewhat incomplete or incorrect.
&lt;/p&gt;

&lt;p&gt;
I managed to manually get all of the files standardized in &quot;%Artist% - %Title%.flac&quot; file name format.  However, What I really wanted was to clear their metadata and just save &quot;Artist&quot; and &quot;Title&quot; tags, pulled from file names.
&lt;/p&gt;

&lt;p&gt;
I looked at a few audio tagging tools in the Ubuntu repos, and came up short finding something simple that covered my needs.  (I use &lt;a href=&quot;http://pwp.netcabo.pt/paol/tagtool/&quot;&gt;Audio Tag Tool&lt;/a&gt; for MP3&#39;s, but it has no FLAC file support.)
&lt;/p&gt;

&lt;p&gt;
So, I figured the easiest way to get this done was a quick Python script.
&lt;/p&gt;

&lt;p&gt;
I grabbed &lt;a href=&quot;https://code.google.com/p/mutagen/&quot;&gt;Mutagen&lt;/a&gt;, a Python module to handle audio metadata with FLAC support.
&lt;/p&gt;

&lt;p&gt;
This is essentially the task I was looking to do:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import glob
import os
from mutagen.flac import FLAC

for filename in glob.glob(&#39;*.flac&#39;):
    artist, title = os.path.splitext(filename)[0].split(&#39; - &#39;, 1)
    audio = FLAC(filename)
    audio.clear()
    audio[&#39;artist&#39;] = artist
    audio[&#39;title&#39;] = title
    audio.save()
&lt;/pre&gt;

&lt;p&gt;
It iterates over .flac files in the current directory, clearing the metadata and rewriting only the artist/title tags based on each file name.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
I created a repository with a slightly more full-featured version, used to re-tag single FLAC files:&lt;br /&gt; &lt;a href=&quot;https://github.com/cgoldberg/audioscripts/blob/master/flac_retag.py&quot;&gt;https://github.com/cgoldberg/audioscripts/blob/master/flac_retag.py&lt;/a&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/2367345880276503522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/2367345880276503522' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/2367345880276503522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/2367345880276503522'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/03/python-re-tag-flac-audio-files-update.html' title='Python - Re-tag FLAC Audio Files (Update Metadata)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-5651956091791965206</id><published>2013-01-28T17:09:00.000-05:00</published><updated>2013-01-28T17:09:31.867-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - verify a PNG file and get image dimensions</title><content type='html'>&lt;p&gt;
useful snippet for getting .png image dimensions without using an external imaging library.
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import struct


def get_image_info(data):
    if is_png(data):
        w, h = struct.unpack(&#39;&gt;LL&#39;, data[16:24])
        width = int(w)
        height = int(h)
    else:
        raise Exception(&#39;not a png image&#39;)
    return width, height


def is_png(data):
    return (data[:8] == &#39;\211PNG\r\n\032\n&#39;and (data[12:16] == &#39;IHDR&#39;))


if __name__ == &#39;__main__&#39;:
    with open(&#39;foo.png&#39;, &#39;rb&#39;) as f:
        data = f.read()

    print is_png(data)
    print get_image_info(data)
&lt;/pre&gt;

&lt;p&gt;
/headnods:&lt;br /&gt;
&lt;a href=&quot;https://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py&quot;&gt;getimageinfo.py source&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Portable_Network_Graphics&quot;&gt;Portable_Network_Graphics (Wikipedia)&lt;/a&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/5651956091791965206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/5651956091791965206' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5651956091791965206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5651956091791965206'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/01/python-verify-png-file-and-get-image.html' title='Python - verify a PNG file and get image dimensions'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-1827847815105061327</id><published>2013-01-23T18:06:00.000-05:00</published><updated>2013-01-23T18:06:49.946-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><category scheme="http://www.blogger.com/atom/ns#" term="unittest"/><title type='text'>Python Unit Testing Tutorial (PyMOTW unittest update)</title><content type='html'>
&lt;p&gt;
&lt;b&gt;tl;dr&lt;/b&gt;: an update to PyMOTW for `unittest` in Python 3: &lt;strong&gt;&lt;a href=&quot;http://cgoldberg.github.com/python-unittest-tutorial/&quot;&gt;Python Unit Testing Tutorial&lt;/a&gt;&lt;/strong&gt;.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
When I was learning programming in &lt;a href=&quot;http://www.python.org/&quot;&gt;Python&lt;/a&gt;, Doug Hellmann&#39;s &lt;a href=&quot;http://www.doughellmann.com/PyMOTW/&quot;&gt;&#39;PyMOTW&#39; (Python Module Of The Week)&lt;/a&gt; blog-series was one of the best resources to learn Python&#39;s &lt;a href=&quot;http://docs.python.org/3.3/library/&quot;&gt;standard library&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
His series later culminated in the book: &lt;a href=&quot;http://www.doughellmann.com/books/byexample/&quot;&gt;&#39;The Python Standard Library By Example&#39;&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
The &lt;a href=&quot;http://www.doughellmann.com/PyMOTW/unittest/&quot;&gt;PyMOTW entry on `unittest`&lt;/a&gt; was a great introduction to unit testing in Python.  Since the PyMOTW version is getting quite outdated, I updated the `unittest` module entry.
&lt;/p&gt;

&lt;p&gt;
This new version includes some edits and updates to the text, and all code and examples have been updated to reflect Python 3.3.
&lt;/p&gt;

&lt;p&gt;
Have a look at my updated Python 3.3 version:&lt;br /&gt;
&lt;strong&gt;&lt;a href=&quot;http://cgoldberg.github.com/python-unittest-tutorial/&quot;&gt;&#39;Python Unit Testing Tutorial&#39;&lt;/a&gt;&lt;/strong&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
&lt;i&gt;license:
&lt;a href=&quot;http://creativecommons.org/licenses/by-nc-sa/3.0/us/&quot;&gt;Creative Commons Attribution, Non-commercial, Share-alike 3.0&lt;/a&gt;&lt;/i&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
say no to bugs...
&lt;/p&gt;

&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu5lURtHahuaxBaiq2PofrId4AlkxXIVY_yxfVbMfvaCf-WuzD07uo2swY8eZ04h_qCGUU8DAz4EloV966RXwiEjkXit0tpX9AzygL-YlzBglk_fu2tEhWNZwG8gynznrp2YFA7GQFE3Y/s1600/ladybug_for_blogpost.jpg&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; width=&quot;355&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu5lURtHahuaxBaiq2PofrId4AlkxXIVY_yxfVbMfvaCf-WuzD07uo2swY8eZ04h_qCGUU8DAz4EloV966RXwiEjkXit0tpX9AzygL-YlzBglk_fu2tEhWNZwG8gynznrp2YFA7GQFE3Y/s400/ladybug_for_blogpost.jpg&quot; /&gt;&lt;/a&gt;
</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/1827847815105061327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/1827847815105061327' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1827847815105061327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1827847815105061327'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/01/python-unit-testing-tutorial-pymotw.html' title='Python Unit Testing Tutorial (PyMOTW unittest update)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu5lURtHahuaxBaiq2PofrId4AlkxXIVY_yxfVbMfvaCf-WuzD07uo2swY8eZ04h_qCGUU8DAz4EloV966RXwiEjkXit0tpX9AzygL-YlzBglk_fu2tEhWNZwG8gynznrp2YFA7GQFE3Y/s72-c/ladybug_for_blogpost.jpg" height="72" width="72"/><thr:total>2</thr:total><georss:featurename>Boston, MA 02116, USA</georss:featurename><georss:point>42.353068 -71.076518800000031</georss:point><georss:box>42.306118 -71.157199800000029 42.400018 -70.995837800000032</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-401558891799222288</id><published>2013-01-14T09:42:00.001-05:00</published><updated>2013-01-14T09:58:43.975-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - &quot;The Matrix&quot; in your terminal</title><content type='html'>&lt;p&gt;
Linux console program in Python, that scrolls binary numbers vertically in your terminal. Inspired by the movie: The Matrix
&lt;/p&gt;

&lt;p&gt;
a screenshot:
&lt;/p&gt;

&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzeZ-Lt4tMZIC9oEUHghTQR_EUcTNqqgJBg97gvEhalE5_WnLRjSHiM2-iKTn54L86me7MvFjz4-xvJE-xo-XVJbUE1KQWRTdNzJnSfGMLPUvwX8dQHs_Hhl2IUIrQ5BFvTh0W2I0q30Q/s1600/matrix_code.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;329&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzeZ-Lt4tMZIC9oEUHghTQR_EUcTNqqgJBg97gvEhalE5_WnLRjSHiM2-iKTn54L86me7MvFjz4-xvJE-xo-XVJbUE1KQWRTdNzJnSfGMLPUvwX8dQHs_Hhl2IUIrQ5BFvTh0W2I0q30Q/s400/matrix_code.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;

&lt;p&gt;
in action:
&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/96crI0NCbPg&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;
the Code:
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/4530348.js&quot;&gt;&lt;/script&gt;

&lt;a href=&quot;https://gist.github.com/4530348&quot;&gt;https://gist.github.com/4530348&lt;/a&gt;

&lt;hr /&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/401558891799222288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/401558891799222288' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/401558891799222288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/401558891799222288'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/01/python-matrix-in-your-terminal.html' title='Python - &quot;The Matrix&quot; in your terminal'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzeZ-Lt4tMZIC9oEUHghTQR_EUcTNqqgJBg97gvEhalE5_WnLRjSHiM2-iKTn54L86me7MvFjz4-xvJE-xo-XVJbUE1KQWRTdNzJnSfGMLPUvwX8dQHs_Hhl2IUIrQ5BFvTh0W2I0q30Q/s72-c/matrix_code.png" height="72" width="72"/><thr:total>3</thr:total><georss:featurename>Boston, MA, USA</georss:featurename><georss:point>42.3584308 -71.0597732</georss:point><georss:box>42.170560800000004 -71.38249669999999 42.5463008 -70.7370497</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-1511106015880966704</id><published>2013-01-06T16:35:00.000-05:00</published><updated>2013-01-06T16:35:56.432-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="phantomjs"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="selenium"/><title type='text'>Python Testing - PhantomJS with Selenium WebDriver</title><content type='html'>&lt;p&gt;
&lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; is a headless &lt;a href=&quot;http://en.wikipedia.org/wiki/WebKit&quot;&gt;WebKit&lt;/a&gt; with JavaScript API.  It can be used for headless website testing.  
&lt;/p&gt;

&lt;p&gt;
PhantomJS has a lot of different uses.  The interesting bit for me is to use PhantomJS as a lighter-weight replacement for a browser when running web acceptance tests.  This enables faster testing, without a display or the overhead of full-browser startup/shutdown.
&lt;/p&gt;

&lt;p&gt;
I write my web automation using &lt;a href=&quot;http://seleniumhq.org/&quot;&gt;Selenium WebDriver&lt;/a&gt;, in &lt;a href=&quot;http://pypi.python.org/pypi/selenium&quot;&gt;Python&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
In future versions of PhantomJS, the &lt;a href=&quot;https://github.com/detro/ghostdriver&quot;&gt;GhostDriver&lt;/a&gt; component will be included.
&lt;/p&gt;

&lt;p&gt;
GhostDriver is a pure JavaScript implementation of the &lt;a href=&quot;http://code.google.com/p/selenium/wiki/JsonWireProtocol&quot;&gt;WebDriver Wire Protocol&lt;/a&gt; for PhantomJS. It&#39;s a Remote WebDriver that uses PhantomJS as back-end.
&lt;/p&gt;

&lt;p&gt;
So, Ghostdriver is the bridge we need to use Selenium WebDriver with Phantom.JS.
&lt;/p&gt;

&lt;p&gt;
Since it is not available in the current PhantomJS release, you can try it yourself by compiling a special version of PhantomJS:
&lt;/p&gt;

&lt;p&gt;
It wes pretty trvial to setup on Ubuntu (12.04):
&lt;/p&gt;

&lt;pre style=&quot;font-size:10px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
$ sudo apt-get install build-essential chrpath git-core libssl-dev libfontconfig1-dev
$ git clone git://github.com/ariya/phantomjs.git
$ cd phantomjs
$ git checkout 1.8
$ ./build.sh
$ git remote add detro https://github.com/detro/phantomjs.git
$ git fetch detro &amp;&amp; git checkout -b detro-ghostdriver-dev remotes/detro/ghostdriver-dev
$ ./build.sh
&lt;/pre&gt;

&lt;p&gt;
Then grab the `phantomjs` binary it produced (look inside `phantomjs/bin`).  This is a self-contained executable, it can be moved to a different directory or another machine.  Make sure it is located somewhere on your PATH, or declare it&#39;s location when creating your PhantomJS driver like the example below.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;for these examples, `phantomjs` binary is located in same directory as test script.
&lt;p&gt;
&lt;b&gt;Example: Python Using PhantomJS and Selenium WebDriver&lt;/b&gt;.
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

driver = webdriver.PhantomJS(&#39;./phantomjs&#39;)
# do webdriver stuff here
driver.quit()
&lt;/pre&gt;

&lt;p&gt;
&lt;b&gt;Example: Python Unit Test Using PhantomJS and Selenium WebDriver&lt;/b&gt;.
&lt;/p&gt; 

&lt;pre style=&quot;font-size:14px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import unittest
from selenium import webdriver


class TestUbuntuHomepage(unittest.TestCase):
    
    def setUp(self):
        self.driver = webdriver.PhantomJS(&#39;./phantomjs&#39;)
        
    def testTitle(self):
        self.driver.get(&#39;http://www.ubuntu.com/&#39;)
        self.assertIn(&#39;Ubuntu&#39;, self.driver.title)
        
    def tearDown(self):
        self.driver.quit()


if __name__ == &#39;__main__&#39;:
    unittest.main(verbosity=2)
&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;
resources:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://phantomjs.org/build.html&quot;&gt;http://phantomjs.org/build.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/detro/ghostdriver&quot;&gt;https://github.com/detro/ghostdriver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://goldb.org/sst/selenium2_api_docs/html/selenium.webdriver.phantomjs.webdriver.WebDriver-class.html&quot;&gt;Selenium WebDriver Python API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/1511106015880966704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/1511106015880966704' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1511106015880966704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1511106015880966704'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2013/01/python-testing-phantomjs-with-selenium.html' title='Python Testing - PhantomJS with Selenium WebDriver'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-6586650934818400424</id><published>2012-06-17T10:39:00.000-04:00</published><updated>2012-06-17T10:39:29.618-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python Timer Class - Context Manager for Timing Code Blocks</title><content type='html'>&lt;p&gt;
Here is a handy &lt;strong&gt;Python Timer class&lt;/strong&gt;.  It creates a context manager object, used for timing a block of code.
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFxHNSZm3WmQsAI4AB_-5rnyceZaQ9nrAWQB0293qlSuAHIJSsoMI7-S4MRyTs5lOhlUFX5Bhb0SHoH317IIQ92ICzZ92GGfXq-YbI1TtKu5GIr4p9RBDHW1c-Rg_Gs-h6CMoTglp9VeU/s1600/timer.jpg&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;140&quot; width=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFxHNSZm3WmQsAI4AB_-5rnyceZaQ9nrAWQB0293qlSuAHIJSsoMI7-S4MRyTs5lOhlUFX5Bhb0SHoH317IIQ92ICzZ92GGfXq-YbI1TtKu5GIr4p9RBDHW1c-Rg_Gs-h6CMoTglp9VeU/s200/timer.jpg&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
from timeit import default_timer


class Timer(object):
    def __init__(self, verbose=False):
        self.verbose = verbose
        self.timer = default_timer
        
    def __enter__(self):
        self.start = self.timer()
        return self
        
    def __exit__(self, *args):
        end = self.timer()
        self.elapsed_secs = end - self.start
        self.elapsed = self.elapsed_secs * 1000  # millisecs
        if self.verbose:
            print &#39;elapsed time: %f ms&#39; % self.elapsed
&lt;/pre&gt;

&lt;p&gt;        
To use the Timer (&lt;a href=&quot;http://docs.python.org/reference/datamodel.html#context-managers&quot;&gt;context manager&lt;/a&gt; object), invoke it using Python&#39;s &lt;a href=&quot;http://docs.python.org/reference/compound_stmts.html#with&quot;&gt;`with`&lt;/a&gt; statement.  The duration of the context (code inside your `with` block) will be timed.  It uses the &lt;a href=&quot;http://docs.python.org/library/timeit.html#timeit.default_timer&quot;&gt;appropriate timer&lt;/a&gt; for your platform, via the `timeit` module.
&lt;/p&gt;

&lt;p&gt;
Timer is used like this:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
with Timer() as target:
    # block of code goes here.
    # result (elapsed time) is stored in `target` properties.
&lt;/pre&gt;

&lt;p&gt;
Example script:&lt;br /&gt;
timing a web request (HTTP GET), using the &lt;a href=&quot;http://docs.python-requests.org/&quot;&gt;`requests`&lt;/a&gt; module.
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import requests
from timer import Timer

url = &#39;https://github.com/timeline.json&#39;

with Timer() as t:
    r = requests.get(url)
    
print &#39;fetched %r in %.2f millisecs&#39; % (url, t.elapsed)
&lt;/pre&gt;

&lt;p&gt;
Output:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
fetched &#39;https://github.com/timeline.json&#39; in 458.76 millisecs
&lt;/pre&gt; 

&lt;hr /&gt;

&lt;p&gt;    
&lt;a href=&quot;https://gist.github.com/2942781&quot;&gt;`timer.py`&lt;/a&gt; in GitHub Gist form, with more examples:
&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/2942781.js?file=timer.py&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/6586650934818400424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/6586650934818400424' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6586650934818400424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/6586650934818400424'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/06/python-timer-class-context-manager-for.html' title='Python Timer Class - Context Manager for Timing Code Blocks'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFxHNSZm3WmQsAI4AB_-5rnyceZaQ9nrAWQB0293qlSuAHIJSsoMI7-S4MRyTs5lOhlUFX5Bhb0SHoH317IIQ92ICzZ92GGfXq-YbI1TtKu5GIr4p9RBDHW1c-Rg_Gs-h6CMoTglp9VeU/s72-c/timer.jpg" height="72" width="72"/><thr:total>8</thr:total><georss:featurename>Boston, MA, USA</georss:featurename><georss:point>42.3584308 -71.0597732</georss:point><georss:box>42.2645643 -71.217701699999992 42.4522973 -70.9018447</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-428208208086725158</id><published>2012-06-04T15:45:00.002-04:00</published><updated>2012-06-04T20:07:26.214-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>History of Python - Development Visualization - Gource</title><content type='html'>&lt;p&gt;
I made a new visualization.  Have a look!
&lt;/p&gt;

&lt;p&gt;
&lt;a href=&quot;http://www.youtube.com/watch?v=cNBtDstOTmA&amp;hd=1&quot;&gt;History of Python - Gource - development visualization (august 1990 - june 2012)&lt;/a&gt;&lt;br /&gt;
[HD video, encoded at 1080p. watch on YouTube in highest resolution possible.]
&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/cNBtDstOTmA?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;
&lt;strong&gt;What is it?&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
This is a visualization of Python core development.  It shows growth of the Python project&#39;s source code over time (August 1990 - June 2012).  Nearly 22 years!  The source code history and relations are displayed by Gource as an animated tree, tracking commits over time.  Directories appear as branches with files as leaves. Developers can be seen working on the tree at the times they contributed to the Python project.
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;Video:&lt;/em&gt;&lt;br /&gt;
Rendered with &lt;a href=&quot;http://code.google.com/p/gource/&quot;&gt;Gource&lt;/a&gt; v0.37 on Ubuntu 12.04
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;Music:&lt;/em&gt;&lt;br /&gt;
&lt;a href=&quot;http://freemusicarchive.org/music/Chris_Zabriskie&quot;&gt;Chris Zabriskie - The Life and Death of a Certain K Zabriskie Patriarch&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;Repository:&lt;/em&gt;&lt;br /&gt;
cpython 3.3.0 alpha, retrieved from mercurial on June 2 2012
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
for more visualizations and other videos, check out &lt;a href=&quot;http://www.youtube.com/c0reyg&quot;&gt;my YouTube channel&lt;/a&gt;.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/428208208086725158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/428208208086725158' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/428208208086725158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/428208208086725158'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/06/history-of-python-development.html' title='History of Python - Development Visualization - Gource'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/cNBtDstOTmA/default.jpg" height="72" width="72"/><thr:total>3</thr:total><georss:featurename>Boston, MA, USA</georss:featurename><georss:point>42.3584308 -71.0597732</georss:point><georss:box>42.2645643 -71.217701699999992 42.4522973 -70.9018447</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-5754354347068900419</id><published>2012-04-23T14:02:00.000-04:00</published><updated>2012-04-23T14:02:26.276-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>SST 0.2.1 Release Announcement (selenium-simple-test)</title><content type='html'>&lt;p&gt;
&lt;strong&gt;SST version 0.2.1 has been released.&lt;/strong&gt;
&lt;/p&gt;

&lt;img src=&quot;http://testutils.org/sst/_static/sst-logo_small.png&quot; /&gt;

&lt;p&gt;
&lt;a href=&quot;http://testutils.org/sst&quot;&gt;SST&lt;/a&gt; (selenium-simple-test) is a web test framework that uses Python to generate functional browser-based tests.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
SST version 0.2.1 is on PyPI: &lt;a href=&quot;http://pypi.python.org/pypi/sst&quot;&gt;http://pypi.python.org/pypi/sst&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
install or upgrade with:
&lt;/p&gt;
&lt;pre style=&quot;font-size:15px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:8px;&quot;&gt;
pip install -U sst
&lt;/pre&gt;

&lt;p&gt;
Changelog: &lt;a href=&quot;http://testutils.org/sst/changelog.html&quot;&gt;http://testutils.org/sst/changelog.html&lt;/a&gt;&lt;br /&gt;
SST Docs: &lt;a href=&quot;http://testutils.org/sst&quot;&gt;http://testutils.org/sst&lt;/a&gt;&lt;br /&gt;
SST on Launchpad: &lt;a href=&quot;https://launchpad.net/selenium-simple-test&quot;&gt;https://launchpad.net/selenium-simple-test&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
SST downloads | (Jan 1 2012 - April 23 2012)
&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdoSdOQFwZG_ZJ25H3rwy-6RIyU1NyWyQtCOAYBuMMEUptLhantg1C_yY9t21P4FyqT7aJP3MsUfjZxIMZ-Y9L-WEjT23U5FQhReNQHdjY-BqjSHBIIVITJNyq9sQQNDB-_aemZYm5Dwk/s1600/SST_downloads_pypi_2012-04-23.png&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;276&quot; width=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdoSdOQFwZG_ZJ25H3rwy-6RIyU1NyWyQtCOAYBuMMEUptLhantg1C_yY9t21P4FyqT7aJP3MsUfjZxIMZ-Y9L-WEjT23U5FQhReNQHdjY-BqjSHBIIVITJNyq9sQQNDB-_aemZYm5Dwk/s400/SST_downloads_pypi_2012-04-23.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;
1600+ downloads from PyPI since initial release.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/5754354347068900419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/5754354347068900419' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5754354347068900419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5754354347068900419'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/04/sst-021-release-announcement-selenium.html' title='SST 0.2.1 Release Announcement (selenium-simple-test)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdoSdOQFwZG_ZJ25H3rwy-6RIyU1NyWyQtCOAYBuMMEUptLhantg1C_yY9t21P4FyqT7aJP3MsUfjZxIMZ-Y9L-WEjT23U5FQhReNQHdjY-BqjSHBIIVITJNyq9sQQNDB-_aemZYm5Dwk/s72-c/SST_downloads_pypi_2012-04-23.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-3479065951823805010</id><published>2012-04-09T12:16:00.000-04:00</published><updated>2012-04-09T12:16:49.268-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - Getting Data Into Graphite - Code Examples</title><content type='html'>&lt;p&gt;
This post shows code examples in Python (2.7) for sending data to &lt;a href=&quot;http://coreygoldberg.blogspot.com/2012/04/python-graphite-storage-and.html&quot;&gt;Graphite&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Once you have a &lt;a href=&quot;http://coreygoldberg.blogspot.com/2012/04/installing-graphite-099-on-ubuntu-1204.html&quot;&gt;Graphite server setup&lt;/a&gt;, with Carbon running/collecting, you need to send it data for graphing.
&lt;/p&gt;

&lt;p&gt;
Basically, you write a program to collect numeric values and send them to Graphite&#39;s backend aggregator (Carbon).
&lt;/p&gt;

&lt;p&gt;
To send data, you create a &lt;a href=&quot;http://docs.python.org/library/socket.html&quot;&gt;socket&lt;/a&gt; connection to the graphite/carbon server and send a message (string) in the format:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
&quot;metric_path value timestamp\n&quot;
&lt;/pre&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;`metric_path`&lt;/b&gt;: arbitrary namespace containing substrings delimited by dots. The most general name is at the left and the most specific is at the right.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;`value`&lt;/b&gt;: numeric value to store.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;`timestamp`&lt;/b&gt;: epoch time.&lt;/li&gt;
  &lt;li&gt;messages must end with a trailing newline.&lt;/li&gt;
  &lt;li&gt;multiple messages maybe be batched and sent in a single socket operation. each message is delimited by a newline, with a trailing newline at the end of the message batch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Example message:
&lt;/p&gt;

&lt;pre style=&quot;font-size:13px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
&quot;foo.bar.baz 42 74857843\n&quot; 
&lt;/pre&gt;

&lt;p&gt;
Let&#39;s look at some (Python 2.7) code for sending data to graphite...
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
Here is a simple client that sends a single message to graphite.
&lt;/p&gt;

&lt;p&gt;
Code:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import socket
import time


CARBON_SERVER = &#39;0.0.0.0&#39;
CARBON_PORT = 2003

message = &#39;foo.bar.baz 42 %d\n&#39; % int(time.time())

print &#39;sending message:\n%s&#39; % message
sock = socket.socket()
sock.connect((CARBON_SERVER, CARBON_PORT))
sock.sendall(message)
sock.close()

&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;
Here is a command line client that sends a single message to graphite:
&lt;/p&gt;

&lt;p&gt;
Usage: 
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
$ python client-cli.py metric_path value
&lt;/pre&gt;

&lt;p&gt;
Code:
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python

import argparse
import socket
import time


CARBON_SERVER = &#39;0.0.0.0&#39;
CARBON_PORT = 2003


parser = argparse.ArgumentParser()
parser.add_argument(&#39;metric_path&#39;)
parser.add_argument(&#39;value&#39;)
args = parser.parse_args()


if __name__ == &#39;__main__&#39;:
    timestamp = int(time.time())
    message = &#39;%s %s %d\n&#39; % (args.metric_path, args.value, timestamp)
    
    print &#39;sending message:\n%s&#39; % message
    sock = socket.socket()
    sock.connect((CARBON_SERVER, CARBON_PORT))
    sock.sendall(message)
    sock.close()

&lt;/pre&gt;   

&lt;hr /&gt;

&lt;p&gt;
Here is a client that collects &lt;a href=&quot;http://en.wikipedia.org/wiki/Load_(computing)&quot;&gt;load average&lt;/a&gt; (Linux-only) and sends a batch of 3 messages (1min/5min/15min loadavg) to graphite.  It will run continuously in a loop until killed.  (adjust the delay for faster/slower collection interval):
&lt;/p&gt;

&lt;pre style=&quot;font-size:12px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:4px;&quot;&gt;
#!/usr/bin/env python
 
import platform
import socket
import time


CARBON_SERVER = &#39;0.0.0.0&#39;
CARBON_PORT = 2003
DELAY = 15  # secs


def get_loadavgs():
    with open(&#39;/proc/loadavg&#39;) as f:
        return f.read().strip().split()[:3]


def send_msg(message):
    print &#39;sending message:\n%s&#39; % message
    sock = socket.socket()
    sock.connect((CARBON_SERVER, CARBON_PORT))
    sock.sendall(message)
    sock.close()


if __name__ == &#39;__main__&#39;:
    node = platform.node().replace(&#39;.&#39;, &#39;-&#39;)
    while True:
        timestamp = int(time.time())
        loadavgs = get_loadavgs()
        lines = [
            &#39;system.%s.loadavg_1min %s %d&#39; % (node, loadavgs[0], timestamp),
            &#39;system.%s.loadavg_5min %s %d&#39; % (node, loadavgs[1], timestamp),
            &#39;system.%s.loadavg_15min %s %d&#39; % (node, loadavgs[2], timestamp)
        ]
        message = &#39;\n&#39;.join(lines) + &#39;\n&#39;
        send_msg(message)
        time.sleep(DELAY)

&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;
Resources:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://graphite.wikidot.com&quot;&gt;Graphite Docs&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://graphite.wikidot.com/getting-your-data-into-graphite&quot;&gt;Graphite Docs - Getting Your Data Into Graphite&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://coreygoldberg.blogspot.com/2012/04/installing-graphite-099-on-ubuntu-1204.html&quot;&gt;Installing Graphite 0.9.9 on Ubuntu 12.04 LTS&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://agiletesting.blogspot.com/2011/04/installing-and-configuring-graphite.html&quot;&gt;Installing and configuring Graphite&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/3479065951823805010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/3479065951823805010' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3479065951823805010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3479065951823805010'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/04/python-getting-data-into-graphite-code.html' title='Python - Getting Data Into Graphite - Code Examples'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-2575951543578343606</id><published>2012-04-07T13:21:00.001-04:00</published><updated>2012-04-07T13:26:30.902-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Installing Graphite 0.9.9 on Ubuntu 12.04 LTS</title><content type='html'>&lt;p&gt;
I just setup a &lt;a href=&quot;http://coreygoldberg.blogspot.com/2012/04/python-graphite-storage-and.html&quot;&gt;Graphite server&lt;/a&gt; on Ubuntu 12.04 (Precise).
&lt;/p&gt;

&lt;p&gt;
Here are some instructions for getting it all working (using Apache as web server).
&lt;/p&gt;

&lt;p&gt;
It follows these steps:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;install system dependencies (apache, django, dev libs, etc)&lt;/li&gt;
    &lt;li&gt;install Whisper (db lib)&lt;/li&gt;
    &lt;li&gt;install and configure Carbon (data aggregator)&lt;/li&gt;
    &lt;li&gt;install Graphite (django webapp)&lt;/li&gt;
    &lt;li&gt;configure Apache (http server)&lt;/li&gt;
    &lt;li&gt;create initial database&lt;/li&gt;
    &lt;li&gt;start Carbon (data aggregator)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Once that is done, you should be able to visit the host in your web browser and see the Graphite UI.
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Setup Instructions:&lt;/p&gt;

&lt;pre style=&quot;font-size:10px;border:0.5px #999999 solid;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:2px;&quot;&gt;
#############################
# INSTALL SYSTEM DEPENDENCIES
#############################

$ sudo apt-get install apache2 libapache2 libapache2-mod-wsgi /
    libapache2-mod-python memcached python-dev python-cairo-dev /
    python-django python-ldap python-memcache python-pysqlite2 /
    python-pip sqlite3 erlang-os-mon erlang-snmp rabbitmq-server
    
$ sudo pip install django-tagging

#################
# INSTALL WHISPER
#################

$ sudo pip install http://launchpad.net/graphite/0.9/0.9.9/+download/whisper-0.9.9.tar.gz

################################################
# INSTALL AND CONFIGURE CARBON (data aggregator)
################################################

$ sudo pip install http://launchpad.net/graphite/0.9/0.9.9/+download/carbon-0.9.9.tar.gz
$ cd /opt/graphite/conf/
$ sudo cp carbon.conf.example carbon.conf
$ sudo cp storage-schemas.conf.example storage-schemas.conf

###########################
# INSTALL GRAPHITE (webapp)
###########################

$ sudo pip install http://launchpad.net/graphite/0.9/0.9.9/+download/graphite-web-0.9.9.tar.gz

or

$ wget http://launchpad.net/graphite/0.9/0.9.9/+download/graphite-web-0.9.9.tar.gz
$ tar -zxvf graphite-web-0.9.9.tar.gz
$ mv graphite-web-0.9.9 graphite
$ cd graphite
$ sudo python check-dependencies.py
$ sudo python setup.py install

##################
# CONFIGURE APACHE
##################

$ cd graphite/examples
$ sudo cp example-graphite-vhost.conf /etc/apache2/sites-available/default
$ sudo cp /opt/graphite/conf/graphite.wsgi.example /opt/graphite/conf/graphite.wsgi
$ sudo mkdir /etc/httpd
$ sudo mkdir /etc/httpd/wsgi
$ sudo /etc/init.d/apache2 reload

#########################
# CREATE INITIAL DATABASE 
#########################

$ cd /opt/graphite/webapp/graphite/
$ sudo python manage.py syncdb
$ sudo chown -R www-data:www-data /opt/graphite/storage/
$ sudo /etc/init.d/apache2 restart
$ sudo cp local_settings.py.example local_settings.py

################################
# START CARBON (data aggregator)
################################

$ cd /opt/graphite/
$ sudo ./bin/carbon-cache.py start

&lt;/pre&gt;

&lt;p&gt;
Resources:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://graphite.readthedocs.org/en/latest/install.html&quot;&gt;http://graphite.readthedocs.org/en/latest/install.html&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://graphite.wikidot.com/installation&quot;&gt;http://graphite.wikidot.com/installation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://geek.michaelgrace.org/2011/09/how-to-install-graphite-on-ubuntu/&quot;&gt;http://geek.michaelgrace.org/2011/09/how-to-install-graphite-on-ubuntu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;
* works on my machine, Ubuntu 12.04
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/2575951543578343606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/2575951543578343606' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/2575951543578343606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/2575951543578343606'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/04/installing-graphite-099-on-ubuntu-1204.html' title='Installing Graphite 0.9.9 on Ubuntu 12.04 LTS'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-4866018540846996112</id><published>2012-04-07T07:45:00.000-04:00</published><updated>2012-04-07T07:45:28.170-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - Graphite: Storage and Visualization of Time-series Data</title><content type='html'>&lt;p&gt;
I&#39;m doing some work with &lt;strong&gt;Graphite&lt;/strong&gt; in Python.  Here is a quick overview of what Graphite is...
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
&lt;strong&gt;Graphite&lt;/strong&gt; provides real-time visualization and storage of numeric time-series data.
&lt;/p&gt;

&lt;p&gt;
Links:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project: &lt;a href=&quot;https://launchpad.net/graphite&quot;&gt;https://launchpad.net/graphite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href=&quot;http://graphite.readthedocs.org&quot;&gt;http://graphite.readthedocs.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Graphite does two things:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store numeric time-series data&lt;/li&gt;
&lt;li&gt;Render graphs of this data on demand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Graphite consists of a storage backend and a web-based visualization frontend.  Client applications send streams of numeric time-series data to the Graphite backend (called carbon), where it gets stored in fixed-size database files similar in design to RRD. The web frontend provides 2 distinct user interfaces for visualizing this data in graphs as well as a simple URL-based API for direct graph generation.
&lt;/p&gt;

&lt;p&gt;
Graphite consists of 3 software components:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;carbon&lt;/strong&gt; - a Twisted daemon that listens for time-series data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;whisper&lt;/strong&gt; - a simple database library for storing time-series data (similar in design to RRD)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;graphite webapp&lt;/strong&gt; - A Django webapp that renders graphs on-demand using Cairo&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP0JJymnzS4AkwYwJq_wFine5Al-rB3QmVcz3yW9UGIMtXAuB6H5wPvBvHUM0hZtr54VsSG-BYAcsq5h9NgAH82Z3k96ulHm61I_BkocBVSuRdrvVlCI-pkq4IQiqRp_cQMTp1GUg3KcU/s1600/graphite_web-graph.png&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;298&quot; width=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP0JJymnzS4AkwYwJq_wFine5Al-rB3QmVcz3yW9UGIMtXAuB6H5wPvBvHUM0hZtr54VsSG-BYAcsq5h9NgAH82Z3k96ulHm61I_BkocBVSuRdrvVlCI-pkq4IQiqRp_cQMTp1GUg3KcU/s400/graphite_web-graph.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/4866018540846996112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/4866018540846996112' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/4866018540846996112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/4866018540846996112'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/04/python-graphite-storage-and.html' title='Python - Graphite: Storage and Visualization of Time-series Data'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP0JJymnzS4AkwYwJq_wFine5Al-rB3QmVcz3yW9UGIMtXAuB6H5wPvBvHUM0hZtr54VsSG-BYAcsq5h9NgAH82Z3k96ulHm61I_BkocBVSuRdrvVlCI-pkq4IQiqRp_cQMTp1GUg3KcU/s72-c/graphite_web-graph.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-3974517846451529992</id><published>2012-04-05T09:17:00.001-04:00</published><updated>2012-04-05T09:17:52.099-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python Book Giveaway - Boston Python User Group - April 12, 2012</title><content type='html'>&lt;p&gt;
I am bringing some of my [lightly read] Python books to give away at the next &lt;a href=&quot;http://meetup.bostonpython.com&quot;&gt;Boston Python User Group&lt;/a&gt; meetup.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&quot;http://meetup.bostonpython.com/events/51175882/&quot;&gt;Boston Python User Group - April Project Night&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;i&gt;When&lt;/i&gt;: Thursday, April 12, 2012, 6:30 PM&lt;br /&gt;
&lt;i&gt;Where&lt;/i&gt;: Microsoft NERD, Cambridge&lt;br /&gt;
&lt;/p&gt;


&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbZDRI9ELHH3tBy84cc0S0aCfrQhju2OIxRGnMwaz6hEPJmZVvP8rg-lAvjIUOqLyi_ziSHlIp5aaP3QfSxCO6AyfOIeBXntV7brVH79q7hV1pZ4rbz6Fi_HWa39vlJrtKcYCYnep6SdM/s1600/bostonpython-book-giveaway.jpg&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; width=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbZDRI9ELHH3tBy84cc0S0aCfrQhju2OIxRGnMwaz6hEPJmZVvP8rg-lAvjIUOqLyi_ziSHlIp5aaP3QfSxCO6AyfOIeBXntV7brVH79q7hV1pZ4rbz6Fi_HWa39vlJrtKcYCYnep6SdM/s400/bostonpython-book-giveaway.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;
Books:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro Python (Alchin)&lt;/li&gt;
&lt;li&gt;Head First Python (Barry)&lt;/li&gt;
&lt;li&gt;Programming in Python 3 (Summerfield)&lt;/li&gt;
&lt;li&gt;Python Programming Patterns (Christopher)&lt;/li&gt;
&lt;li&gt;Hello World! (Sande)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
If you are interested in getting a free book, come to #bostonpython Project Night on April 12!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/3974517846451529992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/3974517846451529992' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3974517846451529992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3974517846451529992'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/04/python-book-giveaway-boston-python-user.html' title='Python Book Giveaway - Boston Python User Group - April 12, 2012'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbZDRI9ELHH3tBy84cc0S0aCfrQhju2OIxRGnMwaz6hEPJmZVvP8rg-lAvjIUOqLyi_ziSHlIp5aaP3QfSxCO6AyfOIeBXntV7brVH79q7hV1pZ4rbz6Fi_HWa39vlJrtKcYCYnep6SdM/s72-c/bostonpython-book-giveaway.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-3183044741162023684</id><published>2012-03-24T12:59:00.000-04:00</published><updated>2012-03-24T12:59:24.712-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python Screencast: Install/Setup &quot;SST Web Test Framework&quot; on Ubuntu 12.04</title><content type='html'>&lt;p&gt;
I uploaded a 5 minute video/screencast showing how to install and setup &lt;a href=&quot;http://testutils.org/sst/&quot;&gt;SST Web Test Framework&lt;/a&gt; on &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; (Precise Pangolin 12.04).
&lt;/p&gt;

&lt;p&gt;
I step through: creating a virtualenv, installing &lt;a href=&quot;http://testutils.org/sst/&quot;&gt;SST&lt;/a&gt; from &lt;a href=&quot;http://pypi.python.org/pypi/sst&quot;&gt;PyPI&lt;/a&gt;, and creating a basic automated web test:
&lt;/p&gt;

&lt;a href=&quot;http://www.youtube.com/watch?v=LpSvGmglZPI&quot;&gt;http://www.youtube.com/watch?v=LpSvGmglZPI&lt;/a&gt;
&lt;br /&gt;

&lt;iframe width=&quot;480&quot; height=&quot;360&quot; src=&quot;http://www.youtube.com/embed/LpSvGmglZPI?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;
the following steps are essentially a transcript of what I did...
&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;
install system package dependencies:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
$ sudo apt-get install python-virtualenv xvfb
&lt;/pre&gt;

&lt;p&gt;
create a &quot;&lt;a href=&quot;http://www.virtualenv.org&quot;&gt;virtualenv&lt;/a&gt;&quot;:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
$ virtualenv ENV
&lt;/pre&gt;

&lt;p&gt;
active the virtualenv:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
$ cd ENV
$ source bin/activate
(ENV)$
&lt;/pre&gt;

&lt;p&gt;
&lt;i&gt;* notice your prompt changed, signifying the virtualenv is active&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
install SST using `&lt;a href=&quot;http://www.pip-installer.org&quot;&gt;pip&lt;/a&gt;`:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
(ENV)$ pip install sst
&lt;/pre&gt;

&lt;p&gt;
Now SST is installed.  You can check the version of SST:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
$ sst-run -V
&lt;/pre&gt;

&lt;hr /&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/3183044741162023684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/3183044741162023684' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3183044741162023684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3183044741162023684'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/03/python-screencast-installsetup-sst-web.html' title='Python Screencast: Install/Setup &quot;SST Web Test Framework&quot; on Ubuntu 12.04'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/LpSvGmglZPI/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-5729428969472644513</id><published>2012-03-08T12:14:00.000-05:00</published><updated>2012-03-08T12:14:52.013-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Codeswarm - Python Core Development Visualization</title><content type='html'>&lt;p&gt;
particle visualization of Python core development commits: Jan 1, 2010 - Mar 06, 2012
&lt;/p&gt;

&lt;a href=&quot;http://www.youtube.com/watch?v=IQPuU_YtN8Q&quot;&gt;http://www.youtube.com/watch?v=IQPuU_YtN8Q&lt;/a&gt;&lt;br /&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/IQPuU_YtN8Q&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;

&lt;p&gt;
data source is the commit log from cpython mercurial trunk:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:6px;&quot;&gt;
$ hg clone http://hg.python.org/cpython
&lt;/pre&gt;

&lt;p&gt;
... trimmed to show development activity since Jan 1, 2010.
&lt;/p&gt;

&lt;p&gt;
(images making up this video were rendered with: &lt;a href=&quot;http://www.michaelogawa.com/code_swarm/&quot;&gt;Codeswarm&lt;/a&gt;)
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/5729428969472644513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/5729428969472644513' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5729428969472644513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/5729428969472644513'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/03/codeswarm-python-core-development.html' title='Codeswarm - Python Core Development Visualization'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/IQPuU_YtN8Q/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-8749377410492757625</id><published>2012-03-05T09:04:00.001-05:00</published><updated>2012-03-05T09:04:10.230-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>SST - Automated Web Page Profiling (Python)</title><content type='html'>&lt;p&gt;
SST - Web Test Framework: &lt;a href=&quot;http://testutils.org/sst&quot;&gt;http://testutils.org/sst&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
The latest release of SST (0.2.0) adds the ability to capture &lt;a href=&quot;http://www.softwareishard.com/blog/har-12-spec/&quot;&gt;HAR (HTTP Archive format)&lt;/a&gt; output for pageload performance tracing/profiling.
&lt;/p&gt;

&lt;p&gt;
New SST doc section: &lt;a href=&quot;http://testutils.org/sst/#performance-tracing-with-browsermob-proxy-har&quot;&gt;Performance tracing with Browsermob Proxy (HAR)&lt;/a&gt;
&lt;/p&gt;
    
&lt;p&gt;
The HAR format is based on JSON, and is used by tools that consume/produce data collected by monitoring HTTP communication.  These files contain a log of HTTP client/server conversation and can be used for additional analysis of page load performance.
&lt;/p&gt;

&lt;p&gt;
The capture is achieved by routing browser requests through &lt;a href=&quot;http://opensource.webmetrics.com/browsermob-proxy/&quot;&gt;BrowserMob Proxy&lt;/a&gt;, which records web page loads while your tests run. SST will launch the proxy and save output to .har files if you enable the `--browsermob` command line option. 
HAR files are saved in the results directory for each page load.
&lt;/p&gt;

&lt;p&gt;
HAR files can be viewed/analyzed with various tools, such as `harviewer`:
  &lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.softwareishard.com/har/viewer/&quot;&gt;http://www.softwareishard.com/har/viewer/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://pcapperf.appspot.com/&quot;&gt;http://pcapperf.appspot.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://code.google.com/p/harviewer/&quot;&gt;http://code.google.com/p/harviewer/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
I created a screencast demo showing it all together:  
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=eJxxP9tZfAo&quot;&gt;Automated Web Page Profiling : SST + BrowserMob&lt;/a&gt;&lt;/b&gt;
&lt;/p&gt;

&lt;iframe width=&quot;420&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/eJxxP9tZfAo&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/8749377410492757625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/8749377410492757625' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/8749377410492757625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/8749377410492757625'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/03/sst-automated-web-page-profiling-python.html' title='SST - Automated Web Page Profiling (Python)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/eJxxP9tZfAo/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-3059175347800814451</id><published>2012-02-26T15:05:00.000-05:00</published><updated>2012-02-27T12:47:52.193-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Canonical"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>SST 0.2.0 Release Announcement (and codebase visualization)</title><content type='html'>&lt;p&gt;
&lt;a href=&quot;http://testutils.org/sst&quot;&gt;SST&lt;/a&gt; (selenium-simple-test) is a web test framework that uses Python to generate functional browser-based tests.
&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;http://testutils.org/sst/_static/sst-logo_small.png&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;80&quot; width=&quot;202&quot; src=&quot;http://testutils.org/sst/_static/sst-logo_small.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;Version 0.2.0 Released!&lt;/h3&gt;

&lt;p&gt;
SST version 0.2.0 is on PyPI: &lt;a href=&quot;http://pypi.python.org/pypi/sst&quot;&gt;http://pypi.python.org/pypi/sst&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
install or upgrade with:
&lt;/p&gt;
&lt;pre style=&quot;font-size:15px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:8px;&quot;&gt;
pip install -U sst
&lt;/pre&gt;

&lt;p&gt;
Changelog: &lt;a href=&quot;http://testutils.org/sst/changelog.html&quot;&gt;http://testutils.org/sst/changelog.html&lt;/a&gt;&lt;br /&gt;
SST Docs: &lt;a href=&quot;http://testutils.org/sst&quot;&gt;http://testutils.org/sst&lt;/a&gt;&lt;br /&gt;
SST on Launchpad: &lt;a href=&quot;https://launchpad.net/selenium-simple-test&quot;&gt;https://launchpad.net/selenium-simple-test&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;

&lt;hr /&gt;

&lt;h3&gt;Development Update&lt;/h3&gt;

&lt;p&gt;
So... what&#39;s up with SST development?  is it active?
&lt;/p&gt;

&lt;p&gt;
I ran &lt;a href=&quot;http://code.google.com/p/gource/&quot;&gt;Gource&lt;/a&gt; against the trunk branch and created an awesome visualization (with soundtrack!) to show off development activity:
&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/5EEicYCRqjY?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;
video: &lt;a href=&quot;http://www.youtube.com/watch?v=5EEicYCRqjY&quot;&gt;link (with soundtrack)&lt;/a&gt;&lt;br /&gt;
video: &lt;a href=&quot;http://www.youtube.com/watch?v=jB9uWpxJg2I&quot;&gt;link (no soundtrack)&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
The magic incantation of `gource` to produce the video:
&lt;/p&gt;

&lt;pre style=&quot;font-size:14px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding:8px;&quot;&gt;
$ gource \
    -s .3 \
    -1280x720 \
    --auto-skip-seconds .3 \
    --multi-sampling \
    --stop-at-end \
    --hide mouse,progress \
    --file-idle-time 0 \
    --max-files 0  \
    --background-colour 222222 \
    --font-size 20 \
    --logo docs/assets/sst-logo_small.png \
    --title &quot;SST Development - lp:selenium-simple-test&quot; \
    --output-ppm-stream - \
    --output-framerate 30 \
    | ffmpeg -y -r 30 -f image2pipe -vcodec ppm -i - -b 2048K movie.mp4
&lt;/pre&gt;

&lt;p&gt;
(rendered on Ubuntu 11.10, audio mixed with Pitivi)
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/3059175347800814451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/3059175347800814451' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3059175347800814451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/3059175347800814451'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/02/sst-020-release-announcement-and.html' title='SST 0.2.0 Release Announcement (and codebase visualization)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/5EEicYCRqjY/default.jpg" height="72" width="72"/><thr:total>2</thr:total><georss:featurename>Boston, MA, USA</georss:featurename><georss:point>42.3584308 -71.0597732</georss:point><georss:box>42.2645643 -71.217701699999992 42.4522973 -70.9018447</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-8891938644331440152</id><published>2012-01-29T15:38:00.000-05:00</published><updated>2012-01-29T15:38:01.216-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python - Matplotlib and Numpy on Debian/Ubuntu</title><content type='html'>&lt;p&gt;
There are `&lt;strong&gt;python-matplotlib&lt;/strong&gt;` and `&lt;strong&gt;python-numpy&lt;/strong&gt;` packages in the Debian/Ubuntu repos.
&lt;/p&gt;

&lt;p&gt;
However, if you want to run in a virtualenv (with no-site-packages), and pip install these packages from PyPI, you need some system dependencies installed first to build with:
&lt;/p&gt;

&lt;pre style=&quot;font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;&quot;&gt;
$ sudo apt-get install build-essential python-dev libfreetype6-dev libpng-dev python-virtualenv
&lt;/pre&gt;

&lt;p&gt;
Then, you can create a virtualenv, and the installers for Numpy and Matplotlib will work:
&lt;/p&gt;

&lt;pre style=&quot;font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;&quot;&gt;
$ virtualenv env
$ cd env
$ source bin/activate
(env)$ pip install numpy matplotlib

...
...
Successfully installed numpy matplotlib
Cleaning up...
&lt;/pre&gt;

&lt;p&gt;
(tested on Ubuntu Oneiric 11.10 and Ubuntu Precise 12.04 alpha)
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/8891938644331440152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/8891938644331440152' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/8891938644331440152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/8891938644331440152'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/01/python-matplotlib-and-numpy-on.html' title='Python - Matplotlib and Numpy on Debian/Ubuntu'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-7385818577698113821</id><published>2012-01-01T18:55:00.000-05:00</published><updated>2012-01-03T09:52:24.836-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Canonical"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Officially Introducing &quot;SST&quot; (Python Web Test Framework)</title><content type='html'>&lt;p&gt;&lt;strong&gt;&quot;SST (selenium-simple-test) is a framework built on Selenium WebDriver, using Python to make writing functional web tests easier with code.&quot;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
Since early 2011, I have been working for &lt;a href=&quot;http://www.canonical.com/&quot;&gt;Canonical&lt;/a&gt; on the &lt;a href=&quot;https://launchpad.net/~canonical-isd-team/+mugshots&quot;&gt;Infrastructure Systems Development team&lt;/a&gt; (Core Dev Ops).
&lt;/p&gt;

&lt;p&gt;
[&lt;a href=&quot;http://dl.dropbox.com/u/216762/Canonical_ISD_hackers_UDS-P_11-03-2011.jpg&quot;&gt;pic of canonical-isd-hackers at UDS-P-Orlando&lt;/a&gt;]
&lt;/p&gt;

&lt;p&gt;
A by-product of our recent development efforts is a web testing framework.  It has been available on &lt;a href=&quot;https://launchpad.net/selenium-simple-test&quot;&gt;Launchpad&lt;/a&gt; for a while, but I&#39;ve never really announced it in public.  We are using SST internally, and I want to expose it to a wider audience.
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Selenium WebDriver?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Selenium (WebDriver) is a popular open-source library for automating browsers.  It can be used to create functional/acceptance tests of a web application.  The Selenium client bindings provide API&#39;s that allow you to programatically drive a browser and access web content/elements.  The bindings are available and supported for many languages and platforms.&lt;/p&gt;

&lt;p&gt;While working directly with Selenium API&#39;s from code is fine for ad-hoc browser interaction, it is rather low-level and lacks things necessary for creating suites of automated web tests.  For larger-scale testing, you will soon want to use a framework to help organize, execute, and report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introducing SST...&lt;/strong&gt;&lt;/p&gt;

&lt;img src=&quot;http://testutils.org/sst/_static/sst-logo_small.png&quot; alt=&quot;SST Logo&quot;&gt;&lt;/img&gt;

&lt;p&gt;SST aims to keep things simple.&lt;/p&gt;

&lt;p&gt;Tests are made up of scripts, created by composing actions that drive a browser and assert conditions. You have the flexibility of the full Python language, along with a convenient set of functions to simplify web testing.&lt;/p&gt;

&lt;p&gt;SST framework consists of:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;user actions and assertions (API) in Python&lt;/li&gt;
    &lt;li&gt;test case loader (generates/compiles scripts to unittest cases)&lt;/li&gt;
    &lt;li&gt;console test runner&lt;/li&gt;
    &lt;li&gt;data parameterization/injection&lt;/li&gt;
    &lt;li&gt;selectable output reports&lt;/li&gt;
    &lt;li&gt;selectable browsers&lt;/li&gt;
    &lt;li&gt;headless (xvfb) mode&lt;/li&gt;
    &lt;li&gt;screenshots on errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Test output can be displayed to the console, saved as an HTML report, or JUnit-compatible XML for compatibility with CI systems.&lt;/p&gt;

&lt;p&gt;SST is free open source software (Apache Licensed).  SST is primarily being developed on Linux, specifically Ubuntu. It should work fine on other platforms, but any issues (or even better - patches) should be reported on the Launchpad project:&lt;/p&gt;
 
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://launchpad.net/selenium-simple-test&quot;&gt;https://launchpad.net/selenium-simple-test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I just uploaded SST 0.1.0 to PyPI:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://pypi.python.org/pypi/sst&quot;&gt;http://pypi.python.org/pypi/sst&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;go ahead, give it a try:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;`$ [sudo] pip install sst`&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;documentation and more info:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://testutils.org/sst&quot;&gt;http://testutils.org/sst&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;a sample test script in SST:&lt;/p&gt;

&lt;pre style=&quot;font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;&quot;&gt;
from sst.actions import *

go_to(&#39;http://www.ubuntu.com/&#39;)
assert_title_contains(&#39;Ubuntu homepage&#39;)
&lt;/pre&gt;

&lt;p&gt;Here is the development progress of SST (shown as a code_swarm visualization) over the past 8 months:&lt;p&gt;

&lt;p&gt;&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/PR8Wf05z9CU&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;

&lt;p&gt;Special thanks to all the SST code committers so far:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Danny Tamez&lt;/li&gt;
    &lt;li&gt;Julien Funk&lt;/li&gt;
    &lt;li&gt;Kenneth Koontz&lt;/li&gt;
    &lt;li&gt;Leo Arias&lt;/li&gt;
    &lt;li&gt;Lukasz Czyzykowkski&lt;/li&gt;
    &lt;li&gt;Rick McBride&lt;/li&gt;
    &lt;li&gt;Sidnei da Silva&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extra special thanks to SST&#39;s initial creator:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Michael Foord&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy New Year!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-Corey Goldberg&lt;/strong&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/7385818577698113821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/7385818577698113821' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/7385818577698113821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/7385818577698113821'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2012/01/officially-introducing-sst-python-web.html' title='Officially Introducing &quot;SST&quot; (Python Web Test Framework)'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/PR8Wf05z9CU/default.jpg" height="72" width="72"/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5236867476487043111.post-1694448256836382037</id><published>2011-12-12T09:22:00.001-05:00</published><updated>2011-12-21T11:46:12.429-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>&quot;Web Performance Testing night&quot; in Boston/Cambridge - Python Meetup Dec. 19</title><content type='html'>&lt;p&gt;
I will be speaking at: &lt;strong&gt;&quot;Web Performance Testing, lightning talks, and beers&quot;&lt;/strong&gt; at the &lt;a href=&quot;http://meetup.bostonpython.com&quot;&gt;Boston Python User Group&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;Event Info:&lt;/strong&gt; &lt;a href=&quot;http://meetup.bostonpython.com/events/36664122/&quot;&gt;http://meetup.bostonpython.com/events/36664122/&lt;/a&gt; &lt;br /&gt;
&lt;strong&gt;Date:&lt;/strong&gt; Monday, December 19, 2011, 7:00 PM &lt;br /&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Microsoft NERD, Cambridge, MA &lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;blockquote&gt;&lt;em&gt;&quot;Corey Goldberg of Canonical and Dan Kuebrich of Tracelytics will tag-team to 
tell us about web performance testing, and a few interesting tools they&#39;ve built.&quot;&lt;/em&gt;&lt;/blockquote&gt;
&lt;/p&gt;

&lt;p&gt;
Free pizza and beer! &lt;br /&gt;
Come Join!
&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKzruaFHH6Z1SVkcu_TMRoYrQLjCwICUK4_prhp1EZObJsqr93rPZJ9xflZsAJEl20II7q8o2BNqB1YifUJjEgmQTnmIkZmpS6ykfD9lNjj-HXoVDWhp0TqEGtH3bXjctc5Gjwgk030HE/s1600/python-icon.jpg&quot; imageanchor=&quot;1&quot; style=&quot;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;228&quot; width=&quot;230&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKzruaFHH6Z1SVkcu_TMRoYrQLjCwICUK4_prhp1EZObJsqr93rPZJ9xflZsAJEl20II7q8o2BNqB1YifUJjEgmQTnmIkZmpS6ykfD9lNjj-HXoVDWhp0TqEGtH3bXjctc5Gjwgk030HE/s400/python-icon.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;
Edit/Update:&lt;br /&gt;
Thanks to all who attended!  The night was a big success.&lt;br /&gt;
&lt;br /&gt;
The slides from my portion of the presentation are posted here:&lt;br /&gt;
&lt;a href=&quot;http://goldb.org/talks/2011/boston-python_webperf/webperf.html&quot;&gt;webperf.html&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://coreygoldberg.blogspot.com/feeds/1694448256836382037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/5236867476487043111/1694448256836382037' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1694448256836382037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5236867476487043111/posts/default/1694448256836382037'/><link rel='alternate' type='text/html' href='http://coreygoldberg.blogspot.com/2011/12/web-performance-testing-night-in.html' title='&quot;Web Performance Testing night&quot; in Boston/Cambridge - Python Meetup Dec. 19'/><author><name>Corey Goldberg</name><uri>http://www.blogger.com/profile/06219872951977664560</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKzruaFHH6Z1SVkcu_TMRoYrQLjCwICUK4_prhp1EZObJsqr93rPZJ9xflZsAJEl20II7q8o2BNqB1YifUJjEgmQTnmIkZmpS6ykfD9lNjj-HXoVDWhp0TqEGtH3bXjctc5Gjwgk030HE/s72-c/python-icon.jpg" height="72" width="72"/><thr:total>6</thr:total></entry></feed>