<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://www.rpatterson.net/</id>
  <title>Ross Patterson's Blog - Posts tagged Zope</title>
  <updated>2025-07-14T00:00:49.122281+00:00</updated>
  <link href="https://www.rpatterson.net/"/>
  <link href="https://www.rpatterson.net/blog/tag/zope/atom.xml" rel="self"/>
  <generator uri="https://ablog.readthedocs.io/" version="0.11.12">ABlog</generator>
  <entry>
    <id>https://www.rpatterson.net/blog/ttw-reflections-from-future/</id>
    <title>Reflections on TTW Programming from the Future</title>
    <updated>2021-04-07T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="reflections-on-ttw-programming-from-the-future"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Playing with &lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt; and &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt; has me remembering the TTW programming fallout
and debate.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;I’ve been working on &lt;a class="reference external" href="../feeding-ablog-to-social-media/"&gt;feeding my ABlog posts to social media&lt;/a&gt;.  I’ve been experimenting
with some external services for this, primarily because implementing something
self-hosted seems like overkill for this and it makes an excuse to explore something
I’ve been wanting to.  I’m intrigued by these services that claim to let you connect
little pieces of functionality, through an intuitive UI, to create “custom”
mini-“applications”.&lt;/p&gt;
&lt;p&gt;I’m old enough to have cut my teeth on &lt;a class="reference external" href="https://zope.org/"&gt;some of the first Through-The-Web (TTW)
programming offerings&lt;/a&gt; and thus long enough to watch the problems that became of
that. The consensus among the communities I’ve been involved in is that it’s a bad idea
to invite users and tinkerers to build their own custom applications with the promise
that it’s easier and achievable because they can do it in their browser.  The issue is
&lt;em&gt;not&lt;/em&gt; that non-programmers can’t learn to program.  They certainly can and I object to
the kind of rarefied elitism that leads others to argue otherwise.  The issue is that no
one can build the kind of custom application one can build with a full programming
language without &lt;em&gt;also&lt;/em&gt; learning most, if not all, of the suite of programming best
practices.  Without those best practices, one is all but guaranteed to end up with a
poorly engineered, unmaintainable mess.  The best case scenario is that your application
fails to become useful and thus never has a chance to become a burden.  That leaves
those who manage to create an actually useful, initially successful application that
users come to depend on.  These successful tinkerers are eventually rewarded by hitting
multiple walls at once.  Thinking about, planning for, and executing on maintainability
and other best practices are simply costs that must be paid.  The apparent savings of
not having to think about such things is an illusion and those costs have been
compounding all along behind your back.&lt;/p&gt;
&lt;p&gt;While the 10th feature was as easy to implement as the 1st, the 100th feature is 10
times as difficult as the 10th and breaks features 20-23; you can infer the curve.  You
took a stab at a major version upgrade of the framework months ago, hit another wall,
and set it aside.  Now the security/LTS of your major version is about to expire meaning
your custom application will soon be vulnerable to multiple publicly available exploits.
Change management is becoming a nightmare with duplicated code all over the place in an
effort to compensate.  A while back, you learned about VCS and the current best-of-breed
in that domain but you also realized that you couldn’t use those tools to manage your
TTW code.  There are better ways to build custom applications even within the framework
you’re using, but not TTW, the effort is comparable to re-implementing the application,
and those that can do it justly charge much more.  BTW, having learned so much from
this, you’re now worth a lot more yourself and are recruited into your first junior
programming job.  Those last two are good things, but the end result is that a team of
users is now dependent on a custom application that’s going to cost them a lot to either
replace or maintain.  They became a company in the business of developing software
without ever intending to, planning on or budgeting for.&lt;/p&gt;
&lt;p&gt;That whole process breeds resentment in a way that doesn’t come from even an equally
blundering and costly but conscious effort to develop one’s own custom software.  Like
much of human happiness, it’s expectations, the surprise, that’s the issue.  That’s how
I understand the issue with TTW programming.  If a framework provides anything
approaching a full programming language, &lt;em&gt;and&lt;/em&gt; offers or promises to save
users-come-developers some portion of software development “hassles”, then everyone is
almost certainly in for some bad-will inducing surprises.&lt;/p&gt;
&lt;p&gt;So that means that any system that allows users to assemble “applications” through a UI
meant to spare them from some portion of software development discipline needs to have
clear, rigid boundaries on expectations.  It needs to narrowly define what can be done,
place firm limits on the size of what can be built (roughly, the quantity of
components).  It doesn’t hurt to provide users an eject button so that they can export
what they’ve done to the filesystem and continue developing it incrementally using a
full software development tool chain and process.  These are the lessons the &lt;a class="reference external" href="https://plone.org/"&gt;Plone&lt;/a&gt;
community tried to learn from our &lt;a class="reference external" href="https://zope.org/"&gt;Zope&lt;/a&gt; TTW roots.  The &lt;a class="reference external" href="https://plone.org/"&gt;Plone&lt;/a&gt; community built web
UI based on these conclusions for both custom content types with custom schemata and for
custom themes.&lt;/p&gt;
&lt;p&gt;Given my involvement in that long (for software) history, I’ve been wanting to check out
&lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt;.  Such custom applet “development” and hosting platforms are solving different
problems, very simple workflow applications connecting various internet services, but I
imagine theses same principles apply.  &lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt; seems to employ these principles quite
firmly.  I’m not aware of any eject button that could meaningfully allow one to
incrementally build software on top of &lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt; applets, but that wouldn’t be terribly
useful anyways given how firmly they restrict the scope of what one can do.  I don’t
have any current need for anything beyond IFTTT’s simple, two-step composition model,
the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;this&lt;/span&gt;&lt;/code&gt; component and the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;that&lt;/span&gt;&lt;/code&gt; component in “If this then that”, but I could
well imagine wanting more than that.  There’s also the limit on 3 applets on the free
tier of their freemium pricing plan, I am already using 2.  Finally, I couldn’t find a
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;then&lt;/span&gt;&lt;/code&gt; component for posting to LinkedIn as a service, that’s the one that really lead
me to seek other options.&lt;/p&gt;
&lt;p&gt;I ran across &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt; a while back and was similarly intrigued, so when that showed up
in my search for something that could post to LinkedIn, I eagerly tried it out.  They
offer 5 applets, which they call “Zaps” (bit of a groaner of a term), on the free tier
of their freemium pricing plan, so point for &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt;.  I haven’t read much of their
docs, but it’s apparent in the web UI that there’s support for at least a somewhat
arbitrary chaining of more than 2 components, another win for &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt;.  I also found
their options for dealing with different “fields” in data, &lt;a class="reference external" href="https://ablog.readthedocs.io/manual/ablog-configuration-options/?highlight=feeds#blog-feeds"&gt;atom feed&lt;/a&gt; items in this
case, to be significantly more rich than those offered by &lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt;, &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt; streaks
ahead.  They do indeed have components that interact with LinkedIn, so &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt; FTW in
this very cursory and superficial scoring.&lt;/p&gt;
&lt;p&gt;In the current moment, I’m very curious to see how the more restrictive &lt;a class="reference external" href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt;
compares in the long term to the more feature-rich and composible &lt;a class="reference external" href="https://zapier.com/"&gt;Zapier&lt;/a&gt; in terms of
user experience, user maintainability, and &lt;em&gt;internal&lt;/em&gt; maintainability.  Even if I were
to pay enough attention to keep up on this, not very likely, I’m even less likely to get
access to the kind of proprietary internal discussion that could yield such insight.
C’est la capitalisme.  At any rate, It’s been fun to reflect on the issue while
automating some things.&lt;/p&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/ttw-reflections-from-future/"/>
    <summary>Playing with IFTTT and Zapier has me remembering the TTW programming fallout
and debate.</summary>
    <category term="IFTTT" label="IFTTT"/>
    <category term="Plone" label="Plone"/>
    <category term="TTW" label="TTW"/>
    <category term="Zapier" label="Zapier"/>
    <category term="Zope" label="Zope"/>
    <published>2021-04-07T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://www.rpatterson.net/blog/emerald-sprint-report-out/</id>
    <title>Emerald Sprint Report Out</title>
    <updated>2013-02-13T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="emerald-sprint-report-out"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Merging versioning and and constrained types into Dexterity near Beautiful Seattle.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Thanks to the fabulous &lt;a class="reference external" href="http://seattleplone.org"&gt;Seattle Plone folk&lt;/a&gt;, we had another west
coast sprint, the &lt;a class="reference external" href="http://www.coactivate.org/projects/emerald-sprint/project-home"&gt;Emerald Sprint&lt;/a&gt;, on lovely &lt;a class="reference external" href="https://maps.google.com/maps?q=48.16269,-122.467258&amp;amp;ll=47.890564,-122.437134&amp;amp;spn=2.232193,5.410767&amp;amp;num=1&amp;amp;t=h&amp;amp;gl=us&amp;amp;z=8"&gt;Camano Island&lt;/a&gt;.  The
focus was polishing &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.dexterity"&gt;Dexterity&lt;/a&gt;, it was a gorgeous location, a very
productive sprint, and I very much hope we can make it an annual
thing.  We might have a better chance at that if we choose a topic
next year such that &lt;a class="reference external" href="http://glicksoftware.com/"&gt;David&lt;/a&gt; can just be another sprinter for once.
:-)&lt;/p&gt;
&lt;p&gt;Firstly, I have to give a huge shout out to our Maven of Fine Dining,
&lt;a class="reference external" href="http://www.linkedin.com/in/skleinfeldt"&gt;Sally&lt;/a&gt;, and to &lt;a class="reference external" href="www.linkedin.com/pub/alice-tseng/4/275/530"&gt;Alice&lt;/a&gt; for yet more above-and-beyond contributions
to the culinary experience of this sprint.  The food was simply
incredible and I have to say I &lt;em&gt;love&lt;/em&gt; a sprint that has that element.
I was spoiled before by the cooking at the &lt;a class="reference external" href="../cioppino-sprint-2012"&gt;Cioppino Sprint&lt;/a&gt; and the
&lt;a class="reference external" href="../sea-sprint-2012-report-out"&gt;Sea Sprint&lt;/a&gt; and the food at this sprint may have out done them!&lt;/p&gt;
&lt;p&gt;The sprint location was an excellent choice and everything was very
well organized by &lt;a class="reference external" href="http://crisewing.com/"&gt;Cris&lt;/a&gt;, &lt;a class="reference external" href="https://twitter.com/luke_brannon"&gt;Luke&lt;/a&gt;, &lt;a class="reference external" href="http://solitonconsulting.com/"&gt;Fulvio&lt;/a&gt; and &lt;a class="reference external" href="http://glicksoftware.com/"&gt;David&lt;/a&gt;.  I was
very sad to learn that &lt;a class="reference external" href="http://crisewing.com/"&gt;Cris&lt;/a&gt; wasn’t going to be able to stay for the
sprint and wish him the best.  Thanks also to &lt;a class="reference external" href="http://andersonleeb.com/"&gt;Ian Anderson and Andy
Leeb&lt;/a&gt; for treating us to a delicious dinner out on our first night.&lt;/p&gt;
&lt;p&gt;We did a brainstorming session where we all voted for what we found to
be the most important.  Then &lt;a class="reference external" href="http://glicksoftware.com/"&gt;David&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/MatthewWilkes"&gt;Matthew&lt;/a&gt; marked the items
that they thought were clear low-hanging fruit that didn’t require a
lot of design or other discussion. After seeing what the other
sprinters chose for I opted for tackling some of the remaining
low-hanging fruit.  That ended up being two tasks both of which
involved merging work done by others previously in add-ons or other
packages not in Dexterity core where they belong: &lt;a class="reference external" href="https://trello.com/card/better-versioning-support/50d18b10540c21f830003269/9"&gt;versioning&lt;/a&gt; and
&lt;a class="reference external" href="https://trello.com/card/ui-for-setting-the-subtypes-for-containers/50d18b10540c21f830003269/21"&gt;constrained types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Working on &lt;a class="reference external" href="https://trello.com/card/better-versioning-support/50d18b10540c21f830003269/9"&gt;versioning&lt;/a&gt; involved merging two add-on packages into
&lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.dexterity"&gt;Dexterity&lt;/a&gt; core.  The &lt;a class="reference external" href="http://pypi.python.org/pypi/collective.cmfeditionsdexteritycompat"&gt;collective.cmfeditionsdexteritycompat&lt;/a&gt;
add-on makes it possible to use the history view on Dexterity content
and I merged it into &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.versioningbehavior"&gt;plone.app.versioningbehavior&lt;/a&gt;.  The
&lt;a class="reference external" href="http://pypi.python.org/pypi/collective.dexteritydiff"&gt;collective.dexteritydiff&lt;/a&gt; add-on brings parity with &lt;a class="reference external" href="http://plone.org/products/archetypes"&gt;Archetypes&lt;/a&gt;
when viewing diffs between versions and I merged it into
&lt;a class="reference external" href="http://pypi.python.org/pypi/Products.CMFDiffTool"&gt;Products.CMFDiffTool&lt;/a&gt;.  Both packages were done by &lt;a class="reference external" href="http://rafaelb.objectis.net/"&gt;Rafael
Oliveira&lt;/a&gt; and worked perfectly, my only job was doing the merge and
reconciling the tests.  Fortunately, &lt;a class="reference external" href="http://rafaelb.objectis.net/"&gt;Rafael&lt;/a&gt; had written tests &lt;em&gt;and&lt;/em&gt;
had done so using &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.testing/4.2.2"&gt;plone.app.testing&lt;/a&gt;.  &lt;em&gt;Unfortunately&lt;/em&gt;,
&lt;a class="reference external" href="http://pypi.python.org/pypi/Products.CMFEditions"&gt;Products.CMFEditions&lt;/a&gt; does not use &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.testing/4.2.2"&gt;plone.app.testing&lt;/a&gt; and since
such tests can not run in the same test run as &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ZopeTestCase&lt;/span&gt;&lt;/code&gt; tests
are run, that meant I had to back-port the tests &lt;a class="reference external" href="http://rafaelb.objectis.net/"&gt;Rafael&lt;/a&gt; wrote off
of &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.testing/4.2.2"&gt;plone.app.testing&lt;/a&gt; back to &lt;cite&gt;ZopeTestCase&lt;/cite&gt;.  I hate going
backwards but enough things build on the &lt;a class="reference external" href="http://pypi.python.org/pypi/Products.CMFEditions"&gt;Products.CMFEditions&lt;/a&gt; tests
that I guessed it would take too long and be to disruptive to convert
all those tests.  After that, I spent the rest of the sprint trying to
complete my &lt;a class="reference external" href="https://github.com/plone/plone.app.testing/tree/simpler-helpers"&gt;plone.app.testing.api&lt;/a&gt; branch which is intended to make
such conversions easier.&lt;/p&gt;
&lt;p&gt;I also had the opportunity to bring &lt;a class="reference external" href="https://picasaweb.google.com/lh/photo/Pq5EEJ3K2izy6gP4aGsrJNMTjNZETYmyPJy0liipFm0?feat=directlink"&gt;Gin Apocrypha&lt;/a&gt; with me and bar
tend for the event.  It was my first time trying to check enough items
on the plane to be able to mix my whole menu and it actually worked
out very well.  So I think I may be willing to check a bag in the
future to be able to bring &lt;a class="reference external" href="https://picasaweb.google.com/lh/photo/Pq5EEJ3K2izy6gP4aGsrJNMTjNZETYmyPJy0liipFm0?feat=directlink"&gt;Gin Apocrypha&lt;/a&gt; to events I don’t drive to
in the future!&lt;/p&gt;
&lt;p&gt;It was a great sprint and I love the Seattle area so I really hope
this happens again.  This sprint being focused on &lt;a class="reference external" href="http://pypi.python.org/pypi/plone.app.dexterity"&gt;Dexterity&lt;/a&gt; and
&lt;a class="reference external" href="http://glicksoftware.com/"&gt;David&lt;/a&gt; being Dexterity’s maintainer and fearless leader, I know I
pestered him a lot as I needed to ask questions and get perspective,
but he did a great job facilitating everything.  For that reason if no
other, I hope the next Emerald Sprint can be on a topic such that
David can get back to basics and enjoy being just another sprinter
again.  :-)&lt;/p&gt;
&lt;div class="note update admonition"&gt;
&lt;p class="admonition-title"&gt;Updated on 13 February 2013&lt;/p&gt;
&lt;p&gt;Imported from Plone on Mar 15, 2021.  The date for this update is the last
modified date in Plone.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/emerald-sprint-report-out/"/>
    <summary>Merging versioning and and constrained types into Dexterity near Beautiful Seattle.</summary>
    <category term="Plone" label="Plone"/>
    <category term="Python" label="Python"/>
    <category term="Testing" label="Testing"/>
    <category term="Zope" label="Zope"/>
    <published>2013-02-13T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://www.rpatterson.net/blog/prgmr-com-vps-hosting-we-dont-assume-you-are-stupid/</id>
    <title>prgmr.com VPS: “We don’t assume you are stupid”</title>
    <updated>2013-02-04T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="prgmr-com-vps-we-don-t-assume-you-are-stupid"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;Excellent, affordable VPS service done in a way that feels very much like participating in an open-source community.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;I just wanted to drop a quick note praising &lt;a class="reference external" href="http://prgmr.com/xen/"&gt;prgmr.com&lt;/a&gt; for their excellent and very affordable VPS service.  Unfortunately, I had to change hosting providers for other reasons but  would have been happy to stay with them indefinitely.&lt;/p&gt;
&lt;p&gt;Their slogan is “We don’t assume you are stupid” and that’s very apt.  There’s a combination of no hand-holding combined with support.  The support is a particularly good part of their service.  It’s generous but in a particular way that works very well for me.  They’ll help you up with no real hierarchy or bureaucracy up to a limit that I think almost anyone who has participated significantly in an open-source project will find familiar.  Beyond that, you’re on your own.  I really like this balance and always found the lack of bureaucracy more than worth it for any relative lack of hand-holding.&lt;/p&gt;
&lt;p&gt;At any rate, if you want an excellent and affordable VPS in the Bay Area, I can recommend no one better.&lt;/p&gt;
&lt;div class="note update admonition"&gt;
&lt;p class="admonition-title"&gt;Updated on 04 February 2013&lt;/p&gt;
&lt;p&gt;Imported from Plone on Mar 15, 2021.  The date for this update is the last
modified date in Plone.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/prgmr-com-vps-hosting-we-dont-assume-you-are-stupid/"/>
    <summary>Excellent, affordable VPS service done in a way that feels very much like participating in an open-source community.</summary>
    <category term="Plone" label="Plone"/>
    <category term="Zope" label="Zope"/>
    <published>2013-02-01T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://www.rpatterson.net/blog/poskeyerror-during-commit/</id>
    <title>POSKeyError During Commit</title>
    <updated>2012-11-21T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="poskeyerror-during-commit"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;A terrifying tale of ZODB errors that only showed during the hardest time to debug.&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Believe it or not, I’m a &lt;a class="reference external" href="http://plonechix.blogspot.com/2009/12/definitive-guide-to-poskeyerror.html"&gt;POSKeyError&lt;/a&gt; virgin, I’ve never run into
one…  Until now!&lt;/p&gt;
&lt;p&gt;I was working on a very small &lt;a class="reference external" href="http://plone.org"&gt;Plone&lt;/a&gt; 3.1.1 to 4.2.2 upgrade.  Not too
many add-ons, simple skin/theme customizations, 1,810 objects in
~800MB.  No problem, right?&lt;/p&gt;
&lt;p&gt;Wrong.  I got a &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POSKeyError&lt;/span&gt;&lt;/code&gt; after the upgrade step that converts
files and images to &lt;a class="reference external" href="http://svn.zope.org/ZODB/trunk/src/ZODB/blob.py?view=markup"&gt;BLOBs&lt;/a&gt;.  The wierd part is that it only happened
during the &lt;a class="reference external" href="http://www.zodb.org/zodbbook/transactions.html"&gt;transaction.commit()&lt;/a&gt;, not during &lt;a class="reference external" href="http://zodb.org"&gt;ZODB&lt;/a&gt; object access:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/Zope2-2.13.18-py2.7.egg/Zope2/App/startup.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;
    &lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/transaction-1.1.1-py2.7.egg/transaction/_manager.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/transaction-1.1.1-py2.7.egg/transaction/_transaction.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;329&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_commitResources&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/transaction-1.1.1-py2.7.egg/transaction/_transaction.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_commitResources&lt;/span&gt;
    &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/ZODB3-3.10.5-py2.7-linux-x86_64.egg/ZODB/Connection.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;572&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt;
    &lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/ZODB3-3.10.5-py2.7-linux-x86_64.egg/ZODB/BaseStorage.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;416&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;checkCurrentSerialInTransaction&lt;/span&gt;
    &lt;span class="n"&gt;committed_tid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getTid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/ZODB3-3.10.5-py2.7-linux-x86_64.egg/ZODB/FileStorage/FileStorage.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;770&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;getTid&lt;/span&gt;
    &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lookup_pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/opt/src/eggs/ZODB3-3.10.5-py2.7-linux-x86_64.egg/ZODB/FileStorage/FileStorage.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_lookup_pos&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;POSKeyError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;POSKeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0x055350&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I tried all the tools in &lt;a class="reference external" href="http://svn.zope.org/ZODB/trunk/src/ZODB/scripts/README.txt?view=markup"&gt;ZODB.scripts&lt;/a&gt; and &lt;cite&gt;zc.zodbdgc&lt;/cite&gt; but they
couldn’t tell me anything about the &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oid&lt;/span&gt;&lt;/code&gt; in question.  That’s
probably because it was a different &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oid&lt;/span&gt;&lt;/code&gt; every time I attempted the
upgrade step &lt;em&gt;on the same ZODB&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Without being able to use the typical tools to find out what ZODB
objects were referring to those &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oids&lt;/span&gt;&lt;/code&gt; I was really stuck.  Then &lt;a class="reference external" href="http://glicksoftware.com/"&gt;David
Glick&lt;/a&gt; came to my rescue.  Actually, he was staying at my apartment
so I drafted him.  :-)  He suggested that I might have to create a
mapping of &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oids&lt;/span&gt;&lt;/code&gt; to stack frames at the time when objects were added
to the transaction so that I could figure out what &lt;em&gt;had been&lt;/em&gt; going on
once I knew &lt;em&gt;which&lt;/em&gt; &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oid&lt;/span&gt;&lt;/code&gt; would be the problem.  This worked very well
and much thanks to David.&lt;/p&gt;
&lt;p&gt;I added the following to the place where the objects were being added
to the transaction, &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;ZODB.Connection.Connection.readCurrent()&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;XXX&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XXX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XXX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_p_oid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_getframe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then once I had my &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;POSKeyError&lt;/span&gt;&lt;/code&gt; in &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pdb.post_mortem()&lt;/span&gt;&lt;/code&gt; I could invoke
&lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;pdb&lt;/span&gt;&lt;/code&gt; at the place where the offending &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;oid&lt;/span&gt;&lt;/code&gt; had been added:&lt;/p&gt;
&lt;div class="highlight-default notranslate"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;pdbr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;pdbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;pdbr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XXX&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Using that I was able to find out what objects were involved.  They
were all &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;portal_catalog/path&lt;/span&gt;&lt;/code&gt; index &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;Trees.IIBTree.IITreeSet&lt;/span&gt;&lt;/code&gt;
objects.  What’s odd is that the error happens even if I do a catalog
clear and rebuild first.&lt;/p&gt;
&lt;p&gt;After much more debugging and discussion, we determined that the
&lt;a class="reference external" href="http://zope3.pov.lt/trac/browser/ZODB/trunk/src/ZODB/interfaces.py#L289"&gt;ZODB.Connection.Connection.readCurrent()&lt;/a&gt; support was involved
somehow.  Also, as I deleted the images that were involved I noticed
another migration error earlier on went away for each image I
removed.  That’s the key, when the BLOB migration fails for one file
or image, it uses a savepoint to rollback &lt;em&gt;just&lt;/em&gt; that image’s
migration and proceed with the rest.  It sure seems like there’s a bug
in the ZODB where when a savepoint is rolled back the objects
registered with the transaction are cleaned up but the objects
registered for &lt;code class="docutils literal notranslate"&gt;&lt;span class="pre"&gt;readCurrent&lt;/span&gt;&lt;/code&gt; are not.  Gee, someone should write a
test case.  :-)&lt;/p&gt;
&lt;p&gt;In the meantime, it turns out the &lt;a class="reference external" href="https://github.com/plone/plone.app.blob/commit/d06895d4a026539e5eb8717e7df9832104bf350c"&gt;reason the image migrations were
failing&lt;/a&gt; was something else all together but I thought I should share
this debugging technique for capturing stack information when you
can’t know which stack you need to inspect until later.  I also hope
this ZODB bug gets squashed.&lt;/p&gt;
&lt;div class="note update admonition"&gt;
&lt;p class="admonition-title"&gt;Updated on 21 November 2012&lt;/p&gt;
&lt;p&gt;Imported from Plone on Mar 15, 2021.  The date for this update is the last
modified date in Plone.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/poskeyerror-during-commit/"/>
    <summary>A terrifying tale of ZODB errors that only showed during the hardest time to debug.</summary>
    <category term="Plone" label="Plone"/>
    <category term="Python" label="Python"/>
    <category term="Zope" label="Zope"/>
    <published>2012-11-21T00:00:00+00:00</published>
  </entry>
  <entry>
    <id>https://www.rpatterson.net/blog/wsgi-apps-on-iis/</id>
    <title>WSGI apps on IIS</title>
    <updated>2012-10-30T00:00:00+00:00</updated>
    <author>
      <name>Ross Patterson</name>
    </author>
    <content type="html">&lt;section id="wsgi-apps-on-iis"&gt;

&lt;blockquote&gt;
&lt;div&gt;&lt;p&gt;iiswsgi provides a WSGI server providing a FCGI gateway to IIS and setup.py commands for distributing apps as WebPI packages&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://github.com/rpatterson/iiswsgi"&gt;iiswsgi&lt;/a&gt; module implements a FastCGI to &lt;a class="reference external" href="http://wsgi.readthedocs.org/en/latest/"&gt;WSGI&lt;/a&gt; gateway that
is compatible with &lt;a class="reference external" href="http://www.iis.net"&gt;IIS&lt;/a&gt;’s variation of the &lt;a class="reference external" href="http://www.fastcgi.com/drupal/"&gt;FastCGI protocol&lt;/a&gt;.  It also
provides &lt;a class="reference external" href="http://docs.python.org/distutils/"&gt;distutils&lt;/a&gt; commands for building, distributing and installing
&lt;a class="reference external" href="http://www.iis.net/downloads/microsoft/web-deploy"&gt;Microsoft Web Deploy&lt;/a&gt; (MSDeploy) packages through the &lt;a class="reference external" href="http://www.microsoft.com/web/downloads/platform.aspx"&gt;Web Platform
Installer&lt;/a&gt; (WebPI).&lt;/p&gt;
&lt;p&gt;The goals of the code in &lt;a class="reference external" href="https://github.com/rpatterson/iiswsgi"&gt;iiswsgi&lt;/a&gt; are to do the following for
deploying WSGI apps on IIS:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;make it open source as far as possible, right up to IIS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;be Pythonic as far as possible, right up to the MSDeploy packaging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;re-use our existing tool-chain for distributing packages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;share the maintenance burden for a WSGI on Windows story across the community&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the &lt;a class="reference external" href="http://plone.org"&gt;Plone&lt;/a&gt; project, it’s always been simultaneously a necessity
that we support a Windows deployment story and one of our biggest pain
points.  The Windows installers have always been very different from
the other installers.  They have had different layouts from our user
and developer documentation and even from each other.  They have never
been maintained or supported by more than one entity, either a company
or an individual, and as such have often and ultimately languished.
And as for the poor individuals who have tackled the Windows
installers, they have almost always burned out and can no longer
provide any significant Windows support at all.  This is not a healthy
open source community dynamic.  And yet there is wide consensus that
it’s not an option &lt;em&gt;not&lt;/em&gt; to have a Windows deployment story.&lt;/p&gt;
&lt;p&gt;My hope is that by generalizing the IIS deployment architecture as a
&lt;a class="reference external" href="https://github.com/rpatterson/iiswsgi#iiswsgi-fcgi-gateway"&gt;WSGI server&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/rpatterson/iiswsgi#build-msdeploy-package"&gt;distutils commands&lt;/a&gt;, it can be of use to the
general Python &lt;a class="reference external" href="http://wsgi.readthedocs.org/en/latest/"&gt;WSGI&lt;/a&gt; world.  I also hope that by doing things ‘The
Right Way’, it will be something that will be clearer and easy to
support and maintain.  With those two together maybe we can solve the
burnout issue by distributing the maintenance load.  I’d very much
appreciate any help to that end, particularly including feedback on
how to get there.  I don’t care where the code lives and would be
happy to see some of it merged back into the packages it derives from
or moved into larger packages.  So please let me know if you’d like to
coordinate moving things around with me.&lt;/p&gt;
&lt;section id="help-needed"&gt;
&lt;h2&gt;Help Needed&lt;/h2&gt;
&lt;p&gt;Any contributions are very welcome.  Here are a few things I’m looking
for in particular:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;addressing &lt;a class="reference external" href="https://github.com/rpatterson/iiswsgi#known-issues"&gt;Known Issues&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IIS app name and Python dist name conventions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fostering community ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;writing tests&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m particularly apologetic for the last one, I’m ashamed by the lack
of tests.  In my defense, this whole problem was such a fog for me
when I started that I just needed to start writing things and poking
around.  Believe me this is not my usual MO, I almost always do TDD
and beg your forgiveness.  :-)&lt;/p&gt;
&lt;p&gt;I look forward to getting this going!&lt;/p&gt;
&lt;div class="note update admonition"&gt;
&lt;p class="admonition-title"&gt;Updated on 30 October 2012&lt;/p&gt;
&lt;p&gt;Imported from Plone on Mar 15, 2021.  The date for this update is the last
modified date in Plone.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;/section&gt;
</content>
    <link href="https://www.rpatterson.net/blog/wsgi-apps-on-iis/"/>
    <summary>iiswsgi provides a WSGI server providing a FCGI gateway to IIS and setup.py commands for distributing apps as WebPI packages</summary>
    <category term="Plone" label="Plone"/>
    <category term="Python" label="Python"/>
    <category term="Zope" label="Zope"/>
    <category term="fastcgi" label="fastcgi"/>
    <category term="fcgi" label="fcgi"/>
    <category term="iis" label="iis"/>
    <category term="msdeploy" label="msdeploy"/>
    <category term="webpi" label="webpi"/>
    <category term="wsgi" label="wsgi"/>
    <published>2012-10-30T00:00:00+00:00</published>
  </entry>
</feed>
