<?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/front-page/RSS">
  <title>Ross Patterson</title>
  <link>http://rpatterson.net</link>
  
  <description>
    
       Welcome to my blog, professional website, and resume.
       
  </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.gif"/>

  <items>
    <rdf:Seq>
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/testbrowser-redirects-with-fragments"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/re-using-and-multiplexing-ssh"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/user-name-with-spaces-and-psvn.el"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/adding-testbrowser-form-inputs"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/aerobie-aeropress"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/buildout-one-zope2-build"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/software/collective.formcriteria"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/software/collective.testcaselayer"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/products.pdbdebugmode-egg"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/debugging-with-mockmailhost"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/software/rpatterson.mailsync"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/software/z3c.persistentfactory"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/hotel-and-cafe-internet-on-ubuntu"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/python-openid-2.0.2-broken"/>
        
        
            <rdf:li rdf:resource="http://rpatterson.net/blog/zopetestcase-and-packages"/>
        
    </rdf:Seq>
  </items>

</channel>

    <item rdf:about="http://rpatterson.net/blog/testbrowser-redirects-with-fragments">        <title>Testbrowser Redirects with Fragments - Using zope.testbrowser when a redirect URL includes a fragment</title>        <link>http://rpatterson.net/blog/testbrowser-redirects-with-fragments</link>        <description>
&lt;p&gt;I was trying to add functional test coverage for commenting on content when I kept getting 404 NotFound errors.&amp;nbsp; I tried it in a real browser and everything worked just fine.&amp;nbsp; After a little googling, I found an answer in &lt;a class="external-link" href="http://mail.zope.org/pipermail/zope3-dev/2006-June/019671.html"&gt;a post&lt;/a&gt; on the zope3-dev mailing list:&lt;/p&gt;
&lt;p class="discreet"&gt;Note that the fragment identifier is *never* going to be passed to the server by a "real" browser:  instead, the browser strips of the fragment part, submits the remainder of the URL to the server, and then does a search for the appropriate '&amp;lt;a name="bar"&amp;gt;' element *on the client side*.&lt;/p&gt;
&lt;p class="discreet"&gt;I'm not sure how this is pertinent to the problem you have found, but Zope will never traverse '#bar' or '%23bar' in the real world.&lt;/p&gt;
&lt;p&gt;It seems like maybe testbrowser should not send fragments to the underlying mechanize browser.&amp;nbsp; But failing that, for now I just add a note to my tests about why we expect a 404, NotFound error in our tests that we won't see in a real browser.&lt;/p&gt;
&lt;p&gt;Hope this saves someone else the search time.&amp;nbsp; :)&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-08-09T00:33:59Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/re-using-and-multiplexing-ssh">        <title>Re-using SSH Connections - Automatic master SSH connections for sharing and multiplexing </title>        <link>http://rpatterson.net/blog/re-using-and-multiplexing-ssh</link>        <description>
&lt;p&gt;Yet again I've discovered that somethign I've been dreaming of forever already existed for just about that long.&amp;nbsp; :)&lt;/p&gt;
&lt;p&gt;I use SSH for so many things these days that the startup time for connections really begins to add up.&amp;nbsp; Enter &lt;a class="external-link" href="http://www.torchbox.com/blog/ssh_tips_2.html"&gt;OpenSSH connection sharing&lt;/a&gt;.&amp;nbsp; See that blog post for details.&amp;nbsp; Also see &lt;a class="external-link" href="http://svn.haxx.se/dev/archive-2008-07/0494.shtml"&gt;this thread&lt;/a&gt; on the SVN development list for details of a workaround for an svn+ssh issue.&lt;/p&gt;
&lt;p&gt;I was still left wanting, however.&amp;nbsp; The lion's share of the time I want to save re-using SSH connections is for svn+ssh.&amp;nbsp; The SVN workaround requires that I think enough ahead to start the master for every host I connect to.&amp;nbsp; I connect to a lot of hosts and they're constantly changing so I wanted something I didn't have to think about.&amp;nbsp; Also mildly annoying is the fact that the first SSH session to a host would become the master and couldn't be closed or killed without killing all slaves and, of course, killing the master.&lt;/p&gt;
&lt;p&gt;I wrote a wrapper for SSH that would start the master in the background if need be and then run the ssh command as a normal slave.&amp;nbsp; This solution allows the individual connection to close or be killed without affecting the master.&amp;nbsp; It also obviates the need for the svn+ssh workaround.&amp;nbsp; Enjoy:&lt;/p&gt;
&lt;pre&gt;#!/bin/sh
## Wrapper script for ssh that backgrounds the control master if one
## isn't already started.

## the real ssh
SSH="/usr/bin/ssh"

## optstring assembled from `man ssh`
optstring="+1246AaCfgKkMNnqsTtVvXxYb:c:D:e:F:i:L:l:m:O:o:p:R:S:w:"
## get ssh options
opts=`getopt -- "$optstring" "$@"`

## the non-option args follow "--"
## convert to an array of IFS separated strings
args=(${opts#*--})

## the host is the first non-option arg
## use eval to process the quoted strings returned by getopt
host=`eval echo ${args[0]}`

## if the master isn't running, start it in the background
$SSH -q -O check $host 2&amp;gt;/dev/null || $SSH -MNf $host

## replace ourselves with the reall ssh call
exec $SSH "$@"
&lt;/pre&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-07-26T07:25:56Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/user-name-with-spaces-and-psvn.el">        <title>Spaces in User Names and psvn.el - Handling SVN user names with spaces in emacs' svn-status.</title>        <link>http://rpatterson.net/blog/user-name-with-spaces-and-psvn.el</link>        <description>
&lt;p&gt;I recently started on a project using &lt;a class="external-link" href="http://svnbook.red-bean.com/en/1.4/svn-book.html#svn.serverconfig.svnserve.sshtricks.fixedcmd"&gt;svnserve's --tunnel-user&lt;/a&gt; option where many of the committers have user names with spaces.&amp;nbsp; Much to my chagrin, my beloved svn-status in emacs choked on those user names un able to tell where the user name ended and the filename began.&lt;/p&gt;
&lt;p&gt;Then I found a comment in the &lt;a class="external-link" href="http://xsteve.at/prg/emacs/psvn.el"&gt;current version of psvn.el&lt;/a&gt; detailing how to work around this.&amp;nbsp; Just be sure you have the current version on your load-path and add something like the following to your ~/.emacs:&lt;/p&gt;
&lt;pre&gt;(setq svn-user-names-including-blanks '(\"feng shui\" \"mister blank\"))
(add-hook 'svn-pre-parse-status-hook 'svn-status-parse-fixup-user-names-including-blanks)
&lt;/pre&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-07-25T17:43:50Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/adding-testbrowser-form-inputs">        <title>Adding testbrowser Form Inputs - Mock dynamic form inputs with zope.testbrowser</title>        <link>http://rpatterson.net/blog/adding-testbrowser-form-inputs</link>        <description>
&lt;p&gt;When writing functional tests that cover forms with elements that are dynamically manipulated from JavaScript, such as the ReferenceBrowserWidget, I often simply didn't cover those elements becuase it simply wasn't worth it to add Selenium or zc.testbrowser.real as a testing dependency&amp;nbsp; for what are usually very small pieces of what is being tested.&lt;/p&gt;
&lt;p&gt;What I've always wanted was a way to reproduce the effects of the dynamic manipulation in the testbrowser.&amp;nbsp; When I was recently bitten by a bug that I didn't catch for lack of functional coverage of a ReferenceField, I dug into the ClientForm package that zope.testbrowser uses and found the HTMLForm.new_control() method.&amp;nbsp; This is the method that ClientForm uses to construct the controls that zope.testbrowser provides lookup for.&lt;/p&gt;
&lt;p&gt;Since Firefox allows you to inspect the DOM either by selecting the elements and using "View selection source" or with Web Developer's DOM inspector, you can ferret out what the dynamic manipulation created and use that information to construct the HTMLForm.new_control() call that will reproduce that.&amp;nbsp; The following example would add the foo object to the related items on another object's edit form.&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; form = browser.getForm(name="edit_form")
&amp;gt;&amp;gt;&amp;gt; form.mech_form.new_control(
...     type='checkbox',
...     name='relatedItems:list',
...     attrs=dict(checked='checked', value=foo.UID()))
&lt;/pre&gt;
&lt;p&gt;See the ClientForm source for more details.&lt;/p&gt;
&lt;p&gt;BTW, it seems the the ReferenceBrowserWidget includes an empty string on submission of the form.&amp;nbsp; This empty string case seems to be handled in the &lt;em&gt;field's&lt;/em&gt; set() method and not in the widget where it seems like it should be.&amp;nbsp; Not knowing this, I implemented a custom mutator with a bug that I didn't catch because I didn't have test coverage on the form submission.&amp;nbsp; Now I do.&amp;nbsp; :)&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-06-01T23:02:14Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/aerobie-aeropress">        <title>Aerobie AeroPress - Who knew the best coffee maker would come from a toy company?</title>        <link>http://rpatterson.net/blog/aerobie-aeropress</link>        <description>
&lt;p&gt;I resisted it for some time.&amp;nbsp; Becoming a coffee snob, that is.&amp;nbsp; But it's happened and it's time I acknowledged it.&lt;/p&gt;
&lt;p&gt;One of my favorite baristas made the most peculiar recommendation for a coffee maker for home, the &lt;a class="external-link" href="http://aerobie.com/Products/aeropress.htm"&gt;Aerobie Aeropress&lt;/a&gt;.&amp;nbsp; He warned me not to judge the book by its cover and he was right.&amp;nbsp; The only things that make better coffee are ~$10k espresso machines or the ~$10k Clover.&amp;nbsp; The AeroPress is only ~$35 and I don't need a barista's skill to make great coffee at home.&amp;nbsp; Wow, I sound like an ad.&amp;nbsp; Ok, but it's worth it just this once.&amp;nbsp; I keep finding myself wanting to pack it when I travel.&amp;nbsp; It's rediculous.&lt;/p&gt;
&lt;p&gt;Seriously, if you like coffee at all, try it.&amp;nbsp; Pay no attention to the cheesy marketing, neither theirs nor mine.&amp;nbsp; :)&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-05-25T03:07:13Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/buildout-one-zope2-build">        <title>Buildout - One Zope2 Build - I can share one Zope2 build between all buildouts</title>        <link>http://rpatterson.net/blog/buildout-one-zope2-build</link>        <description>
&lt;p&gt;It's possible to share one Zope2 buildout between buildouts without modifying the buildouts' config files.&amp;nbsp; It's documented on the PyPI page of &lt;a class="external-link" href="http://pypi.python.org/pypi/plone.recipe.zope2install"&gt;plone.recipe.zope2instance&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Updated: Somehow I'd missed this for sometime.&amp;nbsp; I think I was looking at the docs for an old egg.&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-05-25T01:33:56Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/software/collective.formcriteria">        <title>collective.formcriteria - User enterable search criteria forms for collections/topic/smart folders.</title>        <link>http://rpatterson.net/software/collective.formcriteria</link>        <description>
&lt;p&gt;This package provides new criteria types based on the&lt;br /&gt;ATContentTypes.criteria types that are used to create a form at the&lt;br /&gt;top of the topic view.&amp;nbsp; Users can use the form to submit criteria to&lt;br /&gt;supplement any search criteria in the topic.&amp;nbsp; Values entered on the&lt;br /&gt;criteria tab for the topic become the default values on the form.&lt;br /&gt;&lt;br /&gt;Also provided is an alternative display layout that uses the folder&lt;br /&gt;contents table and can still display the search form viewlet.&lt;/p&gt;
&lt;p&gt;See the &lt;a class="external-link" href="http://pypi.python.org/pypi/collective.formcriteria"&gt;PyPI page&lt;/a&gt; for more details.&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</dc:creator>        <dc:rights></dc:rights>                    <dc:subject>Front Page</dc:subject>                    <dc:subject>Planet Plone</dc:subject>                    <dc:subject>Software</dc:subject>                <dc:date>2008-06-30T04:59:45Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/software/collective.testcaselayer">        <title>collective.testcaselayer - Use test cases as zope.testing layers</title>        <link>http://rpatterson.net/software/collective.testcaselayer</link>        <description>
&lt;p&gt;The support for layers provided by zope.testing helps to lessen the amount of time consumed during test driven development by sharing expensive test fixtures, such as is often requires for functional test.&amp;nbsp; This package provides several well tested facilities to make writing and using layers faster and easier.&lt;/p&gt;
&lt;p&gt;Layer authors often end up reproducing the functionality provided by their test case classes since the same functionality is needed to perform layer set up or tear down.&amp;nbsp; The collective.testcaselayer.ztc, collective.testcaselayer.ctc, and collective.testcaselayer.ptc modules provide layer base classes that mix in the test case functionality from ZopeTestCase, CMFTestCase, and PloneTestCase, respectively.&amp;nbsp; See the collective.testcaselayer.ztc, and collective.testcaselayer.ptc sections below (or ztc.txt and ptc.txt if reading this in the source) for more details.&amp;nbsp; These layer base classes also include the layer base class support from collective.testcaselayer.layer and the sandboxed ZODB layer support from collective.testcaselayer.sandbox described below.&amp;nbsp; Additionally, these modules allow for using the test case fixtures as layers themselves.&lt;/p&gt;
&lt;p&gt;While class objects can be used as layers, as opposed to instances of classes, doing so means that it is not possible for a layer to subclass another layer *just* to re-use functionality without also depending on that layer being set up as well.&amp;nbsp; See the collective.testcaselayer.layer section below (or layer.txt if reading this in the source) for more details.&lt;/p&gt;
&lt;p&gt;The DemoStorage included with the ZODB provides a way to "nest" ZODB stores such that all writes will go to the DemoStorage while reads will be taken from the base storage if not available from the DemoStorage.&amp;nbsp; The collective.testcaselayer.sandbox module uses this feature to associate a DemoStorage with each sandboxed layer to which set up changes are committed and restore the base storage on tear down.&amp;nbsp; Thus sibling layers that write to the ZODB can be isolated from each other.&amp;nbsp; See the collective.testcaselayer.sandbox section below (or sandbox.txt if reading this in the source) for more details.&lt;/p&gt;
&lt;p&gt;See the &lt;a class="external-link" href="http://pypi.python.org/pypi/collective.testcaselayer"&gt;PyPI page&lt;/a&gt; for more details.&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</dc:creator>        <dc:rights></dc:rights>                    <dc:subject>Front Page</dc:subject>                    <dc:subject>Planet Plone</dc:subject>                    <dc:subject>Software</dc:subject>                <dc:date>2008-05-24T06:22:41Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/products.pdbdebugmode-egg">        <title>Products.PDBDebugMode Egg - I've eggified my post_mortem debugging tool</title>        <link>http://rpatterson.net/blog/products.pdbdebugmode-egg</link>        <description>
&lt;p&gt;Just a quick heads up that I've eggified Products.PDBDebugMode so it's a lot easier to use in buildouts.&amp;nbsp; It can be as simple as:&lt;/p&gt;
&lt;pre&gt;[buildout]
eggs =
    ...
    Products.PDBDebugMode
&lt;/pre&gt;
&lt;p&gt;If you want some isolation, then you can use zc.recipe.egg in a separate part:&lt;/p&gt;
&lt;pre&gt;[instance]
...
eggs = 
    ...
    Products.PDBDebugMode
&lt;/pre&gt;
&lt;p&gt;Update: Simplified per Martin's comment.&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-05-16T01:01:03Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/debugging-with-mockmailhost">        <title>Debugging with MockMailHost - Using the mock MailHost on a real instance</title>        <link>http://rpatterson.net/blog/debugging-with-mockmailhost</link>        <description>
&lt;p&gt;I often find the need to debug user registration or other functionality that involves sending mail through the MailHost where I either don't want the mail to go out, or I want to intercept it for examination or both.&amp;nbsp; Using "zopectl debug" I replace the MailHost with a MockMailHost as follows::&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; app.Plone._delObject('MailHost')
&amp;gt;&amp;gt;&amp;gt; from Products.PasswordResetTool.tests import utils
&amp;gt;&amp;gt;&amp;gt; mail_host = utils.MockMailHost('MailHost')
&amp;gt;&amp;gt;&amp;gt; app.Plone._setObject('MailHost', mail_host)
'MailHost'
&amp;gt;&amp;gt;&amp;gt; app.Plone.MailHost
&amp;lt;MockMailHost at /Plone/MailHost&amp;gt;
&amp;gt;&amp;gt;&amp;gt; import transaction
&amp;gt;&amp;gt;&amp;gt; transaction.commit()
&lt;/pre&gt;
&lt;p&gt;Then using PDBDebugMode or "zopectl debug" again, the messages sent through the MailHost can be examined as follows::&lt;/p&gt;
&lt;pre&gt;(Pdb) print self.MailHost.messages[-1]
&lt;/pre&gt;
&lt;p&gt;I have long intended to build a package with a GenericSetup profile that will do this for me, but I wanted to get this out there for now.&amp;nbsp; Enjoy!&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-05-12T18:16:52Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/software/rpatterson.mailsync">        <title>rpatterson.mailsync - OfflineIMAP, mswatch, and Gnus integration for realtime mail</title>        <link>http://rpatterson.net/software/rpatterson.mailsync</link>        <description>
&lt;p&gt;Like many others I've been frustrated with the options that are available for email clients.&amp;nbsp; I recently had a bit of break through and &lt;a class="external-link" href="http://pypi.python.org/pypi/rpatterson.mailsync"&gt;packaged&lt;/a&gt; the reusable parts of my mail setup for consumption by others.&amp;nbsp; See the &lt;a class="external-link" href="http://pypi.python.org/pypi/rpatterson.mailsync#backstory"&gt;backstory&lt;/a&gt; for all the gory details of the hisotry.&amp;nbsp; I've factored everything with an eye towards extensibility so if there's enough interest, I'll start a project and a public repo somewhere and put this out there.&amp;nbsp; See the &lt;a class="external-link" href="http://pypi.python.org/pypi/rpatterson.mailsync#todo"&gt;TODO&lt;/a&gt; list if your interested in any of the ideas I have for improvements.&lt;/p&gt;
&lt;p&gt;To try it out, just see the &lt;a class="external-link" href="http://pypi.python.org/pypi/rpatterson.mailsync"&gt;README&lt;/a&gt; on the pypi page.&amp;nbsp; Here's a brief description.&lt;/p&gt;
&lt;p&gt;This package provides some scripts that wrap parts of mswatch and&lt;br /&gt;OfflineIMAP and integrate with Gnus to provide a local maildir that&lt;br /&gt;is synchronized with a remote maildir as changes occur, instead of&lt;br /&gt;polling on a regular basis.&amp;nbsp; This provides for near instant delivery&lt;br /&gt;of new mail while also reducing resource utilization.&amp;nbsp; Integration&lt;br /&gt;with the Emacs mail and newsreader, Gnus, is also provided in such a&lt;br /&gt;way that your single threaded Emacs process is blocked much less as&lt;br /&gt;changes occur to the maildirs.&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</dc:creator>        <dc:rights></dc:rights>                    <dc:subject>Front Page</dc:subject>                    <dc:subject>Planet Plone</dc:subject>                    <dc:subject>Software</dc:subject>                <dc:date>2008-06-30T05:00:24Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/software/z3c.persistentfactory">        <title>z3c.persistentfactory - Persistent instance method ZCA factories</title>        <link>http://rpatterson.net/software/z3c.persistentfactory</link>        <description>
&lt;p&gt;Homepage: &lt;a class="external-link" href="http://pypi.python.org/pypi/z3c.persistentfactory"&gt;http://pypi.python.org/pypi/z3c.persistentfactory&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The ZCA and the ZODB are a good combination where components require
persistent state.  ZCA factories or handlers typically retrieve any
persistent state required from the persistent objects being adapted.
If the persistent state required is not specific to the objects being
adapted, a common solution is to register a persistent utility which
is then looked up in the factory or handler.  The persistent utility
approach requires, however, that the one appropriate utility is looked
up which requires support in the ZCA registrations either in the
interface provided or the utility name.&lt;/p&gt;
&lt;p&gt;In some cases, however, it is more consistent with the object oriented
semantics of Python and the ZCA to think of the factory or handler as
an instance method of a persistent object.  With this approach the
non-context specific persistent state can be accessed on self.&lt;/p&gt;
&lt;div class="section"&gt;
&lt;h2&gt;&lt;a id="instance-method-event-handler" name="instance-method-event-handler"&gt;Instance Method Event Handler&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One example where this may be useful is where some non-context
persistent state is tightly coupled to some event handlers in such a
way where instance methods are better semantics.&lt;/p&gt;
&lt;p&gt;The Baz class uses the decorator in the python code.  Note that the
factory decorator must come before the declaration decorators so that
it will be run last and will reflect the declarations.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; from z3c.persistentfactory import testing&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; baz = testing.Baz()&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Register the persistent factory wrapped instance method as a handler.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; from zope import component&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; component.provideHandler(factory=baz.factory)&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The method adapts IFoo, so create an object providing IFoo to be used
as the event.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; component.adaptedBy(baz.factory)&lt;br /&gt;(&amp;lt;InterfaceClass z3c.persistentfactory.testing.IFoo&amp;gt;,)&lt;br /&gt;&lt;/pre&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; from zope import interface&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; foo = testing.Foo()&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; interface.alsoProvides(foo, testing.IFoo)&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;When the event is notified, the method is called with the event as an
argument.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; import zope.event&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; zope.event.notify(foo)&lt;br /&gt;Called &amp;lt;bound method Baz.factory of&lt;br /&gt;&amp;lt;z3c.persistentfactory.testing.Baz object at ...&amp;gt;&amp;gt;&lt;br /&gt;  args: (&amp;lt;z3c.persistentfactory.testing.Foo object at ...&amp;gt;,)&lt;br /&gt;  kwargs: {}&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2&gt;&lt;a id="instance-method-adapter-factory" name="instance-method-adapter-factory"&gt;Instance Method Adapter Factory&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another example is where an adapter factory needs to look up
persistent state specific to the objects being adapted but where that
state can't be stored on the adapted objects them selves.  The
component storing the shared persistent state can register one of it's
instance methods as the adapter factory which will look up the
necessary persistent state on self.&lt;/p&gt;
&lt;p&gt;Register the persistent factory wrapped instance method as an adapter
factory.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; component.provideAdapter(factory=baz.factory)&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The method implements IBar.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; tuple(interface.implementedBy(baz.factory))&lt;br /&gt;(&amp;lt;InterfaceClass z3c.persistentfactory.testing.IBar&amp;gt;,)&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;When the adapter is looked up, the metod is called with the object to
be adapted as an argument.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="doctest-block"&gt;&amp;gt;&amp;gt;&amp;gt; result = component.getAdapter(foo, testing.IBar)&lt;br /&gt;Called &amp;lt;bound method Baz.factory of&lt;br /&gt;&amp;lt;z3c.persistentfactory.testing.Baz object at ...&amp;gt;&amp;gt;&lt;br /&gt;  args: (&amp;lt;z3c.persistentfactory.testing.Foo object at ...&amp;gt;,)&lt;br /&gt;  kwargs: {}&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; result&lt;br /&gt;(&amp;lt;bound method Baz.factory of&lt;br /&gt; &amp;lt;z3c.persistentfactory.testing.Baz object at ...&amp;gt;&amp;gt;,&lt;br /&gt; (&amp;lt;z3c.persistentfactory.testing.Foo object at ...&amp;gt;,), {})&lt;br /&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section"&gt;
&lt;h2&gt;&lt;a id="changelog" name="changelog"&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</dc:creator>        <dc:rights></dc:rights>                    <dc:subject>Front Page</dc:subject>                    <dc:subject>Planet Plone</dc:subject>                    <dc:subject>Software</dc:subject>                <dc:date>2008-04-09T21:10:48Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/hotel-and-cafe-internet-on-ubuntu">        <title>Hotel internet on Ubuntu - TCP window scaling and broken routers</title>        <link>http://rpatterson.net/blog/hotel-and-cafe-internet-on-ubuntu</link>        <description>
&lt;p&gt;I've run into odd networking problems on certain networks, generally hotel networks but also some cafe networks.&amp;nbsp; The problem afflicts both wireless and wired connections.&amp;nbsp; I'm able to &lt;br /&gt;get an IP address from the DHCP server most of the time, and I can even establish an SSH connection to my server, but all other traffic is hampered by continuous timeouts.&amp;nbsp; Oh, and the really annoying thing is that it only affects Linux, not Windows or Mac.&lt;/p&gt;
&lt;p&gt;In my most recent bout with this problem I finally found &lt;a class="external-link" href="http://lwn.net/Articles/92727/"&gt;an article&lt;/a&gt; that describes the problem and a workaround.&amp;nbsp; According to the article,&amp;nbsp; the problem stems from broken routers that are mishandling a TCP option.&amp;nbsp; See the article for the details and for the workaround.&lt;/p&gt;
&lt;p&gt;There's one bit that troubles me:&lt;/p&gt;
&lt;p class="discreet"&gt;If, instead, the
situation is left as it is, pressure on the router manufacturers should get
the problem fixed relatively quickly.  It has been a few years, now, that
Linux has a strong enough presence in the networking world that it can get
away with taking this sort of position.&lt;/p&gt;
&lt;p&gt;I see and agree with the point where Linux is a server OS.&amp;nbsp; In this case, however, Linux is a desktop and laptop OS and having a setting that causes problems that Windows and Mac users don't encounter makes us look bad against the competition.&amp;nbsp; It really doesn't matter if the fault is the routers.&amp;nbsp; Maybe the TCP window scaling option should be disabled by Ubuntu for desktop installs?&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-02-11T06:22:13Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/python-openid-2.0.2-broken">        <title>Is python-openid 2.0.2 broken - an upgrade broke openid login</title>        <link>http://rpatterson.net/blog/python-openid-2.0.2-broken</link>        <description>
&lt;p&gt;I want to document my adventures getting openid login working on my Plone 3.0 site.&amp;nbsp; My site is using the plone-site package from Debian unstable which uses the python-openid 2.0.2 package.&amp;nbsp; When visitors reported openid login wasn't working, I started by trying to reproduce the problem on my Ubuntu laptop.&amp;nbsp; I found that the problem didn't occur if version 2.0.0 of the python-openid was installed.&amp;nbsp; This was true in both debian and ubuntu.&lt;/p&gt;
&lt;p&gt;I worked around this issue on my server running Debian by installing the python-openid 2.0.0 package from Ubuntu Gutsy, which is not an approach for the faint of Debian heart and involves a little /etc/apt/preference and /etc/apt/sources.list hackery.&lt;/p&gt;
&lt;p&gt;I don't know if the problem occurs with a vanilla python-openid from source because I can't find a distribution.&amp;nbsp; I also didn't dig any deeper to see if the fault for this lies in Plone or python-openid.&lt;/p&gt;
&lt;p&gt;At any rate, openid login and commenting is now available on this site.&amp;nbsp; Now you know, and knowing is half the battle!&amp;nbsp; :)&lt;/p&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</dc:creator>        <dc:rights></dc:rights>                    <dc:subject>Front Page</dc:subject>                    <dc:subject>Planet Plone</dc:subject>                <dc:date>2008-02-11T06:22:13Z</dc:date>        <dc:type>News Item</dc:type>    </item>
    <item rdf:about="http://rpatterson.net/blog/zopetestcase-and-packages">        <title>ZopeTestCase and packages - Please put ZopeTestCase out of my misery</title>        <link>http://rpatterson.net/blog/zopetestcase-and-packages</link>        <description>
&lt;p&gt;In this wonderful world between Zope 2 and 3, called limbo... I mean Five, there's a fun little trap concerning ZCML, packages as products and ZopeTestCase.&amp;nbsp; I wanted to document it somewhere so here it is.&lt;/p&gt;
&lt;p&gt;If you're using packages as products, then to install the package as a product for tests, you'll need the ZCML of the package to be loaded.&amp;nbsp; If the package happens to be included in the configure.zcml of a product,then you'll need Five's loadProducts to have been run in order to install the package as a product.&amp;nbsp; With ZopeTestCase, in order for a product to be available for Five's loadProducts, installProduct must be called before loadProducts is run.&amp;nbsp; Five's loadProducts is usually run in the instance's site.zcml which for Plone tests is usually loaded by the ZCML layer.&lt;/p&gt;
&lt;p&gt;The end result is that all installProduct calls must be made *before* loadProducts is run which in turn must be run before any installPackage calls can be made if you do any including of packages as products in product configure.zcml files.&lt;/p&gt;
&lt;p&gt;Admittedly, this problem goes away if you don't include the ZCML for packages as products inside a product's ZCML.&lt;/p&gt;
&lt;p&gt;If anyone is interested here's an example of using layers to work around this:&lt;/p&gt;
&lt;pre&gt;from Testing import ZopeTestCase
from Products.PloneTestCase import layer

ADDONS = [
    # Your product dependencies here
    ]

class InstallProducts(object):
    """Install products before the ZCML layer so that their ZCML will
    be loaded"""

    @classmethod
    def setUp(cls):
        for dep in ADDONS:
            if ZopeTestCase.hasProduct(dep):
                ZopeTestCase.installProduct(dep)
    
    @classmethod
    def tearDown(cls):
        pass

    @classmethod
    def testSetUp(cls):
        pass

    @classmethod
    def testTearDown(cls):
        pass

class InstallPackages(InstallProducts, layer.ZCML):
    """Install packages after the ZCML layer so that products will
    have had a chance to include the package ZCML"""

    @classmethod
    def setUp(cls):
        for dep in ADDONS:
            if ZopeTestCase.hasPackage(dep):
                ZopeTestCase.installPackage(dep)
    
    @classmethod
    def tearDown(cls):
        pass

    @classmethod
    def testSetUp(cls):
        pass

    @classmethod
    def testTearDown(cls):
        pass
&lt;/pre&gt;
</description>        <dc:publisher>No publisher</dc:publisher>        <dc:creator>ross</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>2008-02-11T06:22:13Z</dc:date>        <dc:type>News Item</dc:type>    </item>




</rdf:RDF>
