<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns="http://purl.org/rss/1.0/">




    



<channel rdf:about="http://rpatterson.net/blog/aggregator/RSS">
  <title>Blog</title>
  <link>http://rpatterson.net</link>

  <description>
    
      Notes, findings, and ideas
    
  </description>

  

  
            <syn:updatePeriod>daily</syn:updatePeriod>
            <syn:updateFrequency>1</syn:updateFrequency>
            <syn:updateBase>2007-12-20T00:21:18Z</syn:updateBase>
        

  <image rdf:resource="http://rpatterson.net/logo.png" />

  <items>
    <rdf:Seq>
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/buildout-performance-improvements" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/experimental.broken" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/making-easy_install-play-nicely-with-multi-arch" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/300-ticket-for-plone-conference-2011" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/looking-for-projects-and-or-a-team" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/centralized-git-svn-mirror" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/ratpoison-is-dead-long-live-stumpwm" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/grab-bag-of-git-svn-stuff" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/using-functional-tests-for-profiling" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/ratpoison-under-gnome" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/cioppino-sprint" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/migrating-a-blobstorage" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/trying-out-chameleon" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/does-the-tool-really-deserve-the-credit" />
      
      
        <rdf:li rdf:resource="http://rpatterson.net/blog/dogfood-dinner-bell" />
      
    </rdf:Seq>
  </items>

</channel>


  <item rdf:about="http://rpatterson.net/blog/buildout-performance-improvements">
    <title>Buildout Performance Improvements</title>
    <link>http://rpatterson.net/blog/buildout-performance-improvements</link>
    <description>Getting a 6-7 fold decrease in zc.buildout run times.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I've been <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292">baffled</a> by
the amount of time running buildout takes.  In particular, it seemed
like a lot of duplicate work was being done when multiple parts had
identical or very similar sets of required eggs/distributions.  After
a bunch of <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292">profiling</a> <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15302">and</a> <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15307">timing</a>, I've found there are a number of ways
to increase your buildout performance.</p>
<dl class="docutils">
<dt>Use <a class="reference external" href="http://pypi.python.org/pypi/buildout.dumppickedversions">buildout.dumppickedversions</a> version 0.5 or later:</dt>
<dd>If you're using <a class="reference external" href="http://pypi.python.org/pypi/buildout.dumppickedversions">buildout.dumppickedversions</a>, use
version 0.5.  This release includes <a class="reference external" href="http://dev.plone.org/collective/changeset/247821">a fix</a> I contributed
which yields a <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15302">3-4 fold decrease</a> in runtime if buildout is run
with just the <tt class="docutils literal"><span class="pre">-N</span></tt> option and no <tt class="docutils literal"><span class="pre">-v</span></tt> options.  If your're using
<a class="reference external" href="http://pypi.python.org/pypi/buildout-versions">buildout-versions</a> instead of
buildout.dumppickedversions, unfortunately <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15319">it suffers from the
same problem</a>.
The author knows about this and may address it but until then you
may want to switch to buildout.dumppickedversions.</dd>
<dt>Use <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2">zc.buildout version 1.5</a> or later:</dt>
<dd>This seems to yield a <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15307">2-3 fold decrease</a>
in buildout runtime when run with <tt class="docutils literal"><span class="pre">-N</span></tt> and addresses a <a class="reference external" href="http://zope3.pov.lt/trac/changeset/124059">similar
hot loop</a> as found in
buildout.dumppickedversions.  In fact, it's resolution of required
distributions seems to be much more efficient in general.  If
you're stuck with 1.4, I've <a class="reference external" href="http://zope3.pov.lt/trac/changeset/124060">contributed</a> the same fix as for
buildout.dumppickedversions to the 1.4 branch so it should make it
into a next release if someone makes a new 1.4 release.</dd>
<dt>Use the <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2#newest-and-offline-modes">-N</a> option:</dt>
<dd>With the above newest releases of zc.buildout and
buildout.dumppickedversions, you can now exercise a lot of control
of your run times <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15307">depending on what command-line options you use</a>.
In particular, make sure <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2#newest-and-offline-modes">newest</a>
is false and that <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2#predefined-buildout-options">verbosity</a> is not
increased.  Both of these can be influenced by options in the
buildout configuration, so keep an eye out for that, but if no
such options are interfering then this means just invoking
buildout like <tt class="docutils literal">$ bin/buildout <span class="pre">-N</span> <span class="pre">-c</span> buildout.cfg</tt>.  IOW, use one
<tt class="docutils literal"><span class="pre">-N</span></tt> option and no <tt class="docutils literal"><span class="pre">-v</span></tt> options.  Before the improvements in
zc.buildout 1.5 and the fix to buildout.dumppickedversions, a lot
of time was wasted doing work that would only actually be used if
<tt class="docutils literal"><span class="pre">-v</span></tt> had been given.</dd>
<dt>Clean out your egg cache and use <tt class="docutils literal">virtualenv <span class="pre">--no-site-packages</span></tt>:</dt>
<dd>Some of the remaining inefficiencies in zc.buildout are
<a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15305">proportional to the number of distributions</a>
available on <tt class="docutils literal">sys.path</tt>.  IOW if you reduce the number of
distributions to be scanned, you can increase performance.  If
you're using a <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2#user-defaults">shared</a>
<a class="reference external" href="http://pypi.python.org/pypi/zc.buildout/1.5.2#predefined-buildout-options">eggs-directory</a> or have a
buildout that has been around for a long time, there may be a lot
of different versions of the same packages in <tt class="docutils literal"><span class="pre">eggs-directory</span></tt>.
By cleaning those out you reduce the number of distributions that
buildout needs to scan.  I recommend just emptying your
<tt class="docutils literal"><span class="pre">eggs-directory</span></tt> and then letting buildout re-download all the
eggs it actually needs now.  I takes a while once, but then it's
done.  Similarly, using <tt class="docutils literal">virtualenv <span class="pre">--no-site-packages</span></tt> can
reduce the number of dists buildout needs to scan.</dd>
<dt>Help me get <a class="reference external" href="http://zope3.pov.lt/trac/log/zc.buildout/branches/env-cache">zc.buildout/branches/env-cache</a> merged and released:</dt>
<dd>Having said the above about cleaning out the egg cache,
<tt class="docutils literal">buildout</tt>, <tt class="docutils literal">distribute</tt>, and <tt class="docutils literal">setuptools</tt> shouldn't be
scanning these paths multiple time anyways.  Along with package
indexes, these paths are global in nature and so the dists found
there should only be scanned for once and cached globally.  I've
started this work on the <a class="reference external" href="svn+ssh://svn.zope.org/repos/main/zc.buildout/branches/env-cache">env-cache</a>
branch of zc.buildout.  In my timing tests, this branch seems to
yield another <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15307">~60% decrease</a>
in run time.  The zc.buildout tests, however, <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292">are a PITA</a>
and Jim Fulton is <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15315">a very busy man</a>
with little time to evaluate this branch.  If anyone else can help
me shepherd this branch through to merge and then release, that
would be great.  I've <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/15292/focus=15306">written up</a>
how to use this branch with your existing buildouts.</dd>
</dl>
<p>With all this in effect I took a production buildout and another
development buildout from 2 minute run times down to 20 second run
times.  This really makes re-running buildout something I no longer
feel an urge to avoid.  So use zc.buildout 1.5.2,
buildout.dumppickedversions 0.5, <tt class="docutils literal"><span class="pre">-N</span></tt> and do what you can to help
get the <tt class="docutils literal"><span class="pre">env-cache</span></tt> branch merged.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2012-01-27T18:08:32Z</dc:date>
    
    <dc:modified>2012-01-27T18:08:32Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/experimental.broken">
    <title>experimental.broken</title>
    <link>http://rpatterson.net/blog/experimental.broken</link>
    <description>Graceful handling of broken interfaces and components in the ZODB.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Worst.package.name.ever... inentionally!  :-)  But seriously, <em>read the warnings</em> and heed them.  If I have to tell you to read the warnings, you shouldn't use this package.</p>
<p>We in <a class="reference external" href="http://plone.org">Plone</a> land have been long frustrated about how easily a poorly behaved add-on could break a Plone site.  Simply installing the add-on and removing it can leave your site inaccessible, even the ZMI!  Often times add-ons that provide only minimal additional object behavior can break the entire object when removed.</p>
<p>Now this isn't actually the ZODB's fault at all.  The <a class="reference external" href="http://pypi.python.org/pypi/ZODB3">ZODB</a> actually has quite robust handling of broken object and it works quite well.  I'm afraid that fault here lies in <a class="reference external" href="http://pypi.python.org/pypi/zope.interface">zope.interface</a> and <a class="reference external" href="http://pypi.python.org/pypi/zope.component">zope.component</a>.  They're simply both too central to almost <em>all</em> ZODB applications to fail to provide graceful handling of broken objects.  So I've taken advantage of the <a class="reference external" href="http://ploneconf.org/event/sprints">sprints</a> following the <a class="reference external" href="http://ploneconf.org/">Plone Conference</a> here in San Francisco to work on this.</p>
<p>The <a class="reference external" href="https://github.com/rpatterson/experimental.broken">experimental.broken</a> package provides patches for zope.interface and zope.component to make the services they provide more tolerant of broken objects in the ZODB and allows them to function as if the interfaces and components aren't there when the add-on has been removed.  Even better, if the add-on is restored, the full behavior of the interfaces and components is restored.</p>
<p>That said, this is all highly experimental so don't use it.  If you do use it, never use it in production and only use it on a copy of your ZODB.  And if you do use it, <em>definitely</em> report your experience.  If you do have a broken site I'd love to hear how it works for you.  Just add experimental.broken to your instance eggs.</p>
<p>If this approach tests well and the core Zope developers think it's the right approach I'll be merging this into zope.interface and zope.component.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-11-07T07:54:57Z</dc:date>
    
    <dc:modified>2011-11-07T07:54:57Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/making-easy_install-play-nicely-with-multi-arch">
    <title>Making easy_install play nicely with multi-arch</title>
    <link>http://rpatterson.net/blog/making-easy_install-play-nicely-with-multi-arch</link>
    <description>How to help extensions built with easy_install find Debian/Ubuntu multi-arch libraries.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>The poorly documented <tt class="docutils literal"><span class="pre">~/.pydistutils.cfg</span></tt> allows setting defaults for command-line arguments to <tt class="docutils literal">distutils</tt> <tt class="docutils literal">setup.py</tt> commands such as <tt class="docutils literal">python setup.py build_ext <span class="pre">--library-dirs</span></tt>.  Use this to get <tt class="docutils literal">easy_install</tt> to build eggs with extension modules that need to find libaries on <tt class="docutils literal"><span class="pre">multi-arch</span></tt> systems like Ubuntu and Debian.  Just add the following two lines to <tt class="docutils literal"><span class="pre">~/.pydistutils.cfg</span></tt>:</p>
<pre class="literal-block">
[build_ext]
library_dirs = /usr/lib:/usr/lib/i386-linux-gnu:/usr/local/lib
</pre>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-10-26T20:08:21Z</dc:date>
    
    <dc:modified>2011-10-26T20:08:21Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/300-ticket-for-plone-conference-2011">
    <title>$300 Ticket for Plone Conference 2011</title>
    <link>http://rpatterson.net/blog/300-ticket-for-plone-conference-2011</link>
    <description>My old boss has a ticket to Plone Conference 2011 that he can't use afterall.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I'm sad to hear it but Rob Stephenson can't come to the conference afterall.  The good news is that he's looking to sell his ticket to someone for just $300.  If anyone's interested email him: rstephe at alumni dot princeton dot edu.]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-10-05T20:17:59Z</dc:date>
    
    <dc:modified>2011-10-05T20:17:59Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/looking-for-projects-and-or-a-team">
    <title>Looking for Projects and/or a Team</title>
    <link>http://rpatterson.net/blog/looking-for-projects-and-or-a-team</link>
    <description>I'm available for work and am interested in contract/consultant projects or a position with a team.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I've been doing a lot of thinking recently about which direction I
want to take my professional life as a software developer and I've
come to some conclusions.  I'll detail more about that below if you're
interested in my process and thinking on that but first I'll summarize
what I'm looking for.</p>
<dl class="docutils">
<dt>Consulting/Contract Opportunities</dt>
<dd><p class="first">I'm perfectly happy to keep working independently or as a
sub-contractor with a larger consultancy on <a class="reference external" href="http://plone.org/">Plone</a> projects.  I know Plone very well and am
very happy to continue working with it on projects such as:</p>
<ul class="last simple">
<li>Intranet workflow/business-process applications</li>
<li>Custom web publishing CMS projects</li>
<li>Quickly solving critical problems as a Plone &quot;hired gun&quot;</li>
<li>Building a project while also cross-training internal developers</li>
<li>Social justice related projects</li>
<li>Etc., pretty much any Plone project</li>
</ul>
</dd>
<dt>Opportunities with a Team</dt>
<dd><p class="first">I'm eager to join a team, either as an employee or as a
contractor, that can offer some of the following:</p>
<ul class="last simple">
<li>More collaboration as a part of a team that genuinely like each other</li>
<li>More technological diversity outside of Plone/Zope</li>
<li>Opportunity to work on social justice related projects</li>
</ul>
</dd>
</dl>
<div class="section" id="team-collaboration">
<h3>Team Collaboration</h3>
<p>I've been working as an independent freelancer since 2005 in one form
or another.  I've probably worked about 1/3 as a &quot;sub-contractor&quot; for
a larger consultancy as a developer team member on larger projects.
The rest of my work has been as a solo contractor doing everything
from requirements gathering to deployment and support, end-to-end.</p>
<p>This has worked quite well for me.  I've got my personal project
management down to an art such that context switches cost either
project almost no time.  I enjoy the flexibility a lot such as being
able to work from home or my favorite cafe and also being able to work
at the times of day and the week when my brain is most productive.
(Oddly, I seem to be most productive writing code between midnight and
4AM, and more so Sunday nights to Monday mornings, go figure.)</p>
<p>I started working with Plone in 1999-2000 and initially I was a total
hermit, not getting involved in the community at all.  Eventually, I
started to come out of my shell and get more involved.  It was
something I waited far too long to do, especially in a community as
awesome and fun to work with as Plone's.  I've enjoyed the greater
interaction and collaboration in software development a lot and I'm
interested in having more of that in my working life.</p>
<p>As such, I'm interested in opportunities to join a team where there's
a solid connection and more collaboration.  I do enjoy my swingin'
freelancing location and hours flexibility, but I'm interested in
making that trade-off for the opportunity to work closely with people
with whom I have a good rapport.</p>
</div>
<div class="section" id="happy-code-monkey">
<h3>Happy Code Monkey</h3>
<p>For the last few years, I've also been wondering where I might want to
take my career.  It seemed to me there were two basic models for
advancement as a software developer and they're kind of the same
model: IT management, or starting a business.  While I'm very good at
solo project management, I'm not well suited to managing a team.  I
greatly value a good project manager, they're just a godsend.
Similarly, I'm just not inspired by the challenges of running a
business.  More generally, I don't have much natural capacity in those
domains and my lack of passion there means I'd be no good at
developing capacity there.</p>
<p>I suppose another &quot;path for advancement&quot; might be as someone who
creates new software frameworks, code used by code to build things.
Whether or not you think of that as a path for advancement, I have
similar feelings about this path.  I very much enjoy participating in
and contributing to the development of exciting frameworks and I feel
I have a lot to contribute there, but I'm not passionate about leading
such projects.</p>
<p>Finally it occurred to me that maybe I should just set my sights on
what I'm already passionate about, being a happy code monkey, a
conclusion aided and finalized by too many drinks with Liz and Spanky
after a sprint.  :-)  I find this conclusion very liberating which I
take as affirmation.</p>
<p>As such, I'm looking for opportunities where being a happy code monkey
is valued.  IOW, I'm interested opportunities to join a team with more
diverse opportunities for advancement other than IT management or
ownership.</p>
</div>
<div class="section" id="diversifying">
<h3>Diversifying</h3>
<p>I am a self-taught web developer who has spent most of that time as a
freelancer who <em>loves</em> working with the stack he first learned.  It's
hard to formulate a better recipe for over-specialization.  This is a
difficult issue because I really do love working with Plone but I also
know I would be happier and a better developer having more diversity
in my experience.</p>
<p>As such, I'm very interested in opportunities where I can leverage my
current expertise to gain new experience.  Anything in the Python web
app world would be good since I have very strong <a class="reference external" href="http://bfg.repoze.org/">Python</a> skills.  Working with the new direction
<a class="reference external" href="https://www.pylonsproject.org/">Pylons</a> is taking, <a class="reference external" href="https://www.pylonsproject.org/projects/pyramid/about">Pyramid</a>, could be an
even better fit since I can leverage my in-depth familiarity with it's
<a class="reference external" href="http://bfg.repoze.org/">Zope</a> underpinnings and heritage.</p>
</div>
<div class="section" id="social-justice">
<h3>Social Justice</h3>
<p>Finally, while I've gotten to work with clients in the education
domain here and there as well as some non-profits I support heartily,
I've never had the opportunity to work on projects relating to the
issues I am most passionate about, social justice issues.  I'm
interested in any opportunities to work on projects for organizations
doing work on queer, gender, labor, race, or environmental justice
issues.  I'm <em>very</em> interested in working for any technology
organization that provides technology services to such organizations.</p>
</div>
<div class="section" id="summary">
<h3>Summary</h3>
<p>If you're looking for a consultant/contractor or a team member, or
know of any such opportunities, which you think I'm suited for.
Please let me know.  Here is my contact information and links to my
online resumes.</p>
<blockquote>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name">
<col class="field-body">
<tbody valign="top">
<tr class="field"><th class="field-name">Name:</th><td class="field-body">Ross Patterson</td>
</tr>
<tr class="field"><th class="field-name">Resume:</th><td class="field-body"><a class="reference external" href="http://www.linkedin.com/in/rossp">LinkedIn</a></td>
</tr>
<tr class="field"><th class="field-name">Resume:</th><td class="field-body"><a class="reference external" href="http://careers.stackoverflow.com/rpatterson">Careers 2.0</a></td>
</tr>
<tr class="field"><th class="field-name">Email:</th><td class="field-body"><a class="reference external" href="mailto:me@rpatterson.net">me&#64;rpatterson.net</a></td>
</tr>
<tr class="field"><th class="field-name">Phone:</th><td class="field-body">+1 (415) 894-5323</td>
</tr>
<tr class="field"><th class="field-name">IRC:</th><td class="field-body"><a class="reference external" href="mailto:zenwryly@irc.freenode.net">zenwryly&#64;irc.freenode.net</a></td>
</tr>
<tr class="field"><th class="field-name">plone.org:</th><td class="field-body"><a class="reference external" href="http://plone.org/author/rossp">rossp</a></td>
</tr>
<tr class="field"><th class="field-name">GTalk:</th><td class="field-body"><a class="reference external" href="mailto:merpattersonnet@gmail.com">merpattersonnet&#64;gmail.com</a></td>
</tr>
<tr class="field"><th class="field-name">Yahoo IM:</th><td class="field-body">patterson_ross</td>
</tr>
<tr class="field"><th class="field-name">AIM:</th><td class="field-body">rosspatters</td>
</tr>
<tr class="field"><th class="field-name">MSN:</th><td class="field-body"><a class="reference external" href="mailto:me@rpatterson.net">me&#64;rpatterson.net</a></td>
</tr>
</tbody>
</table>
</blockquote>
</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-09-15T00:21:42Z</dc:date>
    
    <dc:modified>2011-09-15T00:21:42Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/centralized-git-svn-mirror">
    <title>Centralized Git-SVN mirror</title>
    <link>http://rpatterson.net/blog/centralized-git-svn-mirror</link>
    <description>For those of us using lots of "git svn clone"s, is any sort of central mirror worth it?</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I do almost everything in git these days, so when the code I'm committing to lives in <tt class="docutils literal">svn</tt> that means <tt class="docutils literal"><span class="pre">git-svn</span></tt>.  The initial <tt class="docutils literal">git svn clone</tt> can take quite a while, however.  <a class="reference external" href="http://rpatterson.net/blog/grab-bag-of-git-svn-stuff">Using gitify</a> can help such that you only need to <tt class="docutils literal">git svn clone</tt> once for each project accross multiple buildouts/branches, but it's maddening knowing that if it were just git, we'd be able to share the same clone across multiple <em>users</em>.  So I've been wondering about options for git-svn mirrors for a while now.</p>
<p>I ran across <a class="reference external" href="http://vimeo.com/28762003">this video</a> on a &quot;Planet ...&quot; feed of some sort recently describing what I've been looking for.  This guy also has a lot of other good <a class="reference external" href="http://www.tfnico.com/presentations/git-and-subversion">git-svn thoughts</a>.  I'm just not sure it's worth it.  I guess it all depends on how quickly people migrate to github or some such natively.  If there's any shared interest, leave a comment or email me.  If there's interest I'll start a thread somewhere.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-09-12T23:14:56Z</dc:date>
    
    <dc:modified>2011-09-12T23:14:56Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/ratpoison-is-dead-long-live-stumpwm">
    <title>Ratpoison is Dead, Long Live StumpWM</title>
    <link>http://rpatterson.net/blog/ratpoison-is-dead-long-live-stumpwm</link>
    <description>Replacing ratpoison with StumpWM.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>This is definitely of those &quot;Why did I wait so long?&quot; moments.  I've been <a class="reference external" href="http://rpatterson.net/blog/ratpoison-under-gnome">using ratpoison</a> for quite a while.  From time to time I would research other keyboard-driven, <a class="reference external" href="http://en.wikipedia.org/wiki/Tiling_window_manager#List_of_tiling_window_managers_for_X">tiling window managers</a> so I'd heard of and evaluated StumpWM before.  Somehow I'd missed that it was <em>intended</em> as the successor to ratpoison.  Doh!</p>
<p>At any rate, thanks to a <a class="reference external" href="http://www.rlazo.org/2011/09/10/stumpwm-my-new-window-manager/">Planet Emacsen blog post</a> I decided to give it a try.  It's a clear win for me.  Better group manaagement, key binding system, and plays nicely with the Gnome/Unity-2D panel when I need it.  It's all around more modern and less of a fight with modern desktops like Gnome/Unity-2D.  I don't think I'll be going back as long as the instability everyone mentions is manageable.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-09-12T06:16:18Z</dc:date>
    
    <dc:modified>2011-09-12T06:16:18Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/grab-bag-of-git-svn-stuff">
    <title>Grab Bag of git/svn stuff</title>
    <link>http://rpatterson.net/blog/grab-bag-of-git-svn-stuff</link>
    <description>Using gitify to pretend everyone has already switched</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>A while back I looked into gitify after someone mentioned it.  For some strange reason, I dismissed it.  I think it may have been <a class="reference external" href="http://davisagli.com/">David Glick</a> who mentioned it again when I was ranting recently, so I looked at it again and it is exactly what I want.  It allows treating an svn checkout as both an svn checkout <em>and</em> a git-svn clone with a local git cache.  Now if only I could get this to work with mr.developer.</p>
<p>But wait, hidden in a corner of mr.developer, and totally undocumented is a mr.developer.gitsvn module that does exactly that!  You can use a &quot;gitsvn&quot; checkout type and you're in business:</p>
<pre class="literal-block">
[sources]
...
collective.formcriteria = gitsvn https://svn.plone.org/svn/collective/collective.formcriteria/trunk
...
</pre>
<p>I was going to start modifying all my local.cfg buildout files to change all the &quot;svn&quot; checkouts to &quot;gitsvn&quot; checkouts when I noticed something about how mr.developer registers checkout types.  At the very bottom of mr/developer/gitsvn.py I changed:</p>
<pre class="literal-block">
common.workingcopytypes['gitsvn'] = GitSVNWorkingCopy
</pre>
<p>to:</p>
<pre class="literal-block">
common.workingcopytypes['gitsvn'] = GitSVNWorkingCopy
common.workingcopytypes['svn'] = GitSVNWorkingCopy
</pre>
<p>Viola!  Now mr.developer uses gitify for all svn checkouts.  Now I'm
getting close to being able to pretend svn doesn't exist.</p>
<p>I would love to see mr.developer use a global switch so I don't have
to modify the egg like this, maybe something in
~/.buildout/default.cfg.  If there's interest in that, I'd be happy to
contribute such a thing.  I should also mention that gitify is often
pretty rough and leaves svn and git in an inconsistent state which is
only really repairable by someone who is very familiar with both svn
and git.  The next time I run into that, I'll be trying to run it to
ground and contribute fixes.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-07-26T04:14:37Z</dc:date>
    
    <dc:modified>2011-07-26T04:14:37Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/using-functional-tests-for-profiling">
    <title>Using Functional Tests for Profiling</title>
    <link>http://rpatterson.net/blog/using-functional-tests-for-profiling</link>
    <description>Use your functional tests with zope.testing/zope.testrunner to do easier profiling.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I've always enjoyed <a class="reference external" href="http://zope2.zope.org/">Zope2's</a> support for <a class="reference external" href="http://lionfacelemonface.wordpress.com/2011/02/08/profiling-plone-4-well-profiling-zope-while-running-plone-4/">profiling requests</a>, but it's also a bit of a PITA.  When profiling, even with cProfile or hotshot, <a class="reference external" href="http://python.org/">Python</a> can be a bit of a dog and with a featureful application like <a class="reference external" href="http://plone.org/">Plone</a>, it makes even a simple page load a painful experience.  So I have to get the page load I want to profile all set up in a browser, stop the instance, enable profiling, fire the instance back up, and then load the page I want to profile.  Then I have to be really careful not to load any pages other than the profiling view because not will they be dog slow but they will pollute the profiling data.  It's also quite laborious to profile a bunch of different page loads to try and get a more representative sense of where your hot spots are.  Finally, I <em>have</em> to use the Zope2 profiling view, I can't use other tools.</p>
<p>I've known about <a class="reference external" href="http://pypi.python.org/pypi/zope.testing">zope.testing</a>/<a class="reference external" href="http://pypi.python.org/pypi/zope.testrunner">zope.testrunner's</a> <a class="reference external" href="http://pypi.python.org/pypi/zope.testrunner#profiling">&quot;--profile=cProfile&quot;</a> command line option for sometime.  When you use it, it spits out the &quot;top 50 stats, sorted by cumulative time and number of calls&quot;.  Under a featureful application like Plone, however, the top 50 stats are usually consumed with the top publisher and template rendering calls and don't actually tell you anything useful.</p>
<p>Recently I needed to do some profiling of the baseline performance of an application.  Since I use functional <a class="reference external" href="http://pypi.python.org/pypi/zope.testbrowser">zope.testbrowser</a> tests a lot (some would say too much), my functional tests are actually a pretty good representation of the real world application usage.  So I was thrilled to find that the testrunner actually leaves the <em>raw profiling data</em> behind after a test run!  It leaves the data in the working directory in which the test run was invoked.  If you're doing this in buildout using a <a class="reference external" href="http://pypi.python.org/pypi/zc.recipe.testrunner">zc.recipe.testrunner</a> part named &quot;test&quot;, as is the convention, the file will be in parts/test/tests_profile.??????.prof.</p>
<p>In order to avoid the test fixture setup from polluting the profiling data, I use the <a class="reference external" href="http://pypi.python.org/pypi/zope.testrunner#repeating-tests">&quot;--repeat&quot;</a> command line option for the test runner to make sure that profiling data from the actual tests are much louder in the profiling data than the test setup.  For a large functional test suite I tend to use &quot;--repeat=3&quot; since the suite is long enough as it is and any more repetitions just take too long:</p>
<pre class="literal-block">
$ bin/test --profile=cProfile --repeat=3
</pre>
<p>If I'm profiling one test or a small number of tests, however, I like to use &quot;--repeat=10&quot; to be very sure that my profiling data isn't skewed:</p>
<pre class="literal-block">
$ bin/test -t my/functional/test.txt --profile=cProfile --repeat=10
</pre>
<p>Once the tests are finished I can fire up python and use the <a class="reference external" href="http://docs.python.org/library/profile.html#module-pstats">pstats module</a> to browse my stats.  Here I discovered another surprising convenience.  Since I use mr.developer everywhere right now, all the code I generally have an interest in optimizing is in &quot;src&quot;.  I can use that fact to get much more targeted stats reporting by <a class="reference external" href="http://docs.python.org/library/profile.html#pstats.Stats.print_stats">limiting the stats</a> to those for code in &quot;src&quot;:</p>
<blockquote>
<pre class="doctest-block">
&gt;&gt;&gt; import os
&gt;&gt;&gt; import pstats
&gt;&gt;&gt; stats = pstats.Stats('parts/test/tests_profile.??????.prof').sort_stats('cumulative')
&gt;&gt;&gt; stats.print_stats(os.getcwd()+'/src', 50)
...    parts/test/tests_profile.??????.prof
         ... function calls (... primitive calls) in ... CPU seconds
   Ordered by: cumulative time
   List reduced from ... to ... due to restriction &lt;'.../src'&gt;
   List reduced from ... to 50 due to restriction &lt;50&gt;
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   ...
</pre>
</blockquote>
<p>I'm actually wondering if this might be a better default for the testrunner output when &quot;--profile&quot; is used.  If the ZTK people think I should do that, just let me know and I'd be happy to contribute that.</p>
<p>You should also, however, be careful when just looking at the code in &quot;src&quot;.  For example, if your code is rendering templates when it doesn't need to, then limiting the stats to &quot;src&quot; will hide that from you.  Filtering by &quot;src&quot; is a good start, but be sure to also check out the top 50 overall and to look into single tests in detail so you don't miss anything.  See the <a class="reference external" href="http://docs.python.org/library/profile.html#pstats.Stats.print_stats">print_stats docs</a> to see everything you can do.</p>
<p>Finally, one should never just assume that even <em>functional</em> tests represent real-world load profiles.  I would love to see a tool for capturing and sanitizing request data from production along with the response times for those requests which can then turn that sanitized real-world data into functional load test suites.  This would be useful for doing continuous integration that can alert developers when they introduce performance regressions but it would also be <em>very</em> useful for targeted profiling where you could be nearly certain that your optimizations would get you the biggest bang for your users' bucks.  This is something I'd love to work on in a sprint sometime.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-07-26T03:48:17Z</dc:date>
    
    <dc:modified>2011-07-26T03:48:17Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/ratpoison-under-gnome">
    <title>Ratpoison under Gnome</title>
    <link>http://rpatterson.net/blog/ratpoison-under-gnome</link>
    <description>Configuring ratpoison as Gnome's window manager preserving all the Gnome goodness.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>As a keyboard junkie, I've been using and loving <a class="reference external" href="http://www.nongnu.org/ratpoison/">ratpoison</a> for many years now.  Many
ratpoison users use ratpoison as a part of ditching a desktop manager,
such as Gnome, altogether.  For my part, however, I want the desktop
integration: notifications, volume management, and using software
whose only exposed interface is through the system tray.  My interest
in ratpoison is driving the 99% of my computer usage, which is
application interaction, using the keyboard.  In those cases I want to
be able to completely ignore the desktop knowing I can use it smoothly
for that 1% of the time I want it.</p>
<p>Over my years of using ratpoison, I've resorted to some truly horrific
hacks to try and approximate this goal.  I've tried stalonetray and
trayer.  I've written ugly wrapper scripts that waited a while before
killing metacity and starting ratpoison.  I couldn't figure why I
couldn't just let gnome-panel and nautilus (in the case of Ubuntu
Desktop) or netbook-launcher-efl (in the case of Ubuntu Netbook) live
in peace alongside ratpoison.  Finally, I decided to dig into how
Gnome does session startup and to try to get at the root of it.</p>
<p>The first hurdle was getting Gnome to use ratpoison as it's window
manager.  Gnome consults the
/desktop/gnome/session/required_components/windowmanager gconf key to
decide what window manager to use.  In the case of Ubuntu Netbook
Edition 2D, you can't set this gconf key without first unlocking it
since UNE locks down a bunch of configurability.  So the first order
of business under UNE is to unlock the key.  As root, edit
/var/lib/gconf/une-efl.mandatory/%gconf-tree.xml and remove the
&quot;&lt;entry name=&quot;windowmanager&quot;...&quot; under the same path for the key in
the XML &lt;dir&gt; elements, it's towards the top.</p>
<p>Next we have to tell Gnome to accept ratpoison as a provider of the
&quot;windowmanager&quot; required component.  To do this, as root, copy
/usr/share/applications/metacity.desktop to
/usr/share/applications/ratpoison.desktop and in the new file replace,
case insensitive, all occurrences of &quot;metacity&quot; with &quot;ratpoison&quot;.</p>
<p>At this point you must log out and log back in so gdm will restart and
gconf will see the changes.  Now you can, as your normal user, set the
key to ratpoison using gconf-editor or the following command line:</p>
<pre class="literal-block">
$ gconftool-2 --type string --set /desktop/gnome/session/required_components/windowmanager ratpoison
</pre>
<p>Now that Gnome will use ratpoison as it's window manager, we need to
tell ratpoison to leave gnome-panel and nautilus/netbook-launcher-efl
(Gnome/UNE 2D) windows alone.  Tell ratpoison not to manage those
windows by adding the following to your normal user's ~/.ratpoisonrc:</p>
<pre class="literal-block">
unmanage Top Expanded Edge Panel
unmanage Bottom Expanded Edge Panel
unmanage Netbook Launcher EFL
unmanage x-nautilus-desktop
</pre>
<p>Now we get into the part where somewhat less ugly hacks than my
previous solutions, but still ugly hacks are required.  Firstly, the
gnome-panel and nautilus/netbook-launcher-efl (Gnome/UNE 2D) windows
need to be opened <em>after</em> ratpoison has already fired up.  Otherwise,
ratpoison mangles the windows.  Secondly, we need to make sure
gnome-panel starts up <em>last</em> so that it will appear on top of the
unmanaged windows.  Gnome has discussed setting up startup
dependencies, which is the right solution to this, but it's not there
yet at least as far as I could tell.</p>
<p>Without such dependencies, the hacks required are so ugly, I suggest
using gnome-session-properties (&quot;Startup Applicatons&quot; in the Gnome
Sytem Preferences menu) instead of ~/.ratpoisonrc to do your
app startup to solve the first problem.  If ratpoison isn't opening
your apps, it starts up lightning fast when set as the gnome window
manager and window mangling isn't an issue at least for me.</p>
<p>The second issue, getting gnome-panel to startup after
nautilus/netbook-launcher-efl, still requires an ugly hack, at least
as far as I could tell.  Make sure ~/bin is on your normal user's
PATH, the default in recent Ubuntus at least.  Then add a wrapper
around gnome-panel so that it waits for nautilus/netbook-launcher-efl
to start before it does by adding an executable ~/bin/gnome-panel with
the following contents:</p>
<pre class="literal-block">
#! /bin/bash
set -x
IFS='
'

command=${0##*/}

# Find the next path for command
for path in $( which -a $command )
do
    if [ $next ]
    then
        break
    elif [ $path == $0 ]
    then
        next=1
    fi
done

# Determine command dependencies
case $DESKTOP_SESSION in
    gnome)
        depends_name=&quot;nautilus&quot;
        ;;
    une-efl)
        depends_name=&quot;netbook-launcher-efl&quot;
        ;;
    *)
        exec $path &quot;$&#64;&quot;
        ;;
esac

# Wait for the dependency to start
while [ 1 ]
do
    # check for the process, if present continue
    ps -C &quot;$depends_name&quot; -o pid,user | grep $USER &amp;&amp; break || sleep 1
done

# pause for window initialization
sleep 1

# Start the real command
exec $path &quot;$&#64;&quot;
</pre>
<p>Now you should be able to log out of Gnome and back in, ratpoison will
startup and tell you so immediately.  Sometime later,
nautilus/netbook-launcher-efl and gnome-panel will startup as
unmanaged windows and your gnome-session startup apps will open.  The
windows ratpoison doesn't manage can be seen by clearing all the
ratpoison manged windows with &quot;C-t -&quot;.  IOW, when using ratpoison
under gnome, &quot;C-t -&quot; is equivalent to switching to the desktop.</p>
<p>This all only works under Ubuntu Netbook Edition 2D, since under 3D it
appears everything, gnome-panel, the launcher, <em>everything</em> is
actually all pulled into the mutter window manager used by unity.  I
think this is fine since I don't see much point in using ratpoison
under unity.  Under the 2D version of UNE, however, it works
beautifully.</p>
<p>The one hitch I've found is that since the Gnome desktop windows are
not managed by ratpoison, many completed actions, such as completing a
dialog, will return you back to the previous ratpoison managed
window.  Most of the time, this is actually best for keyboard junkies
since we tend to want to have as little to do with the desktop
interface as possible.  It can be annoying, however, when you have
multiple interactions to have with the desktop in a row since you have
to keep doing &quot;C-t -&quot; after each operation to get back to the desktop.</p>
<p>Since I was figuring this out as I went, I didn't do this setup in
this on a clean install, so there may be some hitches.  Sign in via
openid and comment if you run into problems and I'll try to cleanup
the procedure for anyone else.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2011-03-13T06:57:30Z</dc:date>
    
    <dc:modified>2011-03-13T06:57:30Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/cioppino-sprint">
    <title>Cioppino Sprint</title>
    <link>http://rpatterson.net/blog/cioppino-sprint</link>
    <description>I'm back home after the west coast sprint formerly known as the Tahoe sprint, plone.net is now on plone.org, and I can spell Cioppino without looking it up.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Last night I got home from the <a class="reference external" href="http://www.coactivate.org/projects/snow-sprint-west-2011/project-home">Cioppino Sprint</a>
in beautiful Bodega Bay, CA.  <a class="reference external" href="http://www.linkedin.com/in/smcmahon">Steve McMahon</a> did an excellent putting
arranging the sprint and got us a vacation house with a stunning view
and a hot tub.  Combine all this with a few great cooks and California
fresh produce, we ate well, enjoyed the view and got a lot of coding
done.</p>
<p>The sprint was focused on &quot;achievable tasks that provide immediate
wins for Plone-the-product or Plone-the-community&quot;, meaning
low-hanging fruit mostly on the plone.org site itself.  With Limi, I
took on merging the <a class="reference external" href="http://plone.net">plone.net</a> service providers
site into <a class="reference external" href="http://plone.org/support/providers">plone.org</a> itself.
For my part, this involved:</p>
<blockquote>
<ul class="simple">
<li>updating <a class="reference external" href="http://dev.plone.org/collective/browser/Products.PloneServicesCenter">Products.PloneServicesCenter</a>
to Plone 4 along other fixes, cleanup and improvements</li>
<li>exporting the content from the plone.net then importing it on
plone.org</li>
<li>doing a few selective catalog updates</li>
<li>re-creating some content</li>
<li>setting up some content rules</li>
</ul>
</blockquote>
<p>Pretty easy stuff and it was mostly done by Friday.  It was also the
first time I got my hands on plone.org itself.  Call me a fan-boy but I still get giddy when I get one step closer to the core
of Plone, a project I was once totally on the outside of.</p>
<p>I also spent some time walking through the creation of a new custom AT
content type with Bill and <a class="reference external" href="https://www.facebook.com/tom.kapanka">Spanky</a> to see how hard it is to
approach this task as a newcomer to Plone.  I always enjoy helping get
started and happily, Bill even <a class="reference external" href="https://github.com/bdbaddog/Plone-Book-Review-Product">posted his code</a> to github.</p>
<p id="manhattan">Not to toot my own horn, but my mixology seems to have been a hit.  My
Manhattan was particularly popular and since <a class="reference external" href="http://www.linkedin.com/in/billdeegan">Bill Deegan</a> asked, here's the recipe:</p>
<pre class="literal-block">
Cioppino Manhattan

1.5 oz      Buffalo Trace Bourbon (good bang for buck, not quite top-shelf)
1.5 oz      Carpano Antica Formula (really good sweet vermouth)
1-2 dashes  Blood Orange Bitters

Stir with lots of ice for a good while to melt plenty and mellow
out the cocktail.  Strain and serve.
</pre>
<p>In summary, the Cioppino Sprint was quite a success, I had a great
time, and I very much hope it becomes an annual tradition!</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Tahoe Sprint 2010</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    
      <dc:subject>Front Page</dc:subject>
    
    <dc:date>2011-06-13T15:29:12Z</dc:date>
    
    <dc:modified>2011-06-13T15:29:12Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/migrating-a-blobstorage">
    <title>Migrating a blobstorage</title>
    <link>http://rpatterson.net/blog/migrating-a-blobstorage</link>
    <description>Addressing the "ZODB.blob WARNING (PID) The `lawn` blob directory layout is deprecated due to scalability issues on some file systems, please consider migrating to the `bushy` layout." warnings.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Update: Filed a ZODB <a class="reference external" href="https://bugs.launchpad.net/zodb/+bug/683874">bug</a>.</p>
<p>I've been getting he following log message ever since I migrated to ZODB BLOBs:</p>
<pre class="literal-block">
ZODB.blob WARNING (PID) The `lawn` blob directory layout is deprecated due to scalability issues on some file systems, please consider migrating to the `bushy` layout.
</pre>
<p>It's not obvious what to do about this, even after initial googling, so I thought I'd document it.  Firstly, we need to use the ZODB.scripts.migrateblobs script so create a console script for it that has all the necessary eggs available.  Unfortunately, the ZODB3 egg doesn't define a console_scripts entry point for this script so I used zc.recipe.egg to work around this:</p>
<pre class="literal-block">
[buildout]
...
parts +=
    zeo
...
    migrateblobs
...
[migrateblobs]
recipe = zc.recipe.egg
eggs = ZODB3
entry-points = migrateblobs=ZODB.scripts.migrateblobs:main
</pre>
<p>After re-running buildout and shutting down ZEO, I used the generated
script to migrate the blobstorage:</p>
<pre class="literal-block">
$ mv var/blobstorage var/blobstorage-lawn
$ bin/migrateblobs var/blobstorage-lawn/ var/blobstorage
(PID) Blob directory `var/blobstorage-lawn/` has layout marker set. Selected `lawn` layout.
(PID) The `lawn` blob directory layout is deprecated due to scalability issues on some file systems, please consider migrating to the `bushy` layout.
(PID) Blob directory '.../var/blobstorage/' does not exist. Created new directory.
(PID) Blob temporary directory 'var/blobstorage/tmp' does not exist. Created new directory.
Migrating blob data from `var/blobstorage-lawn/` (lawn) to `var/blobstorage` (bushy)
        OID: 0x###### - 1 files
...
</pre>
<p>Now I'm able to fire up ZEO and I can access AT file and image objects
fine without the log warning.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2010-12-01T23:44:23Z</dc:date>
    
    <dc:modified>2010-12-01T23:44:23Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/trying-out-chameleon">
    <title>Trying out Chameleon</title>
    <link>http://rpatterson.net/blog/trying-out-chameleon</link>
    <description>My experiences with Chameleon, testing compatibility and z3c.form</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I'm about to upgrade a sizable client deployment to Plone 4 and wanted to see if I could switch to the <a class="reference external" href="http://chameleon.repoze.org/">Chameleon</a> template engine at the same time.  I'm recording things I found here:</p>
<div class="section" id="testing-both-with-and-without-chameleon">
<h3>Testing both with and without Chameleon</h3>
<p>For some add-ons of mine, I found it useful to be able to run the tests both with and without Chameleon.  It turns out to be <a class="reference external" href="https://dev.plone.org/collective/changeset/145722/">remarkably simple</a> with buildout.</p>
</div>
<div class="section" id="integrating-cmf-pt-and-z3c-form">
<h3>Integrating cmf.pt and z3c.form</h3>
<p>There are some gotchas when using both cmf.pt and z3c.form together.  You have to be sure to include z3c.ptcompat, which you can do with z3c.form's poorly named &quot;extra&quot; extras_require.  I did this in my project's setup.py by adding the following:</p>
<pre class="literal-block">
      install_requires=[
...
          'z3c.form[extra]&lt;2.3dev',
...
</pre>
<p>Unfortunately, z3c.ptcompat uses an environment variable to switch on the use of Chameleon so you have to add the environment variable to the buildout instances and test runners:</p>
<pre class="literal-block">
[instance]
...
environment-vars =
  PREFER_Z3C_PT True
...
[test]
...
environment = testenv
...
[testenv]
PREFER_Z3C_PT = True
</pre>
</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2010-10-07T23:37:15Z</dc:date>
    
    <dc:modified>2010-10-07T23:37:15Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/does-the-tool-really-deserve-the-credit">
    <title>Does the Tool Really Deserve the Credit?</title>
    <link>http://rpatterson.net/blog/does-the-tool-really-deserve-the-credit</link>
    <description>When we rave about a tool being superior because we used it to solve a given problem, is it really the tool or the familiarity with the problem we gained in learning to use the tool?</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>To get it out of the way, this is not about <a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> or <a class="reference external" href="http://pypi.python.org/pypi/z3c.form">z3c.form</a>.  I have nothing but praise
for virtualenv, I just use it very rarely.  I have much to criticize
about z3c.form, but that's another topic and may be a problem <a class="reference external" href="http://blog.ianbicking.org/on-form-libraries.html">endemic
to all forms libraries</a>.  I'd like to
keep this and any ensuing discussion to the more abstract issue of
incidental familiarity and how it affects our perspectives on the
value of a given tool.</p>
<p>I use <a class="reference external" href="http://www.ubuntu.com/">Ubuntu Linux</a> for my development
platform (and everything else).  As such, I've had the luxury of a
pretty good OS installed python development environment.  I really
don't know much about virtualenv.  I do know its one of those tools
that many people swear by with a bit of zeal.  Some won't assist with
a problem unless you first setup a virtualenv to eliminate variables.
The thing is, it's never actually solved a problem of mine that I can
think of by eliminating a variable.  I have on a very few occasions
found it useful to smash my way out of a horrible environment when I'm
not under one of my trusty Ubuntu environments, but even then just to
get up and running.  So for me, it's a tool I don't know well that I
will use only when I need to to meet someone else's requirements or to
solve a problem quickly when finding the root cause isn't worth my
time.</p>
<p><a class="reference external" href="http://plone.org/">Plone 3</a>, unfortunately (go <a class="reference external" href="http://plone.org/products/plone/releases/4.0">Plone 4</a>, GO!), still requires
Python 2.4 and Ubuntu has, quite appropriately, recently dropped 2.4.
While struggling to keep my Plone 3 buildouts running and with some
RHEL deployments, I found myself reaching for virtualenv.  The
problems were a mess of path issues (PATH, PYTHONPATH,
LD_LIBRARY_PATH, etc.).  I don't know much about these issues and I
don't want to.  I prefer to delegate to my trusty OS and to buildout.
In the end, though virtualenv helped somewhat, I still had to come to
understand far more about that path issues than I feel I should.</p>
<p>It occurred to me, however, that if I'd been working on something
other than Ubuntu all these years, I would have run into many more
path and similar problems and I probably would have fallen in love
with virtualenv.  It also occurred to me, that in the process of
learning to use virtualenv to help resolve these issues, I would
probably have learned a lot more about all the path issues and would
probably be fairly competent at comprehending such issues.  I would
probably also not be aware that I had gained such further familiarity
and might attribute my new-found greater ease with my Python
environments disproportionately to virtualenv.</p>
<p>This reminded me of my experience with <a class="reference external" href="http://pypi.python.org/pypi/zope.formlib">zope.formlib</a> and z3c.form.  A while
back I'd built a number of forms with zope.formlib/zope.app.form.  I
found it initially much more productive than <a class="reference external" href="http://plone.org/products/archetypes">Archetypes</a>, mostly due to much more
appropriate decoupling, but as time went on it seemed likely I would
have to put at least as much time into understanding things I don't
want to as I have had to do with Archetypes.  Given I already have the
requisite familiarity with Archetypes and can be quite productive in
it, I limited my investment in zope.formlib.  When z3c.form came
around, I was very excited at the prospect that I might get much of
the benefit of zope.fomrlib forms without having to know as many
things I don't want to know.  I'm now considerably more invested in
z3c.form than I ever was in zope.formlib and I can safely say I need
to know just about as much I don't feel I should have to as I did with
zope.formlib.</p>
<p>I have noted that the advocates of z3c.form often seem to find the
appropriate approach to a given problem to be very clear to them and
take a lot of pride in being able to point to the right place in the
docs.  For my experience, however, I find that even after reading the
right place in the docs and reviewing several other docs, I still have
to do way too much UTSL to solve my problem.  I also have the strong
sense that after putting this much time into learning z3c.form, the
obviousness of &quot;The Right Way&quot; will only come to me once I've had to
learn nearly as much I shouldn't have to as I've had to do with
Archetypes.  I take from this that it may be another case of somewhat
erroneously attributing the value of comprehension, understanding, and
experience to the tool whose use lead to this familiarity largely
incidentally.</p>
<p>(To be very clear, I don't want to discuss z3c.form here.  I think
investing in some successor to AT is very necessary at this point and
we may not be able to afford waiting for something else.  The
documentation is also absolutely worth being proud of.  I think most
of the value of z3c.form will be in putting our collective weight
behind <em>something</em>.  I use z3c.form and will continue to do so.)</p>
<p>Now for the disturbing part, I know I've done this very thing <em>many</em>
times but I can't yet list them.  It's much easier to come to see a
pattern like this when looking critically at or feeling frustrated
with tools I'm just using but not heavily invested in than it is to do
so with tools I'm building.  I hope to temper my strategic decisions
for adopting and suggesting tools with this critical awareness.  I
also hope to temper my own perspective of the value of tools I'm
developing or becoming deeply invested in.  I also hope our
development community can learn to better ask whether the perceived
value of a given tool is being unduly influenced by the incidental
familiarity we've developed in building or using that tool.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Ross Patterson</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    
      <dc:subject>Planet Zope</dc:subject>
    
    <dc:date>2010-08-17T00:26:41Z</dc:date>
    
    <dc:modified>2010-08-17T00:26:41Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://rpatterson.net/blog/dogfood-dinner-bell">
    <title>Dogfood Dinner Bell</title>
    <link>http://rpatterson.net/blog/dogfood-dinner-bell</link>
    <description>It's that time again to upgrade my Blog to the latest Plone.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>With the first Plone 4 Beta out it's time to eat my own dogfood and
upgrade my blog.  This site is now running on Plone 4.0b1-1.  So come
poke around if you like and tell me what's broken.  :)</p>
<p>The upgrade went pretty smoothly for my main site.  I had some other,
older, Plone portals where I've installed various add-ons in the past
and for those I had to do some manual cleanup of some broken objects.</p>
<p>The unified folder implementation makes removing broken objects very
difficult.  The manage_delObjects(), _delObject, and _delOb methods
are all broken before the folders have been migrated but the migration
won't complete if there are broken objects in the folder.  I had to do
something like this where &quot;idx&quot; is the index in _objects of the broken
object and 'foo' is the id:</p>
<pre class="literal-block">
&gt;&gt;&gt; folder._objects = folder._objects[:idx]+folder._objects[idx+1:]
&gt;&gt;&gt; delattr(folder, 'foo')
&gt;&gt;&gt; import transaction
&gt;&gt;&gt; transaction.commit()
</pre>
<p>On two of my portals I also had some regular TextIndex'es in the
catalog, which I guess are no longer around.  Those I was able to just
delete in the &quot;Indexes&quot; tab of the ZMI for portal_catalog.   Since
these were core indexes like &quot;Title&quot; I used portal_setup to install
just the catalog import step from the Plone base profile.  Being a
base profile this means running the import step cleared the
indexes so I also had to update those catalogs.</p>
<p>After all that was done I just uninstalled the classic theme and Kupu
and then installed and configured <a class="reference external" href="http://bluedynamics.com/articles/jens/plone-4-and-caching">plone.app.caching</a>.
Everything seems to be working well.</p>
<p>Just to polish things off, I wanted to make sure I was getting the
full benefit of <a class="reference external" href="http://n2.nabble.com/ExtensionClass-Base-vs-ZODB-td4617874.html">Hanno's ExtensionClass/ZODB fix</a>.
The one thing I can't find is a clear migration procedure.  As far as
I understand the ZODB, the objects created before the fix would need
to be written to the ZODB again to see the benefit from the fix.  So I
used the following at a &quot;bin/instance debug&quot; prompt:</p>
<pre class="literal-block">
&gt;&gt;&gt; app.ZopeFindAndApply(app, search_sub=1, apply_func=lambda obj, path: setattr(obj, '_p_changed', True))
&gt;&gt;&gt; import transaction
&gt;&gt;&gt; transaction.commit()
</pre>
<p>That <em>should</em> do it, but if anyone knows how that's insufficient or
knows a better way to accomplish the migration, please do leave a comment.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>admin</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Front Page</dc:subject>
    
    
      <dc:subject>Planet Plone</dc:subject>
    
    
      <dc:subject>Ideas</dc:subject>
    
    <dc:date>2010-04-02T04:02:22Z</dc:date>
    
    <dc:modified>2010-04-02T04:02:22Z</dc:modified>
    <dc:type>News Item</dc:type>
  </item>





</rdf:RDF>

