
<?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>Mental Pandiculation &#187; python</title>
	<atom:link href="http://mentalpandiculation.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://mentalpandiculation.com</link>
	<description>One Man's Attempt To Find Elegant Code Through Big Words</description>
	<lastBuildDate>Mon, 27 Jun 2011 23:31:03 +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>Word Wrap Kata in Python</title>
		<link>http://mentalpandiculation.com/2011/01/word-wrap-kata-in-python/</link>
		<comments>http://mentalpandiculation.com/2011/01/word-wrap-kata-in-python/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 00:16:12 +0000</pubDate>
		<dc:creator>Niklaus Wirth's Ghost</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[katas]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://mentalpandiculation.com/?p=318</guid>
		<description><![CDATA[Last month at Dallas Hack Club, we did the Word Wrap Kata from Uncle Bob Martin&#8217;s &#8220;Clean Coder&#8221;. I got there a touch late and rapidly figured out that we were doing it in Ruby. Now, my Ruby skills are right up there with my Mandarin Chinese skills which is to say, I can&#8217;t even [...]]]></description>
			<content:encoded><![CDATA[<p>Last month at <a href="http://dallashackclub.com/">Dallas Hack Club</a>, we did the <a href="http://thecleancoder.blogspot.com/2010/10/craftsman-62-dark-path.html">Word Wrap Kata</a> from Uncle Bob Martin&#8217;s &#8220;Clean Coder&#8221;.  I got there a touch late and rapidly figured out that we were doing it in Ruby.  Now, my Ruby skills are right up there with my Mandarin Chinese skills which is to say, I can&#8217;t even order a scotch or find the restroom so I quickly figured out that if I followed along, I&#8217;d be sitting in a puddle of pee wishing I was drunk.  So I made the executive decision to ignore most everyone else and do it in parallel with the group but in Python since I can at least code like I&#8217;m drunk in Python.  </p>
<p>My experience was surprisingly similar to the post linked above, e.g. I went down the hardest path trying to solve the wrong test.  I&#8217;ve since gone back and deleted the code but the pseudocode went something like this:</p>
<pre class="brush: python; title: ; notranslate">Break text into a list using a list comprehension based on the length of the column
Start looking for words with spaces
Try to repiece things together based on the column length and the last space
Cry
</pre>
<p>Clearly, this wasn&#8217;t going to work.  About that time, we ran out of time and went to the Flying Saucer to drink beer and pretend like we weren&#8217;t geeks.  But I decided to finish the kata this week during a slow period at work.  Since I didn&#8217;t have Jerry there to talk me through how dumb I was, I started reading the post up until the point where it describes writing the wrong test and spending too much time trying to solve it.  So I backed up, deleted everything and started down the easier path of solving all the non-space related issues first.  Once I did that, and once I figured out that recursion was going to be a big help, the project really got easier.</p>
<p>The final solution is below:</p>
<pre class="brush: python; title: ; notranslate">
def wrap(text, num):

  if len(text) &lt;= num:
    return text
  elif text[num-1] == ' ':
    return text[:num].rstrip() + '\r\n' + wrap(text[num:], num)
  elif text[:num].find(' ') &gt; -1:
    rightSpaceIdx = text.rfind(' ')
    return text[:rightSpaceIdx] + '\r\n' + wrap(text[rightSpaceIdx:].lstrip(' '), num)
  else:
    return text[:num] + '\r\n' + wrap(text[num:].lstrip(), num)
</pre>
<p>It&#8217;s fascinating how quickly the algorithm starts to come together when you write the correct test.  The problem is, I&#8217;m terrible at all this so it&#8217;s going to take some time getting enough experience to correctly select what test to write next.  I was writing a ton of code trying to solve a problem that was too hard and the solution I eventually would have come up with would have been effective but brittle.  </p>
<p>The more I do TDD/BDD, the more I realize that it is *THE* way to develop software, especially if you&#8217;re working in a dynamic language.  I&#8217;m currently working through the tutorials at <a href="http://rubytutorials.org">Ruby Tutorials</a> and it&#8217;s great to see that TDD is a fundamental part of the process.  As I learned Python and Pylons, it was up to me to figure out best practices it seemed like and that&#8217;s workable but frustrating in the long run.  I&#8217;m planning on doing more katas in an effort to improve my craft.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentalpandiculation.com/2011/01/word-wrap-kata-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Route Gotchas In Pylons</title>
		<link>http://mentalpandiculation.com/2010/12/route-gotchas-in-pylons/</link>
		<comments>http://mentalpandiculation.com/2010/12/route-gotchas-in-pylons/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 21:26:29 +0000</pubDate>
		<dc:creator>Niklaus Wirth's Ghost</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pylons]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[routes]]></category>

		<guid isPermaLink="false">http://mentalpandiculation.com/?p=310</guid>
		<description><![CDATA[I&#8217;ve been working on a Pylons app quite a bit lately and occasionally I run across issues that warrant documentation on the interwebs. That happened today concerning routes and how Pylons deals with them. If you start getting an Import error that says &#8220;No module named content found&#8221;, you&#8217;ve run into it. According to the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a Pylons app quite a bit lately and occasionally I run across issues that warrant documentation on the interwebs.  That happened today concerning routes and how Pylons deals with them.</p>
<p>If you start getting an Import error that says &#8220;No module named content found&#8221;, you&#8217;ve run into it.  According to the <a href="http://pylonsbook.com/en/1.1/urls-routing-and-dispatch.html#unnecessary-routes-features">Pylons book</a>, &#8220;Routes has a surprising legacy feature that means that if you don’t specify a controller and an action for a particular route, the implicit defaults of controller=&#8217;content&#8217; and action=&#8217;index&#8217; will be used for you&#8221;.  This is certainly surprising to me and as always, things that are implicit tend to annoy me.  Luckily, you can change this behavior.  In your config/routing.py file, set map.explicit = True and then you&#8217;ll need to alter the route that is giving you problems to make the controller and action explicit.  For example:</p>
<p>Before</p>
<pre class="brush: python; title: ; notranslate">def make_map(config):
    &quot;&quot;&quot;Create, configure and return the routes Mapper&quot;&quot;&quot;
    map = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'])
    map.minimization = False
    map.explicit = False 

    # The ErrorController route (handles 404/500 error pages); it should
    # likely stay at the top, ensuring it can always be resolved
    map.connect('/error/{action}', controller='error')
    map.connect('/error/{action}/{id}', controller='error')

    # CUSTOM ROUTES HERE
    map.connect('schedule_entry', 'schedule/index/{scheduleDay}')
    map.connect('/{controller}/{action}')
    map.connect('/{controller}/{action}/{id}')

    return map
</pre>
<p>As you can see, the default behavior is for map.explicit to be set to False.  The first route under CUSTOM ROUTES HERE is a named route that to my eye should match schedule up with a controller and index up with the action.  Unfortunately, instead it tries to find the default implicit controller &#8220;content&#8221; which it can&#8217;t find and that throws the ImportError listed above.  To fix it do this:</p>
<p>After</p>
<pre class="brush: python; title: ; notranslate">
def make_map(config):
    &quot;&quot;&quot;Create, configure and return the routes Mapper&quot;&quot;&quot;
    map = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'])
    map.minimization = False
    map.explicit = True 

    # The ErrorController route (handles 404/500 error pages); it should
    # likely stay at the top, ensuring it can always be resolved
    map.connect('/error/{action}', controller='error')
    map.connect('/error/{action}/{id}', controller='error')

    # CUSTOM ROUTES HERE
    map.connect('/schedule/index/{scheduleDay}', controller='schedule', action='index')
    map.connect('/{controller}/{action}')
    map.connect('/{controller}/{action}/{id}')

    return map
</pre>
<p>Now the map is set to explicit and the controller and action are explicitly specified which works just fine.  This all may be an artifact my novice understanding of Routes but since the book documents it this way, I guess this is the way I&#8217;m going to do it.  </p>
]]></content:encoded>
			<wfw:commentRss>http://mentalpandiculation.com/2010/12/route-gotchas-in-pylons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TDD with Pylons</title>
		<link>http://mentalpandiculation.com/2010/11/tdd-with-pylons/</link>
		<comments>http://mentalpandiculation.com/2010/11/tdd-with-pylons/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 21:01:30 +0000</pubDate>
		<dc:creator>Niklaus Wirth's Ghost</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pylons]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Test Driven Development]]></category>

		<guid isPermaLink="false">http://mentalpandiculation.com/?p=298</guid>
		<description><![CDATA[I&#8217;ve written about test driven development and Pylons before but there have apparently been some changes to how it all works since Pylons 1.0. I didn&#8217;t run across anything in the documentation detailing the changes, specifically to the template context global and how you access it in your tests. From the Pylons docs on testing: [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve <a href="http://mentalpandiculation.com/2009/06/tdd-with-python-and-pylons/">written about</a> test driven development and Pylons before but there have apparently been some changes to how it all works since Pylons 1.0.  I didn&#8217;t run across anything in the documentation detailing the changes, specifically to the template context global and how you access it in your tests.</p>
<p>From the <a href="http://wiki.pylonshq.com/display/pylonsdocs/Unit+Testing">Pylons docs</a> on testing:</p>
<blockquote><p>Pylons will provide several additional attributes for the paste.fixture response object that let you access various objects that were created during the web request:</p>
<ol>
<li>session &#8212; Session object</li>
<li>req &#8212; Request object</li>
<li>c &#8212; Object containing variables passed to templates</li>
<li>g &#8212; Globals object</li>
</ol>
<p>To use them, merely access the attributes of the response after you&#8217;ve used a get/post command:</p>
<pre class="brush: python; title: ; notranslate">response = app.get('/some/url')
assert response.session['var'] == 4
assert 'REQUEST_METHOD' in response.req.environ</pre>
</blockquote>
<p>As it turns out, that&#8217;s sort of true.  I have a test that looks like this:</p>
<pre class="brush: python; title: ; notranslate">from nbapowerrank.tests import *

class TestGamedetailsController(TestController):

    def test_index(self):
        response = self.app.get(url(controller='admin/gamedetails', action='index'))
        self.assertEqual(len(response.c.games) &gt; 0, True)</pre>
<p>and a controller that looks like this:</p>
<pre class="brush: python; title: ; notranslate">from nbapowerrank.lib.base import BaseController, render
from nbapowerrank.model import meta
from nbapowerrank.model.game import Game

log = logging.getLogger(__name__)

class GamedetailsController(BaseController):
  def __before__(self):
    self.game_q = meta.Session.query(Game)

  def index(self):
    yesterday = datetime.today() - timedelta(1)
    c.games = self.game_q.filter_by(gamedate=yesterday).all()

    return render('/gamedetails.mako')</pre>
<p>Unfortunately, contra the documentation that says the &#8220;c&#8221; alias will be available on the test response object, that test always fails with an AttributeError stating that in fact, the c attribute does not exist.  It frustrated me even more because all the other attributes that are supposed to be on the response like session and g were in fact there.  After doing some random digging, I came across this in the <a href="http://wiki.pylonshq.com/display/pylonscommunity/Pylons+Roadmap+to+1.0">Pylons 1.0 roadmap</a>: &#8220;Deprecate pylons.c, pylons.g, and pylons.buffet. These have been disrecommended since 0.9.7.&#8221;</p>
<p>Apparently, they are/have deprecated using the c alias for tmpl_context even though when you create a controller under Pylons 1.0, it still aliases the context as c.  Sigh.  So in order to test data that you have added to your context for templating, your test should use the explicit tmpl_context instead of the c like this:</p>
<pre class="brush: python; title: ; notranslate">from nbapowerrank.tests import *

class TestGamedetailsController(TestController):

    def test_index(self):
        response = self.app.get(url(controller='admin/gamedetails', action='index'))
        self.assertEqual(len(response.tmpl_context.games) &gt; 0, True)</pre>
<p>And then all will be well with your world.  I do have to say that compared to both ASP.Net MVC and Rails, the testing support in Python/pylons seems to be a second class citizen.  I&#8217;m not sure why that is because as a dynamic language, it seems to benefit greatly from a TDD approach.  Maybe it&#8217;s just me getting back into a framework after a year&#8217;s worth of changes.</p>
<p>Anyway, that may help some people out there trying to search in the googleplex about TDD and Pylons.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentalpandiculation.com/2010/11/tdd-with-pylons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Development on Windows</title>
		<link>http://mentalpandiculation.com/2010/06/python-development-on-windows/</link>
		<comments>http://mentalpandiculation.com/2010/06/python-development-on-windows/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 16:56:24 +0000</pubDate>
		<dc:creator>Niklaus Wirth's Ghost</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[windows programming]]></category>

		<guid isPermaLink="false">http://mentalpandiculation.com/?p=289</guid>
		<description><![CDATA[I&#8217;ve been rededicating myself to a Python project over the last couple of days and hence have been trying to get my Dell Windows 7 laptop set up for Python development again. It hasn&#8217;t been particularly easy. The things I&#8217;ve run into so far: 1. Python 2.6 happily runs on Windows 64bit whatever but not [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been rededicating myself to a Python project over the last couple of days and hence have been trying to get my Dell Windows 7 laptop set up for Python development again.  It hasn&#8217;t been particularly easy.  The things I&#8217;ve run into so far:</p>
<p>1.  Python 2.6 happily runs on Windows 64bit whatever but not all 3rd party libraries are so forward thinking.  Specifically, if you&#8217;ve got a project using PostgreSQL and SqlAlchemy, SqlAlchemy will complain about the Python driver psycopg2 on 64bit systems.  There are other drivers out there but my solution was just to rollback my 64bit installation of Python and reinstall a 32bit version.  That seems to be working fine though I haven&#8217;t gotten to the point of actually reading and writing data yet.</p>
<p>2.  PYTHONPATH on Windows via the registry doesn&#8217;t seem to work, at least on my Windows 7 64bit installation.  I have added the required registry keys per the documentation, rebooted 42 times and done the Guido van Rossum Purple Rain Remix dance with exactly zero results.  For now, I&#8217;m just creating an environment variable the old fashioned way.</p>
<p>3.  The real problem that led me to having to modify PYTHONPATH was that package imports just don&#8217;t seem to be working.  I&#8217;m sure this is me being the Python equivalent of Charlie in Flowers For Algernon.  I think in the past I must have had some magical setting or batch file that modified PYTHONPATH at startup or something but I wish my subpackage imports worked without having to resort to that.  </p>
<p>On the plus side, my first TDD test passed first time up so I&#8217;ve got that going for me, which is nice.  At least the code isn&#8217;t so stale that it doesn&#8217;t even function anymore.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentalpandiculation.com/2010/06/python-development-on-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making It Easy To Learn Programming</title>
		<link>http://mentalpandiculation.com/2010/01/making-it-easy-to-learn-programming/</link>
		<comments>http://mentalpandiculation.com/2010/01/making-it-easy-to-learn-programming/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 20:29:05 +0000</pubDate>
		<dc:creator>Niklaus Wirth's Ghost</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[learn to program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://mentalpandiculation.com/?p=226</guid>
		<description><![CDATA[Glenn Reynolds talks about a shortage of geeks and one of his readers comments that a key contribution to this is when computers stopped shipping with BASIC. Glenn makes the plea to computer makers to include BASIC on the computers as a public service. Of course, Macs already ship with both Python and Ruby, surely [...]]]></description>
			<content:encoded><![CDATA[<p>Glenn Reynolds talks about a <a href="http://pajamasmedia.com/instapundit/91890/">shortage of geeks</a> and one of his readers comments that a key contribution to this is when computers stopped shipping with BASIC.  Glenn makes the plea to computer makers to include BASIC on the computers as a public service.  Of course, Macs already ship with both Python and Ruby, surely superior languages to BASIC and excellent learning languages as well.</p>
<p>On a Mac, all you have to do is fire up a terminal (Apple Key + Space Bar and then type &#8220;Terminal&#8221;), type &#8220;python&#8221; in the new terminal and you have a place to start learning programming.  Work through the <a href="http://docs.python.org/tutorial/">Python tutorial</a> and you&#8217;re well on the way to becoming a novice Python programmer.</p>
<p>Of course, on a Windows machine you&#8217;re going to have to do a little more work because, well, it is Windows after all.</p>
]]></content:encoded>
			<wfw:commentRss>http://mentalpandiculation.com/2010/01/making-it-easy-to-learn-programming/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

