<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://nedbatchelder.com/rssfull2html.xslt" media="screen" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://purl.org/rss/1.0/">
	<channel rdf:about="http://nedbatchelder.com//blog">
		<title>Ned Batchelder's blog</title>
		<link>http://nedbatchelder.com/blog</link>
		<description>Ned Batchelder's personal blog.</description>
		<dc:language>en-US</dc:language>
		<image rdf:resource="http://nedbatchelder.com/pix/rss-banner.gif"/>
		<items>
			<rdf:Seq>
				<rdf:li resource="http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/test_classes_singular_or_plural.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/25_minutes_is_a_bitch.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/custom_letters_2009.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/lost_cake.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/pycon_on_the_charles_part_2.html"/><rdf:li resource="http://nedbatchelder.com/blog/201002/ipad_ergonomics.html"/><rdf:li resource="http://nedbatchelder.com/blog/201001/running_code_at_python_startup.html"/><rdf:li resource="http://nedbatchelder.com/blog/201001/pycon_on_the_charles_part_1.html"/>
			</rdf:Seq>
		</items>
	</channel>
	<image rdf:about="http://nedbatchelder.com/pix/rss-banner.gif">
		<title>Ned Batchelder's blog</title>
		<link>http://nedbatchelder.com/blog</link>
		<url>http://nedbatchelder.com/pix/rss-banner.gif</url>
	</image>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html">
		<title>A preventable Python packaging peeve</title>
		<link>http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html</link>
		
		<dc:date>2010-02-09T07:58:37-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>Python packaging is a common theme on which to complain, and rightly so.
It's no one's first love, so it tends not to get the devoted attention of say,
Numpy.  And it's a hard problem to solve well.  So we have a mish-mash of tools
that each do about 75% of the job.</p><p>But there's one small aspect of Python packaging that could easily be solved
well if people just attended to it:  Not enough Python projects clearly state
what versions of Python they run on.</p><p>For example, suppose you are in the market for a mock object library for your
tests.  There's no shortage.  Less than a minute at PyPI produces
<a class="offsite" href="http://pypi.python.org/pypi/mock/0.6.0">mock</a>,
<a class="offsite" href="http://pypi.python.org/pypi/MiniMock/1.2.5">MiniMock</a>,
<a class="offsite" href="http://pypi.python.org/pypi/mocktest/0.3.1">mocktest</a>,
<a class="offsite" href="http://pypi.python.org/pypi/Mocky/0.2">Mocky</a>,
<a class="offsite" href="http://pypi.python.org/pypi/pmock/0.3">pmock</a>,
<a class="offsite" href="http://pypi.python.org/pypi/mocker/0.10.1">mocker</a>,
<a class="offsite" href="http://pypi.python.org/pypi/mockito/0.2.0">mockito</a>, and
<a class="offsite" href="http://pypi.python.org/pypi/ludibrio/2.0">ludibrio</a>.
Some of those PyPI pages have extensive documentation.  Not a single one explicitly
mentions the versions of Python supported.  And I don't mean 2.x vs. 3.x.  I want
to know if it will run on 2.4 or not.  Ludibrio and Mocky offer a slight clue
in that they are available for download as an egg, for 2.5 and 2.4 respectively.
pMock mentions &gt;= 2.3 support on the home page linked from the PyPI page.</p><p>On top of all the other well-known difficulties people have with Python
packaging, at the very least, we should be able to manage this: clearly state
what versions of Python you support.  This is a simple three-step process:</p><ol>
<li>Decide what versions you want to support.</li>
<li>Test your code on those versions.</li>
<li>Add a sentence like this to your PyPI documentation: "SpockMocker runs
on Python 2.5 and 2.6".</li>
</ol><p>The Python community will thank you.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html">
		<title>21st century life in transition</title>
		<link>http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html</link>
		
		<dc:date>2010-02-08T07:44:47-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>Sitting at the breakfast table, my wife <a class="offsite" href="http://susansenator.com">Susan</a>
was reading the paper, and when she got to the end of a story, dragged her
finger down the paper to try to scroll the newspaper.</p><p>I've sat in a movie theater watching trailers, and glanced at the bottom of
the screen to try to see the progress bar to see how much time was left in the
short clip.</p><p>Max said when he's writing on paper with a pencil, and makes a mistake, his
left hand twitches as if to hit cmd-Z.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/test_classes_singular_or_plural.html">
		<title>Test classes, singular or plural?</title>
		<link>http://nedbatchelder.com/blog/201002/test_classes_singular_or_plural.html</link>
		
		<dc:date>2010-02-07T19:26:33-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>A minor hiccup in writing unit tests is how to name the classes that contain
them.  The jUnit style of test class, which has been adopted by virtually
everyone, including Python's unittest module, is that tests are methods of a
class. The class is instantiated once for each test method, then three methods
are called: setUp, the test method, and tearDown.</p><p>As a result, you end up with test classes that look like this:</p><blockquote class="code"><tt><span class="p_commentline">#&#160;Tests&#160;for&#160;double_it,&#160;and&#160;no,&#160;no&#160;one&#160;would&#160;write&#160;them&#160;this&#160;way...</span><br/>
<span class="p_word">class</span><span class="p_default">&#160;</span><span class="p_classname">DoubleItTests</span><span class="p_operator">(</span><span class="p_identifier">unittest</span><span class="p_operator">.</span><span class="p_identifier">TestCase</span><span class="p_operator">):</span><br/>
<span class="p_default">&#160;&#160;&#160;&#160;</span><span class="p_word">def</span><span class="p_default">&#160;</span><span class="p_defname">test_ten</span><span class="p_operator">(</span><span class="p_identifier">self</span><span class="p_operator">):</span><br/>
<span class="p_default">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</span><span class="p_word">assert</span><span class="p_default">&#160;</span><span class="p_identifier">double_it</span><span class="p_operator">(</span><span class="p_number">10</span><span class="p_operator">)</span><span class="p_default">&#160;</span><span class="p_operator">==</span><span class="p_default">&#160;</span><span class="p_number">20</span><br/>
<span class="p_default">&#160;&#160;&#160;&#160;</span><br/>
<span class="p_default">&#160;&#160;&#160;&#160;</span><span class="p_word">def</span><span class="p_default">&#160;</span><span class="p_defname">test_twenty</span><span class="p_operator">(</span><span class="p_identifier">self</span><span class="p_operator">):</span><br/>
<span class="p_default">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</span><span class="p_word">assert</span><span class="p_default">&#160;</span><span class="p_identifier">double_it</span><span class="p_operator">(</span><span class="p_number">20</span><span class="p_operator">)</span><span class="p_default">&#160;</span><span class="p_operator">==</span><span class="p_default">&#160;</span><span class="p_number">40</span><br/>
</tt></blockquote><p>Here I've named the class DoubleItTests, plural.  That's because I can see
that it's a container for a number of tests.  This feels right if you think
about the class simply as a namespace for the test methods.</p><p>But what is instantiated from the class?  Only single tests.  In this case,
the class will be instantiated twice, once to run test_ten, and once to run
test_twenty.  The class' name should really be the name of the objects.  No one
would name their user class Users under the theory that the class encompasses
a number of users.</p><p>So the test class should really be called DoubleItTest, which I guess fits
in with the unittest.TestCase base class it derives from.  But somehow it just
looks wrong.</p><p>This is reminiscent of the
<a class="offsite" href="http://stackoverflow.com/questions/338156/table-naming-dilemma-singular-vs-plural-names">SQL table naming dilemma</a>.
Is it the CUSTOMER table, or the CUSTOMERS table? How you feel about it seems to
come down to whether you think natively in SQL, or whether it's just a backing
store for your ORM.</p><p>I'm getting used to the singular test class name, but it still doesn't come
naturally, I have to remind myself to leave off those tempting plurals.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/25_minutes_is_a_bitch.html">
		<title>25 minutes is a bitch</title>
		<link>http://nedbatchelder.com/blog/201002/25_minutes_is_a_bitch.html</link>
		
		<dc:date>2010-02-06T09:04:16-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>This is the season for preparing talks for PyCon, which is less than two
weeks away.  I've not only been working on mine, but I organized rehearsals
for the other Boston-area speakers, so I've been immersed in the process.
</p><p>PyCon talks generally have half-hour slots, with five minutes at the end
intended for questions from the audience, leaving only 25 minutes in which to
get your message across.  In some ways, 25 minutes is a long time to stand in
front of a crowd of distracted strangers and try to explain something.  If you've
never done it before, you'll probably feel like you don't have enough to say.</p><p>But that isn't true, because if you've chosen a topic to propose for
PyCon, and written a good enough proposal to get it accepted, you have identified
a topic about which you are passionate.  And expecting someone to talk about their
passion in only 25 minutes is expecting a lot.</p><p>Thinking back over the eight talks I've seen in draft form this past month,
they all have something in common: they aren't going to fit in their time slot.
The speaker has over-stuffed the talk with all of the things that fascinate them
about their chosen topic, and there just isn't enough time.</p><p>You have to make harsh cuts to the topic, you have to choose the one point
you really need to make, and you need to avoid all the fascinating side alleys
and back stories and witty asides you can.  You need to make sure that you have
a clear arc of a story to tell, and that arc has to fit in 25 minutes.</p><p>I use the word "story" intentionally, and it may seem out of place in a
description of a programming talk.  But no matter how dry you think your material
is ("Here's how the __frabbitz__ methods work"), you need to give the listener
a reason to care, and that reason will involve a story about a person like them.
So you'll want the talk to include at least a little something like, "You're
trying to write a program, your job will be much easier if you use __frabbitz__
like this...".</p><p>Once you have the arc of the story established, then you can add in asides
and jokes and so on.  It's important to be engaging and entertaining, but it
can't be at the expense of your main points.  You have to establish the skeleton
of the talk (the main points and how you'll explain them) before you can embellish
it with the extra stuff.</p><p>Unfortunately, 25 minutes means you have to abandon a lot of your cherished
ideas on the cutting room floor.  There will be fascinating points about which
you are passionate, and you will not have time to mention them.</p><p>One important thing to remember: your listeners don't have to leave the room
as expert as you are.  It may be enough simply to convince them that this is a
topic they care about, even if it means they have to go back later and really
learn the details.  If they go home knowing that __frabbitz__ is important,
why it's important to them in particular and have some vague memory of some
milestones along the journey, then they can fill in the details on their own, in
their own learning style, later. You've done your job by planting those
seeds.</p><p>For more on presentations in general, take a look at these
<a href="http://nedbatchelder.com/text/presentationtips.html">presentation tips</a> I wrote a few years back.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/custom_letters_2009.html">
		<title>Custom letters 2009</title>
		<link>http://nedbatchelder.com/blog/201002/custom_letters_2009.html</link>
		
		<dc:date>2010-02-03T06:06:14-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p><a class="offsite" href="http://www.lettercult.com/archives/1184">Custom Letters 2009</a>
is an encyclopedic collection of hundreds of custom lettering projects done
in the past year.  The diversity is astounding, ranging from simple primitive
art to elaborate hyper-calligraphic orgies.  Some are witty, some are beautiful,
some are illegible but leave a nice taste in your mouth.   This one by Michiel Van der Born
in particular caught my eye:</p><p align="center"><a href="http://www.lettercult.com/archives/1184/2"><img src="http://nedbatchelder.com/pix/LC_TYPOTALK.jpg" alt="Typotalk poster by Michiel Van der Born" width="500" height="682"></a></p><p>They say today they're picking a top ten, and Friday something called AlphaBattle
begins.  I don't know what it is, but it sounds interesting.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/lost_cake.html">
		<title>Lost cake</title>
		<link>http://nedbatchelder.com/blog/201002/lost_cake.html</link>
		
		<dc:date>2010-02-02T18:17:36-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>Tonight is the first episode of the final season of
<a class="offsite" href="http://abc.go.com/shows/lost">Lost</a>.  Max has long been obsessed
with the show, but the rest of us had
<a href="http://nedbatchelder.com/blog/200603/lost_rhapsody.html">never watched it</a>.
That is, until early December when we decided to power-chug through the existing
five seasons on DVD, so we'd be ready for tonight. We finished watching the DVDs
a few weeks ago, and are eager to see what's coming.
</p><p>As is typical in our family, that excitement translates into cake:</p><p align="center"><a href="http://nedbatchelder.com/pix/lostcake.jpg"><img src="http://nedbatchelder.com/pix/lostcake_thumb.jpg" alt="LOST cake" width="450" height="299"></a></p><p>It's a little hard to see the detail: we have a chunk of fuselage (cake),
with a broken wing (chocolate bar) complete with turbine engine (Twinkie).
Palm trees are Tootsie Rolls topped with gummy worms.
</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/pycon_on_the_charles_part_2.html">
		<title>PyCon on the Charles, part 2</title>
		<link>http://nedbatchelder.com/blog/201002/pycon_on_the_charles_part_2.html</link>
		
		<dc:date>2010-02-02T07:55:29-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>Tomorrow night is 
<a class="offsite" href="http://python.meetup.com/181/calendar/12189588/">PyCon on the Charles, part 2</a>.
a rehearsal for four Boston-area PyCon speakers.  The first session two weeks
ago was a big success.  About 60 Pythonistas showed up to hear the speakers and
give them valuable feedback to get ready for Atlanta.</p><p>Join us if you want to see some great Python talks.
<a class="offsite" href="http://python.meetup.com/181/calendar/12189588/">RSVP here</a>.
</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201002/ipad_ergonomics.html">
		<title>iPad ergonomics</title>
		<link>http://nedbatchelder.com/blog/201002/ipad_ergonomics.html</link>
		
		<dc:date>2010-02-01T18:59:04-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I watched the iPad announcement last week with interest.  I'm not a
gadget-hound, but Max and I were both home that day, so he gave me play-by-play
commentary of the announcement.  It's certainly an intriguing device with plenty
of interesting facets to debate (open/closed, produce/create, and so on).
</p><p>One thing I definitely don't get is the ergonomics of it. Look at this
demonstration of editing a slide show on the iPad:</p><p align="center"><object width="560" height="340">
        <param name="movie" value="http://www.youtube.com/v/SBPnB3noTa8&amp;hl=en_US&amp;fs=1&amp;">
        <param name="allowFullScreen" value="true">
        <param name="allowscriptaccess" value="always">
        <embed src="http://www.youtube.com/v/SBPnB3noTa8&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed>
    </object></p><p>First of all, I don't understand his emphasis on the apparent miracle of
coming up with ways to manipulate objects on the screen with touch.  I thought
we had all gotten used to the concept of touch and multi-touch.  But that's not
the main point.  Watch it again, but don't look at the screen: look at his <em>hands</em>.
</p><p>He looks uncomfortable. He's trying to hold the iPad in his left hand, and
perform precise touching with his right. His non-touching fingers are being held
stiffly up out of the way to avoid making an accidental multi-touch. He's got
nowhere to rest his right hand. And when he has to touch with both hands, they
keep crossing over each other like some kind of crazy-advanced piano sonata. 
</p><p>I can see using the iPad to watch stuff, or any task that doesn't require
much input. But that demo showed me that it will be much too awkward to make the
sort of gestures needed to do real work. People need to rest their hands on
something. It's hard to hold your arm up without something to help carry the
weight. Keyboards have palm rests, mice let your wrist sit on the desk.
Palm-sized devices like the iPhone are light enough to hold while tapping with
your thumbs. Maybe it would be OK while sitting in a chair with arm rests?</p><p>I'll be interested to see how people use the iPad. I could see propping it up
in my lap with one hand and tapping for a while with the other, but long
sessions, or two-handed use, just seem too unnatural.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201001/running_code_at_python_startup.html">
		<title>Running code at Python startup</title>
		<link>http://nedbatchelder.com/blog/201001/running_code_at_python_startup.html</link>
		
		<dc:date>2010-01-14T08:44:00-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>I recently had need to run a piece of Python code before every invocation
of the interpreter.  In my case, it was to enable coverage testing of processes
spawned by a test suite.  Certain tests would run Python code in a subprocess,
and I wanted to measure coverage within that process.
</p><p>I added a function to coverage.py that is suitable for executing on startup.
It examines the environment to determine whether to start measuring coverage.
(This code isn't released yet, but if you want to try it, it's on the trunk
at <a class="offsite" href="http://bitbucket.org/ned/coveragepy">bitbucket</a>.)</p><p>Perl has a command line switch (-M) for this, as does Ruby (-r), but Python
doesn't.  I came up with two ways to do it for Python, both depending on the
<a class="offsite" href="http://docs.python.org/library/site.html">site</a> module which is
imported automatically on startup.</p><p>The first way is to create a sitecustomize.py file on the path somewhere.
This module will be imported automatically by site.py. Any lines you add to that
file are executed when Python starts:</p><blockquote class="code"><tt><span class="p_word">import</span><span class="p_default">&#160;</span><span class="p_identifier">coverage</span><br/>
<span class="p_identifier">coverage</span><span class="p_operator">.</span><span class="p_identifier">process_startup</span><span class="p_operator">()</span><br/>
</tt></blockquote><p>This is simple, but editing an existing sitecustomize.py could be awkward,
and you may not even have permissions to do it.</p><p>The second way is to create a .pth file with an executable line.  Usually
lines in .pth files are directory names, but if the line starts with "import ",
it is executed (what a hack!), so you can create a .pth file like this:
</p><blockquote class="code"><tt><span class="p_word">import</span><span class="p_default">&#160;</span><span class="p_identifier">coverage</span><span class="p_operator">;</span><span class="p_default">&#160;</span><span class="p_identifier">coverage</span><span class="p_operator">.</span><span class="p_identifier">process_startup</span><span class="p_operator">()</span><br/>
</tt></blockquote><p>This has the advantage that you can create a new file without worrying about
touching existing files, all .pth files will be examined and interpreted.
Unfortunately, you might have to give the file a strange name, since they are
executed alphabetically, and a package you need may only be available after its
.pth file has been seen.  In my case, I named my .pth file
zzz_coverage_process_start.pth to be sure it ran after coverage was added to
the path.</p><p>Neither of these feels clean or elegant.  I'm wondering if there are better
techniques I'm overlooking?  Python has a clean way to register functions to
be called at process exit (<a class="offsite" href="http://docs.python.org/library/atexit.html">atexit</a>),
which has been designed so that multiple authors of exit functions don't need to
cooperate to avoid interfering with each other.  It'd be nice to have a similar
facility for startup functions.</p>
]]></description>
	</item>
	
	<item rdf:about="http://nedbatchelder.com/blog/201001/pycon_on_the_charles_part_1.html">
		<title>PyCon on the Charles, part 1</title>
		<link>http://nedbatchelder.com/blog/201001/pycon_on_the_charles_part_1.html</link>
		
		<dc:date>2010-01-13T09:19:29-05:00</dc:date>
		<dc:creator>Ned Batchelder</dc:creator>
		<description><![CDATA[<p>The Cambridge Python Meetup will have a session next Wednesday, January 20.
Three Boston-area PyCon speakers will be rehearsing their talks.  PyCon 2010
is (as you must know) in Atlanta in February.  This is a chance for speakers
to practice and get some feedback to improve their talks.  It's also a chance
for Pythonistas who can't get to Atlanta to see some of the PyCon content.
Heck, even if you are going to Atlanta, this is a way to resolve some of those
"can't be in two places at once" problems at PyCon, which this year will have
<a class="offsite" href="http://spreadsheets.google.com/pub?key=t4SBtBV9Qi0pHXHOUAc83Aw&amp;output=html">five parallel tracks</a>!
</p><p>Full details and RSVP: <a class="offsite" href="http://python.meetup.com/181/calendar/12189514/">PyCon on the Charles, part 1</a>.
There may even be snacks.</p><p>Boston has six speakers this year, so part 2 will be on February 3:
<a class="offsite" href="http://python.meetup.com/181/calendar/12189588/">PyCon on the Charles, part 2</a>.
</p>
]]></description>
	</item>
	
</rdf:RDF>
