<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Ryan Kanno: The diary of an Enginerd in Hawaii&#187; Technology</title>
	<atom:link href="http://blog.localkinegrinds.com/category/technology/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.localkinegrinds.com</link>
	<description>Everything you&#039;ve ever thought, but never had the balls to say.</description>
	<lastBuildDate>Sat, 03 Sep 2011 13:19:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Update: Using Capistrano 2.5 to deploy Rails 2.3 to Webfaction</title>
		<link>http://blog.localkinegrinds.com/2009/07/27/update-using-capistrano-2-5-to-deploy-rails-2-3-to-webfaction/</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 2.3 [...]]]></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" rel="lightbox[366]"><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="" />]]></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>
		</item>
		<item>
		<title>Lessons Learned: Google App Engine + App Engine Patch + Django + Boto</title>
		<link>http://blog.localkinegrinds.com/2009/04/02/lessons-learned-google-app-engine-app-engine-patch-django-boto/</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 [...]]]></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="" />]]></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>
		</item>
		<item>
		<title>Using Capistrano to deploy to WebFaction</title>
		<link>http://blog.localkinegrinds.com/2008/09/16/using-capistrano-to-deploy-to-webfaction/</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 [...]]]></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" rel="lightbox[215]"><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="" />]]></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>
		</item>
		<item>
		<title>web2email.py &#8211; A web to email Python backup script</title>
		<link>http://blog.localkinegrinds.com/2008/09/02/web2emailpy-a-web-to-email-python-backup-script/</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&#8242;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="" />]]></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>
		</item>
		<item>
		<title>ERB block comments in RHTML templates using Ruby on Rails</title>
		<link>http://blog.localkinegrinds.com/2008/05/02/erb-block-comments-in-rhtml-templates-using-ruby-on-rails/</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="" />]]></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>
		</item>
		<item>
		<title>Google App Engine on Win2K (using django-yui-layout-templates)</title>
		<link>http://blog.localkinegrinds.com/2008/04/17/google-app-engine-on-win2k-using-django-yui-layout-templates/</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 [...]]]></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="" />]]></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>
		</item>
		<item>
		<title>Yahoo! UI (YUI) + Django templates == Google Code project! FTW!</title>
		<link>http://blog.localkinegrinds.com/2008/03/21/yahoo-ui-yui-django-templates-google-code-project-ftw/</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="" />]]></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>
		</item>
		<item>
		<title>Backing up your Subversion (SVN) repository on Dreamhost with cron</title>
		<link>http://blog.localkinegrinds.com/2008/02/10/backing-up-your-subversion-svn-repository-on-dreamhost-with-cron/</link>
		<comments>http://blog.localkinegrinds.com/2008/02/10/backing-up-your-subversion-svn-repository-on-dreamhost-with-cron/#comments</comments>
		<pubDate>Sun, 10 Feb 2008 22:02:56 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Dreamhost]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[back-up]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[crontabs]]></category>
		<category><![CDATA[hotcopy]]></category>
		<category><![CDATA[scheduler]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/2008/02/10/backing-up-your-subversion-svn-repository-on-dreamhost-with-cron/</guid>
		<description><![CDATA[Two events spurred me to write this blog. First, my 2 year old &#8220;Subversion + Dreamhost + Post-Commit&#8221; blog still gets quite a number of hits. Second, after the latest Dreamhost outage move, I&#8217;m beginning to feel a little more vigilant about backing up my data. As a standard disclaimer, if you&#8217;re not familiar with [...]]]></description>
			<content:encoded><![CDATA[<h3>Two events spurred me to write this blog.</h3>
<p>First, my <a href="http://blog.localkinegrinds.com/2006/12/15/dreamhost-subversion-post-commit-tutorial/">2 year old &#8220;Subversion + Dreamhost + Post-Commit&#8221; blog</a> still gets quite a number of hits.  Second, after the latest <a href="http://www.dreamhoststatus.com/2008/02/08/randy-move-going-ahead/">Dreamhost <strike>outage</strike> move</a>, I&#8217;m beginning to feel a little more vigilant about backing up my data.  </p>
<div class="disclaimer">As a standard disclaimer, if you&#8217;re not familiar with the Unix shell, I <strong>highly suggest</strong> you not try this unless under the supervision of someone who reads Perl books for fun.  By accessing your Dreamhost shell, you can seriously f-up your account and I will not fix it for you.  You have been warned. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  (Don&#8217;t you just love smileys?)</div>
<h3>Setup</h3>
<p>There are a few prerequisites to being able to back up your <a href="http://subversion.tigris.org/">SVN</a> repository.</p>
<ol>
<li>First and foremost, you must have already installed a SVN repository into your Dreamhost account via the <a href="https://panel.dreamhost.com/index.cgi?tree=goodies.svn&#038;">control panel</a>.</li>
<li>Second, you must know how to <a href="http://wiki.dreamhost.com/Ssh">SSH into your Dreamhost account</a>.  As a FYI, you sorta-kinda-need to know what that means in order to follow this tutorial.</li>
</ol>
<h3>Grabbing the backup script</h3>
<p>Wait, you didn&#8217;t think I was writing my own right?  In any case, if you actually installed/compiled Subversion on your own, it would&#8217;ve contained this file, <a href="http://svn.collab.net/repos/svn/trunk/tools/backup/hot-backup.py.in">hotbackup.py</a>.  Fortunately for us, Dreamhost has this file conveniently available at: <strong>/usr/bin/svn-hot-backup</strong>, but it&#8217;s an older version of the backup script.  There are some subtle differences like being unable to pass in the number of backups you want the script to manage.  Personally, I like to be on the edge, so let&#8217;s get the latest version.  Execute the following commands from your home directory.</p>
<pre class="console">
$ cd ~
$ mkdir scripts
$ cd scripts
$ wget http://svn.collab.net/repos/svn/trunk/tools/backup/hot-backup.py.in
$ mv hot-backup.py.in svn-hot-backup.py
</pre>
<p>The commands issued above created a directory called scripts in your home directory, switched into the directory, downloaded the latest hot-backup.py file from <a href="http://www.collab.net">CollabNet</a>, and renamed it to svn-hot-backup.py.  Now that you have the file, you&#8217;ll need to make a few edits.  Personally, I&#8217;m accustomed to vi, but pick your poison (pico, nano, text editor of your choice) and find these two values (they should be close to the top of the file in consecutive lines).</p>
<pre class="script">
# Path to svnlook utility
svnlook = r"@SVN_BINDIR@/svnlook"

# Path to svnadmin utility
svnadmin = r"@SVN_BINDIR@/svnadmin"
</pre>
<p>and change them to the following:</p>
<pre class="script">
# Path to svnlook utility
svnlook = r"/usr/bin/svnlook"

# Path to svnadmin utility
svnadmin = r"/usr/bin/svnadmin"
</pre>
<p>(If you&#8217;re wondering, if and when you compile/install Subversion yourself, these two variables would have been automagically filled in for you.)</p>
<p>The python script we downloaded not only performs a <a href="http://svnbook.red-bean.com/en/1.0/re33.html">hotcopy</a> of your svn directory, but also can archive it and manage a set number of copies.  <strong>Pretty neat right?</strong></p>
<h3>Preparing for the backups</h3>
<p>Before you can actually back up your SVN repository, you&#8217;ll want to create a directory structure to manage your backups.  Execute the following commands from your home directory.</p>
<pre class="console">
$ cd ~
$ mkdir backup
$ cd backup
$ mkdir svn
$ cd ~/scripts
</pre>
<p>The commands issued above created a directory called <strong>backup</strong> in your home directory, switched into the directory, and created another directory called <strong>svn</strong> within the backup directory.  We&#8217;ll be using this directory to store all your backups.  Finally, we switched back into the scripts directory created in the previous steps.  Now that we have the backup script and directory structure to manage the back ups, let&#8217;s test it out!</p>
<p>Before you can back up your repository, you&#8217;ll have to know the name of the Subversion repository you&#8217;re trying to back up.  To find the name of your repository, you can either look in the svn directory in your home directory, or you can check out the <a href="https://panel.dreamhost.com/index.cgi?tree=goodies.svn&#038;">ID value in your Subversion Goodies control panel</a>.  In any case, remember the name of your SVN repository and issue the following commands.</p>
<pre class="console">
$ cd ~/scripts/
$ python2.4 svn-hot-backup.py --archive-type=zip --num-backups=10 ~/svn/REPOSITORY_NAME_HERE/ ~/backup/svn/
</pre>
<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 REPOSITORY_NAME_HERE to the id of the SVN repository you want backed up.</div>
<p>You should see the following in the console:</p>
<pre class="console">
Beginning hot backup of '/home/USERNAME/svn/lkg/'.
Youngest revision is REVISION_NUMBER
Backing up repository to '/home/USERNAME/backup/svn/REPOSITORY_NAME_HERE-701'...
Done.
Archiving backup to '/home/USERNAME/backup/svn/REPOSITORY_NAME_HERE-701.zip'...
Archive created, removing backup '/home/USERNAME/backup/svn/REPOSITORY_NAME_HERE-701'...
</pre>
<div style="font:bold 1.1em arial; background-color:#DDFFDD; border:1px solid #009900; padding:1em; margin:1em 0;">If you see the following, the backup was a <span style="font:bold 1.25em arial; color:#006600;">success</span>!  You can even check on the file by changing into the backup/svn directory!</div>
<h2>Voila! (But there&#8217;s more)</h2>
<h3>Automating the backups</h3>
<p>Now that you actually have the script backing up your SVN repository, let&#8217;s automate them!  To do so, we&#8217;ll use the handy <a href="http://en.wikipedia.org/wiki/Crontab">cron daemon</a>.  Cron has similarities to the Windows task scheduler in that it provides a service that enables a user to execute commands at a specified date/time or set intervals.  To tell cron the tasks you want to execute, you&#8217;ll need to load a configuration file called a crontab.  You can read more about it <a href="http://blog.dreamhosters.com/kbase/index.cgi?area=2506">here</a> and <a href="http://wiki.dreamhost.com/Cron">here</a>. In any case, here&#8217;s what my crontab configuration file looks like.</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.4 /home/USERNAME/scripts/svn-hot-backup.py --archive-type=zip --num-backups=10 /home/USERNAME/svn/REPOSITORY_NAME/ /home/USERNAME/backup/svn/
</pre>
<p>Create a file in your scripts directory called svn_backup_once_a_day.cron and copy the contents above into your file.  I&#8217;ve setup my crontab to backup my svn repository once a day.</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), USERNAME to your Dreamhost username, and REPOSITORY_NAME to your Subversion repository.</div>
<p>Once you have this file called svn_backup_once_a_day.cron in your scripts directory, load the file into your crontab by issuing the following command:</p>
<pre class="console">
$ crontab svn_backup_once_a_day.cron
</pre>
<p>As a FYI, this will replace your old crontab.  If you have other items already running on cron, it&#8217;s a good idea to list them via the crontab -l command first.  If you want to make sure that your cron will run, you can test it out by setting the values in the crontab to the time you want it to run.  I&#8217;ll leave this as an exercise to the reader. <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Storing your backups</h3>
<p>Though out of scope of this blog, you&#8217;ll still have to store your backups somewhere.  Please just don&#8217;t leave them in your <a href="http://www.dreamhost.com">Dreamhost</a> account.  Your best bet is probably to get an <a href="http://aws.amazon.com/s3">Amazon S3 account</a> and store your backups there.  Personally, I like to run another script immediately after the hotcopy finishes that pushes the backup to my S3 account.  Other options include scp/sftp&#8217;ing the backups to your home machine.  Here&#8217;s a <a href="http://blog.dreamhosters.com/kbase/index.cgi?area=2599">link</a> to read more about that option.</p>
<h2>Voila! Enjoy!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=165&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/02/10/backing-up-your-subversion-svn-repository-on-dreamhost-with-cron/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Upgrading your DVR: How to increase your DVR&#8217;s recording time</title>
		<link>http://blog.localkinegrinds.com/2008/02/01/upgrading-dvr-with-more-recording-time/</link>
		<comments>http://blog.localkinegrinds.com/2008/02/01/upgrading-dvr-with-more-recording-time/#comments</comments>
		<pubDate>Fri, 01 Feb 2008 10:05:14 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[8300hd]]></category>
		<category><![CDATA[dvr]]></category>
		<category><![CDATA[hawaii]]></category>
		<category><![CDATA[recording-time]]></category>
		<category><![CDATA[scientific-atlanta]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/2008/02/01/upgrading-dvr-with-more-recording-time/</guid>
		<description><![CDATA[This blog is for all my Hawaii television addicts. Since I rarely have time to watch live television, my Oceanic Time Warner DVR is constantly filled to max capacity. This means I&#8217;m always battling my inner demons on what shows I have to erase&#8230; Rock of Love, A Shot at Love, Flavor of Love&#8230; you [...]]]></description>
			<content:encoded><![CDATA[<h2>This blog is for all my Hawaii television addicts.</h2>
<p>Since I rarely have time to watch live television, my <a href="http://www.oceanic.com/OceanicWebApps/Index.html">Oceanic Time Warner</a> DVR is constantly filled to max capacity.  This means I&#8217;m always battling my inner demons on what shows I have to erase&#8230; <a href="http://blog.vh1.com/2007-12-20/rock-of-love-2-first-look/">Rock of Love</a>, <a href="http://remotecontrol.mtv.com/2007/11/28/a-shot-at-love-recap-episode-8-lap-dance-granny/">A Shot at Love</a>, <a href="http://blog.vh1.com/2007-08-03/flavor-flavs-backwith-a-new-taste/">Flavor of Love</a>&#8230; you know, all the good stuff.  To solve my problem, I&#8217;ve finally decided to invest the $150 to upgrade my DVR and increase its total number of recording hours.</p>
<h4>Luckily for you, I&#8217;ll walk you through the steps to upgrade your own DVR!</h4>
<p style="width:95%; font-size:1em; background-color:#ffeeee; border:1px solid #990000; padding:1.5em; margin:1em 0;">
As a standard disclaimer, if you attempt to upgrade your own DVR and f-it up, I can&#8217;t and won&#8217;t fix it.  So&#8230; if technology scares you, please parents, do not try this unless supervised by your technology-oriented youngster.  If you don&#8217;t understand what SATA, external enclosures, or hard drives mean, do not, and I repeat <strong>do not try this at home!</strong>
</p>
<h3>The setup</h3>
<p>Before you can upgrade your DVR, you&#8217;ll need to make sure that you have the <a href="http://www.scientificatlanta.com/products/consumers/new_explorer8300HD.htm">Scientific Atlanta Explorer 8300HD</a>.  Just match what your DVR looks like to the one in the picture.  It&#8217;s not that hard.  This is what mine looks like: <a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10500014.jpg' title='The front of my DVR' rel="lightbox">the front</a> and <a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg09170003.jpg' title='The back of my DVR' rel="lightbox">the back</a>. I do know for a fact that Oceanic has a few versions of their cable boxes out in the wild.  I&#8217;m pretty sure you can upgrade (some of) the other models as well, but I&#8217;ve personally only upgraded the 8300HD.  So if you want to be ballsy and upgrade a different cable box, feel totally free &#8211; just be warned that this guide won&#8217;t apply to you.  I&#8217;m not even sure if you can still turn in your old cable box because of the <a href="http://the.honoluluadvertiser.com/article/2007/Dec/17/ln/hawaii712170349.html">demand for HDTV in Hawaii</a>, but calling up Oceanic can&#8217;t hurt.</p>
<p>Aside from owning an 8300HD, you&#8217;ll need three additional components to make this upgrade work.  I&#8217;ve included links to where I purchased the following items.  Fear not, I don&#8217;t make any commissions on these links so feel free to buy these products from anywhere you see fit.  </p>
<ul>
<li>1 external SATA enclosure (I used a <a href="http://shop4.outpost.com/product/4573757;jsessionid=WwPVfJx9HgljtUbOWPH75Q**.node2?site=sr:SEARCH:MAIN_RSLT_PG">KingWin from Fry&#8217;s</a> for 30 bucks.)</li>
<li>1 SATA/IDE harddrive (I used a <a href="http://shop4.outpost.com/%7B2Qbw-GvA+uzSPeJ1taMJHQ**.node2%7D/product/4551377">Maxtor 500 GB</a> for about a 100.)</li>
<li>1 SATA to eSATA cable (I used a <a href="http://www.monoprice.com/products/product.asp?c_id=102&#038;cp_id=10226&#038;cs_id=1022603&#038;p_id=3750&#038;seq=1&#038;format=2">6 ft cable from Monoprice.com</a> for 5 bucks.)</li>
</ul>
<p>Here are a few pictures of the aforementioned items.</p>
<p style="text-align:center; margin:auto;">
<a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10200005.jpg' title='External SATA enclosure' rel="lightbox[requirements]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10200005.thumbnail.jpg' alt='External SATA enclosure' class="thumb"/></a><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg09060001.jpg' title='Maxtor SATA 500 GB hard drive' rel="lightbox[requirements]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg09060001.thumbnail.jpg' alt='Maxtor SATA 500 GB hard drive' class="thumb"/></a><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10340008.jpg' title='eSATA to SATA cable' rel="lightbox[requirements]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10340008.thumbnail.jpg' alt='eSATA to SATA cable' class="thumb"/></a><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10280006.jpg' title='Everything unpacked!' rel="lightbox[requirements]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10280006.thumbnail.jpg' alt='Everything unpacked!' class="thumb"/></a>
</p>
<h3>The results</h3>
<p>First, make sure your 8300HD is turned off.  Place the hard drive into the external enclosure.  Next, after <a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg09180004.jpg' title='Connecting the hard drive to the dvr' rel="lightbox">connecting the external SATA enclosure to the 8300HD</a> (with the SATA to eSATA cable), power the external hard drive before turning the DVR box back on.  Note, it&#8217;s extremely important that the external SATA enclosure be turned on prior to the cable box being powered on.  Once booted, the 8300HD should recognize a new, external data source and prompt you to format the new drive.  The following message should appear:</p>
<p><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10400011.jpg' title='Format hard drive prompt' rel="lightbox"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10400011.thumbnail.jpg' alt='Format hard drive prompt' class="thumb" /></a></p>
<p>Once formatted, you should see a success message:</p>
<p><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10410012.jpg' title='Format success!' rel="lightbox"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10410012.thumbnail.jpg' alt='Format success!' class="thumb"/></a></p>
<h2>Voila! DVR Upgraded!</h2>
<h3>The benes</h3>
<p>There are numerous benefits to increasing your DVR&#8217;s total recording time.</p>
<ul>
<li>No more having to rush home because you forgot the DVR is full.</li>
<li>No more making those life-altering decisions about what movies to delete.</li>
<li>Being able to store almost a year&#8217;s worth of reality crap is fun!</li>
</ul>
<p>Of course, there&#8217;s the almost 4X increase in the DVR&#8217;s recording time as you can see by the  following before and after pictures.  Not bad!</p>
<p style="text-align:center; margin:auto;">
<a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10380009.jpg' title='Before upgrade' rel="lightbox[results]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10380009.thumbnail.jpg' alt='Before upgrade' class="thumb"/></a><a href='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10420013.jpg' title='After upgrade' rel="lightbox[results]"><img src='http://blog.localkinegrinds.com/wp-content/uploads/2008/01/cimg10420013.thumbnail.jpg' alt='After upgrade' class="thumb"/></a>
</p>
<h3>The cons</h3>
<p>There&#8217;s no such thing as a free pass in life&#8230; so here are a few of the cons.</p>
<ul>
<li>As I wrote earlier, the <strong style="font-size:110%;">external hard drive needs to be powered on before your cable box.</strong>  This means one of two things.  Either you always turn the external drive on first or leave it on permanently.  Since I know I could never remember to do the former, I&#8217;ve decided to leave the device on permanently &#8211; meaning a slightly larger electricity bill.  As someone trying to get off the grid, that makes me sad.</li>
<li>You can&#8217;t rip the recorded video off the external hard drive.  Unfortunately, the <a href="http://www.google.com/search?q=8300hd+encrypted&#038;ie=utf-8&#038;oe=utf-8&#038;aq=t&#038;rls=org.mozilla:en-US:official&#038;client=firefox-a">data is encrypted</a>.  Unless you&#8217;re a cryptographic expert, worked on the 8300HD, or have a few <a href="http://en.wikipedia.org/wiki/Beowulf_(computing)">Beowulf clusters</a>, deal with it.  You won&#8217;t be able to share your recordings.</li>
<li>$150 bucks is a lot to spend on easing one&#8217;s mind, but I think it&#8217;s money well spent considering the prices <a href="http://www.weaknees.com/maxtor-quickview-expander-qvx.php">here</a> and <a href="http://discountechnology.com/8300HD-eSATA-Hard-Drive-for-Scientific-Atlanta-8300HD-DVR-250GB?category=12">here</a>.
</ul>
<h3>Some linkage</h3>
<p>Of course I couldn&#8217;t have upgraded my DVR without the Internet.  Here&#8217;s a link to the forums and guides I read to assist me along the way.  Check them out, some of them are quite interesting.</p>
<ul>
<li><a href="http://www.scientificatlanta.com/ExplorerClubGuides/getting_started/4003870.pdf">Scientific Atlanta 8300HD User Guide</a></li>
<li><a href="http://www.avsforum.com/avs-vb/showthread.php?t=471859">AVSForum&#8217;s SA 8300 HD Tips &#038; Tricks &#8212; SARA thread</a></li>
<li><a href="http://baseportal.com/cgi-bin/baseportal.pl?htx=/xnappo/main">Scientific Atlanta 8300HD SARA eSATA Database</a></li>
</ul>
<p>Finally, check out <a href="http://flickr.com/photos/ryankanno/sets/72157603820776544/">my flickr set</a> if you need to see any more pictures!</p>
<h2>Enjoy!</h2>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=151&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2008/02/01/upgrading-dvr-with-more-recording-time/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Update: footerStickAlt w/ jQuery &amp; Yahoo! UI Grids</title>
		<link>http://blog.localkinegrinds.com/2007/12/13/update-footerstickalt-w-jquery-yahoo-ui-grids/</link>
		<comments>http://blog.localkinegrinds.com/2007/12/13/update-footerstickalt-w-jquery-yahoo-ui-grids/#comments</comments>
		<pubDate>Thu, 13 Dec 2007 10:29:11 +0000</pubDate>
		<dc:creator>ryankanno</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[footerStickAlt]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yahoo!-ui]]></category>

		<guid isPermaLink="false">http://blog.localkinegrinds.com/2007/12/13/update-footerstickalt-w-jquery-yahoo-ui-grids/</guid>
		<description><![CDATA[Update : December 9, 2008 If you&#8217;re using jQuery 1.2.6, there is an updated version of the footerStickAlt javascript within the comments below. Thanks Luca! A few months ago, I wrote a blog about implementing footerStickAlt using jQuery &#038; Yahoo! UI Grids. Fast forward to the present and I have a small update to post. [...]]]></description>
			<content:encoded><![CDATA[<h3>Update : December 9, 2008</h3>
<p>If you&#8217;re using <a href="http://code.google.com/p/jqueryjs/downloads/detail?name=jquery-1.2.6.min.js&#038;downloadBtn=">jQuery 1.2.6</a>, there is an updated version of the footerStickAlt javascript within the comments below.  Thanks Luca! <img src='http://blog.localkinegrinds.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<hr/>
A few months ago, I <a href="http://blog.localkinegrinds.com/2007/06/30/yahoo-ui-grids-footerstickalt-w-jquery-goodness/">wrote a blog</a> about implementing <a href="http://www.themaninblue.com/experiment/footerStickAlt/">footerStickAlt</a> using <a href="http://jquery.com/">jQuery</a> &#038; <a href="http://developer.yahoo.com/yui/grids/">Yahoo! UI Grids</a>.  Fast forward to the present and I have a small update to post.  In my previous implementation, one of the required libraries was the <a href="http://plugins.jquery.com/project/dimensions">jQuery Dimensions plugin</a> because of its nifty window/document height() calculations.  However, after reading the <a href="http://jqueryjs.googlecode.com/svn/trunk/plugins/dimensions/ChangeLog.txt">plugin&#8217;s changelog</a> and seeing as how jQuery 1.2 core <a href="http://docs.jquery.com/CSS/height">now supports the height function</a>, this plugin is no longer required.  So without further adieu, here&#8217;s the updated footerStickAlt implementation instructions.</p>
<p>It&#8217;s been tested in <a href="http://www.microsoft.com/windows/products/winfamily/ie/default.mspx">IE</a> 5.5+ and <a href="http://www.mozilla.com/en-US/firefox/">Firefox</a> 2.</p>
<p>*<b>Note</b>*:  In this implementation, I don&#8217;t check for the margin on the &#8216;body&#8217; element since we&#8217;ve set all our margins and padding on <body> to 0.  See the demos for details.</p>
<h2 style="text-decoration:underline;">Requirements</h2>
<ul>
<li>Yahoo! UI Grids [<a href="http://developer.yahoo.com/yui/download/">download</a>]
<li>JQuery 1.2+ [<a href="http://code.jquery.com/jquery-latest.js">uncompressed</a>] [<a href="http://code.jquery.com/jquery-latest.pack.js">compressed</a>]</li>
<li>Place the Javascript below in a file of your choosing! Don&#8217;t forget to include it in your page!</li>
</ul>
<pre style="font-size:125%; background-color:#ffffee; border:1px solid #ccc; padding:1em;">
$(document).ready(function() {
     if ($(window).height() > $(document).height()) {
          $('#bd').css({
               height: $('#bd').height() +
                         ($(window).height() -
                          $(document).height()) + 'px'
          });
     }
});
</pre>
<p>Check out the demos here: <a href="http://www.localkinegrinds.com/demo/footerStickAltUpdate/demo-short.html">page with short content</a>, <a href="http://www.localkinegrinds.com/demo/footerStickAltUpdate/demo-long.html">page with long content</a>!</p>
<p>(Notice the pages no longer depend upon jQuery Dimensions! Wheee!)</p>
<h3>Enjoy!</h3>
<img src="http://blog.localkinegrinds.com/?ak_action=api_record_view&id=146&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.localkinegrinds.com/2007/12/13/update-footerstickalt-w-jquery-yahoo-ui-grids/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Served from: blog.localkinegrinds.com @ 2012-02-07 20:54:11 -->
