<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Ryan Kanno: The diary of an Enginerd in Hawaii</title>
	
	<link>http://blog.localkinegrinds.com</link>
	<description>Everything you've ever thought, but never had the balls to say.</description>
	<lastBuildDate>Thu, 17 Dec 2009 01:32:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ryankanno" /><feedburner:info uri="ryankanno" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-nc-sa/3.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><item>
		<title>Update: Using Capistrano 2.5 to deploy Rails 2.3 to Webfaction</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/oqjBLhnQuCg/</link>
		<comments>http://blog.localkinegrinds.com/2009/07/27/update-using-capistrano-2-5-to-deploy-rails-2-3-to-webfaction/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 09:41:07 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[WebFaction]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=366</guid>
		<description><![CDATA[Update
Having been a Capistrano user for a few years, I absolutely love sweet, sweet automation.  A few months ago, I wrote a blog about how to use Capistrano to deploy to WebFaction.  However, since that post, the winds of change have swept through the Rails and Capistrano community with the release of Rails [...]]]></description>
			<content:encoded><![CDATA[<h2>Update</h2>
<p>Having been a <a href="http://www.capify.org/">Capistrano</a> user for a few years, I absolutely love sweet, sweet automation.  A few months ago, I wrote a blog about <a href="http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/">how to use Capistrano to deploy to WebFaction</a>.  However, since that post, the winds of change have swept through the Rails and Capistrano community with the release of Rails 2.3 and Capistrano 2.5.  WebFaction&#8217;s Ruby installation precludes you from taking advantage of these great updates, so I&#8217;ve come up with a little update to my previous post.</p>
<hr/>
<p><a href="http://blog.localkinegrinds.com/wp-content/uploads/2008/09/automator-icon.jpg"><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/09/automator-icon.jpg" alt="" title="automator-icon" width="200" height="200" class="alignright size-full wp-image-233" /></a></p>
<h2>Learn to Change, Change to Learn</h2>
<p>To be able to deploy Rails 2.3 with Capistrano 2.5, we&#8217;ll first have to jump through a few hoops.  Nice, easy hoops, mind you, but still hoops nonetheless.</p>
<h3>Your own Ruby installation</h3>
<p>You&#8217;ll have to install a custom Ruby installation into your WebFaction home directory.  By following Step 1 <a href="https://help.webfaction.com/index.php?_m=knowledgebase&#038;_a=viewarticle&#038;kbarticleid=89&#038;nav=0,21">here</a>, you&#8217;ll have a working Ruby 1.8.7 installation and RubyGem 1.3.  You&#8217;ll need these if you want to deploy a Rails 2.3 application.  Also, install a version of Mongrel tied to your Ruby installation.</p>
<p><strong>Note:</strong> Typically, I like to install custom installations into ~/opt/local/lib/.  </p>
<h3>Edit Autostart.cgi</h3>
<p>You&#8217;ll have to make a few edits to a few files from <a href="http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/">my previous blog post</a>.</p>
<p>Next, open up your favorite editor of choice (*cough*vi*cough*) and edit the <strong>autostart.cgi</strong> file. Jump to the end of the file and comment out the following line from my previous blog:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #808080; font-style: italic;"># os.system('/usr/local/bin/mongrel_rails start -c /home/&lt;webfaction_username&gt;/webapps-releases/&lt;webfaction_app_name&gt;/current -d -e production -P /home/&lt;webfaction_username&gt;/webapps/&lt;webfaction_app_name&gt;/log/mongrel.pid -p &lt;port&gt;')</span></pre></td></tr></table></div>

<p>and change it to the following:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">&nbsp;
 <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/&lt;webfaction_username&gt;/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails start -c /home/&lt;webfaction_username&gt;/webapps-releases/&lt;webfaction_app_name&gt;/current -d -e production -P /home/&lt;webfaction_username&gt;/webapps/&lt;webfaction_app_name&gt;/log/mongrel.pid -p &lt;port&gt;'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><strong>Notice:</strong> We&#8217;re using the path to Mongrel tied to our custom Ruby installation!  This might be different in your installation!</p>
<h3>Edit the Capfile</h3>
<p>In my previous blog, we placed a custom <strong>deploy.rb</strong> into the config directory.  With the latest version of Capistrano, you no longer need to do this.  Rather, place the following into a file called <strong>Capfile</strong> in the root of your Rails project.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
<span style="color:#CC0066; font-weight:bold;">load</span> <span style="color:#996600;">'deploy'</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:webfaction_username</span>, <span style="color:#996600;">&quot;&lt;webfaction_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db_type</span>, <span style="color:#996600;">&quot;&lt;webfaction_db_type&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db</span>, <span style="color:#996600;">&quot;&lt;webfaction_db&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db_username</span>, <span style="color:#996600;">&quot;&lt;webfaction_db_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_port</span>, <span style="color:#996600;">&quot;&lt;webfaction_port (get from autostart.cgi)&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:database_yml_template</span>, <span style="color:#996600;">&quot;database.example.yml&quot;</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:application</span>, <span style="color:#996600;">&quot;test&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:deploy_to</span>, <span style="color:#996600;">&quot;/home/#{webfaction_username}/webapps-releases/#{application}&quot;</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:scm</span>, <span style="color:#ff3333; font-weight:bold;">:subversion</span>
set <span style="color:#ff3333; font-weight:bold;">:scm_user</span>, <span style="color:#996600;">&quot;&lt;scm_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:scm_password</span>, <span style="color:#CC0066; font-weight:bold;">Proc</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">Capistrano::CLI</span>.<span style="color:#9900CC;">password_prompt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Subversion password for #{scm_user}: &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
set <span style="color:#ff3333; font-weight:bold;">:repository</span>, <span style="color:#CC0066; font-weight:bold;">Proc</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;--username #{scm_user} --password #{scm_password} --no-auth-cache &lt;http://path/to/your/svn/goes/here/&gt;&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span> 
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:user</span>, <span style="color:#996600;">&quot;#{webfaction_username}&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:use_sudo</span>, <span style="color:#0000FF; font-weight:bold;">false</span> 
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:domain</span>, <span style="color:#996600;">&quot;&lt;webfaction_domain&gt;&quot;</span>
&nbsp;
role <span style="color:#ff3333; font-weight:bold;">:app</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:web</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:db</span>,  domain, <span style="color:#ff3333; font-weight:bold;">:primary</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
desc <span style="color:#996600;">&quot;Symlink public to what webfaction expects the webroot to be&quot;</span>
task <span style="color:#ff3333; font-weight:bold;">:after_symlink</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:web</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  run <span style="color:#996600;">&quot;ln -nfs #{release_path}/public /home/#{webfaction_username}/webapps/#{application}/&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
namespace <span style="color:#ff3333; font-weight:bold;">:deploy</span> <span style="color:#9966CC; font-weight:bold;">do</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Taken from http://jonathan.tron.name/2006/07/15/capistrano-password-prompt-tips </span>
  <span style="color:#008000; font-style:italic;"># Thanks Jonathan! :)</span>
  desc <span style="color:#996600;">&quot;Creates the database configuration on the fly&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:create_database_configuration</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;yaml&quot;</span>
    set <span style="color:#ff3333; font-weight:bold;">:production_db_password</span>, <span style="color:#CC0066; font-weight:bold;">proc</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">Capistrano::CLI</span>.<span style="color:#9900CC;">password_prompt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Remote production database password: &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    db_config = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::load_file<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;config/#{database_yml_template}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    db_config.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'test'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    db_config.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'development'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'adapter'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db_type}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'database'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'username'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db_username}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'password'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = production_db_password
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'host'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;localhost&quot;</span>
&nbsp;
    put <span style="color:#CC00FF; font-weight:bold;">YAML</span>::dump<span style="color:#006600; font-weight:bold;">&#40;</span>db_config<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">&quot;#{release_path}/config/database.yml&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:mode</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 0664
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  after <span style="color:#996600;">&quot;deploy:update_code&quot;</span>, <span style="color:#996600;">&quot;deploy:create_database_configuration&quot;</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:start&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:start</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails start -c #{deploy_to}/current -d -e production -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid -p #{webfaction_port}&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:restart&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:restart</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails restart -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:stop&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:stop</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/opt/local/lib/ruby1.8/lib/ruby/gems/1.8/bin/mongrel_rails stop -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<div style="font:normal 1.1em arial; background-color:#E5F3FF; padding:1em; margin:1em 0; border:1px solid #114477; color:#33415D;"><strong>Note:</strong> Change all the values in tags like <strong>&lt;webfaction_username&gt;</strong>, <strong>&lt;webfaction_db&gt;</strong>, <strong>&lt;webfaction_db_username&gt;</strong>, etc. to those values that fit your configuration!<br/>Otherwise, this file in itself won&#8217;t do you any good.</div>
<p><strong>Now, you should be able to run the standard Capistrano tasks to deploy your application to WebFaction with the latest version of Rails!</strong></p>
<h3>Explanation</h3>
<p>Basically, the only thing I&#8217;ve done is shown you how to update your version of Ruby, RubyGems, Mongrel, and Capistrano to place nicely in WebFaction.  This should allow you to run commands like &#8216;cap deploy:setup&#8217;, &#8216;cap deploy:update&#8217; on your local machine and update your live code on WebFaction&#8217;s servers. Nothing too serious going on here!  As always, feel free to use, steal, take, and/or copy anything on this blog. Hopefully somewhere, someone on the Interwebs will find these tips handy!</p>
<p><strong>And if you find anything wrong with these scripts, don&#8217;t hesitate to leave a comment or email!</strong></p>
<h2>Voila! (Enjoy)</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=366&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/oqjBLhnQuCg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2009/07/27/update-using-capistrano-2-5-to-deploy-rails-2-3-to-webfaction/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2009/07/27/update-using-capistrano-2-5-to-deploy-rails-2-3-to-webfaction/</feedburner:origLink></item>
		<item>
		<title>Lessons Learned: Google App Engine + App Engine Patch + Django + Boto</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/gK1YAuazNUQ/</link>
		<comments>http://blog.localkinegrinds.com/2009/04/02/lessons-learned-google-app-engine-app-engine-patch-django-boto/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 08:00:18 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[app-engine]]></category>
		<category><![CDATA[boto]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lessons-learned]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=348</guid>
		<description><![CDATA[Update:
Mitch Garnaat from CloudRight has pointed out that you can actually set the policy of the S3 file in the set_contents_from_file call instead of making another roundtrip request into S3 (and saving you some coin).  Thanks Mitch!
Btw, I&#8217;m using App Engine Patch 1.0 and Boto 1.6a.

Sorry I haven&#8217;t updated my blog in a few [...]]]></description>
			<content:encoded><![CDATA[<h3>Update:</h3>
<p>Mitch Garnaat from <a href="http://cloudright.com/">CloudRight</a> has pointed out that you can actually set the policy of the S3 file in the set_contents_from_file call instead of making another roundtrip request into S3 (and saving you some coin).  <strong>Thanks Mitch!</strong></p>
<p><strong>Btw, I&#8217;m using App Engine Patch 1.0 and Boto 1.6a.</strong></p>
<hr/>
<p>Sorry I haven&#8217;t updated my blog in a few <strike>weeks</strike> months, but I&#8217;ve been a little busy.  With that said, along with <a href="http://erlang.org">Erlang</a>, I&#8217;ve been playing around with <a href="http://code.google.com/appengine">Google App Engine</a>, <a href="http://code.google.com/p/app-engine-patch/">App Engine Patch</a> (for <a href="http://www.djangoproject.com">Django</a> support), and the <a href="http://code.google.com/p/boto">Boto library</a> (for <a href="https://s3.amazonaws.com">Amazon S3</a> support).  After not having touched Python code in a few months, I wanted to document some of my lessons learned to help over developers who may be in a similar boat.</p>
<h2>Lessons learned</h2>
<ul>
<li>If you&#8217;re upgrading the App Engine Patch, make sure you don&#8217;t have the App Engine library installed in a hidden directory</li>
<li>Uploading bulk data changed ever so slightly</li>
<li>If you&#8217;re not running off of Boto&#8217;s trunk, you&#8217;ll need to patch your Boto installation to work with App Engine.</li>
</ul>
<h3>Make sure the App Engine library isn&#8217;t installed in a hidden directory</h3>
<p>Apparently, Google&#8217;s SDK 1.1.9 doesn&#8217;t like to rely on files that won&#8217;t be uploaded with your application &#8211; and hidden directories are no longer uploaded.  I was running into the dreaded purple-nurple screen of death.  Thank goodness for this <a href="http://groups.google.com/group/google-appengine/browse_thread/thread/7b2445428b8115c2/c09621c0bf3f038d?#c09621c0bf3f038d">AppEngine Google Group post</a>, but I&#8217;m still not even sure when this popped up considering Google&#8217;s articles still <a href="http://code.google.com/appengine/articles/appengine_helper_for_django.html">refer to this setup</a>.</p>
<h3>Bulk upload</h3>
<p>Compared to the previous SDK I was playing around with, bulk uploading changed significantly.  I recall having to patch Goog&#8217;s bulkupload.py file to get unicode support.  However, their new <a href="http://code.google.com/appengine/articles/remote_api.html">remote api tool</a> has definitely fixed this issue, so +1 for Googs.  People are <a href="http://code.google.com/p/googleappengine/issues/detail?id=157">reporting that uploading unicode</a> is still broken, but it&#8217;s not.  <em>Or at least it wasn&#8217;t for me.</em>  Second, if you&#8217;re like me and don&#8217;t read documentation, you&#8217;ll find out (the hard way) that the method signature to HandleEntity changed.  Instead of accepting a datastore.Entity, it&#8217;s now expecting a db.Model object.</p>
<p><strong>Note:</strong>  When actually running the remote api tool, you&#8217;ll also want to make sure your PYTHONPATH includes your current project.  (Another one-liner in the documentation. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> )</p>
<h3>Integrating Boto + App Engine</h3>
<p>I wasn&#8217;t running off of Boto&#8217;s trunk and I was getting an obscure type conversion error.  Being too lazy to check out the source, I jumped to their issue tracker and <a href="http://code.google.com/p/boto/issues/detail?id=115">found a patch</a> (halfway down the page) by one of the App Engine Patch lead devs.  Apply the patch and you&#8217;ll be on your way to uploading images/data from App Engine into Amazon S3!  If you&#8217;re looking for example code, I&#8217;ve included a small snippet of what I tested.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">    @<span style="color: #008000;">staticmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> upload_to_s3<span style="color: black;">&#40;</span>original_filename, photo<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; Upload a photo file, storing its original name as metadata in an S3 bucket &quot;&quot;&quot;</span>
        connection = Connection<span style="color: black;">&#40;</span>settings.<span style="color: black;">AWS_ACCESS_KEY_ID</span>, settings.<span style="color: black;">AWS_SECRET_ACCESS_KEY</span><span style="color: black;">&#41;</span>
        bucket = connection.<span style="color: black;">get_bucket</span><span style="color: black;">&#40;</span>settings.<span style="color: black;">AWS_IMAGE_BUCKET_NAME</span><span style="color: black;">&#41;</span>
        photo_uuid = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        new_key = Key<span style="color: black;">&#40;</span>bucket<span style="color: black;">&#41;</span>
        new_key.<span style="color: black;">key</span> = photo_uuid
        new_key.<span style="color: black;">set_metadata</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'original_filename'</span>, original_filename<span style="color: black;">&#41;</span>
        new_key.<span style="color: black;">set_contents_from_file</span><span style="color: black;">&#40;</span>photo, policy=<span style="color: #483d8b;">'public-read'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> photo_uuid</pre></td></tr></table></div>

<p><strong>Note: </strong> I only tested the code above with small images ~300-500K in size and it seemed to work perfectly fine (with no load! <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ).  As always, feel free to use, steal, take, and/or copy anything on this blog.  Hopefully somewhere, someone on the Interwebs will find these tips handy!</p>
<h2>Enjoy!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=348&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/gK1YAuazNUQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2009/04/02/lessons-learned-google-app-engine-app-engine-patch-django-boto/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2009/04/02/lessons-learned-google-app-engine-app-engine-patch-django-boto/</feedburner:origLink></item>
		<item>
		<title>Seven Things Meme aka Damn you, Harper Reed!</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/jjtIelJfTb4/</link>
		<comments>http://blog.localkinegrinds.com/2009/01/22/seven-things-meme-aka-damn-you-harper-reed/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 16:42:02 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[7 things]]></category>
		<category><![CDATA[7 things meme]]></category>
		<category><![CDATA[about me]]></category>
		<category><![CDATA[harperreed]]></category>
		<category><![CDATA[meme]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[ryankanno]]></category>
		<category><![CDATA[seven things]]></category>
		<category><![CDATA[stalk me]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=268</guid>
		<description><![CDATA[Internet memes rock my socks!
Unfortunately, I was tagged by Harper for a &#8220;7 things&#8221; meme where I have to divulge seven tidbits of randomness about myself.  I&#8217;m generally not a big fan of these things since most of you on the Interweb could care less about me, but it is Harper&#8230; and well, he [...]]]></description>
			<content:encoded><![CDATA[<h3>Internet memes rock my socks!</h3>
<p>Unfortunately, I was <em>tagged</em> by <a href="http://nata2.org">Harper</a> for a &#8220;7 things&#8221; meme where I have to divulge seven tidbits of randomness about myself.  I&#8217;m generally not a big fan of these things since most of you on the Interweb could care less about me, but it is Harper&#8230; and well, he is <a href="http://harperreedisyournewbicycle.com/">my new bicycle</a>, so here goes:</p>
<p><strong>1.</strong> <span style="font-weight:bold; color:#333;">I have &#8220;girlie&#8221; handwriting</span></p>
<p style="margin:0 1.25em;">I blame this 1000% all on my sister.  Throughout the years, people have told me that I write like a girl &#8211; whatever that means.  I don&#8217;t know how many days of my childhood I spent playing &#8220;school&#8221;, but it&#8217;s quite apparent that it was damn too many.  Thanks Stace!</p>
<p><strong>2.</strong> <span style="font-weight:bold; color:#333;">I used to play an inordinate amount of video games</span></p>
<p style="margin:0 1.25em;">They say a picture is worth a thousand words, but <a href="http://ryankanno.com">this one</a> just might make you speechless.  Damn you, <a href="http://en.wikipedia.org/wiki/John_D._Carmack">John Carmack</a>, for making one of the <a href="http://www.idsoftware.com/games/quake/quake/">greatest games of my generation</a> and *almost* failing me out of college.  I&#8217;ve just recently been sucked into this wonderful <a href="http://www.worldofwarcraft.com/">World of Warcraft</a>.  God, help me.</p>
<p><strong>3.</strong> <span style="font-weight:bold; color:#333;">I <3 puzzles</span></p>
<p style="margin:0 1.25em;">Whether it&#8217;s the crosswords, <a href="http://www.websudoku.com/">sudoku</a>, <a href="http://www.kakuro.com/">kakuro</a>, chess, or that damn <a href="http://www.popcap.com/gamepopup.php?theGame=diamondmine">Bejeweled</a>, I absolutely love puzzles.  I typically have a really short attention span, but puzzles have known to captivate me for hours on end.</p>
<p><strong>4.</strong> <span style="font-weight:bold; color:#333;">I am ultra-competitive</span></p>
<p style="margin:0 1.25em;">I don&#8217;t know if it was the math games my mom challenged me with as a child, but I&#8217;m probably on the extremely far end of the competitiveness scale.  It could be eating (grr, Kobayashi, here I come), games at <a href="http://www.daveandbusters.com/">Dave and Buster&#8217;s</a>, or just a game of pickup basketball, I&#8217;ll compete at anything.  And if you&#8217;re lucky, I&#8217;ll probably throw in some trash talking as well.</p>
<p><strong>5.</strong> <span style="font-weight:bold; color:#333;">I am a total sucker for 80&#8217;s cartoons</span></p>
<p style="margin:0 1.25em;">Whether it&#8217;s <a href="http://www.hasbro.com/gijoe/">G.I. Joe</a>, <a href="http://www.hasbro.com/transformers/">Transformers</a>, <a href="http://en.wikipedia.org/wiki/M.A.S.K.">M.A.S.K.</a>, <a href="http://en.wikipedia.org/wiki/Thundercats">Thundercats</a>, <a href="http://www.voltron.com/">Voltron</a>, or <a href="http://en.wikipedia.org/wiki/Silverhawks">Silverhawks</a>; I&#8217;m an uber 80&#8217;s cartoon fan.  I don&#8217;t know if I should be admitting this as a 30 year old, but I have an extensive collection of Transformers and G.I. Joes safely stored away at my parent&#8217;s house.  Thanks, Mom &#038; Dad!</p>
<p><strong>6.</strong> <span style="font-weight:bold; color:#333;">I love to read</span></p>
<p style="margin:0 1.25em;">I&#8217;m not sure when this happened in my life, but I&#8217;ve come to love reading.  When I was younger, I absolutely loved <a href="http://">Encyclopedia Brown</a> and the <a href="http://www.cyoa.com/">Choose Your Own Adventure</a> series.  As I&#8217;ve gotten older, I&#8217;ve stuck to the more non-fiction variety, and I&#8217;m currently working on these books <a href="http://www.nationalreview.com/100best/100_books.html">here</a>.  One of these days, I&#8217;m hoping someone will get me an <a href="http://www.amazon.com/kindle/">Amazon Kindle</a>. =P (*hint* *hint*)</p>
<p><strong>7.</strong> <span style="font-weight:bold; color:#333;">Hi, my name is Ryan, and I&#8217;m a <strike>caffeine</strike> Coke Zero addict</span></p>
<p style="margin:0 1.25em;">Since my parents never allowed me to drink caffeine as a child, I don&#8217;t know exactly when this happened.  It could have been all those all-nighters in grad school trying finish up the last bits of code, or the late nights playing online games.  In any case, I drink a six pack a day, on the conservative estimate, but I&#8217;m really, really trying to stop. I think.</p>
<h3>Whew!</h3>
<p>And there you have it folks &#8211; a few lame tidbits about me.  Now, according to Harper, to make this official, I have to tag 7 other unfortunate online souls.  So&#8230; I tag:</p>
<ul style="font-size:.9em;">
<li style="margin-bottom:.7em;"><a href="http://www.world-wide-ed.com/">Ed S</a> &#8211; I met Ed through a <a href="http://hoopsinparadise.com">basketball league</a>, and it just so happens we share a similar interest in all things technology.  Not only does he manage <a href="http://www.aroundhawaii.com/">one of the larger media sites</a> in Hawaii, but he is also a <a href="http://worldwideed.honadvblogs.com/">featured blogger @ the Honolulu Advertiser</a>.</li>
<li style="margin-bottom:.7em;"><a href="http://it808.com/">Stephen F</a> &#8211; A former co-worker, I&#8217;m hoping that this will kick-start his blogging.  Since he&#8217;s busy with kids, school, and work, I&#8217;m not sure he&#8217;ll have time for this, but hey, it&#8217;s worth a try.  He knows all things .Net and Ruby.</li>
<li style="margin-bottom:.7em;"><a href="http://kevinmarshall.tumblr.com/">Kevin M</a> &#8211; We met during our freshman year at U of I in calculus. He&#8217;s a .Net machine working for <a href="http://blogs.claritycon.com/blogs/kevin_marshall/">Clarity Consulting</a> and is full of zany ideas.  He was even featured on Microsoft&#8217;s Coding4Fun for his <a href="http://blogs.msdn.com/coding4fun/archive/2006/10/31/910302.aspx">DIY foosball hack</a>.  I&#8217;m sure he&#8217;ll have something great to write.</li>
<li style="margin-bottom:.7em;"><a href="http://www.pulpconnection.net/">Greg Y</a> &#8211; We used to work in the same organization, and I&#8217;d help him out with small projects.  He&#8217;s leading the Hawaii Web 2.0 charge in the organization and also masquerades as a part-time blogger @ <a href="http://www.pulpconnection.net/">Pulp Connection</a>.</li>
<li style="margin-bottom:.7em;"><a href="http://blog.mirthlab.com">Mark Q</a> &#8211; One of my current co-workers who knows all things CSS and Mac.  He&#8217;s a Symfony user *cough*fanboy*cough* and is currently trying to convince me to switch over to the darkside.  &#8220;<strong>Resistance is futile.</strong>&#8220;</li>
<li style="margin-bottom:.7em;"><a href="http://morefishthanman.com/">Scott V</a> &#8211; We met during our freshman year at U of I playing what else but Quake.  Not only is he half man, half crazy, but he&#8217;s also the nerdvana of all things system administration.  He currently works at <a href="http://threadless.com">Threadless</a> with Harper causing all sorts of havoc.</li>
<li style="margin-bottom:.7em;"><a href="http://blog.fuexy.com/">Trent N</a> &#8211; I mentored Trent through <a href="http://hitechquest.com">HiTechQuest</a>.  He&#8217;s a young&#8217;un but has all types of technological potential.  Since he&#8217;s the youngest I&#8217;ve tagged, I&#8217;m sure he&#8217;ll have all sorts of interesting things to teach us old folk.</li>
</ul>
<div style="background-color:#fffde5; padding:.5em; margin.25em 0em;">
<p style="margin:.5em 0em .5em 0em;">And if you&#8217;re one of the chosen ones, here are the rules:</p>
<ul style="font-size:.85em;">
<li style="margin-bottom:.25em;">Link your original tagger(s), and list these rules on your blog.</li>
<li style="margin-bottom:.25em;">Share seven facts about yourself in a post &#8211; some random, some weird.</li>
<li style="margin-bottom:.25em;">Tag seven people at the end of your post by leaving their names and the links to their blogs.</li>
<li style="margin-bottom:.25em;">Let them know they&#8217;ve been tagged by leaving a comment on their blogs and/or Twitter</li>
</ul>
</div>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=268&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/jjtIelJfTb4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2009/01/22/seven-things-meme-aka-damn-you-harper-reed/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2009/01/22/seven-things-meme-aka-damn-you-harper-reed/</feedburner:origLink></item>
		<item>
		<title>Another turning point, a fork stuck in the road…</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/5gtmsBImZ24/</link>
		<comments>http://blog.localkinegrinds.com/2008/10/10/another-turning-point-a-fork-stuck-in-the-road/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 13:54:31 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[compacflt]]></category>
		<category><![CDATA[farewell]]></category>
		<category><![CDATA[navy]]></category>
		<category><![CDATA[spawar]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=244</guid>
		<description><![CDATA[&#8220;50 years from now, when you look back at your life, don&#8217;t you want to say you had the guts to get in the car?&#8221;
Shia LaBeouf as Sam Witwicky, Transformers
As some of you may know, I recently left my position as a Navy contractor at COMPACFLT for another position at a small, local technology startup. [...]]]></description>
			<content:encoded><![CDATA[<h3>&#8220;50 years from now, when you look back at your life, don&#8217;t you want to say you had the guts to get in the car?&#8221;</h3>
<p align="right"><strong><i>Shia LaBeouf as Sam Witwicky, Transformers</i></strong></p>
<p>As some of you may know, I recently left my position as a Navy contractor at <a href="http://www.cpf.navy.mil/">COMPACFLT</a> for another position at a small, local technology startup.   Having come from a family of &#8220;lifers&#8221;, it wasn&#8217;t an easy decision.  Even though I absolutely loved both the work and people, I felt that I would have too many regrets not taking this opportunity.</p>
<p><strong>So with that said, here&#8217;s a few of my lasting memories:</strong></p>
<ul>
<li>Late nights in the dreaded server room with Wally and co.</li>
<li>The lunchroom gang &#8211; Our topics ranged the gamut; from MMA to the next <a href="http://en.wikipedia.org/wiki/4chan">4chan</a> meme.
<li>Admiral&#8217;s Cup &#8211; We won a basketball game! (Not by forfeit!)</li>
<li>Ping pong Fridays!</li>
<li>Almost killing my co-worker Cindy with the Wii controller&#8230; and then my yo-yo.</li>
<li>Monday morning chats with Gits about his weekend PS3 adventures.</li>
<li>Steve&#8217;s yellow lunch truck</li>
</ul>
<p>Though I came in a contractor, I feel as though I&#8217;m leaving as family.  So with that said, farewell, good luck, and Godspeed to everyone at FLT!</p>
<p align="center">
<a href="http://flickr.com/photos/ryankanno/sets/72157607882338532/"><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/10/mullet.jpg" alt="" title="mullet" width="500" height="375" class="aligncenter size-full wp-image-252" style="padding:5px; border:1px solid #114477;"/></a>
</p>
<p style="text-align:center;">
Click on my picture to check out <a href="http://flickr.com/photos/ryankanno/sets/72157607882338532/">my flickr set</a>!</p>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=244&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/5gtmsBImZ24" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/10/10/another-turning-point-a-fork-stuck-in-the-road/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/10/10/another-turning-point-a-fork-stuck-in-the-road/</feedburner:origLink></item>
		<item>
		<title>Using Capistrano to deploy to WebFaction</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/qYVcfV11F6k/</link>
		<comments>http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/#comments</comments>
		<pubDate>Tue, 16 Sep 2008 16:57:30 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[WebFaction]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[ror]]></category>
		<category><![CDATA[ruby on rails]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=215</guid>
		<description><![CDATA[Update
If you like to stay on the edge, check out my latest post describing how to use Capistrano 2.5 to deploy Rails 2.3 to Webfaction!  


There&#8217;s nothing I love more than sweet automation.
After spending the better part of an hour searching the great Googs, there was only a single blog I could find describing [...]]]></description>
			<content:encoded><![CDATA[<h2>Update</h2>
<p>If you like to stay on the edge, check out my latest <a href="http://blog.localkinegrinds.com/2009/07/27/update-using-capistrano-2-5-to-deploy-rails-2-3-to-webfaction/">post describing how to use Capistrano 2.5 to deploy Rails 2.3 to Webfaction</a>!  </p>
<hr/>
<p><a href="http://blog.localkinegrinds.com/wp-content/uploads/2008/09/automator-icon.jpg"><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/09/automator-icon.jpg" alt="" title="automator-icon" width="200" height="200" class="alignright size-full wp-image-233" /></a></p>
<h2>There&#8217;s nothing I love more than sweet automation.</h2>
<p>After spending the better part of an hour searching the great Googs, there was only a single blog I could find describing <a href="http://mega.blaix.com/2007/8/29/capistrano-on-webfaction">how to use Capistrano to deploy to WebFaction</a>.  <em>Unfortunately, Justin was describing a Capistrano 1.4 deployment.</em> I found a <a href="http://forum.webfaction.com/viewtopic.php?id=598">few</a> <a href="http://forum.webfaction.com/viewtopic.php?id=1610">posts</a> on the <a href="http://forum.webfaction.com/">WebFaction forums</a>, but nothing concrete.  So after a few hours fiddling with the technology, here&#8217;s how I configured my <a href="http://www.rubyonrails.org/">Rails</a> 2.1.1 project to use <a href="http://www.capify.org/">Capistrano</a> 2.5 to deploy to <a href="http://www.webfaction.com">WebFaction</a>.</p>
<h3>Assumptions</h3>
<p>Before getting started, I&#8217;m going to assume the following:</p>
<ul>
<li>I&#8217;m assuming you&#8217;ve already used the one-click WebFaction goodness to create a brand new Rails application in ~/webapps/&lt;application_name&gt;.  If you don&#8217;t know what I&#8217;m referring to, make sure to check out the <a href="http://www.webfaction.com/demos/rails-typo">Rails and Typo Demo screencast</a>.  Make sure you have a domain, application, and website configured.</li>
<li>I&#8217;m also going to assume that your nifty Rails application is safely stored away in either a <a href="http://subversion.tigris.org/">Subversion</a> or <a href="http://git.or.cz/">Git</a> repository and you&#8217;ve frozen Rails in your application.</li>
<li>Finally, I&#8217;m going to assume you setup your database via <a href="http://www.webfaction.com/screencasts/control-panel-demo/demo.html">WebFaction&#8217;s control panel</a>.
</ul>
<h3>Installing Capistrano</h3>
<p>The very first thing you have to do is install Capistrano on your <em>local machine</em> by issuing the following command:</p>
<pre class="console">
$ gem install -y capistrano
</pre>
<p>After installing Capistrano, the first thing you have to do is to &#8220;capify&#8221; your local Rails project.  Change into your project&#8217;s root directory and issue the following command:</p>
<pre class="console">
$ capify .
</pre>
<p>This configures your Rails project to play nicely with Capistrano.  Two files should&#8217;ve been created; <strong>Capfile</strong> in the project root and <strong>config/deploy.rb</strong>.  The deploy.rb file contains the Rails project application-specific deployment configuration.</p>
<h3>Configuring WebFaction</h3>
<p>Jumping back to WebFaction, I followed a few of the steps in <a href="http://mega.blaix.com/2007/8/29/capistrano-on-webfaction">Justin&#8217;s blog</a>.  First thing&#8217;s first, ssh into your WebFaction account and create a directory called <strong>webapps-releases</strong> in your home directory.  This directory is where we&#8217;re going to deploy the application to.</p>
<p>Since you&#8217;ve already configured a Rails application at ~/webapps/&lt;application_name&gt;, change into that directory.  You should see a standard Rails project with the exception of an extra file called autostart.cgi.  Remove everything in the directory except the autostart.cgi file by issuing the following commands:</p>
<pre class="console">
$ cd ~/webapps/&lt;application_name&gt;
$ mv autostart.cgi ~/
$ rm -rf *
$ mv ~/autostart.cgi .
</pre>
<p>Once the directory is clear, create a symlink to the log directory that will be in the webapps-releases directory we created earlier.</p>
<pre class="console">
$ ln -s ~/webapps-releases/&lt;application_name&gt;/shared/log ~/webapps/&lt;application_name&gt;/log
</pre>
<p><strong>Note:</strong> I&#8217;m assuming here that the WebFaction app and the Rails application have identical names.</p>
<p>Next, open up your favorite editor of choice (*cough*Vi*cough*) and edit the <strong>autostart.cgi</strong> file.  Jump to the end of the file and comment out the following line:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #808080; font-style: italic;"># os.system('/usr/local/bin/mongrel_rails start -d -e production -P /home/&lt;webfaction_username&gt;/webapps/&lt;webfaction_app_name&gt;/log/mongrel.pid -p &lt;port&gt;')</span></pre></td></tr></table></div>

<p>and right below it, cut and paste the following:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">&nbsp;
  <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/usr/local/bin/mongrel_rails start -c /home/&lt;webfaction_username&gt;/webapps-releases/&lt;webfaction_app_name&gt;/current -d -e production -P /home/&lt;webfaction_username&gt;/webapps/&lt;webfaction_app_name&gt;/log/mongrel.pid -p &lt;port&gt;'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h3>Creating your custom deploy.rb</h3>
<p>After configuring WebFaction, we have to configure the Capistrano application deployment configuration.  On your local machine, find the file <strong>config/deploy.rb</strong> and replace it with the one below.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:webfaction_username</span>, <span style="color:#996600;">&quot;&lt;webfaction_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db_type</span>, <span style="color:#996600;">&quot;&lt;webfaction_db_type&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db</span>, <span style="color:#996600;">&quot;&lt;webfaction_db&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_db_username</span>, <span style="color:#996600;">&quot;&lt;webfaction_db_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:webfaction_port</span>, <span style="color:#996600;">&quot;&lt;webfaction_port (get from autostart.cgi)&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:database_yml_template</span>, <span style="color:#996600;">&quot;database.example.yml&quot;</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:application</span>, <span style="color:#996600;">&quot;test&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:deploy_to</span>, <span style="color:#996600;">&quot;/home/#{webfaction_username}/webapps-releases/#{application}&quot;</span>
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:scm</span>, <span style="color:#ff3333; font-weight:bold;">:subversion</span>
set <span style="color:#ff3333; font-weight:bold;">:scm_user</span>, <span style="color:#996600;">&quot;&lt;scm_username&gt;&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:scm_password</span>, <span style="color:#CC0066; font-weight:bold;">Proc</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">Capistrano::CLI</span>.<span style="color:#9900CC;">password_prompt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Subversion password for #{scm_user}: &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
set <span style="color:#ff3333; font-weight:bold;">:repository</span>, <span style="color:#CC0066; font-weight:bold;">Proc</span>.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;--username #{scm_user} --password #{scm_password} --no-auth-cache &lt;http://path/to/your/svn/goes/here/&gt;&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span> 
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:user</span>, <span style="color:#996600;">&quot;#{webfaction_username}&quot;</span>
set <span style="color:#ff3333; font-weight:bold;">:use_sudo</span>, <span style="color:#0000FF; font-weight:bold;">false</span> 
&nbsp;
set <span style="color:#ff3333; font-weight:bold;">:domain</span>, <span style="color:#996600;">&quot;&lt;webfaction_domain&gt;&quot;</span>
&nbsp;
role <span style="color:#ff3333; font-weight:bold;">:app</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:web</span>, domain
role <span style="color:#ff3333; font-weight:bold;">:db</span>,  domain, <span style="color:#ff3333; font-weight:bold;">:primary</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
&nbsp;
desc <span style="color:#996600;">&quot;Symlink public to what webfaction expects the webroot to be&quot;</span>
task <span style="color:#ff3333; font-weight:bold;">:after_symlink</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:web</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  run <span style="color:#996600;">&quot;ln -nfs #{release_path}/public /home/#{webfaction_username}/webapps/#{application}/&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
namespace <span style="color:#ff3333; font-weight:bold;">:deploy</span> <span style="color:#9966CC; font-weight:bold;">do</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Taken from http://jonathan.tron.name/2006/07/15/capistrano-password-prompt-tips </span>
  <span style="color:#008000; font-style:italic;"># Thanks Jonathan! :)</span>
  desc <span style="color:#996600;">&quot;Creates the database configuration on the fly&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:create_database_configuration</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">&quot;yaml&quot;</span>
    set <span style="color:#ff3333; font-weight:bold;">:production_db_password</span>, <span style="color:#CC0066; font-weight:bold;">proc</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">Capistrano::CLI</span>.<span style="color:#9900CC;">password_prompt</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;Remote production database password: &quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
    db_config = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::load_file<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;config/#{database_yml_template}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    db_config.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'test'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    db_config.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'development'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'adapter'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db_type}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'database'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'username'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;#{webfaction_db_username}&quot;</span>
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'password'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = production_db_password
    db_config<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'production'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'host'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;localhost&quot;</span>
&nbsp;
    put <span style="color:#CC00FF; font-weight:bold;">YAML</span>::dump<span style="color:#006600; font-weight:bold;">&#40;</span>db_config<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#996600;">&quot;#{release_path}/config/database.yml&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:mode</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> 0664
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  after <span style="color:#996600;">&quot;deploy:update_code&quot;</span>, <span style="color:#996600;">&quot;deploy:create_database_configuration&quot;</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:start&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:start</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/usr/local/bin/mongrel_rails start -c #{deploy_to}/current -d -e production -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid -p #{webfaction_port}&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:restart&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:restart</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/usr/local/bin/mongrel_rails restart -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  desc <span style="color:#996600;">&quot;Redefine deploy:stop&quot;</span>
  task <span style="color:#ff3333; font-weight:bold;">:stop</span>, <span style="color:#ff3333; font-weight:bold;">:roles</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:app</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    invoke_command <span style="color:#996600;">&quot;/usr/local/bin/mongrel_rails stop -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:via</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> run_method
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

<div style="font:normal 1.1em arial; background-color:#E5F3FF; padding:1em; margin:1em 0; border:1px solid #114477; color:#33415D;"><strong>Note:</strong> Change all the values in tags like <strong>&lt;webfaction_username&gt;</strong>, <strong>&lt;webfaction_db&gt;</strong>, <strong>&lt;webfaction_db_username&gt;</strong>, etc. to those values that fit your configuration!<br/>Otherwise, this file in itself won&#8217;t do you any good.</div>
<p><strong>Props out to <a href="http://jonathan.tron.name/">Jonathan</a> for the fantastic Capistrano tips!</strong></p>
<p>After copying the deploy.rb file and editing the appropriate variables, run the following command in your Rails project&#8217;s root directory:</p>
<pre class="console">
$ cap deploy:setup
</pre>
<p>This command creates the appropriate directory structure for Capistrano on the deployment server based upon values set in your deploy.rb.  Next, run the following command to check your dependencies.</p>
<pre class="console">
$ cap deploy:check
</pre>
<p>If everything is successful, you should see a message that reads something like&#8230;<br/></p>
<p><strong>You appear to have all necessary dependencies installed</strong></p>
<p>Next, push your code out to the server using the following command:</p>
<pre class="console">
$ cap deploy:update
</pre>
<p>Finally, to start up your application run the following Capistrano command:</p>
<pre class="console">
$ cap deploy:start
</pre>
<p>Now, you should be able to run the standard Capistrano tasks to deploy your application to WebFaction!</p>
<h3>Explanation</h3>
<p>Most techies like to have an explanation of what&#8217;s going on with the Capistrano deploy.rb.  I could probably write another blog about it, but I&#8217;m lazy (and pressed for time).  The :create_database_configuration task basically writes the database.yml production configuration on the fly (courtesy of this <a href="http://jonathan.tron.name/2006/07/15/capistrano-password-prompt-tips">blog posting</a>).</p>
<p>The basic gyst of the rest of the script is that WebFaction is proxying a Mongrel instance.  The Capistrano deploy.rb override the original deploy:start, deploy:stop, and deploy:restart tasks to run Mongrel commands that WebFaction can understand.  Typically, the default Capistrano tasks run script/spin and reaper, but it was easier just to redefine the task.  <strong>If anyone has any tips/suggestions to improve the script, I&#8217;m all ears!  </strong></p>
<h2>Voila! (Enjoy)</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=215&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/qYVcfV11F6k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/</feedburner:origLink></item>
		<item>
		<title>web2email.py – A web to email Python backup script</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/GruMGYNh6ME/</link>
		<comments>http://blog.localkinegrinds.com/2008/09/02/web2emailpy-a-web-to-email-python-backup-script/#comments</comments>
		<pubDate>Tue, 02 Sep 2008 08:14:43 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[smtp]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=191</guid>
		<description><![CDATA[I&#8217;m back, at least for the time being.  There&#8217;s definitely a calm before the impending storm, but until then, I&#8217;m back posting little tidbits of uselessness.  Enjoy!
Python goodness
While introducing the concept of automation to a friend of mine, I came across a requirement to archive a series of URL&#8217;s on a daily basis. [...]]]></description>
			<content:encoded><![CDATA[<div class="info"><b>I&#8217;m back</b>, at least for the time being.  There&#8217;s definitely a calm before the impending storm, but until then, I&#8217;m back posting little tidbits of uselessness.  <strong>Enjoy!</strong></div>
<h2>Python goodness</h2>
<p>While introducing the concept of automation to a friend of mine, I came across a requirement to archive a series of URL&#8217;s on a daily basis.  Luckily for me, the URL&#8217;s consisted primarily of plain text.  Loading up VIM, I concocted this Python script in a few hours &#8211; most of which was spent searching Googs <3.  </p>
<p>If you're looking for a true web crawler, this won't be for you - though loading up <a href="http://codespeak.net/lxml/">lxml</a>/<a href="http://www.crummy.com/software/BeautifulSoup/">Beautiful Soup</a>, <a href="http://code.google.com/p/cssutils/">cssutils</a>, and a Javascript parser to determine what artifacts need to be downloaded shouldn&#8217;t be all that difficult&#8230;</p>
<h3>But, I&#8217;ll leave that as an exercise for the reader (That&#8217;s you, btw!)</h3>
<p>In any case, the following script crawls a URL and sends the page via Googs or <a href="http://www.webfaction.com">Webfaction</a> via SMTP-AUTH or via a plain SMTP server of your choosing.  Sorta-kinda like having your own <a href="http://www.archive.org/web/web.php">WayBackMachine</a>.  In any case, cut and paste the following into a neat file called web2email.py.<br />
<br/></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/env python2.5</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Copyright (c) 2008 Ryan Kanno (ryankanno@localkinegrinds.com)</span>
<span style="color: #808080; font-style: italic;"># License: GNU GPLv3</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib2</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">MIMEMultipart</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEMultipart
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">MIMEBase</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEBase
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">MIMEText</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEText
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">Utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> COMMASPACE, formatdate
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span> <span style="color: #ff7700;font-weight:bold;">import</span> Encoders
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> OptionParser
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">logging</span>
&nbsp;
__doc__ = <span style="color: #483d8b;">&quot;&quot;&quot;
&nbsp;
This script retrieves a URL and sends its contents via email to 
a list of recipients.  Typically, this script is run from a cron
job that sends emails to a Gmail account to archive the contents
of a URL.
&nbsp;
Mail can be sent via normal or authenticated SMTP.  Tested using 
Gmail SMTP (authenticated), Webfaction SMTP (authenticated), and
localhost (normal).
&nbsp;
Example:
&nbsp;
Sends the contents of http://www.espn.com to friend@domain.com using your Gmail settings
&nbsp;
    python web2email.py -u gmail_username <span style="color: #000099; font-weight: bold;">\</span>
                        -p gmail_password <span style="color: #000099; font-weight: bold;">\</span>
                        -f gmail_username@gmail.com <span style="color: #000099; font-weight: bold;">\</span>
                        -r friend@domain.com http://www.espn.com
&nbsp;
Sends the contents of http://www.espn.com to friend@domain.com using your Webfaction settings
&nbsp;
    python web2email.py -u webfaction_username <span style="color: #000099; font-weight: bold;">\</span>
                        -p webfaction_password <span style="color: #000099; font-weight: bold;">\</span>
                        -f webfaction_account@webfaction_domain.com <span style="color: #000099; font-weight: bold;">\</span>
                        -s smtp.webfaction.com <span style="color: #000099; font-weight: bold;">\</span>
                        -r friend@domain.com http://www.espn.com
&nbsp;
Sends the contents of http://www.espn.com to friend@domain.com using your local settings
&nbsp;
    python web2email.py -f your_email@domain.com <span style="color: #000099; font-weight: bold;">\</span>
                        -s localhost <span style="color: #000099; font-weight: bold;">\</span>
                        --port 25 <span style="color: #000099; font-weight: bold;">\</span>
                        -r friend@domain.com http://www.espn.com
&quot;&quot;&quot;</span>
&nbsp;
__author__  = <span style="color: #483d8b;">&quot;ryankanno@localkinegrinds.com&quot;</span>
__url__     = <span style="color: #483d8b;">&quot;http://blog.localkinegrinds.com&quot;</span>
__version__ = <span style="color: #483d8b;">&quot;0.1&quot;</span>
&nbsp;
USAGE = <span style="color: #483d8b;">&quot;usage: %prog [options] url&quot;</span> 
DESC  = __doc__.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> configure_logging<span style="color: black;">&#40;</span>log_level, format=<span style="color: #483d8b;">'%(asctime)s %(levelname)s %(message)s'</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=log_level, format=format<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _validate_options_and_args<span style="color: black;">&#40;</span><span style="color: #dc143c;">parser</span>, options, args<span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Validating options and arguments.&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Incorrect number of arguments.  Script expects 1 (URL to backup), but received %i.&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Command line syntax error</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #ff7700;font-weight:bold;">not</span> options.<span style="color: black;">recipients</span>: 
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;You must include at least one recipient.&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: black;">&#40;</span>options.<span style="color: black;">username</span> <span style="color: #ff7700;font-weight:bold;">and</span> options.<span style="color: black;">password</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span>options.<span style="color: black;">username</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">and</span> options.<span style="color: black;">password</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;You must include both a username and password.&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #ff7700;font-weight:bold;">not</span> options.<span style="color: black;">from_email</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;You must include a valid from email address.&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> 
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getPage<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Attempting to retrieve %s&quot;</span> <span style="color: #66cc66;">%</span> url<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        response = <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">HTTPError</span>, e:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;HTTPError (%s) occurred retrieving %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>e.<span style="color: #dc143c;">code</span>, url<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">URLError</span>, e:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;URLError (%s) occurred retrieving %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>e.<span style="color: black;">reason</span>, url<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> mail<span style="color: black;">&#40;</span>send_from, send_to, subject, text, content_type, files=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>, server=<span style="color: #483d8b;">'localhost'</span>, port=<span style="color: #ff4500;">25</span>, username=<span style="color: #008000;">None</span>, password=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _auth<span style="color: black;">&#40;</span>server, port, username, password<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Attempting to send email via %s:%i using the following credentials (%s:%s).&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>server, port, username, password<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        smtp = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span>server, port<span style="color: black;">&#41;</span> 
        smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">starttls</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">login</span><span style="color: black;">&#40;</span>username, password<span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>username, send_to, msg.<span style="color: black;">as_string</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _unauth<span style="color: black;">&#40;</span>server, port<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Attempting to send email via %s:%i&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>server, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        smtp = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span>server, port<span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>send_from, send_to, msg.<span style="color: black;">as_string</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        smtp.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>send_to<span style="color: black;">&#41;</span>==<span style="color: #008000;">list</span>
&nbsp;
    msg=MIMEMultipart<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    msg<span style="color: black;">&#91;</span><span style="color: #483d8b;">'From'</span><span style="color: black;">&#93;</span> = send_from
    msg<span style="color: black;">&#91;</span><span style="color: #483d8b;">'To'</span><span style="color: black;">&#93;</span> = COMMASPACE.<span style="color: black;">join</span><span style="color: black;">&#40;</span>send_to<span style="color: black;">&#41;</span>
    msg<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Date'</span><span style="color: black;">&#93;</span> = formatdate<span style="color: black;">&#40;</span>localtime=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    msg<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Subject'</span><span style="color: black;">&#93;</span> = subject
&nbsp;
    text = MIMEText<span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>
    text.<span style="color: black;">set_type</span><span style="color: black;">&#40;</span>content_type<span style="color: black;">&#41;</span>
    text.<span style="color: black;">set_param</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'charset'</span>, <span style="color: #483d8b;">'UTF-8'</span><span style="color: black;">&#41;</span>
&nbsp;
    msg.<span style="color: black;">attach</span><span style="color: black;">&#40;</span>text<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files:
        part = MIMEBase<span style="color: black;">&#40;</span><span style="color: #483d8b;">'application'</span>, <span style="color: #483d8b;">&quot;octet-stream&quot;</span><span style="color: black;">&#41;</span>
        part.<span style="color: black;">set_payload</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">file</span>,<span style="color: #483d8b;">&quot;rb&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        Encoders.<span style="color: black;">encode_base64</span><span style="color: black;">&#40;</span>part<span style="color: black;">&#41;</span>
        part.<span style="color: black;">add_header</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Disposition'</span>, <span style="color: #483d8b;">'attachment; filename=&quot;%s&quot;'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        msg.<span style="color: black;">attach</span><span style="color: black;">&#40;</span>part<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> username <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> password:
        _unauth<span style="color: black;">&#40;</span>server, port<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        _auth<span style="color: black;">&#40;</span>server, port, username, password<span style="color: black;">&#41;</span> 
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">parser</span> = OptionParser<span style="color: black;">&#40;</span>usage=USAGE, description=DESC<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-u&quot;</span>, <span style="color: #483d8b;">&quot;--username&quot;</span>, dest=<span style="color: #483d8b;">&quot;username&quot;</span>, metavar=<span style="color: #483d8b;">&quot;USER&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;Username to SMTP server&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-p&quot;</span>, <span style="color: #483d8b;">&quot;--password&quot;</span>, dest=<span style="color: #483d8b;">&quot;password&quot;</span>, metavar=<span style="color: #483d8b;">&quot;PWD&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;Password to SMTP server&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-s&quot;</span>, <span style="color: #483d8b;">&quot;--server&quot;</span>, dest=<span style="color: #483d8b;">&quot;server&quot;</span>, metavar=<span style="color: #483d8b;">&quot;SERVER&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;SMTP server (Defaults to Gmail)&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;--port&quot;</span>, dest=<span style="color: #483d8b;">&quot;port&quot;</span>, metavar=<span style="color: #483d8b;">&quot;PORT&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;int&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;SMTP server port (Defaults to Gmail)&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-f&quot;</span>, <span style="color: #483d8b;">&quot;--from&quot;</span>, dest=<span style="color: #483d8b;">&quot;from_email&quot;</span>, metavar=<span style="color: #483d8b;">&quot;FROM&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;From address&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-r&quot;</span>, <span style="color: #483d8b;">&quot;--recipient&quot;</span>, action=<span style="color: #483d8b;">&quot;append&quot;</span>, dest=<span style="color: #483d8b;">&quot;recipients&quot;</span>, metavar=<span style="color: #483d8b;">&quot;RCPT&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;string&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;Email recipient&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-t'</span>, <span style="color: #483d8b;">'--test'</span>, action=<span style="color: #483d8b;">&quot;store_true&quot;</span>, dest=<span style="color: #483d8b;">&quot;test&quot;</span>, metavar=<span style="color: #483d8b;">&quot;TEST&quot;</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">&quot;Run tests&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-v'</span>, <span style="color: #483d8b;">'--verbose'</span>, action=<span style="color: #483d8b;">'store_const'</span>, dest=<span style="color: #483d8b;">'log_level'</span>, const=<span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span>, <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'Verbose output'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">set_defaults</span><span style="color: black;">&#40;</span>server=<span style="color: #483d8b;">&quot;smtp.gmail.com&quot;</span>, port=<span style="color: #ff4500;">587</span>, <span style="color: #dc143c;">test</span>=<span style="color: #008000;">False</span>, log_level=<span style="color: #dc143c;">logging</span>.<span style="color: black;">INFO</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#40;</span>options, args<span style="color: black;">&#41;</span> = <span style="color: #dc143c;">parser</span>.<span style="color: black;">parse_args</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    _validate_options_and_args<span style="color: black;">&#40;</span><span style="color: #dc143c;">parser</span>, options, args<span style="color: black;">&#41;</span>
    configure_logging<span style="color: black;">&#40;</span>options.<span style="color: black;">log_level</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: #dc143c;">test</span>:
        _test<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Too lazy to write a test for this script.  @TODO - use mocks </span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Retrieve URL and return html</span>
    html = getPage<span style="color: black;">&#40;</span>args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Send mail with returned html as body </span>
    mail<span style="color: black;">&#40;</span>options.<span style="color: black;">from_email</span>, options.<span style="color: black;">recipients</span>, 
         <span style="color: #483d8b;">'%s @ %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%A %B %d %I:%M:%S %p %Y&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, 
         html, <span style="color: #483d8b;">'text/html'</span>, 
         server=options.<span style="color: black;">server</span>, port=options.<span style="color: black;">port</span>, username=options.<span style="color: black;">username</span>, password=options.<span style="color: black;">password</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Return with appropriate exit code</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _test<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">doctest</span>
    <span style="color: #dc143c;">doctest</span>.<span style="color: black;">testmod</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">modules</span><span style="color: black;">&#91;</span>__name__<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h3>All right stop, cron time! (imagine a 90&#8217;s pop song)</h3>
<p>As an added bonus, you can install this script to run via <a href="http://en.wikipedia.org/wiki/Cron">cron</a> so you&#8217;ll magically end up with webpages archived in your inbox!  Neat.  You can read my <a href="http://blog.localkinegrinds.com/2008/02/10/backing-up-your-subversion-svn-repository-on-dreamhost-with-cron/">previous post on cron</a>, or you can create the following crontab.</p>
<pre class="script">
MAILTO=ryankanno@CHANGE_TO_YOUR_EMAIL.com
# minute (0-59),
# |      hour (0-23),
# |      |       day of the month (1-31),
# |      |       |       month of the year (1-12),
# |      |       |       |       day of the week (0-6 with 0=Sunday).
# |      |       |       |       |       commands
  0      0       *       *       *      /usr/bin/python2.5 /PATH/TO/web2email.py -u GMAIL_USER -p GMAIL_PWD -f FROM_USER -r RECIPIENT URL
</pre>
<p><strong>As a side note, don&#8217;t forget double quotes around URL if there&#8217;s spaces!</strong></p>
<div style="font:bold 1.1em arial; background-color:#E5F3FF; padding:1em; margin:1em 0; border:1px solid #114477; color:#33415D;">Notice, change the value of ryankanno@CHANGE_TO_YOUR_EMAIL.com to your email address (or comment the line out with a # if you don&#8217;t want emails sent to you), GMAIL_USER to your Google username, GMAIL_PWD to your Google password, FROM_USER to the from address in the mail header, RECIPIENT to the recipient email address, and URL to the URL you want backed up.</div>
<h3>I know, I know. The critics.</h3>
<p>The critics will say that your Gmail username and password are in cleartext.  I know.  <strong>They are.</strong>  So&#8230; I&#8217;m hoping that since you just need an archive of a publicly available URL on the Internets, the data doesn&#8217;t need to be super-duper-Fort-Knox-protected.  If it does, this script isn&#8217;t for you. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />   Oh, yeah, before I forget&#8230; here&#8217;s a hint&#8230; *<strong>cough</strong>*create another Google account*<strong>cough</strong>*.  With that said, archive to your heart&#8217;s content!</p>
<h2>Enjoy!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=191&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/GruMGYNh6ME" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/09/02/web2emailpy-a-web-to-email-python-backup-script/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/09/02/web2emailpy-a-web-to-email-python-backup-script/</feedburner:origLink></item>
		<item>
		<title>Got Toes? The Vibram FiveFingers Review</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/2PmY-FQcaH4/</link>
		<comments>http://blog.localkinegrinds.com/2008/07/08/got-toes-the-vibram-fivefingers/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 08:25:22 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[barefooting]]></category>
		<category><![CDATA[fivefingers]]></category>
		<category><![CDATA[inventions]]></category>
		<category><![CDATA[marathon]]></category>
		<category><![CDATA[running]]></category>
		<category><![CDATA[toes]]></category>
		<category><![CDATA[vibram]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=184</guid>
		<description><![CDATA[Let me first preface this blog by stating that no, I&#8217;m not dead.  I&#8217;ve been a little really busy with work.  Don&#8217;t worry, I have a bunch of new blogs planned around all the useless pieces of software that I&#8217;m working on.  Until then, check out some of my latest buys.
I finally [...]]]></description>
			<content:encoded><![CDATA[<div class="bold info">Let me first preface this blog by stating that no, I&#8217;m not dead.  I&#8217;ve been <strike>a little</strike> really busy with work.  Don&#8217;t worry, I have a bunch of new blogs planned around all the useless pieces of software that I&#8217;m working on.  Until then, check out some of my latest buys.</div>
<h2>I finally succumbed to peer pressure.</h2>
<p><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/07/vibram.jpg'><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/07/vibram.jpg" alt="Vibram FiveFingers" title="Vibram FiveFingers" width="139" height="125" class="alignright size-full wp-image-190" /></a><br />
After some careful online research (like <a href="http://mygaragegym.blogspot.com/">here</a>, <a href="http://runningsoules.wordpress.com/2008/06/07/vibram-fivefinger-review/">here</a>, and <a href="http://www.posetech.com/video/index.php/weblog/vibram_fivefingers_review/">here</a>) and being persuaded by my co-worker <a href="http://twitter.com/stephaneliu">Stephane</a>, I finally <a href="http://www.urbandictionary.com/define.php?term=mozy">mozied</a> on down to get myself a pair of <a href="http://www.vibramfivefingers.com/">Vibram FiveFingers</a>.  After all, being named one of <a href="http://www.vibramfivefingers.com/UserFiles/File/Time_award.jpg">Time Magazine&#8217;s Inventions of the Year</a> couldn&#8217;t be all that bad&#8230; right? <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>After perusing <a href="http://www.vibramfivefingers.com/productSupport/store_locator.cfm#">their website</a>, I found only two retailers on Oahu that sold them.</p>
<ul>
<li>Uyeda Shoe Store across from Puck&#8217;s Alley (<a href="http://maps.google.com/maps?hl=en&#038;um=1&#038;ie=UTF-8&#038;q=2615+S+King+St+Honolulu,+HI+96826&#038;fb=1&#038;geocode=9933992599662061239,21.294595,-157.824138&#038;oi=manybox&#038;ct=14&#038;cd=1&#038;resnum=1">map</a>)</li>
<li>The Wheatgrass Center behind the Bank of Hawaii on Waialae (<a href="http://maps.google.com/maps?hl=en&#038;um=1&#038;ie=UTF-8&#038;q=1215+Center+St+Honolulu,+HI+96816&#038;fb=1&#038;geocode=6158308545376850426,21.285763,-157.801557&#038;oi=manybox&#038;ct=14&#038;cd=1&#038;resnum=1">map</a>)</li>
</ul>
<p>After calling Uyeda&#8217;s several times and being greeted with one of those funky fax feedback tones each time (note &#8211; please update your online phone number), I finally decided to ring up The Wheatgrass Center.  For those of you instructionally-impaired like myself, just take a left on Waialae Ave. before the Bank of Hawaii heading Kahala bound.  Located behind the bank, The Wheatgrass Center is quite an interesting store selling both the Vibram FiveFingers and of course&#8230; wheatgrass.  (Why people want to ruminate like cows is still truly beyond me.)</p>
<h2>Review</h2>
<p>When I first saw the Vibram FiveFinger, I did what any other (semi) normal human being would do &#8211; I laughed.  Not any normal laugh, mind you &#8211; but a &#8220;there&#8217;s no f-in way I&#8217;m wearing <strong>that</strong> in public&#8221; laugh.  They resemble footwear of a <a href="http://www.realultimatepower.net/index4.htm">ninja-in-training</a>, and since I&#8217;m neither of the two (a ninja or in training), I really couldn&#8217;t fathom seeing myself in a pair.  </p>
<p>But after trying them on, I was immediately taken back; back to small kid time when I ran barefoot and carefree in the red dirt hills of Mililani.  The Vibram FiveFingers not only allows you to feel the contour of the ground, but also provides protection to the soles of your feet.  After being given the sales pitch by Mr. Fukuda, I was sold.  There&#8217;s a few models; I ended up purchasing the <a href="http://www.vibramfivefingers.com/products/products_classic.cfm">Classic</a>.  (Check out <a href="http://www.vibramfivefingers.com/products/products_footwear.cfm">their website</a> to see the entire product line).  Not to mention, Mr. Fukuda <strike>instructed</strike> ordered me to wear the pair out the door.  After a full weekend&#8217;s worth of wear and tear, here&#8217;s a few images of them on my feet &#8211; along with a short list of my pros and cons.</p>
<p style="text-align:center; margin:auto;">
<a rel="lightbox[vibram]" href='http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1091.jpg'><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1091-150x150.jpg" alt="Vibram flat on the kitchen floor" title="Vibram flat on the kitchen floor" width="150" height="150" class="thumb" /></a><a rel="lightbox[vibram]" href='http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1092.jpg'><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1092-150x150.jpg" alt="Vibram side profile" title="Vibram side profile" width="150" height="150" class="thumb" /></a><a rel="lightbox[vibram]" href='http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1095.jpg'><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1095-150x150.jpg" alt="Vibram angle" title="Vibram angle" width="150" height="150" class="thumb" /></a><a rel="lightbox[vibram]" href='http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1090.jpg'><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/07/cimg1090-150x150.jpg" alt="Vibram overhead view" title="Vibram overhead view" width="150" height="150" class="thumb" /></a>
</p>
<h3>The Pros</h3>
<ul>
<li>It&#8217;s surprisingly comfortable.  Sometimes my toes still feel weird being separated, but it&#8217;s pretty neat to actually feel the ground without fear of having a rock in your foot.  Btw, if you like the separated toe thing, check <a href="http://www.injinji.com/">these socks out from Injini</a>.</li>
<li>If everything the Internet world says is true (like we all know it is!), I&#8217;ll have crazy leg/toe muscles, damnit!  And, not to mention, it promotes a more natural walking motion.  To learn more, read <a href="http://www.marathonandbeyond.com/choices/clift.htm">this article about barefoot running</a>.</li>
</ul>
<h3>The Cons</h3>
<ul>
<li>I developed a blister on the back of my foot near my Achilles from the back strap.  It&#8217;s pretty sore, but after reading other reviews, I&#8217;m sure I&#8217;ll get used to it.</li>
<li>Since I&#8217;m fairly self-deprecating and a non-fashionista (you should see my car), the design doesn&#8217;t faze me one bit &#8211; but I could see how embarrassment could set in.</li>
<li>The price.  $73 bucks isn&#8217;t a drop in the bucket in this economy.  Damn, do you know how many beers I&#8217;m giving up for this?</li>
</ul>
<h4>I&#8217;ll tell you in December how the Honolulu Marathon goes with these on!</h4>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=184&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/2PmY-FQcaH4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/07/08/got-toes-the-vibram-fivefingers/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/07/08/got-toes-the-vibram-fivefingers/</feedburner:origLink></item>
		<item>
		<title>ERB block comments in RHTML templates using Ruby on Rails</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/0d_q4D23NlY/</link>
		<comments>http://blog.localkinegrinds.com/2008/05/02/erb-block-comments-in-rhtml-templates-using-ruby-on-rails/#comments</comments>
		<pubDate>Fri, 02 May 2008 14:05:23 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[block comment]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[comment]]></category>
		<category><![CDATA[erb]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rhtml]]></category>
		<category><![CDATA[ror]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=169</guid>
		<description><![CDATA[This blog is simply a reminder to myself more than anything else.
After searching the great Googs and reading here, here, and here about commenting out regions in your RHTML templates, I couldn&#8217;t find a (good) solution aside from the () paradigm.  Using Rails 1.2.3 (I know, I know&#8230; we&#8217;re old school), to get block [...]]]></description>
			<content:encoded><![CDATA[<div class="bold info">This blog is simply a reminder to myself more than anything else.</div>
<p>After <a href="http://www.google.com/search?q=rhtml+comments&#038;ie=utf-8&#038;oe=utf-8&#038;aq=t&#038;rls=org.mozilla:en-US:official&#038;client=firefox-a">searching the great Googs</a> and reading <a href="http://www.neeraj.name/229/commenting-out-the-code-in-rhtml">here</a>, <a href="http://lists.netisland.net/archives/phillyonrails/phillyonrails-2005/msg00083.html">here</a>, and <a href="http://www.nabble.com/Re:-RHTML-comments-p12844273s27020.html">here</a> about commenting out regions in your RHTML templates, I couldn&#8217;t find a (good) solution aside from the (<... if false ...>) paradigm.  Using Rails 1.2.3 (I know, I know&#8230; we&#8217;re <a href="www.urbandictionary.com/define.php?term=old+school">old school</a>), to get block comments in Rails, the following worked for me, but unfortunately, still wasn&#8217;t recognized by <a href="http://www.netbeans.org/ ">NetBeans</a> 6.0 (Boo!).</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;">&lt;table&gt;
  ...
  &lt;tbody&gt;
    &lt;tr id=&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#996600;">&quot;photographer_#{photographer.id}&quot;</span><span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;&gt;
      &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span> 
<span style="color:#000080; font-style:italic;">=begin %&gt;</span>
<span style="color:#006600; font-weight:bold;">&lt;%</span>= h photographer.<span style="color:#9900CC;">first_name</span> <span style="color:#9966CC; font-weight:bold;">unless</span> photographer.<span style="color:#9900CC;">blank</span>? <span style="color:#006600; font-weight:bold;">%&gt;&lt;%</span> 
=<span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  ...
&lt;/table&gt;</pre></td></tr></table></div>

<h2>Happy Coding!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=169&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/0d_q4D23NlY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/05/02/erb-block-comments-in-rhtml-templates-using-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/05/02/erb-block-comments-in-rhtml-templates-using-ruby-on-rails/</feedburner:origLink></item>
		<item>
		<title>Google App Engine on Win2K (using django-yui-layout-templates)</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/66NjTzCsp8U/</link>
		<comments>http://blog.localkinegrinds.com/2008/04/17/google-app-engine-on-win2k-using-django-yui-layout-templates/#comments</comments>
		<pubDate>Thu, 17 Apr 2008 10:38:38 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[django-yui-layout-templates]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[yahoo!-ui]]></category>
		<category><![CDATA[yui]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/?p=171</guid>
		<description><![CDATA[Update : September 1, 2008
I guess Googs finally caught on as their 1.1.2 installer works on Win2K!  FTW!

Update
After finally getting time to play around with the Google App Engine Django helpers, here&#8217;s a few more steps to integrate nicely with the helper suite.  

Move the appengine installation from C:\AppEngine\ to where the Windows [...]]]></description>
			<content:encoded><![CDATA[<h3>Update : September 1, 2008</h3>
<p>I guess Googs finally caught on as their <a href="http://googleappengine.googlecode.com/files/GoogleAppEngine_1.1.2.msi">1.1.2 installer</a> works on Win2K!  FTW!</p>
<hr/>
<h3>Update</h3>
<p>After finally getting time to play around with the <a href="http://code.google.com/p/google-app-engine-django/">Google App Engine Django helpers</a>, here&#8217;s a few more steps to integrate nicely with the helper suite.  </p>
<ul>
<li>Move the appengine installation from C:\AppEngine\ to where the Windows installer would have installed it to: <strong>C:\Program Files\Google\google_appengine</strong> (make sure to clean up your .pyc files)
<li>Add the following to your PYTHONPATH system variable: <strong>%APPENGINE%\;%APPENGINE%\lib;%APPENGINE%\lib\yaml\lib;%APPENGINE%\lib\webob;</strong></li>
</ul>
<p>After <a href="http://code.google.com/appengine/articles/appengine_helper_for_django.html">following the instructions</a>, you should be good to go with <a href="http://www.djangoproject.com">Django</a> + <a href="http://code.google.com/appengine/">AppEngine</a>! FTW! Whee. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<hr/>
So I finally get an hour or so to play around with the <a href="http://code.google.com/appengine/">Googs App Engine</a> and luckily for me, all my machines decided to puke except for my Windows 2000 Server.  How ironic is that?  In disbelief, I downloaded <a href="http://code.google.com/appengine/downloads.html">the Google App Engine SDK Windows installer</a> and what do I get?</p>
<p class="center">
<a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/04/google_windows_installer.jpg' rel="lightbox" title="h.a.t.e.r.a.d.e I tell you"><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/04/google_windows_installer-300x231.jpg" alt="Google App Engine Windows installer" title="google_windows_installer" width="300" height="231" class="thumb"/></a>
</p>
<h4>I sense some pure, unadultered haterade. (j/k)</h4>
<p>Since <a href="http://www.python.org">Python</a> is one of those insert_any_synonym_for_fun languages that just works, here&#8217;s how to get the Google App Engine SDK working in Win2K.  </p>
<ul>
<li><a href="http://code.google.com/appengine/downloads.html">Download</a> the Linux/Other platform package and unzip to somewhere neat.</li>
<li>Add a System Environment variable called &#8216;APP_ENGINE_HOME&#8217; that points to your App Engine installation.  (Notice, I installed mine into <strong>C:\AppEngine</strong>)
<p class="center"><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/04/system_variable.jpg' rel="lightbox" title="Adding a system environment variable"><img src="http://blog.localkinegrinds.com/wp-content/uploads/2008/04/system_variable-259x300.jpg" alt="Add system variable" title="Add system variable" width="259" height="300" class="thumb" /></a></p>
</li>
<li>Add the System Environment variable to your System Path so the Windows shell can execute the included Python files.</li>
<li>Make sure you have .py files associated with the python.exe executable located in your Python installation.  (Check file types under folder options)</li>
<li>Follow the tutorials: <a href="http://code.google.com/appengine/docs/gettingstarted/">here</a> and <a href="http://www.42topics.com/dumps/django/docs.html">here</a>, or <a href="http://www.appenginebase.com/">learn with others</a> &#8211; just to name a few.</li>
<li>Oh, and before I forget, if you develop an application and realize that you can&#8217;t kill the development appserver (<strong>dev_appserver.py</strong>) by pressing Ctrl-C, I <a href="http://boodebr.org/main/python/cherrypy-under-google-appserver">found a solution here</a>.  Basically, press Ctrl-C, hit the server with your browser one more time and voila, the development application server dies.  Thanks Frank!</li>
</ul>
<h3>As an added bonus&#8230;</h3>
<div class="info">Checkout my <a href="http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/">my previous post</a> using the <a href="http://developer.yahoo.com/yui/">Yahoo UI library</a> to create a set of default <a href="http://http://www.djangoproject.com/documentation/templates/">Django templates</a>.  I&#8217;ve updated <a href="http://code.google.com/p/django-yui-layout-templates/"><strong>django-yui-layout-templates</strong></a> with patches and suggestions, and I&#8217;ve also created a few branches to support the Googly App Engine.  Check out the <a href="http://django-yui-layout-templates.googlecode.com/svn/branches/">branches directory in the Subversion repository</a>!</div>
<h3>Last but not least&#8230;</h3>
<p>Big ups to <a href="http://fitz.blogspot.com/">Mr. Fitz</a> for solving all my Google App Engine issues and thanks to <a href="http://www.nata2.org/">Mr. Harper</a> for causing them. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>Voila! (Enjoy)</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=171&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/66NjTzCsp8U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/04/17/google-app-engine-on-win2k-using-django-yui-layout-templates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/04/17/google-app-engine-on-win2k-using-django-yui-layout-templates/</feedburner:origLink></item>
		<item>
		<title>Yahoo! UI (YUI) + Django templates == Google Code project! FTW!</title>
		<link>http://feedproxy.google.com/~r/ryankanno/~3/VbUhKnCAc1c/</link>
		<comments>http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/#comments</comments>
		<pubDate>Fri, 21 Mar 2008 19:56:50 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[base-css]]></category>
		<category><![CDATA[fonts-css]]></category>
		<category><![CDATA[grids-css]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[reset-css]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[yahoo!-ui]]></category>
		<category><![CDATA[yui]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/</guid>
		<description><![CDATA[Let me first preface this blog by saying that I&#8217;m not a designer.  When it comes to art and creativity, I&#8217;m so left brained, I actually wonder if my right brain even partakes in the process.
Three things spurred me to release django-yui-layout-templates.

I&#8217;ve always wanted to see what GoogleCode offered in relation to SourceForge / [...]]]></description>
			<content:encoded><![CDATA[<div class="disclaimer"><b>Let me first preface this blog by saying that I&#8217;m not a designer.</b>  When it comes to art and creativity, I&#8217;m so left brained, I actually wonder if my right brain even partakes in the process.</div>
<h3>Three things spurred me to release <a href="http://code.google.com/p/django-yui-layout-templates/">django-yui-layout-templates</a>.</h3>
<ol>
<li>I&#8217;ve always wanted to see what <a href="http://code.google.com/">GoogleCode</a> offered in relation to <a href="http://sourceforge.net/">SourceForge</a> / <a href="http://www.rubyforge.org/">RubyForge</a>.</li>
<li>I&#8217;m so caught up in corporate America staring at Java / Ruby code all day, not only haven&#8217;t I blogged about anything <a href="http://www.djangoproject.com/">Django</a> related in quite a while, but it&#8217;s nice to get some commentary from the community, i.e. &#8220;your code sucks&#8221;. (Brings me back to reality)</li>
<li>I found myself using the same templates on a variety of projects and figured that I could do my part and help eliminate unncessary cruft/duplication.</li>
</ol>
<p>So without further adieu, check out the project <a href="http://code.google.com/p/django-yui-layout-templates/">here</a>.  I know, I know &#8211; nothing revolutionary here, but I figure since Django is <a href="http://antoniocangiano.com/2008/03/20/djangos-tipping-point/">picking up some steam</a>, these templates might help a Djangonaut get a head start on their next million dollar idea. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Voila! Enjoy!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=166&type=feed" alt="" /><img src="http://feeds.feedburner.com/~r/ryankanno/~4/VbUhKnCAc1c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.900 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-03-16 20:47:13 -->
