<?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>tail -f findings.out &#187; Programming</title>
	<atom:link href="http://dancingpenguinsoflight.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancingpenguinsoflight.com</link>
	<description></description>
	<lastBuildDate>Sun, 21 Aug 2011 14:33:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Spruce up your desktop with the National Geographic Photo of the Day</title>
		<link>http://dancingpenguinsoflight.com/2011/02/spruce-up-your-desktop-with-the-national-geographic-photo-of-the-day/</link>
		<comments>http://dancingpenguinsoflight.com/2011/02/spruce-up-your-desktop-with-the-national-geographic-photo-of-the-day/#comments</comments>
		<pubDate>Sat, 19 Feb 2011 21:54:45 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1877</guid>
		<description><![CDATA[[Update, 2011-02-24] Reader Jason Coombs kindly made the necessary changes to get this working on Windows 7! Now I might be shamed into getting it working for Mac OS X as well His changes are here. I&#8217;ve updated my script &#8230; <a href="http://dancingpenguinsoflight.com/2011/02/spruce-up-your-desktop-with-the-national-geographic-photo-of-the-day/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>[Update, 2011-02-24] Reader Jason Coombs kindly made the necessary changes to get this working on Windows 7! Now I might be shamed into getting it working for Mac OS X as well <img src='http://dancingpenguinsoflight.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  His <a target="_blank" href="https://bitbucket.org/jaraco/jaraco.util/changeset/7cfc6de94873">changes are here</a>. I&#8217;ve updated my script linked below as well. I&#8217;ll add some nicer instructions for Windows users soon .[/Update]</em></p>
<p>I love checking the <a title="NatGeo Photo of the day site" target="_blank" href="http://photography.nationalgeographic.com/photography/photo-of-the-day">National Geographic Photo of the Day page</a> to see what wonderful slice of nature or mankind some intrepid soul has captured and shared. Often a wallpaper-sized image download is provided. I wanted to automate the process of checking the page for a wallpaper link, downloading the file, putting it somewhere appropriate, and setting it as my background. The result is <a target="_blank" title="Background script on GitHub" href="https://github.com/shuckins/sph_code/blob/master/misc-scripts/nat-geo_background-setter.py">this script</a>, which does all that and even:</p>
<ul>
<li>Verifies you have at least 25% free disk space before continuing</li>
<li>Renames the image to the title shown on the page</li>
<li>Creates a dir to hold these images if it doesn&#8217;t exist</li>
</ul>
<p><span id="more-1877"></span></p>
<h2>Windows users</h2>
<p>Download that script and double click assuming Python is installed. </p>
<h2>Linux users</h2>
<p>Download it, set it to be executable (chmod u+x nat-geo_background-setter.py), put it somewhere like /opt. You could add an alias to run it whenever you fancy:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Update path to where you placed the script:</span><br />
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">newbg</span>=<span style="color: #ff0000;">&quot;/opt/USER/nat-geo_background-setter.py&quot;</span></div></td></tr></tbody></table></div>
<p>If you want it to run every day on Linux you could add a crontab entry:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">crontab <span style="color: #660033;">-e</span><br />
<span style="color: #666666; font-style: italic;"># Inside your crontab:</span><br />
<span style="color: #666666; font-style: italic;"># Set BG to picture of the day</span><br />
<span style="color: #000000;">0</span> <span style="color: #000000;">6</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>USER<span style="color: #000000; font-weight: bold;">/</span>nat-geo_background-setter.py</div></td></tr></tbody></table></div>
<p>Enjoy a bit of nature on your desktop!</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2011/02/spruce-up-your-desktop-with-the-national-geographic-photo-of-the-day/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Reminder for mysql rubygem install on Ubuntu</title>
		<link>http://dancingpenguinsoflight.com/2011/01/reminder-for-mysql-rubygem-install-on-ubuntu/</link>
		<comments>http://dancingpenguinsoflight.com/2011/01/reminder-for-mysql-rubygem-install-on-ubuntu/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 03:09:10 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1841</guid>
		<description><![CDATA[Quick easy steps to get up and running with ruby, mysql, sqlite, rails, and most especially the mysql gem on a fresh Ubuntu 10.10 64-bit system: 123456789# mysql and dev packages needed for mysql rubygem: sudo apt-get install mysql-server mysql-client &#8230; <a href="http://dancingpenguinsoflight.com/2011/01/reminder-for-mysql-rubygem-install-on-ubuntu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Quick easy steps to get up and running with ruby, mysql, sqlite, rails, and most especially the mysql gem on a fresh Ubuntu 10.10 64-bit system:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># mysql and dev packages needed for mysql rubygem:</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> mysql-server mysql-client libmysqlclient-dev \<br />
libmysqld-dev<br />
<span style="color: #666666; font-style: italic;"># Needed for ruby-debug:</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> ruby1.8-dev <br />
<span style="color: #666666; font-style: italic;"># Rails package includes lots of goodies you'll likely want:</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> rails sqlite3 ruby-debug<br />
<span style="color: #666666; font-style: italic;"># And finally the gem:</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> mysql</div></td></tr></tbody></table></div>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2011/01/reminder-for-mysql-rubygem-install-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Review of Hacking Vim 7.2</title>
		<link>http://dancingpenguinsoflight.com/2010/06/review-of-hacking-vim-7-2/</link>
		<comments>http://dancingpenguinsoflight.com/2010/06/review-of-hacking-vim-7-2/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 01:24:43 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Book Review]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1480</guid>
		<description><![CDATA[Hacking Vim 7.2 by Kim Schulz is filled with a variety of useful explanations and helpful tips for Vim users wanting to improve their efficiency and learn more about their editor. While I&#8217;ve enjoyed finding new and better ways to &#8230; <a href="http://dancingpenguinsoflight.com/2010/06/review-of-hacking-vim-7-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img style="float: left; margin-right: 10px;" title="vim_logo" src="http://dancingpenguinsoflight.com/wp-content/uploads/2009/07/vim_logo.png" alt="vim_logo" width="125" height="125" /><a title="Hacking Vim on Packt" href="https://www.packtpub.com/hacking-vim-7-2/book" target="_blank"><em>Hacking Vim 7.2</em></a> by Kim Schulz is filled with a variety of useful explanations and helpful tips for <a title="vim homepage" href="http://www.vim.org/" target="_blank">Vim</a> users wanting to improve their efficiency and learn more about their editor. While I&#8217;ve enjoyed finding <a title="DPOL posts on Vim" href="http://dancingpenguinsoflight.com/?s=vim" target="_blank">new and better ways to use Vim</a> for some time, I still learned quite a lot from this book.</p>
<p>If you use Vim only to edit text files when you happen to be  logged  into a CLI: mosey on along, this isn&#8217;t the book for you. If you   currently use Vim regularly and want to improve your knowledge and effectiveness with it: your time reading this book will be well-spent. If you&#8217;ve somehow never heard of   Vim but are enraptured by the idea of a text editor that can be an effective IDE in   addition to allowing you to play Tetris and Rubik&#8217;s Cube: you might like this book too.<br />
<span id="more-1480"></span><br />
At first this book seemed rather short for such a  potentially expansive topic. In the  end I found this to be mostly a virtue  rather than a problem, as the amount  of information presented is, in fact,  voluminous. A more comprehensive  approach likely would have been too  hefty and less  effective. It doesn&#8217;t pretend to be a  manual for Vim. Instead it  illustrates the best approaches for various issues and situations, suggests improvements  on more common operations, and provides lots of  references to external  resources (primarily Vim internal help and vim.org) to  learn more. Examples and illustrations provide insight into some of Vim&#8217;s lesser known abilities, while commonly used ones are explained and presented in new and useful ways. Groups of features resolve into <em>solutions</em>.</p>
<h2>Chapter by Chapter</h2>
<h3><strong>Chapter 1, Getting Started with Vim</strong></h3>
<p>Primarily a history of the Vim editor. Useful to expand the knowledge of Vim fans, but not really pertinent to <em>hacking</em> your beloved editor. Would probably have been better as an appendix or excised entirely.</p>
<h3><strong>Chapter 2</strong>, <strong>Personalizing Vim</strong></h3>
<p>Editing your Vim config, customizing fonts, colors, menu buttons and other UI elements. Lots of great material for tuning the visual appearance. More about vim.org and other resources for colorschemes (such as <a title="Vim colorscheme test site" href="http://vimcolorschemetest.googlecode.com/svn/html/index-c.html" target="_blank">this gem</a>) would have been helpful. The ability to add tooltip balloons was new to me and quite exciting. Schulz provides a number of great examples for their use. The discussion of abbreviations was a bit confusing, especially considering the recommendation of the more intuitive snippets approach in Chapter 4.</p>
<h3><strong>Chapter 3, Better Navigation</strong></h3>
<p>By now you might already be feeling overwhelmed by the number of key commands to remember. I recommend starting a cheat sheet of those you find especially interesting. Speaking of that, perhaps it&#8217;s just my predilections and lack of a perfect memory, but the vast number of code navigation keys was just a bit too much. Sure, &#8220;extra keys pressed equals extra time wasted&#8221;, but what about extra time sorting through key commands in your thoughts? Still, plenty of tips should be mind-blowing if new to you. Jumping to files named in the text of the current file, for example, is really handy. The information about search improvements, both in user files and in the help system, was quite good. I&#8217;ve yet to really use signs or marks, but found their explanation here illuminating.</p>
<h3><strong>Chapter 4, Production (Productivity?) Boosters</strong></h3>
<p>Templates! Templates are awesome, and this was a welcome introduction to a topic <a title="DPOL post on Bash scripting, template" href="http://dancingpenguinsoflight.com/2009/03/vim-for-bash-scripting-a-happier-union/" target="_blank">I&#8217;ve barely scratched</a> in my Vim journey. I&#8217;ve also not used placeholders in templates before, which look to be quite useful. Tag lists and essential plugins for their use are explained, providing an effective presentation of this feature. I was getting a little worried around pg. 86, as the number of Ctrl + x, Ctrl + SOME_KEY commands started to get cumbersome. Then came the explanation of triggering all completion types using a single key, which was quite refreshing. Complete using dictionaries, words in the current document, language files, and more, all using a single key. The SuperCleverTab function will be a very welcome addition to my configuration. Until seeing the example about macros, I never really felt how useful they might be. This definitely convinced me.</p>
<p>But this meaty chapter isn&#8217;t over yet! Sessions felt rather opaque to me before reading this section, and I think they will now definitely serve a role for me. No more ritual of opening the right files, folding them just how I want, etc every morning. Undo branching&#8230; I still find this rather too complicated and marginal of a feature to care about. But the examples were at least explanatory. Folding is a great eye-saver, and the coverage was adequate. I&#8217;m still not really a fan of vimdiff, as there are other diff utilities out there that make the process faster and more intuitive to me. One exception is finding the diff between the current buffer and the saved file, which is very handy and not something available in most editors for sure! I hadn&#8217;t opened remote files in Vim directly before, so the section on this at the end of this chapter was quite useful.</p>
<h3><strong>Chapter 5, Advanced Formatting</strong></h3>
<p>I felt mostly ambivalent about the beginning of this chapter. To me, if you want text aligned a certain way, or want to create proper lists and use other more advanced document formatting features, you should use a word processor. Adding whitespace to my text files for alignment&#8217;s sake doesn&#8217;t strike me as a good idea.</p>
<p>The second part covering formatting pertinent to coding was much more useful. I&#8217;ve used things like autoindent and formatting of pasted code for a while now, and they are quite essential to sanity. Great coverage for those new to these features. Integration of external formatting tools such as Tidy is also described. <strong></strong></p>
<h3><strong>Chapter 6, Basic Vim Scripting</strong></h3>
<p>&#8220;<em>Now</em> we get to it&#8221; was my feeling starting this chapter. There&#8217;s some very helpful stuff in here, but it&#8217;s strangely organized and should have been moved or at least mentioned earlier in the book to provide the most benefit. Some critically handy items: explanation of Vim configuration file directories, how to properly override layers of configuration, Vimball installation, syntax highlighting and colorscheme creation. Then&#8230; comes an introductory language tutorial. Honestly, it&#8217;s pretty dull and mostly elementary. I would have rather this been moved to an appendix mentioned early in the book. It does provide broad coverage of the basics one would need to start writing Vim scripts.</p>
<h3><strong>Chapter 7, Extended Vim Scripting</strong></h3>
<p><strong></strong>Everything you need to know about actually writing Vim scripts: suggested code format, function structure, adding key mappings, detecting OS and Vim version, debugging and distributing scripts, documentation, even integrating programming languages like Python and Ruby! This is certainly a great reference to get started with Vim scripting. Schulz also gives an example script wrapping up a number of these points, providing something like a Vim scripter&#8217;s &#8220;Hello World&#8221;.</p>
<h3><strong>Appendix A, Vim Can Do Everything</strong></h3>
<p>Examples of the many and varied things you can do with Vim, such as Tweet and play Tetris. Provides amusement, but not a lot of value. The section on Vim as an IDE should really have been expanded to an entire chapter or appendix considering the likely audience for this book.</p>
<h3><strong>Appendix B, Vim Configuration Alternatives</strong></h3>
<p>A number of tips on how to keep your Vim configuration organized. Spends time explaining a system of scripts created by Jos van RisWick that allows the user to make changes to their configuration from GUI menus and make them permanent, instead of editing config files. I had never heard of this and found it quite interesting.</p>
<p>The last few pages deal with storing your Vim configuration online. While I whole-heartedly agree with the intent, the particular manifestation presented is rather terrible. Using this setup, the user&#8217;s .vimrc would be downloaded <em>every time</em> Vim is opened. Then it still has to be parsed, which for heavily customized setups can already take a moment. Not the best when you&#8217;re looking for a lean editor. And what about the legion of scripts and other supporting files outside .vimrc? I think not. My approach to the problem is to keep all of my Vim configuration files inside an SCM system, checking it out on each system the first time I want to use Vim.</p>
<h2>Issues</h2>
<ul>
<li><strong>Confused structure</strong>: Chapters 6 and 7 felt rather strangely divided  in  themselves, and I felt most of the content should have been provided   earlier. Having a better knowledge of the syntax and nature of ex   commands/Vim scripting would have made the content throughout the book   more understandable. I felt I was mostly taking the syntax in the code provided for   granted, without feeling comfortable enough about all the components that I could have written something of my own design.</li>
<li><strong>Typos</strong>: The text would have greatly benefited from another round of   copy-editing. Most of the errors weren&#8217;t very distracting. There were, however, a number of typos in the code provided that   were more problematic, especially for a work on an editor that can be   rather picky about commands. For a first edition, these aren&#8217;t overly   numerous.</li>
<li><strong>Lack of color diagrams</strong>: I&#8217;m all for using black and  white images  when they will suffice, but when providing illustrations of  *color*  highlighting files, images without color are downright useless!  I was  rather surprised at this oversight, first appearing in chapter 2,  then  in multiple places in chapter 6. They could have at least linked  to  color images online.</li>
</ul>
<h2>Conclusion</h2>
<p>All in all this was a very useful  treasure trove of tips. Some I&#8217;ve  already added to my repertoire, and  more I&#8217;m trying to understand  better. In fact, I learned so much from it  that I decided I will likely  need to drop most of my current Vim config  and remake it cleanly. I  know I&#8217;m not alone in collecting bits and  pieces of configuration for  this wonderful editor, in a fashion  occasionally reminiscent of a  deranged hermit crab. Now that I have a  more solid understanding I can  rebuild it quickly and effectively.</p>
<p>In summary, I agree with <a title="Brian Carper's Hacking Vim 7.2 review" href="http://briancarper.net/blog/review-hacking-vim-72" target="_blank">Brian Carper</a>:</p>
<blockquote><p>The best you can hope for in a book is a broad outline to point the way  toward features that you didn&#8217;t know much about. Hacking Vim 7.2  achieves this goal.</p></blockquote>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2010/06/review-of-hacking-vim-7-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>git tip: Ignoring modifications to tracked files</title>
		<link>http://dancingpenguinsoflight.com/2010/02/git-tip-ignoring-modifications-to-tracked-files/</link>
		<comments>http://dancingpenguinsoflight.com/2010/02/git-tip-ignoring-modifications-to-tracked-files/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 04:13:29 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[RubyOnRails]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[VCS]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1427</guid>
		<description><![CDATA[Problem You have a file already tracked in your git repository, but you don&#8217;t want future modifications to it to be tracked. A perfect example of this is the DB config file for Rails projects (config/database.yml). You&#8217;ll probably want to &#8230; <a href="http://dancingpenguinsoflight.com/2010/02/git-tip-ignoring-modifications-to-tracked-files/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Problem</h2>
<p><em>You have a file already tracked in your git repository, but you don&#8217;t want future modifications to it to be tracked.</em></p>
<p>A perfect example of this is the DB config file for Rails projects (config/database.yml). You&#8217;ll probably want to track this to keep the production and staging configuration stored and consistent. But it&#8217;s quite likely that individual development configurations will be different. Having a commit for each developer adding their own local configuration and thereby polluting it for others when they push is just silly.</p>
<h2>Solution</h2>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">git update-index</span> <span style="color: #660033;">--assume-unchanged</span> FILENAME</div></td></tr></tbody></table></div>
<h2>The fun details</h2>
<p>I had initially thought that <a title="git-ignore docs" href="http://ftp.cc.uoc.gr/pub/software/scm/git/docs/gitignore.html" target="_blank">git-ignore</a> was the thing to use for this. That was wrong: git-ignore&#8217;s purpose is to allow ignoring of <em>untracked</em> files. In the case of the Rails DB conf example above, the file is already tracked. It has the instance information that needs to be shared and now we want to add local development details. Since it&#8217;s tracked, any modifications are going to be picked up by <a title="git-status docs" href="http://www.kernel.org/pub/software/scm/git/docs/git-status.html" target="_blank">git-status</a>. When you do a commit including changes to tracked files listed in .gitignore, the changes do indeed get pushed, which isn&#8217;t what we want.</p>
<p>When looking around for solutions to this, I saw &#8220;git rm &#8211;cached FILENAME&#8221; suggested as a way to stop tracking currently tracked files. And it does this, but it also deletes the file in the commit, which isn&#8217;t what we want either.</p>
<p><a title="git update-index man page" href="http://kernel.org/pub/software/scm/git/docs/v1.0.13/git-update-index.html">git update-index</a> allows you to alter your <a title="Post on git's staging area" href="http://www.gitready.com/beginner/2009/01/18/the-staging-area.html" target="_blank">staging area</a> more manually than usual. With it you can perform a wide range of operations not otherwise possible through standard commands. Continuing with the Rails DB conf example, here&#8217;s what the workflow would look like:</p>
<ol>
<li>config/database.yml with permanent instance info is added, committed, and pushed</li>
<li>Application code is pulled down by new developer</li>
<li>Local modifications made to database.yml for new developer&#8217;s local DB setup</li>
<li>git update-index &#8211;assume-unchanged config/database.yml</li>
</ol>
<p>Thereafter, the changes to conf/database.yml won&#8217;t appear in status or get committed. You can continue making and committing other changes, going about business as usual. But any changes to config/database.yml won&#8217;t ever appear.</p>
<p>In case you decide you <em>do</em> want to start tracking changes on a file previously ignored, just run:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">git update-index</span> <span style="color: #660033;">--no-assume-unchanged</span> FILENAME</div></td></tr></tbody></table></div>
<p>Thereafter changes to FILENAME will appear in git-status.</p>
<h2>Gotcha</h2>
<p>The annoying part about this solution is that it has to be run against every new checkout of the repo with the files whose modifications should not be tracked. The command sets a particular bit per checkout, and it&#8217;s not passed on to new checkouts.</p>
<p>Just as I was finishing up some fact checking for this write-up, I came across <a href="http://justaddwater.dk/2009/12/07/how-to-make-git-ignore-files-that-already-exist-in-your-project/" target="_blank">Jesper Rønn-Jensen&#8217;s post</a> on this exact topic. If only it had come up in my initial searches! Here&#8217;s hoping the next searcher has better luck.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2010/02/git-tip-ignoring-modifications-to-tracked-files/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hiding anchor tooltips on hover</title>
		<link>http://dancingpenguinsoflight.com/2009/11/hiding-anchor-tooltips-on-hover/</link>
		<comments>http://dancingpenguinsoflight.com/2009/11/hiding-anchor-tooltips-on-hover/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 18:25:48 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1362</guid>
		<description><![CDATA[Navigation menus on websites most often consist of a list of links. When looking through a menu, it&#8217;s not unreasonable for a visitor to have their mouse cursor over some of the menu item links for a few moments as &#8230; <a href="http://dancingpenguinsoflight.com/2009/11/hiding-anchor-tooltips-on-hover/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Navigation menus on websites most often consist of a list of links. When looking through a menu, it&#8217;s not unreasonable for a visitor to have their mouse cursor over some of the menu item links for a few moments as they read through the options. Using an unadorned <a href="http://www.w3schools.com/TAGS/tag_a.asp">anchor tag</a> in this situation has a troublesome side effect:</p>
<p><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2009/11/title-hover-example.png" alt="title-hover-example" title="title-hover-example" width="634" height="111" class="aligncenter size-full wp-image-1363" style="border: 1px dotted black;" /></p>
<p>The title attribute of the anchor tag will appear as a tooltip, potentially obscuring menu items and minimally being a useless distraction. But removing titles from navigation links isn&#8217;t a good option, since this attribute is helpful for SEO and accessibility purposes.</p>
<p>When discussing this problem with friend Google, I ran across many examples of how to change the display of anchor tooltips, as well as how to hide them altogether. But what I wanted was removal of the title attribute on navigation links only when the mouse cursor hovered over them, adding it back when the cursor left. The solution I settled on consisted of jQuery&#8217;s handy <a title="jQuery hover" target="_blank" href="http://docs.jquery.com/Events/hover">hover function</a> and some basic JavaScript. <em>hover()</em> allows you to specify a function to call when the cursor hovers onto an object and another to call when the cursor hovers off. Perfect! Here&#8217;s a simple example:</p>
<div class="codecolorer-container html4strict blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span>A test<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
<br />
&nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- Load in jQuery for handy hover function --&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; $(document).ready(function() { &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; // All links in main menu div<br />
&nbsp; &nbsp; &nbsp; &nbsp; var menu_links = $('div[id=main-menu] a');<br />
&nbsp; &nbsp; &nbsp; &nbsp; // On mouse hover<br />
&nbsp; &nbsp; &nbsp; &nbsp; menu_links.hover(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // In: Store and remove title<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function() { &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; old_title = $(this).attr('title'); &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(this).attr('title',''); <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Out: Replace title<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function() { &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(this).attr('title', old_title); &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp;<br />
&nbsp; &nbsp; }); &nbsp;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;main-menu&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Titles are great for SEO and accessibility but don&amp;#8217;t need to be seen by users normally!&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;zenoss.com&quot;</span>&gt;</span>MenuItem1<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Titles are great for SEO and accessibility but don&amp;#8217;t need to be seen by users normally!&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;zenoss.com&quot;</span>&gt;</span>MenuItem2<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Titles are great for SEO and accessibility but don&amp;#8217;t need to be seen by users normally!&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;zenoss.com&quot;</span>&gt;</span>MenuItem3<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">ul</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span>I am text! Hurray! <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a> <span style="color: #000066;">title</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;bodylink1&quot;</span> <span style="color: #000066;">target</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;_blank&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;zenoss.com&quot;</span>&gt;</span>I am a normal link.<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">a</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">p</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></td></tr></tbody></table></div>
<p>You can verify the functionality by inspecting one of the MenuItem links with <a title="Get Firebug" target="_blank" href="http://getfirebug.com/">Firebug</a> and watching the title attribute as you move the cursor on and off the same link.</p>
<p>After the page is finished loading, when a cursor hovers onto any links within the div of id &#8220;main-menu&#8221; the title attribute is stored and set to an empty string (so no tooltip). When the cursor leaves, the title attribute is set back to its original value. Simple but effective!</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/11/hiding-anchor-tooltips-on-hover/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A better way to search for methods of Python objects</title>
		<link>http://dancingpenguinsoflight.com/2009/11/a-better-way-to-search-for-methods-of-python-objects/</link>
		<comments>http://dancingpenguinsoflight.com/2009/11/a-better-way-to-search-for-methods-of-python-objects/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 22:08:10 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[efficiency]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1316</guid>
		<description><![CDATA[Python&#8217;s introspection abilities are quite extensive and useful. They are also well-documented, so I won&#8217;t go into the basics here. Check out this article if you need a good overview. N.B.: discussion and code below applies to both methods and &#8230; <a href="http://dancingpenguinsoflight.com/2009/11/a-better-way-to-search-for-methods-of-python-objects/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Python&#8217;s introspection abilities are quite extensive and useful. They are also well-documented, so I won&#8217;t go into the basics here. <a title="Guide to Python Introspection" target="_blank" href="http://www.ibm.com/developerworks/library/l-pyint.html">Check out this article</a> if you need a good overview. N.B.: discussion and code below applies to both methods and attributes. I will simply refer to &#8220;methods&#8221; for simplicity.</p>
<p>Beyond simply listing the methods of an object, however, I often find that I want to search through them for something in particular. And eyeballing the output of dir(obj) is only efficient in the simplest of cases. hasattr(obj, &#8220;method&#8221;) won&#8217;t get you far either, as you need to match the &#8220;method&#8221; name exactly. What if you just have a good guess about the name of a method based on what you need to do? What if you want to know everything you can do with directories in the os module or ISO related methods in datetime.date? I haven&#8217;t found anything to help with this sort of problem yet. Approaches like writing a loop to do the search every time or perusing the pertinent API docs are too circuitous for such quick questions. So let&#8217;s make a tool to do this more easily!</p>
<p>We start with knowing some object and some string containing all or part of the method(s) we&#8217;re interested in:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> mf<span style="color: black;">&#40;</span>obj<span style="color: #66cc66;">,</span> term<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; Searches through the methods and attributes defined for obj, <br />
&nbsp; &nbsp; looks for those containing the term passed.<br />
&nbsp; &nbsp; Returns all matches or a warning if none found.<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; meths <span style="color: #66cc66;">=</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; match_meths <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> meth <span style="color: #ff7700;font-weight:bold;">in</span> meths:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> meth.<span style="color: black;">rfind</span><span style="color: black;">&#40;</span>term<span style="color: black;">&#41;</span> <span style="color: #66cc66;">!=</span> -<span style="color: #ff4500;">1</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match_meths.<span style="color: black;">append</span><span style="color: black;">&#40;</span>meth<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> match_meths:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> match_meths<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;No matches!&quot;</span></div></td></tr></tbody></table></div>
<p>This simply iterates over the methods and attributes defined for the object passed and looks for the term passed within the name of each. rfind returns the highest index of the substring passed in the string it&#8217;s called on and returns -1 if no match is found. Once the matches are collected they are printed out. An example:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span><span style="color: #ff7700;font-weight:bold;">from</span> method_finder <span style="color: #ff7700;font-weight:bold;">import</span> mf<br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span><br />
<span style="color: #66cc66;">&gt;&gt;&gt;</span>mf<span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;dir&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'chdir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'curdir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'fchdir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'listdir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'makedirs'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'mkdir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'pardir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'removedirs'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'rmdir'</span><span style="color: black;">&#93;</span></div></td></tr></tbody></table></div>
<p>For convenience let&#8217;s make it available on the Python interactive prompt at every load without any extra effort. This is easy enough using a .pythonstartup file. This file can be used to load various useful items like tab completion for interactive Python sessions. If you haven&#8217;t used it before, you&#8217;ll need to add the following to your .bashrc:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">PYTHONSTARTUP</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$HOME</span>/.pythonstartup&quot;</span></div></td></tr></tbody></table></div>
<p>Then in your home directory create a .pythonstartup file containing something like the following:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span><br />
<span style="color: #808080; font-style: italic;"># Adds mf(obj, &quot;str&quot;) allowing search for methods matching 'str' on obj</span><br />
<span style="color: #808080; font-style: italic;"># as well as obinfo(obj) returning lots of info on obj</span><br />
util_loc <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;/home/shuckins/code/code_homerepo/python-programming/utilities&quot;</span><br />
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span>util_loc<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><br />
&nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>util_loc<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> utils <span style="color: #ff7700;font-weight:bold;">import</span> mf<span style="color: #66cc66;">,</span> obinfo<br />
&nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">remove</span><span style="color: black;">&#40;</span>util_loc<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">del</span> <span style="color: #dc143c;">sys</span><br />
<span style="color: #ff7700;font-weight:bold;">del</span> <span style="color: #dc143c;">os</span></div></td></tr></tbody></table></div>
<p>You&#8217;ll need to change the path specified to wherever you placed utils.py containing the mf() function of course. You can <a target="_blank" title="utils.py on github" href="http://github.com/shuckins/sph_code/blob/master/python-programming/utilities/utils.py">download mine here</a> if you&#8217;d like. The del statements are to clean up any trace of this operation once you get to the interactive interpreter. This way you get the added functions without mucking up your namespace. </p>
<p>This also loads in an obinfo(obj) function that I included in the same utils.py file. This is based on the interrogate() function written by Patrick O&#8217;Brien in the <a title="Guide to Python Introspection" target="_blank" href="http://www.ibm.com/developerworks/library/l-pyint.html">introspection article mentioned above</a>. My version just adds a check for objects without docstrings and prints more of the docstring:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> obinfo<span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; Print useful information about object.<br />
<br />
&nbsp; &nbsp; From http://www.ibm.com/developerworks/library/l-pyint.html<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>obj<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__name__'</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;NAME: &nbsp; &nbsp;&quot;</span><span style="color: #66cc66;">,</span> obj.__name__<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>obj<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__class__'</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;CLASS: &nbsp; &quot;</span><span style="color: #66cc66;">,</span> obj.__class__.__name__<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;ID: &nbsp; &nbsp; &nbsp;&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;TYPE: &nbsp; &nbsp;&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;VALUE: &nbsp; &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;CALLABLE:&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">callable</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Yes&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;No&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>obj<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__doc__'</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; doc <span style="color: #66cc66;">=</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>obj<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__doc__'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doc <span style="color: #66cc66;">=</span> doc.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; topfive <span style="color: #66cc66;">=</span> 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><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;DOC: &nbsp; &nbsp; &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>topfive<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;No docstring. Yell at the author.&quot;</span></div></td></tr></tbody></table></div>
<p>It&#8217;s fairly useful:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&gt;&gt;&gt;</span> obinfo<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;some&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;list&quot;</span><span style="color: black;">&#93;</span>.<span style="color: black;">count</span><span style="color: black;">&#41;</span><br />
NAME: &nbsp; &nbsp; count<br />
CLASS: &nbsp; &nbsp;builtin_function_or_method<br />
ID: &nbsp; &nbsp; &nbsp; <span style="color: #ff4500;">139922087930696</span><br />
TYPE: &nbsp; &nbsp; <span style="color: #66cc66;">&lt;</span><span style="color: #008000;">type</span> <span style="color: #483d8b;">'builtin_function_or_method'</span><span style="color: #66cc66;">&gt;</span><br />
VALUE: &nbsp; &nbsp;<span style="color: #66cc66;">&lt;</span>built-<span style="color: #ff7700;font-weight:bold;">in</span> method count of <span style="color: #008000;">list</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f422658ef80</span><span style="color: #66cc66;">&gt;</span><br />
CALLABLE: Yes<br />
DOC: &nbsp; &nbsp; &nbsp;L.<span style="color: black;">count</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> integer -- <span style="color: #ff7700;font-weight:bold;">return</span> number of occurrences of value</div></td></tr></tbody></table></div>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/11/a-better-way-to-search-for-methods-of-python-objects/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Catching warnings from the MySQLdb module</title>
		<link>http://dancingpenguinsoflight.com/2009/10/catching-warnings-from-the-mysqldb-module/</link>
		<comments>http://dancingpenguinsoflight.com/2009/10/catching-warnings-from-the-mysqldb-module/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 03:53:50 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1300</guid>
		<description><![CDATA[The MySQLdb Python module implements the Python DB API for MySQL. I&#8217;ve written about its use before. MySQL issues warning messages in a number of circumstances and PEP 249 (which specifies the Python DB API) describes a Warning error message &#8230; <a href="http://dancingpenguinsoflight.com/2009/10/catching-warnings-from-the-mysqldb-module/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The <a target="_blank" title="MySQLdb home" href="http://sourceforge.net/projects/mysql-python/">MySQLdb Python module</a> implements the Python DB API for MySQL. I&#8217;ve written about its use <a target="_blank" title="MySQL queries in Python" href="http://dancingpenguinsoflight.com/2009/03/running-mysql-queries-in-python/">before</a>. MySQL issues <a target="_blank" title="MySQL show warnings" href="http://dev.mysql.com/doc/refman/5.0/en/show-warnings.html">warning messages</a> in a number of circumstances and <a target="_blank" title="PEP 249" href="http://www.python.org/dev/peps/pep-0249/">PEP 249</a> (which specifies the Python DB API) describes a Warning error message to be included.</p>
<p>One issue I ran into recently was how to catch warnings thrown by this module when running queries. Oftentimes tutorials or forum discussions that cover warnings in the context of MySQLdb describe how to filter them (they can clog up script output). But in a recent case I wanted to grab and check the warning, logging a dependent result. I had hoped this clean implementation would work in a method used for all calls to the MySQL DB:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>query<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: black;">Error</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> e<br />
<span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: #008000;">Warning</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> e<br />
<span style="color: #ff7700;font-weight:bold;">finally</span>:<br />
&nbsp; &nbsp; data <span style="color: #66cc66;">=</span> cursor.<span style="color: black;">fetchall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; rows_returned <span style="color: #66cc66;">=</span> cursor.<span style="color: black;">rowcount</span><br />
&nbsp; &nbsp; cursor.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; db.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>But the warnings just went right through. Instead I needed the warnings module&#8217;s assistance:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">warnings</span><br />
<span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">warnings</span>.<span style="color: black;">catch_warnings</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #dc143c;">warnings</span>.<span style="color: black;">simplefilter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'error'</span><span style="color: #66cc66;">,</span> MySQLdb.<span style="color: #008000;">Warning</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>query<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: black;">Error</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> e<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">finally</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; data <span style="color: #66cc66;">=</span> cursor.<span style="color: black;">fetchall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; rows_returned <span style="color: #66cc66;">=</span> cursor.<span style="color: black;">rowcount</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; db.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This catches the warnings and raises them as errors, although their class is still correct, allowing a clean implementation to call the above code (wrapped into a method called do_query):</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">do_query</span><span style="color: black;">&#40;</span>make_cool_table<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Created cool_table table.&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: #008000;">Warning</span>:<br />
&nbsp; &nbsp; logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;cool_table already exists.&quot;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/10/catching-warnings-from-the-mysqldb-module/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>An improved ruby debugger invocation</title>
		<link>http://dancingpenguinsoflight.com/2009/09/an-improved-ruby-debugger-invocation/</link>
		<comments>http://dancingpenguinsoflight.com/2009/09/an-improved-ruby-debugger-invocation/#comments</comments>
		<pubDate>Sun, 27 Sep 2009 01:17:41 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1195</guid>
		<description><![CDATA[I&#8217;d been wanting to write a post for some time on improvements I&#8217;ve found useful in using Ruby&#8217;s debugger. Friend Trevor Rosen beat me to the proverbial punch, however. Give his post a read first, I&#8217;ll wait. Now on top &#8230; <a href="http://dancingpenguinsoflight.com/2009/09/an-improved-ruby-debugger-invocation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d been wanting to write a post for some time on improvements I&#8217;ve found useful in using Ruby&#8217;s debugger. Friend Trevor Rosen <a target="_blank" title="Trevor Rosen's post on improving Ruby debugger" href="http://www.catapult-creative.com/2009/08/12/make-ruby-debug-work-better/">beat me to the proverbial punch</a>, however. Give his post a read first, I&#8217;ll wait.</p>
<p>Now on top of his suggestions I have one more refinement to add. I&#8217;ve defined a snippet in vim for whenever I need to use the debugger. You should be able to define the same in whatever editor you use (and if your editor can&#8217;t do snippets, get <a target="_blank" title="vim home" href="http://www.vim.org/">a real one</a>). When in an .rb file, &#8220;debug&#8221; + Tab becomes:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ruby-debug'</span>; Debugger.<span style="color:#9900CC;">settings</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:autoeval</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0000FF; font-weight:bold;">true</span>; debugger; rubys_debugger = <span style="color:#996600;">&quot;annoying&quot;</span></div></td></tr></tbody></table></div>
<p>In addition to the format Trevor suggested (which calls the necessary module, turns on auto evaluation, and calls the debugger itself) this adds a simple assignment after the debugger is called. I often find this necessary because I want to debug right at the very end of a given suite, a conditional, a method, etc. But if you invoke the debugger as the last statement in such a situation, it won&#8217;t actually be called. Here&#8217;s an example file:</p>
<div class="codecolorer-container ruby blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;">#!/usr/bin/env ruby</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">def</span> troubled_func<span style="color:#006600; font-weight:bold;">&#40;</span>var1<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Entering troubled function...&quot;</span><br />
&nbsp; secret_num = <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">10</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">*</span> var1<br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ruby-debug'</span>; Debugger.<span style="color:#9900CC;">settings</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:autoeval</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0000FF; font-weight:bold;">true</span>; debugger<br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
troubled_func<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>When you run this, you won&#8217;t get a debugger console. All the output you get is &#8220;Entering troubled function&#8230;&#8221; and the script exits. If instead you add the assignment I list above after debugger is called, you will get to the debugger console. Sad, but true. (You can select a less offensive assignment if you wish. I settled on it in disgust.)</p>
<p>Aside from this, the Ruby debugger is a useful and beautiful thing. So add the snippet and forget about it.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/09/an-improved-ruby-debugger-invocation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Useful Bash functions to determine OS and more</title>
		<link>http://dancingpenguinsoflight.com/2009/09/useful-bash-functions-to-determine-os-and-more/</link>
		<comments>http://dancingpenguinsoflight.com/2009/09/useful-bash-functions-to-determine-os-and-more/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 19:07:09 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[CLI]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Bash]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1185</guid>
		<description><![CDATA[In a number of my Bash aliases I need to check two constants: what sort of OS I&#8217;m on and whether it&#8217;s a production box or not. I use the former for aliases that allow me to install and search &#8230; <a href="http://dancingpenguinsoflight.com/2009/09/useful-bash-functions-to-determine-os-and-more/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In a number of my Bash aliases I need to check two constants: what sort of OS I&#8217;m on and whether it&#8217;s a production box or not. I use the former for aliases that allow me to install and search for packages across distributions, <a target="_blank" title="Post on package installation aliases" href="http://dancingpenguinsoflight.com/2008/12/multi-os-package-installation-and-search-functions/">as described here</a>. The latter I use to determine whether I am allowed to use aliases for turning off the machine and the like. The code I used to determine these before was repetitive and hard to work with. So I created functions to determine the values, allowing all the aliases to reference a single source.</p>
<p>The first function determines the OS I am on, in the general categories of &#8220;debian&#8221; and &#8220;redhat&#8221;:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> cur_os <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Attempts to check whether the local box is running Debian/Ubuntu</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># (considered together as &quot;debian&quot;) or Red Hat/CentOS (considered</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># together as &quot;redhat&quot;.</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Make sure we have egrep</span><br />
&nbsp; &nbsp; <span style="color: #007800;">EGREP_VER</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">egrep</span> <span style="color: #660033;">--version</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-n</span> <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${EGREP_VER:0:8}</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;GNU grep&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;egrep isn't installed, sorry.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Make sure we have /etc/issue</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-r</span> <span style="color: #ff0000;">'/etc/issue'</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;/etc/issue isn't readable.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Run checks</span><br />
&nbsp; &nbsp; <span style="color: #007800;">DEB_OS</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">egrep</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">'Ubuntu|Debian'</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>issue<span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; <span style="color: #007800;">RH_OS</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">egrep</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">'CentOS|Red Hat'</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>issue<span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #800000;">${#DEB_OS}</span> <span style="color: #660033;">-gt</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">CUR_OS</span>=<span style="color: #ff0000;">&quot;debian&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">elif</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #800000;">${#RH_OS}</span> <span style="color: #660033;">-gt</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">CUR_OS</span>=<span style="color: #ff0000;">&quot;redhat&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">CUR_OS</span>=<span style="color: #ff0000;">&quot;unknown&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$CUR_OS</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>I chose these two categories because the package handler is the same within each. This could of course be expanded to more systems, these just happen to be the flavors I am always on. Just after I define this function I also include:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cur_os <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null</div></td></tr></tbody></table></div>
<p>This way the variable CUR_OS is populated each time Bash loads but the output doesn&#8217;t dirty up the prompt. Having this variable allows the definition of fairly elegant functions such as:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> inst <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Installs passed packages.</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$CUR_OS</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">'debian'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> $<span style="color: #000000; font-weight: bold;">@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #ff0000;">'redhat'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">yum install</span> $<span style="color: #000000; font-weight: bold;">@</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;You are not on a supported OS.&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">;;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">esac</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>This next function determines whether the current machine is one I consider non-production:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> local_box <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Checks if the current machine is one of my own machines (and thus</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># less risky to run various commands on).</span><br />
&nbsp; &nbsp; <span style="color: #007800;">LOCAL_BOXES</span>=<span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #ff0000;">'ZenSam'</span> <span style="color: #ff0000;">'B74kb0x'</span> <span style="color: #ff0000;">'MediaServer'</span> <span style="color: #ff0000;">'shuckins-alienware'</span> <span style="color: #ff0000;">'laptop-shuckins'</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">CURRENTBOX</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">hostname</span><span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; <span style="color: #007800;">CUR_BOX_LOCAL</span>=<span style="color: #000000;">0</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #800000;">${LOCAL_BOXES[@]}</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$i</span> == <span style="color: #800000;">${CURRENTBOX}</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">CUR_BOX_LOCAL</span>=<span style="color: #000000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span>;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$CUR_BOX_LOCAL</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span><br />
<span style="color: #666666; font-style: italic;"># So that CUR_BOX_LOCAL is set initially:</span><br />
local_box <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null</div></td></tr></tbody></table></div>
<p>The idea is that LOCAL_BOXES holds hostnames of machines that aren&#8217;t as sensitive to things like shutting down. Then when you create aliases for such potentially destructive actions you define a safe form for the potentially sensitive boxes:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$CUR_BOX_LOCAL</span> == <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">off</span>=<span style="color: #ff0000;">&quot;sudo shutdown -h now&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">restart</span>=<span style="color: #ff0000;">&quot;sudo shutdown -r now&quot;</span><br />
<span style="color: #000000; font-weight: bold;">else</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">off</span>=<span style="color: #ff0000;">&quot;echo 'You are on a remote box!'&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">restart</span>=<span style="color: #ff0000;">&quot;echo 'You are on a remote box!'&quot;</span><br />
<span style="color: #000000; font-weight: bold;">fi</span></div></td></tr></tbody></table></div>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/09/useful-bash-functions-to-determine-os-and-more/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Checking options with optparse callbacks</title>
		<link>http://dancingpenguinsoflight.com/2009/08/checking-options-with-optparse-callbacks/</link>
		<comments>http://dancingpenguinsoflight.com/2009/08/checking-options-with-optparse-callbacks/#comments</comments>
		<pubDate>Sun, 16 Aug 2009 05:44:52 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1150</guid>
		<description><![CDATA[optparse is a flexible and powerful module for processing command line options in Python programs. I&#8217;ve used it for a while, but I didn&#8217;t have much occasion to get into callbacks until recently. A callback here is a user-defined function &#8230; <a href="http://dancingpenguinsoflight.com/2009/08/checking-options-with-optparse-callbacks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" title="optparse docs" href="http://docs.python.org/library/optparse.html">optparse</a> is a flexible and powerful module for processing command line options in Python programs. I&#8217;ve used it for a while, but I didn&#8217;t have much occasion to get into <a target="_blank" title="callbacks in optparse" href="http://docs.python.org/library/optparse.html#optparse-option-callbacks">callbacks</a> until recently. A callback here is a user-defined function optparse calls when its associated option is encountered. They can help you keep your script&#8217;s logic clear within a forest of options by providing arbitrary checks when particular options are passed. </p>
<p>When I first began using them, I ran into a critical point of confusion that wasn&#8217;t clearly illuminated in the assorted guides I found for optparse. In response, here is a short overview of how to use callbacks to perform checks and validations against passed options.</p>
<p>First, a very basic script using optparse for option parsing:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">optparse</span><br />
<span style="color: #dc143c;">parser</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">optparse</span>.<span style="color: black;">OptionParser</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<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: #66cc66;">,</span> <span style="color: #483d8b;">&quot;--input-file&quot;</span><span style="color: #66cc66;">,</span> dest<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;inputfile&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">help</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;The file with input&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#40;</span>options<span style="color: #66cc66;">,</span> arguments<span style="color: black;">&#41;</span> <span style="color: #66cc66;">=</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><br />
<br />
<span style="color: #ff7700;font-weight:bold;">print</span> options</div></td></tr></tbody></table></div>
<p>Which outputs:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">python test.py <span style="color: #660033;">-f</span> test.txt<br />
<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">'inputfile'</span>: <span style="color: #ff0000;">'test.txt'</span><span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>For a more detailed coverage of the basics, review Doug Hellman&#8217;s <a target="_blank" title="Doug Hellman's PyMOTW on optparse" href="http://blog.doughellmann.com/2007/08/pymotw-optparse.html">PyMOTW article on optparse</a>. It would be best to verify that this input file exists so that we might inform the user and exit early. Adding that functionality to our example:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">optparse</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> check_file<span style="color: black;">&#40;</span>option<span style="color: #66cc66;">,</span> opt<span style="color: #66cc66;">,</span> value<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">parser</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #dc143c;">optparse</span>.<span style="color: black;">OptionValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s doesn't seem to exist.&quot;</span> % value<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #dc143c;">parser</span>.<span style="color: black;">values</span>.<span style="color: black;">inputfile</span> <span style="color: #66cc66;">=</span> value<br />
<br />
<span style="color: #dc143c;">parser</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">optparse</span>.<span style="color: black;">OptionParser</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<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: #66cc66;">,</span> <span style="color: #483d8b;">&quot;--input-file&quot;</span><span style="color: #66cc66;">,</span> dest<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;inputfile&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;callback&quot;</span><span style="color: #66cc66;">,</span> callback<span style="color: #66cc66;">=</span>check_file<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">type</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;string&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">help</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;The file with input&quot;</span><span style="color: black;">&#41;</span><br />
<span style="color: black;">&#40;</span>options<span style="color: #66cc66;">,</span> arguments<span style="color: black;">&#41;</span> <span style="color: #66cc66;">=</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><br />
<br />
<span style="color: #ff7700;font-weight:bold;">print</span> options</div></td></tr></tbody></table></div>
<p>We&#8217;ve added a check_file() function to perform our check and also added the callback specification to the associated option. The arguments a callback function is passed are described in the <a target="_blank" title="callbacks in optparse" href="http://docs.python.org/library/optparse.html#optparse-option-callbacks">module documentation</a>. optparse.OptionValueError provides an elegant way to send an error message about the problem and quit the program in one step.</p>
<p>So what&#8217;s the problem? When I first wrote a callback, I didn&#8217;t catch the line in the tutorial examples that set the value of the option. I still don&#8217;t understand why this is necessary, but without the &#8220;parser.values.inputfile = value&#8221; line above, you&#8217;d find the inputfile variable to have None for its value. Strange, but true. I could understand the callback function having to <em>return</em> the option value if all was well, but why would the option&#8217;s value get unset in the first place?</p>
<p>Additionally, it turns out you have to set the option&#8217;s type even if the desired value is supposed to be default. In the above example, without &#8216;type=&#8221;string&#8221;&#8216;, the callback function would have thrown an error, complaining that we were claiming to use a string and weren&#8217;t.</p>
<p>So watch out for these details, and clean up your scripts with callbacks.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/08/checking-options-with-optparse-callbacks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

