<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Let’s Discuss the Matter Further</title>
    <link>http://rhodesmill.org/brandon</link>
    <description>Your Blog's short description</description>
    <pubDate>Thu, 19 Jan 2012 00:48:19 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Grok has book. Book good!</title>
      <link>http://rhodesmill.org/brandon/2010/grok-has-book-book-good/</link>
      <pubDate>Thu, 10 Jun 2010 22:32:52 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[books]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=350</guid>
      <description>Grok has book. Book good!</description>
      <content:encoded><![CDATA[
<p>
  I little suspected the great chasm that lies
  between the simple act of agreeing to review a book,
  and the actual exercise of sitting down later to write the review.
  It feels quite pleasant, really,
  to jot off a positive reply to the publisher's polite question.
  One feels magnanimous for agreeing to help advance our civilization
  by reviewing a book about Python,
  and for helping out the publisher in what,
  after all, are such hard economic times.
  It is fun when the free copy arrives,
  crisp and smartly bound.
</p>
<p>
  But then, eventually, one has to write the actual review.
</p>
<div class="dropshadow alignright"> 
  <a href="http://www.amazon.com/gp/product/1847197485?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1847197485"><img border="0" src="http://rhodesmill.org/brandon/static/2010/grok-book.jpg"></a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=1847197485" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
</div>
<p>
  And so,
  a full four months after that friendly email from Packt Publishing,
  it is time that I sit down
  and put together some thoughts
  about Carlos de la Guardia's first book,
  <a href="http://www.amazon.com/gp/product/1847197485?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1847197485"
     >Grok 1.0 Web Development</a>.
  Carlos is a long-time veteran of the Zope and Plone communities,
  and <a href="http://grok.zope.org/">Grok</a>,
  of course,
  is the web framework
  that places a simple and agile convention-driven engine
  atop the otherwise notoriously XML-ridden Zope application framework.
  Grok is an important project,
  because it packages the technology of Python's oldest
  and most experienced community of web developers
  in a way that makes it easy to extend and use.
</p>
<!--more-->
<p>
  First, one notices that the book does exhibit the kind of typos
  for which Packt are well known;
  but not so many, in this case, as to distract me from the text.
  The book tackles increasingly complicated topics
  in roughly the same order as every book in the web development genre:
  first installation, then views, models, forms, and so forth.
  But even here one notices an initial difference!
  Because this is the land of Zope,
  the search engine chapter appears quite early in the book —
  in Chapter 6, in fact.
  While some web frameworks can only support search
  through the installation of a special database extension,
  or perhaps through an entirely separate third-party application,
  Grok comes with search already integrated into its object database.
  This lets the concept be introduced early
  as a natural part of the framework,
  rather than being a difficult exercise in product integration
  best left for after the user has learned deployment.
</p>
<p>
  Not that third-party products are bad!
  In fact, I am happy to see that in many cases Carlos teaches his readers to use them.
  Barely twenty pages into the book,
  the new developer is being taught about using
  <a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>
  to maintain an installation of Python packages;
  and near the end,
  Carlos teaches deployment using the modern and sleek
  <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a> module.
  Some books feel myopically focused on one software community;
  this one, instead, feels expansive,
  a place where best practices from all across the Python ecosystem meet.
</p>
<p>
  It is particularly notable
  that at one point Carlos steps outside of Zope entirely
  and, for an entire chapter, describes how Grok integrates support
  for relational databases through
  <a href="http://www.sqlalchemy.org/">SQLAlchemy</a>,
  Python's most outstanding ORM.
  This both reflects credit upon the flexibility of Grok —
  whose abstractions must be working extremely well
  to build atop an entirely different database model,
  one that is not even native to Zope —
  and it evidences Carlos's determination
  to teach a very wide set of skills in his book.
  In fact, he even goes in the other direction at one point,
  and teaches the interested developer
  how to use the ZODB <i>without</i> Grok
  in case they want to access it from another application!
</p>
<p>
  The book tends to be quite clear in what it explains,
  but it sometimes feels as though a few more side trips
  in its examples would be welcome —
  it was not always clear to me whether a beginner,
  after plowing through an example,
  would understand what alternatives Carlos faced at each step,
  and why Carlos chose to build the solutions in the way he did.
</p>
<p>
  Though the book does cover testing,
  it is not test <i>driven</i> —
  testing is confined to its own chapter near the end of the book,
  rather than motivating the design of each sample application.
  A more interesting omission
  is that the book says nothing about web services,
  despite the fact that XML-RPC and REST are two things that Grok does particularly well!
  A chapter on building web APIs would be a great subject
  for a second edition of this book,
  especially if it then proceeded
  to show how easily Grok can support the Ajax design pattern.
</p>
<p>
  It did strike me as decidedly old-fashioned
  that Carlos repeats the weary canard
  that the Zope template language's awkwardness and verbosity
  are worth it,
  because it allows your templates to remain valid HTML,
  because your designers might, at any moment,
  want to open up and tweak a raw template in their browsers!
  This, of course, only works if your templates are each an entire page —
  if you fail to avail yourself, in other words, of <i>any</i> of the power
  of the macros, slots, and viewlets
  that Carlos goes on to describe later.
  And, in fact, many of his later templates
  are indeed mere un-styled HTML snippets
  that no designer in their right mind would view in isolation.
  All of which leads to the question of why
  <a href="http://genshi.edgewall.org/">Genshi</a>,
  another template language popular with Grok developers,
  does not warrant any mention in the book —
  especially since the book in so many other cases
  is careful to mention more widely deployed Python technologies
  that Grok is able to use.
</p>
<p>
  Finally, I can attest that a concept
  I never managed to learn when I was active with Grok —
  the tangle of concepts that surround
  viewlets, viewlet managers, layers, and skins —
  became quite clear as I sat down
  and read Chapter 8 in close detail.
  On the one topic which I could truly approach as a newcomer, therefore,
  I found Carlos's approach to be very direct and understandable.
</p>
<p>
  Grok has good online documentation,
  but unless you are already an experienced developer
  you will have difficulty putting the pieces together
  into a story that runs smoothly from model to view to deployment.
  If you need help getting the whole picture
  of how Grok apps fit together,
  you will certainly want this book.
  You can purchase it from either
  <a href="http://www.amazon.com/gp/product/1847197485?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1847197485"
     >Amazon</a>
  or directly from its publisher,
  <a href="http://www.packtpub.com/grok-1-0-web-development/book?utm_source=rhodesmill.org&utm_medium=bookrev&utm_content=blog&utm_campaign=mdb_002483"
     >Packt Publishing</a>.
</p>]]></content:encoded>
    </item>
    <item>
      <title>The July 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-july/</link>
      <pubDate>Sat, 15 Aug 2009 03:50:14 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=209</guid>
      <description>The July 2009 issue of Python Magazine</description>
      <content:encoded><![CDATA[
<div class="dropshadow alignright">
  <a>
    <img src="http://rhodesmill.org/brandon/static/2009/pymag-july.jpg"
         alt="Cover of July 2009 Python Magazine"
         width="200" height="258" />
  </a>
</div>
<p>
  I am home from a relaxing vacation to the Midwest,
  and while I was gone last week my excellent publishing team
  released the July issue <i>Python Magazine</i> to the world.
  I am particularly pleased that two of the feature articles in this issue
  come from important segments of the Python world
  that we have not heard much from in previous issues.
</p>
<p>
  First,
  <a href="http://www.codeplex.com/IronPython"
     >IronPython, the .NET version of Python for Windows</a>,
  is the topic of Jonathan Hartley's article about acceptance testing.
  He illustrates that,
  regardless of the language
  in which you write your .NET application,
  you can deploy simple strategies
  to make your application testable
  through a Python test harness,
  and thereby bring Python's strong flexibility as a testing language
  to bear on a product
  that you might be writing in another .NET language.
</p>
<p>
  Second, Malthe Borch, a veteran of the Zope community,
  shares how he has written
  <a href="http://chameleon.repoze.org/">Chameleon,
  one of the fastest template language
  implementations available for Python</a>.
  By processing each template
  and turning it into Python bytecode
  before it is ever used to render a single page,
  Malthe eliminates a huge amount of redundant processing
  as that same code is used over and over again.
  His library is a key ingredient
  in the new high-efficiency web frameworks
  appearing in the Zope world.
  His work might even (fingers crossed) become one of the components
  that the Plone community uses
  as they streamline their framework
  and move towards a lighter and more agile “Plone 4”.
</p>
<p>
  Other technical topics covered are: the
  <a href="http://hadoop.apache.org/">Hadoop</a> map-reduce framework;
  the concept of hash functions, and how they apply to Python;
  and the new
  <a href="http://docs.python.org/library/string.html#format-string-syntax"
     >string formatting operator</a>
  which Guido hopes will replace all of the percent-signs
  that currently litter our code.
  Wrap it all up with an editorial by Steve Holden
  about <a href="http://www.europython.eu/">EuroPython 2009</a>
  and an editorial by me,
  and you have a complete issue!
  If you do not find Python Magazine
  sitting on your local newsstand,
  then I hope you will avail yourself of a subscription
  and, as always, let me know what topics
  you would like to see covered in future issues.
  Enjoy!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Porting a C extension module to Python 3.0</title>
      <link>http://rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/</link>
      <pubDate>Tue, 09 Dec 2008 04:18:16 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=25</guid>
      <description>Porting a C extension module to Python 3.0</description>
      <content:encoded><![CDATA[
<p>
With several packages already advertising
<a href="http://pypi.python.org/pypi?:action=browse&c=214&c=534"
 >Python 3.0 compatibility</a>,
it seemed high time to look into releasing my
<a href="http://rhodesmill.org/pyephem/">PyEphem astronomy package</a>
in an edition compatible with the new language.
But I hesitated:
how difficult is it <i>really</i>,
and how many hours of work will it consume,
to port a C-language extension module to Python 3.0?
</p>
<p>
The answer is that,
while the necessary changes were surprisingly easy,
they took lots of time to figure out
because I did not find them documented in any one place.
I offer the following notes to assist
any other adventurers who want to experiment
with porting their extension modules to 3.0.
These notes might also suggest
useful additions to the official documentation.
</p>
<p>
But, first, I need to issue three cautions.
To develop under 3.0, you may have to forego several Python tools
that you probably thought you could no longer do without.
The world of 3.0 is a windswept and icy landscape
from which the glaciers have just receded,
and you will find the stone tools rather primitive
when compared to the comforts of civilization
that you enjoy under Python 2.
To wit:
</p>
<ul>
<li>I cannot find
 <a href="http://pypi.python.org/pypi/virtualenv/1.3.1">virtualenv</a>
 for 3.0,
 which is a disaster.
 This means that you have to create a separate Python 3.0 install,
 built with a different <tt>--prefix</tt> option to <tt>./configure</tt>,
 for each development environment you want to create on your box.
</li>
<li>I cannot find a version of the
 <a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a>
 available for 3.0.
 This means limiting your <tt>setup.py</tt> instructions
 to the primitive vocabulary of the <tt>distutils</tt> package.
 For example,
 I find myself unable to run the PyEphem test suite at this late hour
 because I have been running it for so long with:
 <pre>$ python setup.py test</pre>
 that I am not sure how to get it running otherwise.
</li>
<li>Should you succeed in porting your extension module,
 it is not at <i>all</i> clear how to distribute it.
 I had expected either a new PyPI to spring into being —
 since every package will need an entirely different version under 3.0 —
 or for a sophisticated scheme to appear
 for registering one <tt>pyephem.tar.gz</tt> as the Python 2 version
 and another <tt>pyephem.tar.gz</tt> for 3.0.
 But while the most recent version of your package can
 mark itself as
 <a href="http://pypi.python.org/pypi?:action=browse&c=214&c=527"
  >2-compatible</a> or
 <a href="http://pypi.python.org/pypi?:action=browse&c=214&c=533"
  >3-compatible</a> (or both)
 using classifiers,
 there is no way to have <i>two</i> “most recent” versions
 of a package.
 Are we supposed to start distributing a single <tt>tar.gz</tt>
 that includes the source code for both Python series,
 and that selects the right code by detecting the interpreter version
 at the top of the <tt>setup.py</tt> file?
</li>
</ul>
<p>
So if you make the effort to port your code right now,
you might find that the shiny new version of your module
is all dressed up, but has no place to go.
If you experiment with the following steps, though,
you will at least be ready
when an official distribution channel does appear
for releasing your package into the wilds of 3.0.
</p>
<!--more-->
<h2>Four Steps To 3.0</h2>
<p>
Yes, four steps were all that were necessary
to convert my quite complex extension module to Python 3.0!
</p>
<ol>
<li><b>Use PyModule_Create().</b>
 The old mechanism that I had been using
 to initialize my extension module,
 the rather clunkily-named <tt>Py_InitModule3()</tt>,
 happily does not even exist in the Python 3.0 header files.
 Instead, call the <tt>PyModule_Create()</tt> function
 which you can find described
 in the <a href="http://docs.python.org/3.0/extending/extending.html#the-module-s-method-table-and-initialization-function"
  >Module Initialization</a>
 section of the <a href="http://docs.python.org/3.0/extending/"
  >Extending and Embedding</a> document.
 And be sure to keep its return value:
 unlike in older Pythons,
 you now have to return the module object it creates
 as the return value from your module initialization function.
</li>
<li>
 <p>
 <b>Adjust all Python object headers.</b>
 Each type object in my code started with a macro
 to set up the common fields that all Python objects share.
 This was then followed by the <b>ob_size</b> field,
 which in my code always is always zero,
 and then the type name:
 </p>

<div class="pygments_murphy syntax_highlight"><pre><span class="cm">/* For Python 2 */</span><br/><br/><span class="k">static</span> <span class="n">PyTypeObject</span> <span class="n">BinaryStarType</span> <span class="o">=</span> <span class="p">{</span><br/>     <span class="n">PyObject_HEAD_INIT</span><span class="p">(</span><span class="nb">NULL</span><span class="p">)</span><br/>     <span class="mi">0</span><span class="p">,</span>                   <span class="cm">/* ob_size */</span><br/>     <span class="s">&quot;ephem.BinaryStar&quot;</span><span class="p">,</span>  <span class="cm">/* tp_name */</span><br/>     <span class="p">...</span><br/></pre></div>


 <p>
 Though the Python 3.0 documentation
 <a href="http://docs.python.org/3.0/extending/newtypes.html"
  ><i>still</i> shows this as the way to create types</a>,
 this technique will now completely fail.
 (The <a href="http://bugs.python.org/issue4385">bug indicating
 that the documentation gets this wrong</a> has,
 as its most recent comment,
 the helpful note
 “I'm lowering the priority so it doesn't block the release.”)
 Anyway, the solution is simple:
 the first two lines in the struct shown above
 simply have to be combined into a single macro call:
 </p>

<div class="pygments_murphy syntax_highlight"><pre><span class="cm">/* For Python 3.0 */</span><br/><br/><span class="k">static</span> <span class="n">PyTypeObject</span> <span class="n">BinaryStarType</span> <span class="o">=</span> <span class="p">{</span><br/>     <span class="n">PyVarObject_HEAD_INIT</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><br/>     <span class="s">&quot;ephem.BinaryStar&quot;</span><span class="p">,</span>  <span class="cm">/* tp_name */</span><br/>     <span class="p">...</span><br/></pre></div>


 <p>
 With this change, my objects are now operating fine.
 </p>
</li>
<li><b>Use plain “static.”</b>
 PyEphem inherits code from an era
 when it was popular to use variations on the <tt>static</tt> keyword
 so that Python could work around problems
 with various troublesome C compilers.
 This filled my code with <tt>staticforward</tt> declarations
 like the one you can see at the top of the old Python 2.2
 <a href="http://www.python.org/doc/2.2/ext/dnt-basics.html"
  >Defining New Types</a> page.
 It turns out that for well-behaved compilers
 these were always simply synonyms for the <tt>static</tt> keyword,
 which is what you must replace them with
 when porting your code to 3.0.
</li>
<li><b>Upgrade to Unicode.</b>
 Python 3.0 makes a clean and sharp distinction
 between strings, which are sequences of Unicode characters,
 and byte arrays, which can represent anything.
 To reflect this sea change down at the C level,
 the decision was made
 to eliminate <i>everything</i> from the C API
 whose name started with <tt>PyString</tt>.
 The obvious compiler errors that result from this
 provide a clear signal to programmers
 that they have to decide,
 everywhere that they had been using an old-style Python string,
 whether they should now represent that data
 with the <tt>PyUnicode</tt> or the <tt>PyBytes</tt> type.
 This was a brilliant decision;
 the transition could have been a nightmare
 had it remained possible for old code to compile
 without having been properly converted!
 <p>
 When migrating the PyEphem code base,
 I found that most of the Unicode transition was very easy.
 Everywhere that my code handled or created a string object,
 I simply changed the prefix of the function to <tt>PyUnicode</tt>
 and everything worked:
 </p>
 <pre>
 PyString_Check      ... becomes ... PyUnicode_Check
 PyString_FromString ... becomes ... PyUnicode_FromString
 PyString_FromFormat ... becomes ... PyUnicode_FromFormat
</pre>
 <p>
 Well, okay, the trick does not work <i>everywhere</i>;
 this one was harder to guess:
 </p>
 <pre>
 PyString_Size ... becomes ... PyUnicode_GET_SIZE
</pre>
 <p>
 The situations that require real thought
 are the places where my code needs to convert a Python string
 into the sort of simple ASCII character array
 that the underlying C library can absorb.
 At the moment, my code is leaning heavily
 on a pitiful <tt>PyUnicode_AsString()</tt> routine
 that I wrote just to get things working;
 in the morning I will have to look into doing this more correctly,
 including catching the error if a fancy Unicode character is present
 that cannot properly be converted.
 </p>
</li>
</ol>
<p>
Overall, I am very impressed with how quickly
I was able to get my extension module compiling and running
under Python 3.0.
The procedure was simple —
I just tried, over and over again, to build the module with:
</p>
<pre>
$ python3.0 setup.py build
</pre>
<p>
and then tackled the compiler errors that resulted.
Once every last warning had been addressed,
the module started up and operated without a single further complaint.
This calls for celebration!
I'm going to bed.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>My NOLA Plone Symposium talk, “the Zope 3 Component Architecture”</title>
      <link>http://rhodesmill.org/brandon/2008/nola-plone-symposium-talk/</link>
      <pubDate>Thu, 05 Jun 2008 23:44:02 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=17</guid>
      <description>My NOLA Plone Symposium talk, “the Zope 3 Component Architecture”</description>
      <content:encoded><![CDATA[
<p>
I have delivered my “Zope 3 Component Architecture” talk
to the <a href="http://plone.org/events/regional/nola08">2008 North American
Plone Symposium</a> meeting here in New Orleans.
I want to thank the folks at
<a href="http://enfoldsystems.com/">Enfold Systems</a>
both for hosting the Symposium, inviting me to speak,
and for generously making it possible for me to attend!
Here are my slides:
</p>

<div class="caption">
<a href="/brandon/static/2008/nola-zope3-talk.pdf">
<img src="/brandon/static/2008/nola-zope3-talk.jpg" alt="opening slide" /></a>
<a href="/brandon/static/2008/nola-zope3-talk.pdf"
 >Download slides as PDF</a>
</div>

<p>
They had asked me to attend so that I could present
the <a href="http://rhodesmill.org/brandon/adapters/">Using Grok
to Walk Like a Duck</a> talk that I gave at PyCon 2008
back in March.
They changed the title, I suppose, to better highlight
why it would be of interest to the Plone community;
but the change actually helped me to rethink the presentation.
I wound up using only the first half of my PyCon slides.
For the second half of the talk,
which at PyCon had consisted of a crazy sequence
of hints and tips about using adapters in your own applications,
I instead did a much more successful series of slides
about how adapters are actually used in Zope 3
to suit up objects for presentation on the web.
I think this made the idea more concrete,
and thus much easier to understand
for people seeing adapters for the first time.
</p>
<p>
The talk was well enough received
that I should perhaps think seriously about finding further opportunities
to share Zope 3 technologies with the Plone community.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Presentations on Buildout and KSS</title>
      <link>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</link>
      <pubDate>Sat, 23 Feb 2008 23:29:13 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</guid>
      <description>Presentations on Buildout and KSS</description>
      <content:encoded><![CDATA[
After several frustrating weeks learning how to create, edit, and publish a screencast under Linux (about which I will write a separate post), I have now published screencasts of both presentations that I gave at the PyAtl meetup in January. I opened with a talk about the <tt>import</tt> statement, and where Python packages lived before egg files were invented:

<div class="movietitle"><a href="http://video.google.com/videoplay?docid=5996823626349389448"><b>Python Before Eggs</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=5996823626349389448&hl=en" flashvars=""> </embed>

</div>

The audience seemed most interested in the last section of the talk, where I discuss three techiques for debugging problems with Python's <tt>import</tt> statement; fast-forward to around 3:00 if you want to catch that part by itself.

Next, Jeremy Jones spoke about eggs, Noah Gift introduced virtualenv, and, finally, I got back up to talk about buildout. This was probably <b>my own favorite</b> among the recent presentations I have given, and it's the one I've worked hardest to adapt to a competent screencast:

<div class="movietitle"><a href="http://video.google.com/videoplay?docid=3428163188647461098&hl=en"><b>Introduction to Buildout</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3428163188647461098&hl=en" flashvars=""> </embed>

</div>

I have prepared a supplement to the above screencast that <a href="/brandon/buildout/">gives additional hints and tips about using buildout</a>, as well as a link to the source code of the module that I use as my example.

Finally, if you're ready to see something a little less polished — something that instead of being a screencast is actually a film of me talking in front of a live audience, and gesturing and jumping around — I filled a vacant lightning-talk slot at our February PyAtl meeting with an impromptu introduction to <a href="http://kssproject.org/">Kinetic Style Sheets</a> (KSS), using an example application that was still sitting on my laptop after at a Georgia Tech developer's luncheon earlier that week:

<div class="movietitle"><a href="http://video.google.com/videoplay?docid=3829442611478268688"><b>Introduction to KSS</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3829442611478268688&hl=en" flashvars=""> </embed>

</div>

Now I can finally turn my attention to preparing for my upcoming talk at PyCon 2008 in Chicago! I will be talking about the basic “adapter” design pattern, and how a framework like Zope 3 can facilitate its use. Stay tuned for more information!
]]></content:encoded>
    </item>
    <item>
      <title>My November Grok Presentation</title>
      <link>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</link>
      <pubDate>Fri, 09 Nov 2007 19:06:24 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</guid>
      <description>My November Grok Presentation</description>
      <content:encoded><![CDATA[
In this post, I provide the slides and examples from a recent talk that I gave to some fellow software developers at Georgia Tech. Many of them were not familiar with web frameworks, and I wanted to introduce them to two common concepts: the idea of “convention over configuration,” and the practice of passing inert data structures to a page template rather than letting it access live objects directly.

But because I am also really enjoying my work with the new Python web framework <a href="http://grok.zope.org/">Grok</a>, I decided to make it the centerpiece of my presentation<!--more--> and illustrate the more general principles of web development by showing how Grok works. I also gave the talk a week later at an Atlanta Plone gathering, where I knew the interest would be more on what makes Grok unique.

When I was asked for a copy of my slides, I realized that my presentation style — which involves showing several slides, moving to my editor and web browser for some actual programming, then diving back into my slides — leaves the PDF of the presentation perhaps not making as much sense by itself as it might otherwise:

<blockquote><a href="http://rhodesmill.org/brandon/static/2007-11/grok-slides.pdf">Click here to download the PDF of my presentation</a></blockquote>

Hence, this post. Here I take the reader through the aspects of my talk that failed to make it on to the slides, showing both the command-line operations and the coding that illustrated and made sense of the presentation itself.

<h2><a id="creating-a-grok-instance" name="creating-a-grok-instance">Creating a Grok Instance</a></h2>

After some initial slides introducing the idea of “convention over configuration,” my presentation introduces Grok itself — making good use, I think, of the symbolic value of his club — and then announces, “Let's create a Grok instance!” This is the point at which I bring up a command prompt and show the audience how easy <tt>grokproject</tt> makes it to start a new project:


<div class="pygments_murphy syntax_highlight"><pre><span class="nv">$ </span>grokproject MyApp<br/><span class="nv">$ </span>./MyApp/bin/zopectl <span class="nb">fg</span><br/></pre></div>



After <tt>zopectl</tt> has finished starting up, I point my web browser at <tt>http://localhost:8080/</tt>, and then suffer a silent moment of frustration about the fact the web page that appears is <em>not</em> simply the welcome message from the new Grok app. Instead, the “admin interface” comes up, and insists on being fed an application instance name before allowing me to proceed. I choose <tt>lotr</tt> as the name, then show the audience that <tt>http://localhost:8080/lotr</tt> is where the new application lives.

Before continuing with my slides, I visit the directory <tt>MyApp/src/MyApp</tt> and give the audience brief glimpses of both <tt>app.py</tt> and the <tt>app_templates</tt> directory. This introduces three items which will be critical as the slides resume: the <tt>MyApp</tt> object, the <tt>Index</tt> view, and the <tt>index.pt</tt> page template. With these three items pointed out, I am ready to proceed with my slides and discuss how the object, view, and page template together form Grok's “Threefold Way” of making objects available on the web.

<h2><a id="the-actual-example" name="the-actual-example">The Actual Example</a></h2>

Only a few slides later, the time arrives for a more sophisticated example. The presentation exaggerates when it instructs me to “go add some models and further views to your application.” I do not, in fact, make the audience watch me write code, but present them with a finished and working example that I prepare before the presentation. You can create it for yourself by putting this file in place of the one <tt>grokproject</tt> created:

<ul>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/app.py">app.py</a></li>
</ul>

and then putting these four files in <tt>app_templates</tt>:

<ul>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/index.pt">index.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/contents.pt">contents.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/battleindex.pt">battleindex.pt</a></li>
<li><a href="http://rhodesmill.org/brandon/static/2007-11/characterindex.pt">characterindex.pt</a></li>
</ul>

The resulting application, though tiny, was probably too complex for my target audience — many eyes, I noticed, glazed over when seeing Zope Page Templates for the first time — but four views is really barely enough to illustrate both that you can have multiple views on the same object (<tt>MyApp</tt> has both an <tt>/index</tt> and a <tt>/contents</tt>), and that several objects can have views with the same name (<tt>Battle</tt> and <tt>Character</tt> have different <tt>/index</tt> views). The example also shows clearly that if you declare four views, you need to write four page templates to go with them.

I emphasize for the audience that most of the 56 lines of <tt>app.py</tt> are concerned with creating the violence-themed object model; only the fifteen lines at the bottom are interesting Grok code, creating four very slender views. This is where I point out “convention over configuration” at work: all of the page templates get discovered without having to be named, and <tt>grok.name()</tt> only has to be employed when we want the view's URL name to differ from the name of the class.

After demonstrating that the application does, in fact, work, we return to the slides and start examining the relationship between page templates and their views.

<h2><a id="moving-to-a-push-model" name="moving-to-a-push-model">Moving to a “push” model</a></h2>

In the presentation I distinguish between “muscular views” and “muscular templates”; perhaps I should have used instead the more conventional idea of templates that “pull” data versus those to which data are “pushed.”

When I reach the slide that reminds me to, “show them your anemic View classes,” I return to my editor and point out that, in the example application, each view has almost no purpose but to associate a particular object class with a particular page template. There is very little information in a declaration like:


<div class="pygments_murphy syntax_highlight"><pre><span class="k">class</span> <span class="nc">CharacterIndex</span><span class="p">(</span><span class="n">grok</span><span class="o">.</span><span class="n">View</span><span class="p">):</span><br/>    <span class="n">grok</span><span class="o">.</span><span class="n">context</span><span class="p">(</span><span class="n">Character</span><span class="p">)</span><br/>    <span class="n">grok</span><span class="o">.</span><span class="n">name</span><span class="p">(</span><span class="s">&#39;index&#39;</span><span class="p">)</span><br/></pre></div>



Whereas there is plenty going on in a template like <tt>characterindex.pt</tt>; every TAL reference it makes is either to the raw <tt>context</tt> object itself, or an object it reaches through the context! Take a look:

<pre>
&lt;h1&gt;The Character:
&lt;span tal:content=&quot;context/name&quot;&gt;Name&lt;/span&gt;&lt;/h1&gt;
This character fought in several battles.
&lt;ul&gt;
  &lt;li tal:repeat=&quot;battle context/battles&quot;&gt;
    &lt;a tal:attributes=&quot;href python: view.url(battle)&quot;
       tal:content=&quot;battle/name&quot;&gt;Name&lt;/a&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</pre>

The slides then continue, pointing out that this makes for very quick coding at the cost of several disadvantages. When the fourth and final intermission arrives (“go make your CharacterIndex View more muscular”), I return to the window where my editor has <tt>app.py</tt> open and rewrite the <tt>CharacterIndex</tt> to look more like this:


<div class="pygments_murphy syntax_highlight"><pre><span class="k">class</span> <span class="nc">CharacterIndex</span><span class="p">(</span><span class="n">grok</span><span class="o">.</span><span class="n">View</span><span class="p">):</span><br/>    <span class="n">grok</span><span class="o">.</span><span class="n">context</span><span class="p">(</span><span class="n">Character</span><span class="p">)</span><br/>    <span class="n">grok</span><span class="o">.</span><span class="n">name</span><span class="p">(</span><span class="s">&#39;index&#39;</span><span class="p">)</span><br/>    <span class="k">def</span> <span class="nf">namespace</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span><br/>        <span class="k">return</span> <span class="p">{</span><br/>            <span class="s">&#39;character_name&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">name</span><span class="p">,</span><br/>            <span class="s">&#39;battles&#39;</span><span class="p">:</span> <span class="p">[</span><br/>                <span class="p">{</span> <span class="s">&#39;name&#39;</span><span class="p">:</span> <span class="n">battle</span><span class="o">.</span><span class="n">name</span><span class="p">,</span><br/>                   <span class="s">&#39;url&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">(</span><span class="n">battle</span><span class="p">)</span> <span class="p">}</span><br/>                <span class="k">for</span> <span class="n">battle</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">battles</span><br/>                <span class="p">],</span><br/>            <span class="p">}</span><br/></pre></div>



Note what this does: it takes all of the work that the page template was doing in order to fetch the character's name, and the names and URLs of the battles in which the character fought, and performs that access in pure Python and in exactly once place. The values in the dictionary that is being passed — <tt>character_name</tt> and <tt>battle_info</tt> — are, if you will examine them carefully, composed of nothing but primitive Python types! They consist solely of lists and dictionaries containing strings. They contain no objects for the template to browse at its leisure; instead, every bit of pertinent data in our objects is reduced to harmless data structures which cannot be used to affect the original objects in any way. This means that the <tt>characterindex.pt</tt> template can be rewritten both more safely, and also more simply:

<pre>
&lt;html&gt;&lt;body&gt;
  &lt;h1&gt;The Character:
  &lt;span tal:content=&quot;character_name&quot;&gt;Name&lt;/span&gt;&lt;/h1&gt;
  This character fought in several battles.
  &lt;ul&gt;
    &lt;li tal:repeat=&quot;battle battles&quot;&gt;
      &lt;a tal:attributes=&quot;href battle/url&quot;
         tal:content=&quot;battle/name&quot;&gt;Name&lt;/a&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a href=&quot;index&quot;&gt;Return home&lt;/a&gt;
&lt;/body&gt;&lt;/html&gt;
</pre>

And after showing the audience that the rewritten view and the rewritten page template work together, I return to my slides and — finally! — conclude my presentation.

The presentation seemed to weigh in at around forty minutes. Next time, I think I will tackle fewer concepts at once. But I do like making lots of use of the picture of the cave man, and his club.
]]></content:encoded>
    </item>
  </channel>
</rss>

