<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xml:lang="en"><title type="text">Corey Goldberg</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/goldblog" /><subtitle type="html">Blog - Technology, Software, Programming, Performance</subtitle><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2012-02-09T13:26:18+00:00</updated><generator uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">141</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="goldblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><id>tag:blogger.com,1999:blog-5236867476487043111</id><geo:lat>42.349622</geo:lat><geo:long>-71.073722</geo:long><entry><title type="text">Python - Matplotlib and Numpy on Debian/Ubuntu</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2012/01/python-matplotlib-and-numpy-on.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2012-01-29T12:38:01-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-8891938644331440152</id><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="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&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="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&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;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-8891938644331440152?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-29T15:38:01.216-05:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry><title type="text">Officially Introducing "SST" (Python Web Test Framework)</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2012/01/officially-introducing-sst-python-web.html" /><category term="python" /><category term="Canonical" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2012-01-03T06:52:24-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-7385818577698113821</id><content type="html">&lt;p&gt;&lt;strong&gt;"SST (selenium-simple-test) is a framework built on Selenium WebDriver, using Python to make writing functional web tests easier with code."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
Since early 2011, I have been working for &lt;a href="http://www.canonical.com/"&gt;Canonical&lt;/a&gt; on the &lt;a href="https://launchpad.net/~canonical-isd-team/+mugshots"&gt;Infrastructure Systems Development team&lt;/a&gt; (Core Dev Ops).
&lt;/p&gt;

&lt;p&gt;
[&lt;a href="http://dl.dropbox.com/u/216762/Canonical_ISD_hackers_UDS-P_11-03-2011.jpg"&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="https://launchpad.net/selenium-simple-test"&gt;Launchpad&lt;/a&gt; for a while, but I'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'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'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="http://testutils.org/sst/_static/sst-logo_small.png" alt="SST Logo"&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="https://launchpad.net/selenium-simple-test"&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="http://pypi.python.org/pypi/sst"&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="http://testutils.org/sst"&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="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
from sst.actions import *

go_to('http://www.ubuntu.com/')
assert_title_contains('Ubuntu homepage')
&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="560" height="315" src="http://www.youtube.com/embed/PR8Wf05z9CU" frameborder="0" 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'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;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-7385818577698113821?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-03T09:52:24.836-05:00</app:edited><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/PR8Wf05z9CU/default.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry><title type="text">"Web Performance Testing night" in Boston/Cambridge - Python Meetup Dec. 19</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/12/web-performance-testing-night-in.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-12-21T08:46:12-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-1694448256836382037</id><content type="html">&lt;p&gt;
I will be speaking at: &lt;strong&gt;"Web Performance Testing, lightning talks, and beers"&lt;/strong&gt; at the &lt;a href="http://meetup.bostonpython.com"&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="http://meetup.bostonpython.com/events/36664122/"&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;"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've built."&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="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-s_87-XNniM4/TuYM2QM3puI/AAAAAAAACXQ/hwQO1DoxAQ8/s1600/python-icon.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="228" width="230" src="http://1.bp.blogspot.com/-s_87-XNniM4/TuYM2QM3puI/AAAAAAAACXQ/hwQO1DoxAQ8/s400/python-icon.jpg" /&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="http://goldb.org/talks/2011/boston-python_webperf/webperf.html"&gt;webperf.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-1694448256836382037?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-21T11:46:12.429-05:00</app:edited><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-s_87-XNniM4/TuYM2QM3puI/AAAAAAAACXQ/hwQO1DoxAQ8/s72-c/python-icon.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total></entry><entry><title type="text">Python - Stock Quotes From Google Finance</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/09/python-stock-quotes-from-google-finance.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-09-27T05:46:17-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-2408922334076933866</id><content type="html">&lt;p&gt;Quick example of retrieving stock quotes from Google Finance in Python:&lt;/p&gt;&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;#!/usr/bin/env python

import json
import pprint
import urllib2


def get_stock_quote(ticker_symbol):   
    url = 'http://finance.google.com/finance/info?q=%s' % ticker_symbol
    lines = urllib2.urlopen(url).read().splitlines()
    return json.loads(''.join([x for x in lines if x not in ('// [', ']')]))


if __name__ == '__main__':
    quote = get_stock_quote('IBM')
    print 'ticker: %s' % quote['t']
    print 'current price: %s' % quote['l_cur']
    print 'last trade: %s' % quote['lt']
    print 'full quote:'
    pprint.pprint(quote)
&lt;/pre&gt;&lt;p&gt;* note: all values in the returned dict object are Unicode strings.&lt;/p&gt;&lt;p&gt;Output:&lt;/p&gt;&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;ticker: IBM
current price: 174.51
last trade: Sep 26, 4:00PM EDT
full quote:
{u'c': u'+5.17',
 u'ccol': u'chg',
 u'cp': u'3.05',
 u'div': u'0.75',
 u'e': u'NYSE',
 u'ec': u'0.00',
 u'eccol': u'chb',
 u'ecp': u'0.00',
 u'el': u'174.51',
 u'el_cur': u'174.51',
 u'elt': u'Sep 26, 6:07PM EDT',
 u'id': u'18241',
 u'l': u'174.51',
 u'l_cur': u'174.51',
 u'lt': u'Sep 26, 4:00PM EDT',
 u'ltt': u'4:00PM EDT',
 u's': u'2',
 u't': u'IBM',
 u'yld': u'1.72'}
 &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-2408922334076933866?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-27T08:46:17.386-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Open Source Code Visualization With code_swarm (Canonical, Selenium, Couchbase)</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/08/open-source-code-visualization-with.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-08-29T16:42:46-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-5540980224027634910</id><content type="html">After a bit of hacking, I got &lt;a href="http://code.google.com/p/codeswarm/"&gt;code_swarm&lt;/a&gt; visualizations running on my Ubuntu 11.04 box.

I'm capturing some pretty cool videos from source repos in git, bzr, and svn.

Here are some of the more interesting code-base visualization videos I've made:
&lt;br /&gt;

&lt;h5&gt;Canonical:&lt;/h5&gt;
 * &lt;a href="http://www.youtube.com/watch?v=OjoghtALSeE"&gt;Unity (2009-10-15 - 2011-08-28) [1 min 58 secs]&lt;/a&gt;
&lt;br /&gt;
 * &lt;a href="http://www.youtube.com/watch?v=9Pe70fw83Zs"&gt;Launchpad (2004-06-22 - 2011-08-28) [7 mins 22 secs]&lt;/a&gt;

&lt;br /&gt;

&lt;h5&gt;Selenium WebDriver:&lt;/h5&gt;
 * &lt;a href="http://www.youtube.com/watch?v=OFTpOO1cxEw"&gt;Selenium trunk (2009-11-22 - 2011-08-29) [1 min 52 secs]&lt;/a&gt;

&lt;h5&gt;Couchbase:&lt;/h5&gt;
 * &lt;a href="http://www.youtube.com/watch?v=3VAOA3PB4mM"&gt;membase ns_server (2011, Aug 27) [1 min 45 secs]&lt;/a&gt;

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-5540980224027634910?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-29T19:42:46.907-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Python - Getting Started With Selenium WebDriver on Ubuntu/Debian</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/07/python-getting-started-with-selenium.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-11T09:48:33-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-8268137651028115633</id><content type="html">&lt;p&gt;
This is a quick introduction to &lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; &lt;a href="http://www.aosabook.org/en/selenium.html"&gt;WebDriver&lt;/a&gt; in Python on Ubuntu/Debian systems.
&lt;/p&gt;

&lt;p&gt;
WebDriver (part of Selenium 2) is a library for automating browsers, and can be used from a variety of language bindings.  It allows you to programmatically drive a browser and interact with web elements.  It is most often used for test automation, but can be adapted to a variety of web scraping or automation tasks.
&lt;/p&gt;

&lt;p&gt;
To use the WebDriver API in Python, you must first install the Selenium Python bindings.  This will give you access to your browser from Python code.  The easiest way to install the bindings is via &lt;a href="http://www.pip-installer.org/"&gt;pip&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
On Ubuntu/Debian systems, this will install pip (and dependencies) and then install the Selenium Python bindings from &lt;a href="http://pypi.python.org/pypi/selenium"&gt;PyPI&lt;/a&gt;:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
$ sudo apt-get install python-pip
$ sudo pip install selenium

&lt;/pre&gt;

&lt;p&gt;
After the installation, the following code should work:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/env python

from selenium import webdriver

browser = webdriver.Firefox()
browser.get('http://www.ubuntu.com/')

&lt;/pre&gt;

&lt;p&gt;
This should open a Firefox browser sessions and navigate to http://www.ubuntu.com/
&lt;/p&gt;

&lt;p&gt;
Here is a simple functional test in Python, using Selenium WebDriver and the &lt;a href="http://docs.python.org/library/unittest.html"&gt;unittest&lt;/a&gt; framework:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/env python

import unittest
from selenium import webdriver


class TestUbuntuHomepage(unittest.TestCase):
    
    def setUp(self):
        self.browser = webdriver.Firefox()
        
    def testTitle(self):
        self.browser.get('http://www.ubuntu.com/')
        self.assertIn('Ubuntu', self.browser.title)
        
    def tearDown(self):
        self.browser.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)

&lt;/pre&gt;    


&lt;p&gt;Output:&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
testTitle (__main__.TestUbuntuHomepage) ... ok

----------------------------------------------------------------------
Ran 1 test in 5.931s

OK

&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-8268137651028115633?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-11T12:48:33.804-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><title type="text">Python - Reading MP3 Meta Information with 'mpeg1audio'</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/07/python-reading-mp3-meta-information.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-09T10:25:26-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-1725099691722768667</id><content type="html">&lt;p&gt;
'&lt;a href="https://github.com/Ciantic/mpeg1audio/"&gt;mpeg1audio&lt;/a&gt;' is a Pure Python MPEG Audio Layer 1, 2 and 3 meta information retrieval package.  It is capable of retrieving duration, bitrate, average bitrate, sample count, etc.
&lt;/p&gt;

&lt;p&gt;
Here is an example of using mpeg1audio for getting meta data from a directory of MP3 files.
&lt;/p&gt;

Code:

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/env python

import glob
import mpeg1audio  # (https://github.com/Ciantic/mpeg1audio/)

for f in sorted(glob.glob('*.mp3')):
    mp3 = mpeg1audio.MPEGAudio(f)
    mb = '%.2f' % (mp3.size / 1048576.0)
    fn = f.replace('.mp3', '')
    print '%s (%s) [%dk] %s MB' % (fn, mp3.duration, mp3.bitrate, mb)

&lt;/pre&gt;    

Output:

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
Eminem - Buffalo Bill (0:03:56) [253k] 7.15 MB
Minor Threat - Betray (0:03:02) [180k] 3.92 MB
Social Distortion - Bakersfield (0:06:24) [320k] 14.68 MB
Social Distortion - Diamond In The Rough (0:04:34) [320k] 10.49 MB
Social Distortion - Prison Bound (0:05:24) [227k] 8.81 MB
Social Distortion - When She Begins (0:05:02) [320k] 11.54 MB

&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-1725099691722768667?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-09T13:25:26.551-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><title type="text">Python - processing GMail IMAP email</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/07/python-processing-gmail-imap-email.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-07T14:34:40-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-6264901944732774336</id><content type="html">&lt;p&gt;
Here is an example of processing your GMail IMAP email in Python.
&lt;/p&gt;

&lt;p&gt;
The script below will:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;login to GMail account using IMAP&lt;/li&gt;
    &lt;li&gt;open your Inbox&lt;/li&gt;
    &lt;li&gt;retrieve and print all messages&lt;/li&gt;
    &lt;li&gt;close mailbox&lt;/li&gt;
    &lt;li&gt;logout&lt;/li&gt;
&lt;/ul&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
#!/usr/bin/env python

import imaplib

USER = 'username@gmail.com'
PASSWORD = 'xxx'

mail = imaplib.IMAP4_SSL('imap.gmail.com', 993)
mail.login(USER, PASSWORD)
mail.select('Inbox')

status, data = mail.search(None, 'ALL')
for num in data[0].split():
    status, data = mail.fetch(num, '(RFC822)')
    print 'Message %s\n%s\n' % (num, data[0][1])
   
mail.close()
mail.logout()
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-6264901944732774336?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-07T17:34:40.087-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Joined Google+</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/07/i-have-account-on-google-go-ahead-and.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-05T09:39:36-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-5284231087502535427</id><content type="html">&lt;p&gt;
I have an account on &lt;a href="https://plus.google.com/u/0/114546378907380458640"&gt;Google+&lt;/a&gt;&lt;br /&gt;
Go ahead and add me if you know me  :)
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://gplus.to/cgoldberg"&gt;http://gplus.to/cgoldberg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://plus.google.com/u/0/114546378907380458640"&gt;https://plus.google.com/u/0/114546378907380458640&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-fYOzuj0w_IQ/ThM25GGC1ZI/AAAAAAAAA1A/aKYrKUSGF_k/s1600/CoreyGoldberg_GooglePlus_screenshot.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 314px;" src="http://4.bp.blogspot.com/-fYOzuj0w_IQ/ThM25GGC1ZI/AAAAAAAAA1A/aKYrKUSGF_k/s400/CoreyGoldberg_GooglePlus_screenshot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5625900714032289170" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-5284231087502535427?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-05T12:39:36.103-04:00</app:edited><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-fYOzuj0w_IQ/ThM25GGC1ZI/AAAAAAAAA1A/aKYrKUSGF_k/s72-c/CoreyGoldberg_GooglePlus_screenshot.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Python - Taking Browser Screenshots With No Display (Selenium/Xvfb)</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/07/python-taking-browser-screenshots-with.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-04T10:41:18-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-4263810995486916552</id><content type="html">&lt;p&gt;
In my last two blog posts, I showed examples of using Selenium WebDriver to &lt;a href="http://coreygoldberg.blogspot.com/2011/06/python-selenium-webdriver-capture.html"&gt;capture screenshots&lt;/a&gt;, and &lt;a href="http://coreygoldberg.blogspot.com/2011/06/python-headless-selenium-webdriver.html"&gt;running in a headless (no X-server) mode&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
This example combines the two solutions to capture screenshots inside a virtual display.
&lt;/p&gt;

&lt;p&gt;
To achieve this, I use a combination of Selenium WebDriver and pyvirtualdisplay (which uses xvfb) to run a browser in a virtual display and capture screenshots.
&lt;/p&gt;

&lt;p&gt;
the setup you need is:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Selenium 2 Python bindings:  &lt;a href="http://pypi.python.org/pypi/selenium"&gt;PyPI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;pyvirtualdisplay Python package (depends on &lt;a href="http://en.wikipedia.org/wiki/Xvfb"&gt;xvfb&lt;/a&gt;):  &lt;a href="http://pypi.python.org/pypi/PyVirtualDisplay"&gt;PyPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
On Debian/Ubuntu Linux systems, you can install everything with:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
$ sudo apt-get install python-pip xvfb xserver-xephyr
$ sudo pip install selenium
&lt;/pre&gt;

&lt;p&gt;
once you have it setup, the following code example should work:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
#!/usr/bin/env python

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=0, size=(800, 600))
display.start()

browser = webdriver.Firefox()
browser.get('http://www.google.com')
browser.save_screenshot('screenie.png')
browser.quit()

display.stop()
&lt;/pre&gt;

&lt;p&gt;
this will:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;launch a virtual display&lt;/li&gt;
  &lt;li&gt;launch Firefox browser inside the virtual display&lt;/li&gt;
  &lt;li&gt;navigate to google.com&lt;/li&gt;
  &lt;li&gt;capture and save a screenshot&lt;/li&gt;
  &lt;li&gt;close the browser&lt;/li&gt;
  &lt;li&gt;stop the virtual display&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-4263810995486916552?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-04T13:41:18.733-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry><title type="text">Python - Headless Selenium WebDriver Tests using PyVirtualDisplay</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/06/python-headless-selenium-webdriver.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2012-01-02T07:25:19-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-1095251415954187012</id><content type="html">&lt;p&gt;
I need to integrate my functional UI tests (Selenium/WebDriver) with my Jenkins CI system.  The problem is that my Jenkins CI server has no display, so I must run my GUI tests in a headless X-server.
&lt;/p&gt;

&lt;p&gt;
A colleague pointed me to &lt;a href="http://pypi.python.org/pypi/PyVirtualDisplay"&gt;PyVirtualDisplay&lt;/a&gt;, a Python wrapper for &lt;a href="http://en.wikipedia.org/wiki/Xvfb"&gt;Xvfb&lt;/a&gt; and Xephyr.
&lt;/p&gt;

&lt;p&gt;
This makes running headless Python Selenium/WebDriver tests very easy.
&lt;/p&gt;

&lt;p&gt;
Here is some Python code showing WebDriver with a virtual display provided by Xvfb:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;    
#!/usr/bin/env python

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=0, size=(800, 600))
display.start()

# now Firefox will run in a virtual display. 
# you will not see the browser.
browser = webdriver.Firefox()
browser.get('http://www.google.com')
print browser.title
browser.quit()

display.stop()
&lt;/pre&gt;

&lt;p&gt;
install PyVirtualDisplay on Ubuntu/Debian:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
$ sudo apt-get install xvfb python-pip
$ sudo pip install pyvirtualdisplay
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-1095251415954187012?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-02T10:25:19.176-05:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total></entry><entry><title type="text">Python - Selenium WebDriver - Capture Screenshot</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/06/python-selenium-webdriver-capture.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-07-12T08:30:48-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-354942069393498892</id><content type="html">&lt;p&gt;
Example of capturing a screenshot from Selenium WebDriver in Python:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/env python
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('http://www.ubuntu.com/')
browser.save_screenshot('screenie.png')
browser.quit()
&lt;/pre&gt;

&lt;p&gt;
&lt;a href="http://code.google.com/p/selenium/"&gt;selenium/webdriver&lt;/a&gt; bindings for Python:  &lt;a href="http://pypi.python.org/pypi/selenium"&gt;http://pypi.python.org/pypi/selenium&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-354942069393498892?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-12T11:30:48.525-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Ubuntu Developer Summit, Oneiric Ocelot</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/05/ubuntu-developer-summit-oneiric-ocelot.html" /><category term="Canonical" /><category term="UDS" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-05-15T07:55:59-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-7362078094589433261</id><content type="html">&lt;p&gt;
I just got back from &lt;a href="http://summit.ubuntu.com/uds-o/"&gt;UDS-O&lt;/a&gt; (Ubuntu Developer Summit, Oneiric Ocelot) in Budapest, Hungary. It was my first UDS, and my first time in Eastern Europe.
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-3RTZWdrJFtY/Tc_lLFzOEKI/AAAAAAAAAwc/FZL_rib0VWs/s1600/IMG_2425.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-3RTZWdrJFtY/Tc_lLFzOEKI/AAAAAAAAAwc/FZL_rib0VWs/s400/IMG_2425.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606952039797887138" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-VyElyMS-fa4/Tc_lLR-pvWI/AAAAAAAAAwk/TS2MftuSUIQ/s1600/IMG_2468.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-VyElyMS-fa4/Tc_lLR-pvWI/AAAAAAAAAwk/TS2MftuSUIQ/s400/IMG_2468.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606952043067063650" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-E_OQ6CxJHZg/Tc_lLfFqRhI/AAAAAAAAAws/836Oe1GPFcE/s1600/IMG_2434.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://1.bp.blogspot.com/-E_OQ6CxJHZg/Tc_lLfFqRhI/AAAAAAAAAws/836Oe1GPFcE/s400/IMG_2434.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606952046586119698" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-OSzkX8RVi6k/Tc_lLmd_LII/AAAAAAAAAw0/FVqjb2fER6Y/s1600/IMG_2480.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-OSzkX8RVi6k/Tc_lLmd_LII/AAAAAAAAAw0/FVqjb2fER6Y/s400/IMG_2480.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606952048567200898" /&gt;&lt;/a&gt;

&lt;p&gt;
I was really worried that the time-change and jet-lag going to eastern Europe would mess me up.  However, I felt really good the entire trip and adjusted almost instantly.  My mood was good and I was ready to hack.
&lt;/p&gt;

&lt;p&gt;
Some quick comments about the summit:
&lt;ul&gt;
&lt;li&gt;Budapest was fun and interesting, with beautiful weather and historic architecture.&lt;/li&gt;
&lt;li&gt;The Ubuntu summit is a very well run event, where important decisions are made and work gets done.&lt;/li&gt;
&lt;li&gt;Our Community rocks!&lt;/li&gt;
&lt;li&gt;Ubuntu rocks!&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
I was able to attend a few UDS sessions throughout the week, but my main mission was an on-site sprint with my team at Canonical (ISD).  Our team is globally-distributed, and this was my first chance to meet and work with all of them in person.  While the entire summit was awesome, my most lasting memories will be of sitting crammed in a hot hotel room with a dozen of the finest hackers/colleagues I have ever worked with.  As a new member to ISD, they made me feel welcomed and let me jump right in.
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-mRcATH9ilHQ/Tc_nhRn903I/AAAAAAAAAxE/mohLRn9tt4c/s1600/1_IMG_2441.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-mRcATH9ilHQ/Tc_nhRn903I/AAAAAAAAAxE/mohLRn9tt4c/s400/1_IMG_2441.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606954619952288626" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-o-IW7kP3XY4/Tc_nhpl-YfI/AAAAAAAAAxM/ZHDQWnZrtF8/s1600/team_IMG_2511.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-o-IW7kP3XY4/Tc_nhpl-YfI/AAAAAAAAAxM/ZHDQWnZrtF8/s400/team_IMG_2511.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606954626386387442" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-VVXYA87NBh8/Tc_nh315jlI/AAAAAAAAAxc/Ibis-rAFfqs/s1600/IMG_2430.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-VVXYA87NBh8/Tc_nh315jlI/AAAAAAAAAxc/Ibis-rAFfqs/s400/IMG_2430.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606954630211276370" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-nHsv5kAs3F0/Tc_nhzTJWrI/AAAAAAAAAxU/7an6akIsXTg/s1600/IMG_2427.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/-nHsv5kAs3F0/Tc_nhzTJWrI/AAAAAAAAAxU/7an6akIsXTg/s400/IMG_2427.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606954628991769266" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-Dbb6UbYqO8Y/Tc_niZEEH6I/AAAAAAAAAxk/Ul30IPCxLAc/s1600/IMG_2431.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-Dbb6UbYqO8Y/Tc_niZEEH6I/AAAAAAAAAxk/Ul30IPCxLAc/s400/IMG_2431.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606954639129059234" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-8-9yzcb8Xmw/Tc_n5ULxDcI/AAAAAAAAAyE/If52FwpOLMg/s1600/IMG_2515.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-8-9yzcb8Xmw/Tc_n5ULxDcI/AAAAAAAAAyE/If52FwpOLMg/s400/IMG_2515.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606955032956177858" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-JgR6GcRVkaI/Tc_n5BGpPHI/AAAAAAAAAx8/VLrO_etK0CI/s1600/IMG_2445.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/-JgR6GcRVkaI/Tc_n5BGpPHI/AAAAAAAAAx8/VLrO_etK0CI/s400/IMG_2445.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606955027834420338" /&gt;&lt;/a&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-Pmcw78e9V1o/Tc_n5PSKcEI/AAAAAAAAAx0/I3LgzIU3lgQ/s1600/IMG_2442.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-Pmcw78e9V1o/Tc_n5PSKcEI/AAAAAAAAAx0/I3LgzIU3lgQ/s400/IMG_2442.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606955031640830018" /&gt;&lt;/a&gt;

&lt;p&gt;
Can't wait until next UDS!
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-s6iLhYciLwI/Tc_mWUt9FPI/AAAAAAAAAw8/PZJXfZ0KQJk/s1600/corey_IMG_2447.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/-s6iLhYciLwI/Tc_mWUt9FPI/AAAAAAAAAw8/PZJXfZ0KQJk/s400/corey_IMG_2447.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5606953332292523250" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-7362078094589433261?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-15T10:55:59.954-04:00</app:edited><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-3RTZWdrJFtY/Tc_lLFzOEKI/AAAAAAAAAwc/FZL_rib0VWs/s72-c/IMG_2425.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Performance and Scalability Testing with Python and Multi-Mechanize</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/03/performance-and-scalability-testing.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-03-31T06:28:03-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-1063019783382648412</id><content type="html">&lt;p&gt;
I put together a slide-deck to help introduce &lt;a href="http://multimechanize.com"&gt;Multi-Mechanize&lt;/a&gt;.  I wanted something a little friendlier and easier to digest than "go read the project wiki".  (It is also the basis of a presentation/talk I might give someday).
&lt;/p&gt;

&lt;p&gt;
Hopefully, this will help people better understand what the project is all about. 
&lt;/p&gt;

&lt;div style="width:425px" id="__ss_7454050"&gt; &lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/coreygoldberg/performance-and-scalability-testing-with-python-and-multimechanize" title="Performance and Scalability Testing with Python and Multi-Mechanize"&gt;Performance and Scalability Testing with Python and Multi-Mechanize&lt;/a&gt;&lt;/strong&gt; &lt;object id="__sse7454050" width="425" height="355"&gt; &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=perfscalepythonmulti-mechanize-110330174840-phpapp02&amp;stripped_title=performance-and-scalability-testing-with-python-and-multimechanize&amp;userName=coreygoldberg" /&gt; &lt;param name="allowFullScreen" value="true"/&gt; &lt;param name="allowScriptAccess" value="always"/&gt; &lt;embed name="__sse7454050" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=perfscalepythonmulti-mechanize-110330174840-phpapp02&amp;stripped_title=performance-and-scalability-testing-with-python-and-multimechanize&amp;userName=coreygoldberg" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-1063019783382648412?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-31T09:28:03.845-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">linux-metrics - Python Package - System Metrics/Stats for Linux</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/03/linux-metrics-python-package-system.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-03-22T06:20:24-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-8128781021584333480</id><content type="html">&lt;p&gt;
I just released my Python package: 'linux-metrics'
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://linux-metrics.googlecode.com"&gt;linux-metrics&lt;/a&gt; contains Python modules for getting OS metrics on systems running the Linux (2.6) kernel.  It is a pure python library with no external dependencies.
&lt;/p&gt;

&lt;p&gt;
This project is under development, and nowhere near comprehensive. Only basic stats for major subsystems are provided (Processor/CPU, Disk, Memory, Network). Hopefully, more are coming.
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Home: &lt;a href="http://linux-metrics.googlecode.com"&gt;http://linux-metrics.googlecode.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PyPI Entry: &lt;a href="http://pypi.python.org/pypi/linux-metrics"&gt;http://pypi.python.org/pypi/linux-metrics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-8128781021584333480?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-22T09:20:24.854-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Going to PyCon 2011!</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2011/01/going-to-pycon-2011.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2011-01-25T14:04:40-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-3975465223553773895</id><content type="html">&lt;p&gt;

This year I am attending my first &lt;b&gt;PyCon&lt;/b&gt; (the annual Python community conference).

&lt;/p&gt;




&lt;p&gt;

I will be in Atlanta: &lt;b&gt;March 10-13&lt;/b&gt;.

&lt;/p&gt;



&lt;p&gt;

If anyone is interested in meeting up or collaborating while I'm there, get in touch:

&lt;/p&gt;



&lt;ul&gt;

    &lt;li&gt;Twitter: &lt;a href="http://www.twitter.com/cgoldberg"&gt;@cgoldberg&lt;/a&gt;&lt;/li&gt;

    &lt;li&gt;Homepage/Info: &lt;a href="http://goldb.org"&gt;goldb.org&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;


&lt;a href="http://us.pycon.org"&gt;

    &lt;img alt="PyCon 2011, Atlanta, March 9-17" src="http://us.pycon.org/2011/site_media/static/img/badges/pycon-badge-400x120.png" /&gt;

&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-3975465223553773895?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-25T17:04:40.403-05:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry><title type="text">Python - Search a Local or Remote Splunk Server</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/12/python-search-local-or-remote-splunk.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-12-01T06:40:24-08:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-2880954091958444162</id><content type="html">&lt;p&gt;
Some basic instructions for searching &lt;a href="http://www.splunk.com/"&gt;Splunk&lt;/a&gt; from &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;...
&lt;/p&gt;    

&lt;p&gt;
First, you must install Splunk on the machine you will run the Python script from.  Splunk installs its own Python interpreter that you can use to run your code.  I am using Splunk 4.14, which includes Python 2.6.
&lt;/p&gt;

&lt;p&gt;
(It looks like you can set some environment variables and install a few Python dependencies along with the Python SDK and get this going "outside" of Splunk.  But the easiest option is just to run on their interpreter).
&lt;/p&gt;

&lt;p&gt;
To run your own Python scripts on Splunk's interpreter:&lt;br /&gt;
- save script into Splunk's "bin" directory&lt;br /&gt; 
(usually "/opt/splunk/bin" or "C:\Program Files\Splunk\bin")&lt;br /&gt;
- go to the "bin" directory and run:&lt;br /&gt; 
splunk cmd python your_script.py
&lt;/p&gt;

&lt;p&gt;
So...&lt;br /&gt;
What goes in your Python code?
&lt;/p&gt;

&lt;p&gt;
First, import the modules you will need:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
import time
import splunk.auth
import splunk.search
&lt;/pre&gt;

&lt;p&gt;
Next, authenticate and get a session key.  
&lt;/p&gt;

&lt;p&gt;
For the local splunk host:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
key = splunk.auth.getSessionKey('user', 'password')
&lt;/pre&gt;

&lt;p&gt;
If you are going to search a remote splunk host, you must authenticate against it by adding the "hostPath" parameter:  
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
key = splunk.auth.getSessionKey('user', 'password', hostPath='https://mysplunk:8089')
&lt;/pre&gt;

&lt;p&gt;
Tips:&lt;br /&gt;
- use https, even if you are not using ssl in your splunk web interface&lt;br /&gt;
- 'admin' user doesn't seem to work.  user a normal user/password.
&lt;/p&gt;

&lt;p&gt;
Next, submit a search job.
&lt;/p&gt;

&lt;p&gt;
For a local search:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
job = splunk.search.dispatch('search index="os" *', earliest_time='-15m')
&lt;/pre&gt;

&lt;p&gt;
For a remote search, use the "hostPath" parameter again:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
job = splunk.search.dispatch('search index="os" *', earliest_time='-15m', hostPath='https://mysplunk:8089')
&lt;/pre&gt;

&lt;p&gt;
print the job details:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
print job
&lt;/pre&gt;

&lt;p&gt;
wait for the results:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
while not job.isDone:
    time.sleep(.25)    
&lt;/pre&gt;

&lt;p&gt;
print results
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
for result in job.results:
    print result
&lt;/pre&gt;        


&lt;hr /&gt;

&lt;p&gt;
Altogether in a Python script:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/env python
# Corey Goldberg - 2010
# 
#  search a remote splunk server
#
#  instructions:
#   - save script into splunk's "bin" directory
#     (usually "/opt/splunk/bin" or "C:\Program Files\Splunk\bin")
#   - go to the "bin" directory and run: 
#     $ splunk cmd python my_script.py
#



import time
import splunk.auth
import splunk.search



SPLUNK_SERVER = '192.168.12.173'
USER_NAME = 'foo'
PASSWORD = 'secret'
SEARCH_STRING = 'search index="os"'
EARLIEST_TIME = '-15m'



def main():
    # authenticate
    key = splunk.auth.getSessionKey(USER_NAME, PASSWORD, hostPath='https://%s:8089' % SPLUNK_SERVER)
    print 'auth key:\n%s' % key
    
    # submit a search job
    job = splunk.search.dispatch(SEARCH_STRING, earliest_time=EARLIEST_TIME, hostPath='https://%s:8089' % SPLUNK_SERVER)
    print 'job details:\n%s' % job

    # wait for results
    while not job.isDone:
        time.sleep(.25)
    
    print 'results:'    
    for result in job.results:
        print result
          
          

if __name__== '__main__':
    main()
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-2880954091958444162?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-01T09:40:24.572-05:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Python - Shorten a URL Using Google's Shortening Service (goo.gl)</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/10/python-shorten-url-using-googles.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-10-08T09:02:44-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-3361028988733434778</id><content type="html">&lt;p&gt;
Using Python to shorten a URL with Google's shortening service (goo.gl):
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
#!/usr/bin/python 
#  Corey Goldberg - 2010

import json
import urllib
import urllib2


def shorten(url):
    gurl = 'http://goo.gl/api/url?url=%s' % urllib.quote(url)
    req = urllib2.Request(gurl, data='')
    req.add_header('User-Agent', 'toolbar')
    results = json.load(urllib2.urlopen(req))
    return results['short_url']


if __name__ == '__main__':
    print shorten('http://www.goldb.org/')
    print shorten('www.yahoo.com')

&lt;/pre&gt;

&lt;p&gt;
You give it a URL to shorten: shorten('http://www.goldb.org/long_url')
&lt;/p&gt;

&lt;p&gt;
... and it returns a shortened URL for you: 'http://goo.gl/jh4W'
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-3361028988733434778?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-08T12:02:44.250-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Python - Linux: Parse Network Stats From ifconfig</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/09/python-linux-parse-network-stats-from.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-09-24T15:04:16-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-5805864631356358652</id><content type="html">&lt;p&gt;
I needed to get some Linux networking stats in my Python program today.  Specifically, I needed 'bytes sent' and 'bytes received' counts since last reboot from the local machine.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://en.wikipedia.org/wiki/Ifconfig"&gt;ifconfig&lt;/a&gt; is a network configuration utility for Linux that you run from the command line:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
corey@studio17:~$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:22:19:e5:07:31  
          inet addr:10.0.0.5  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::222:19ff:fee5:731/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3353822 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3052408 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:3476310326 (3.4 GB)  TX bytes:256706611 (256.7 MB)
          Interrupt:17 
&lt;/pre&gt;

&lt;p&gt;
The following function parses output from ifconfig to get the network stats I was after:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
import re
import subprocess

def get_network_bytes(interface):
    output = subprocess.Popen(['ifconfig', interface], stdout=subprocess.PIPE).communicate()[0]
    rx_bytes = re.findall('RX bytes:([0-9]*) ', output)[0]
    tx_bytes = re.findall('TX bytes:([0-9]*) ', output)[0]
    return (rx_bytes, tx_bytes)
&lt;/pre&gt;    
  
&lt;p&gt;  
Example usage:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
import re
import subprocess

def main():
    rx_bytes, tx_bytes = get_network_bytes('eth0')
    print '%s bytes received' % rx_bytes
    print '%s bytes sent' % tx_bytes
      
def get_network_bytes(interface):
    output = subprocess.Popen(['ifconfig', interface], stdout=subprocess.PIPE).communicate()[0]
    rx_bytes = re.findall('RX bytes:([0-9]*) ', output)[0]
    tx_bytes = re.findall('TX bytes:([0-9]*) ', output)[0]
    return (rx_bytes, tx_bytes)

if __name__ == '__main__':
    main()
&lt;/pre&gt;

&lt;p&gt;
&lt;b&gt;Update:&lt;/b&gt;  someone left an anonymous comment and mentioned you can just read from proc/net/dev rather than using ifconfig.  I modified his code sample and came up with this:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
def get_network_bytes(interface):
    for line in open('/proc/net/dev', 'r'):
        if interface in line:
            data = line.split('%s:' % interface)[1].split()
            rx_bytes, tx_bytes = (data[0], data[8])
            return (rx_bytes, tx_bytes)
&lt;/pre&gt;

&lt;p&gt;
Example Usage:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
def main():
    rx_bytes, tx_bytes = get_network_bytes('eth0')
    print '%s bytes received' % rx_bytes
    print '%s bytes sent' % tx_bytes
      
def get_network_bytes(interface):
    for line in open('/proc/net/dev', 'r'):
        if interface in line:
            data = line.split('%s:' % interface)[1].split()
            rx_bytes, tx_bytes = (data[0], data[8])
            return (rx_bytes, tx_bytes)

if __name__ == '__main__':
    main()
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-5805864631356358652?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-24T18:04:16.301-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry><title type="text">My Chrome Users Now Outnumber Internet Explorer (Traffic Stats)</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/09/my-chrome-users-now-outnumber-internet.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-09-23T08:07:38-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-559092963674349782</id><content type="html">&lt;p&gt;
I really like to analyze the traffic to my various websites (homepage, blog, project pages, open source code).
&lt;/p&gt;

&lt;p&gt;
Since my visitors must be somewhat interested in what I post, I like to think they are *just* *like* *me*.
&lt;/p&gt;

&lt;p&gt;
So... of course, my own personal web metrics are better than anything else out there :)&lt;br /&gt;
(to you they might be worthless, but to me they are gold)
&lt;/p&gt;

&lt;p&gt;
I get a pretty steady stream of about 40k pageviews per month.  In the past year, I've served a paltry half million pageviews.  But hey, its a good enough sample size to work with, and pretty flattering to have attracted that many eyeballs.
&lt;/p&gt;

&lt;p&gt;
Look what happened this past month:
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k7-jvtv2cLo/TJtsXffhbcI/AAAAAAAAAsQ/qolYvcIrTiE/s1600/2010_09_goldb_BrowserShare_2010Sept.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 326px; height: 164px;" src="http://4.bp.blogspot.com/_k7-jvtv2cLo/TJtsXffhbcI/AAAAAAAAAsQ/qolYvcIrTiE/s400/2010_09_goldb_BrowserShare_2010Sept.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5520124919119179202" /&gt;&lt;/a&gt;
&lt;br /&gt;
(stats from aug_22_2010 - sept_21_2010)

&lt;p&gt;
Chrome visitors overtook Internet Explorer in site usage.
&lt;/p&gt;

&lt;p&gt;
Here is how it has been playing out in the past year and a half:
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_k7-jvtv2cLo/TJtsXlKoJHI/AAAAAAAAAsY/yV67anSZBag/s1600/2010_09_goldb_BrowserShare_2009Jan-2010Sept.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 226px;" src="http://4.bp.blogspot.com/_k7-jvtv2cLo/TJtsXlKoJHI/AAAAAAAAAsY/yV67anSZBag/s400/2010_09_goldb_BrowserShare_2009Jan-2010Sept.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5520124920642151538" /&gt;&lt;/a&gt;

&lt;p&gt;
(Notice my Firefox visitors are waning a little also.)  
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-559092963674349782?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-23T11:07:38.696-04:00</app:edited><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_k7-jvtv2cLo/TJtsXffhbcI/AAAAAAAAAsQ/qolYvcIrTiE/s72-c/2010_09_goldb_BrowserShare_2010Sept.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">Python - Multi-Mechanize Script With HTTP Profiling Timers</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/09/python-multi-mechanize-script-with-http.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-09-22T06:50:41-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-6350060284739303075</id><content type="html">&lt;p&gt;
&lt;a href="http://multimechanize.com"&gt;Multi-Mechanize&lt;/a&gt; is an open source framework for web performance and load testing. It allows you to run simultaneous python scripts to generate load (synthetic transactions) against a web site or web service.
&lt;/p&gt;

&lt;p&gt;
The default response timer wraps the entire Transaction(), so it will time everything included.  For more granular timing, you need to instrument your script code with custom timers.
&lt;/p&gt;

&lt;p&gt;
Multi-Mechanize is pure Python and you have access to all of Python's standard library in your scripts.  For example, you can use &lt;a href="http://docs.python.org/library/httplib.html"&gt;httplib&lt;/a&gt; to write a virtual user agent script and get detailed HTTP profiling times (TTFB, TTLB, etc).
http://docs.python.org/library/httplib.html
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
import httplib
import time


class Transaction(object):
    def __init__(self):
        self.custom_timers = {}
    
    def run(self):
        conn = httplib.HTTPConnection('www.example.com')
        start = time.time()
        conn.request('GET', '/')
        request_time = time.time()
        resp = conn.getresponse()
        response_time = time.time()
        conn.close()     
        transfer_time = time.time()
        
        self.custom_timers['request sent'] = request_time - start
        self.custom_timers['response received'] = response_time - start
        self.custom_timers['content transferred'] = transfer_time - start
        
        assert (resp.status == 200), 'Bad HTTP Response'
&lt;/pre&gt;

&lt;p&gt;
To test it out, you can add this to the bottom of the script and run it from the command line:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
if __name__ == '__main__':
    trans = Transaction()
    trans.run()
    
    for timer in ('request sent', 'response received', 'content transferred'):
        print '%s: %.5f secs' % (timer, trans.custom_timers[timer])
&lt;/pre&gt;

&lt;p&gt;
Output:
&lt;/p&gt;
&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
request sent: 0.14429 secs
response received: 0.25995 secs
content transferred: 0.26007 secs
&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;
* if you are running MS Windows, replace the time.time() calls 
with time.clock() for better timer accuracy.  On all other 
operating systems, use time.time()
&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-6350060284739303075?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-22T09:50:41.730-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><title type="text">CSharp/.NET - Use Stopwatch() Instead of DateTime() for Accurate High Precision Timing</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/09/csharpnet-use-stopwatch-instead-of.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-09-20T06:37:34-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-2489354096233574409</id><content type="html">&lt;p&gt;&lt;em&gt;(originally posted at &lt;a href="http://coreygoldberg.blogspot.com/"&gt;coreygoldberg.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt; 

&lt;p&gt;
In C# (.NET), the DateTime() class is not accurate for high precision timing.  Instead, use the Stopwatch() class if you need a timer.  Most hardware and operating systems support a high-resolution performance counter that can be accessed through System.Diagnostics.Stopwatch.
&lt;/p&gt;

&lt;p&gt;
Don't use DateTime() like this if you need accuracy:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
using System;

class Program
{
    public static void Main()
    {
        DateTime start = DateTime.Now;

            // do timed work here

        DateTime stop = DateTime.Now;

        // don't do this. you won't get accurate timing
        Console.WriteLine("{0} ms", (stop - start).TotalMilliseconds);

        // definitely don't do this. you won't get accurate timing or full timer resolution
        Console.WriteLine("{0} ms", (stop - start).Milliseconds);
    }
}
&lt;/pre&gt;

&lt;p&gt;
Stopwatch() uses operating system's high-resolution performance counter:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
using System;
using System.Diagnostics;

class Program
{
    public static void Main()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();

            // do timed work here

        stopWatch.Stop();

        // don't do this. you won't get full timer resolution
        Console.WriteLine("{0} ms", stopWatch.ElapsedMilliseconds);

        // do this to get accurate high precision timing
        Console.WriteLine("{0} ms", stopWatch.Elapsed.TotalMilliseconds);
    }
}
&lt;/pre&gt;

&lt;p&gt;
The Stopwatch class is in the System.Diagnostics namespace:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
using System.Diagnostics;
&lt;/pre&gt;

&lt;p&gt;
Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism.  If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time. Otherwise, the Stopwatch class uses the system timer (DateTime class) to measure elapsed time.
&lt;/p&gt;

&lt;p&gt;
To see if your system supports a high-resolution performance counter, check the Stopwatch.IsHighResolution property:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
if (Stopwatch.IsHighResolution)
    Console.WriteLine("Using the system's high-resolution performance counter.");
else 
    Console.WriteLine("Using the DateTime class.");
&lt;/pre&gt;

&lt;p&gt;
To check the timing accuracy, use the Stopwatch.Frequency property:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt; 
long frequency = Stopwatch.Frequency;

Console.WriteLine("Timer frequency in ticks per second: {0}", frequency);

long nanosecPerTick = (1000L*1000L*1000L) / frequency;

Console.WriteLine("Timer is accurate within {0} nanoseconds", nanosecPerTick);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-2489354096233574409?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-20T09:37:34.043-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Load Testing Web Services with Python and Multi-Mechanize</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/08/load-testing-web-services-with-python.html" /><category term="python" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-08-01T17:48:24-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-4760682998727562735</id><content type="html">&lt;p&gt;&lt;em&gt;(originally posted at &lt;a href="http://coreygoldberg.blogspot.com/"&gt;coreygoldberg.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
I had to test and benchmark a &lt;a href="http://en.wikipedia.org/wiki/SOAP"&gt;SOAP&lt;/a&gt; web service recently, and figured I'd write up some instructions for load testing with Multi-Mechanize.
&lt;/p&gt;

&lt;p&gt;
Multi-Mechanize is a performance and load testing framework that enables you to write plugins (in Python) to create virtual user scripts that run in parallel against your service.
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Project Home: &lt;a href="http://multimechanize.com"&gt;multimechanize.com&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Virtual User Script Development Guide: &lt;a href="http://code.google.com/p/multi-mechanize/wiki/DevelopingScripts"&gt;DevelopingScripts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Since Multi-Mechanize scripts are pure Python, you can use any Python module inside them.  In the case of a web service that uses SOAP, you have a few options.  You can use any 3rd party module, so something like &lt;a href="http://pypi.python.org/pypi/suds"&gt;Suds&lt;/a&gt; (a lightweight SOAP client lib) would be a reasonable choice.  However, I decided to stick with the Python standard library and build my scripts with &lt;a href="http://docs.python.org/library/urllib2.html"&gt;urllib2&lt;/a&gt;.  Afterall, SOAP is just slinging a bunch of XML back-and-forth over HTTP.
&lt;/p&gt;

&lt;p&gt;
So before I get started with Multi-Mechanize and performance/load testing...
&lt;/p&gt;

&lt;p&gt;
Here is a Python (2.x) script using urllib2 to interact with a SOAP web service over HTTP:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
import urllib2

with open('soap.xml') as f:
    soap_body = f.read()
    
req = urllib2.Request(url='http://www.foo.com/service', data=soap_body)
req.add_header('Content-Type', 'text/xml')
resp = urllib2.urlopen(req)
content = resp.read()
&lt;/pre&gt;

&lt;p&gt;
&lt;em&gt;(The script above assumes you have a file named 'soap.xml' in the local directory that contains your payload (SOAP XML message).  It will send an HTTP POST request containing your payload in the body.)&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
After the initial script is created in Python, the next step is to convert it into a Multi-Mechanize script.  To do this, you create a Transaction class with a run() method and add your code there.
&lt;/p&gt;

&lt;p&gt;
As a Multi-Mechanize script, the same thing would be done like this:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
import urllib2


class Transaction(object):
    def __init__(self):
        with open('soap.xml') as f:
            self.soap_body = f.read()
    
    def run(self):
        req = urllib2.Request(url='http://www.foo.com/service', data=self.soap_body)
        req.add_header('Content-Type', 'text/xml')
        resp = urllib2.urlopen(req)
        content = resp.read()
        
        assert ('Example SOAP Response' in content), 'Failed Content Verification'
&lt;/pre&gt;        

&lt;p&gt;
&lt;em&gt;(Notice I also added an assert statement to verify the content returned from the service.)&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Now that you have a script created, it's time to configure Multi-Mechanize and run some tests.
&lt;/p&gt;

&lt;p&gt;
You can download Multi-Mechanize from: &lt;a href="http://code.google.com/p/multi-mechanize/downloads/list"&gt;code.google.com&lt;/a&gt;&lt;br /&gt;
It requires Python 2.x (2.6 or 2.7), and if you want it to generate graphs, you must also install Matplotlib and its dependencies.  See the &lt;a href="http://code.google.com/p/multi-mechanize/wiki/FAQ"&gt;FAQ&lt;/a&gt; for help.
&lt;/p&gt;

&lt;p&gt;
Once you have Multi-Mechanize downloaded, unzip it and go to the "/projects" directory.  You can create a new project directory here.  You can call it "soap_project".  Inside this directory, you will need 2 things:  a config file ("config.cfg"), and a "test_scripts" directory (containing the script you previously created, which you can call "soap_client.py".  Since the script is looking for a data file named "soap.xml", make sure you have one created in the main multi-mechanize directory.
&lt;/p&gt;

&lt;p&gt;
The directory and file layout will look like this:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
/multi-mechanize
    /lib
    /projects
        /soap_project
            /test_scripts
                soap_client.py
            config.cfg
    multi-mechanize.py
    soap.xml
&lt;/pre&gt;

&lt;p&gt;
&lt;em&gt;(you can see the "default_project" for an example of how it should be setup.)&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
To begin with, you can use a simple config.cfg file like this:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
[global]
run_time: 30
rampup: 0
console_logging: on
results_ts_interval: 10

[user_group-1]
threads: 1
script: soap_client.py
&lt;/pre&gt;

&lt;p&gt;
This will just a run a single thread of your virtual user script for 30 seconds; good enough for testing and getting things going.  
&lt;/p&gt;

&lt;p&gt;
To run a test, go to the topmost multi-mechanize directory and run:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
$ python multi-mechanize.py soap_project
&lt;/pre&gt;

&lt;p&gt;
&lt;em&gt;(You should see timer output in the console.)&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Once you have things running well, you can turn off "console_logging" and increase the workload.  It will take some adjustment and plenty of trials to get the load dialed in correctly for your service.  You can also get a lot more sophisticated with your workload model and create multiple virtual user scripts doing different transactions.  In this case, I'll keep it simple and just test one web service request type in isolation.
&lt;/p&gt;

&lt;p&gt;
Once I ran plenty of iterations and got a feel for how the service responded and what its limits were, I settled with a config file like this:
&lt;/p&gt;

&lt;pre style="font-size:11px;border:1px #999999 dashed;font-family:monospace;color:#990000;background-color:#EEEEEE;padding-left:10px;"&gt;
[global]
run_time: 900
rampup: 900
console_logging: off
results_ts_interval: 90

[user_group-1]
threads: 30
script: soap_client.py
&lt;/pre&gt;

&lt;p&gt;
&lt;em&gt;(30 threads, increasing load over 15 mins)&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
After each test run you do, a new results directory is created containing your test results.  Look for "results.html" and view it in your browser to see the output report.
&lt;/p&gt;

&lt;hr /&gt;

&lt;br /&gt;

&lt;p&gt;
Have questions about &lt;a href="http://multimechanize.com"&gt;Multi-Mechanize&lt;/a&gt;?&lt;br /&gt;
Post to the discussion group: &lt;a href="http://groups.google.com/group/multi-mechanize"&gt;groups.google.com/group/multi-mechanize&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-4760682998727562735?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-01T20:48:24.886-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">Rackspace Cloud - Outbound Bandwidth Caps, Network Too Slow</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/07/rackspace-cloud-outbound-bandwidth-caps.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-07-27T09:11:47-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-3217723913347784700</id><content type="html">&lt;p&gt;
Have you seen the network/bandwidth caps that &lt;a href="http://www.rackspacecloud.com"&gt;Rackspace&lt;/a&gt; places on their cloud servers?
&lt;/p&gt;

&lt;p&gt;
From the &lt;a href="http://cloudservers.rackspacecloud.com/index.php/Frequently_Asked_Questions"&gt;Rackspace Cloud Server FAQ&lt;/a&gt;:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
&lt;em&gt;
"Your Cloud Server has a bandwidth cap that is applied in relation to the size of the server. Please note that the bandwidth caps are placed on outbound bandwidth only. Inbound bandwidth is not capped."
&lt;/em&gt;
&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;td&gt;Server Size&lt;/td&gt;&lt;td&gt;Public Limit&lt;/td&gt;&lt;td&gt;ServiceNet Limit&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;10 Mbps&lt;/td&gt;&lt;td&gt;20 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;512MB&lt;/td&gt;&lt;td&gt;20 Mbps&lt;/td&gt;&lt;td&gt;40 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1024MB&lt;/td&gt;&lt;td&gt;30 Mbps&lt;/td&gt;&lt;td&gt;60 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2048MB&lt;/td&gt;&lt;td&gt;40 Mbps&lt;/td&gt;&lt;td&gt;80 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;4096MB&lt;/td&gt;&lt;td&gt;50 Mbps&lt;/td&gt;&lt;td&gt;100 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;8192MB&lt;/td&gt;&lt;td&gt;60 Mbps&lt;/td&gt;&lt;td&gt;120 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;15872MB&lt;/td&gt;&lt;td&gt;70 Mbps&lt;/td&gt;&lt;td&gt;140 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/blockquote&gt;

&lt;p&gt;
I was going to use the Rackspace Cloud to do some performance testing of a new server.  I wanted to run 2 servers in a clustered mode, replicating data to each other.  My first concern was the speed of the internal network interconnects between cloud nodes.
&lt;/p&gt;

&lt;p&gt;
After doing some research, I realized the bandwidth caps make it a non-starter.  20-140 Mbps private interconnects??  That's not enough.  I would saturate the network almost immediately, even on their largest server class.  Sorry Rackspace.
&lt;/p&gt;

&lt;p&gt;
In comparison, &lt;a href="http://aws.amazon.com/ec2/"&gt;Amazon's EC2 Cloud&lt;/a&gt; offers High Performance Computing nodes with 10 Gigabit interconnects:  &lt;a href="http://aws.amazon.com/hpc-applications/"&gt;Amazon HPC&lt;/a&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-3217723913347784700?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-27T12:11:47.079-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><title type="text">WebInject - New Discussion Group Launched</title><link rel="alternate" type="text/html" href="http://coreygoldberg.blogspot.com/2010/07/webinject-new-discussion-group-launched.html" /><author><name>Corey Goldberg</name><email>noreply@blogger.com</email><uri>https://profiles.google.com/114546378907380458640</uri></author><updated>2010-07-25T10:52:05-07:00</updated><id>tag:blogger.com,1999:blog-5236867476487043111.post-3914653040547693196</id><content type="html">&lt;p&gt;
I just started a new discussion group for WebInject:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://groups.google.com/group/webinject"&gt;http://groups.google.com/group/webinject&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
The old forums (&lt;a href="http://www.webinject.org/cgi-bin/forums/YaBB.cgi"&gt;http://www.webinject.org/cgi-bin/forums/YaBB.cgi&lt;/a&gt;) have been broken for several years.  I will leave them up in read-only mode, but some threads are broken and unviewable. 
&lt;/p&gt;

&lt;p&gt;
Feel free to post a message to this new discussion group.&lt;br /&gt;
questions, bugs, patches, collaboration, comments, welcome... 
&lt;/p&gt;

&lt;p&gt;
Updates and new development coming soon...
&lt;/p&gt;

&lt;p&gt;
&lt;br /&gt;
&lt;em&gt;&lt;a href="http://www.webinject.org"&gt;WebInject&lt;/a&gt; is a free tool for automated testing and monitoring of web applications or services.  It can be used standalone, or as a plugin for external monitoring systems.&lt;/em&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5236867476487043111-3914653040547693196?l=coreygoldberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-25T13:52:05.458-04:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>

