<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-17109643</id><updated>2009-03-09T08:30:24.507-04:00</updated><title type='text'>Benji York</title><subtitle type='html'></subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://benjiyork.com/blog/atom.xml'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-17109643.post-7273192512816114468</id><published>2009-03-09T06:19:00.010-04:00</published><updated>2009-03-09T08:30:21.682-04:00</updated><title type='text'>Doctest goes double-digits</title><content type='html'>Several months ago I happened upon the original &lt;a href="http://groups.google.com/group/comp.lang.python/browse_thread/thread/0dfcc7e4daedd391/1c57cfb7b3772763&amp;amp;cd=US&amp;amp;hl=en"&gt;posting&lt;/a&gt; by Tim Peters announcing doctest.  Realizing that it would soon be the 10th anniversary of its creation, I did the only thing a doctest fan could do, I put the auspicious date on my calendar.&lt;br /&gt;&lt;br /&gt;Friday was the big day.  While musing as to the best way to mark the occasion (an ode to doctest? perhaps test-driven cake?), I was surprised to see Tim walk into the office.  Surely he had come by celebrate in person!&lt;br /&gt;&lt;br /&gt;Not quite.  He just dropped in to see how everyone at &lt;a href="http://zope.com/"&gt;ZC&lt;/a&gt; has been getting along without him for the last couple of years.  He also did a good job reminding us of how funny he is.  Oh well, there's always 2019.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/7273192512816114468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=7273192512816114468' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/7273192512816114468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/7273192512816114468'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2009/03/doctest-goes-double-digits.html' title='Doctest goes double-digits'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-3610032705853919678</id><published>2008-03-09T22:37:00.001-04:00</published><updated>2008-03-10T22:34:05.482-04:00</updated><title type='text'>ICP for Faster Web Apps</title><content type='html'>&lt;p&gt;ICP (Internet Cache Protocol, &lt;a href="http://www.ietf.org/rfc/rfc2186.txt"&gt;RFC 2186&lt;/a&gt;) is a simple protocol intended to let one cache server ask it's peers whether or not they have a non-stale copy of a particular object ("object" is cache-speak for the thing on the other end of a URL), but it can also be used to make the most of your web apps.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The RFC is pretty easy reading as such things go, but I'll summarize here: if a cache server doesn't have a local copy of the requested object it can be configured to send out a request (usually over UDP) to all of it's siblings.  The request includes little more than the requested URL.  All the sibling caches send back HIT, MISS, or MISS_NOFETCH (more or less, read the RFC for the details). Here are the definitions of those from the RFC:&lt;br /&gt;&lt;/p&gt;&lt;dl&gt;&lt;dt&gt;ICP_OP_HIT&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;An ICP_OP_HIT response indicates that the requested URL exists in this cache and that the requester is allowed to retrieve it.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;ICP_OP_MISS&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;An ICP_OP_MISS response indicates that the requested URL does not exist in this cache. The querying cache may still choose to fetch the URL from the replying cache.&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;ICP_OP_MISS_NOFETCH&lt;/dt&gt;&lt;br /&gt;&lt;dd&gt;An ICP_OP_MISS_NOFETCH response indicates that this cache is up, but is in a state where it does not want to handle cache misses.&lt;/dd&gt;&lt;/dl&gt;The first server to come back with a HIT will be sent the request, if all servers reply with a MISS, the first server to respond with a MISS will get the request.  Servers that send back a MISS_NOFETCH will not be sent this request.  The response to any particular request has no bearing on any future request; for example, a server can reply with a MISS_NOFETCH for a URL one moment and a HIT for the same URL a split second later.&lt;br /&gt;&lt;br /&gt;This is all very nice for cache servers, but how does this help speed up my dynamic web app?  Well, forward proxies can also use ICP to query "origin servers" (non-cache web servers).  Why is that interesting?  Lets say you have multiple origin servers, being good app servers they each have local caches (for data they request from databases, computed page fragments, etc.). If requests are randomly sent to the various origin servers, the app server cache hit rate will be pretty abysmal.  The negative affects are intensified if there are many back-end servers and if the working data set is much larger than what will fit in the caches, meaning you get a high rate of cache churn; otherwise useful data being evicted because there's not enough room to keep it.&lt;br /&gt;&lt;br /&gt;It's likely that the total cache size is larger than the working set, but since the requests are randomly distributed, poor use is made of the caches.  It would be nice if a request that needed a particular subset of the data went to a server that was likely to have the needed data already cached.  In other words, you want some flavor of "request affinity".&lt;br /&gt;&lt;br /&gt;How you decide to affinitize requests depends on how your data is structured.  For the systems I'm working on, we're serving hundreds of web sites out of a single large database, so site affinity makes the most sense.  This means that all requests for a particular site should tend to go to the same server or set of servers (if there is more load than a single origin server can handle).&lt;br /&gt;&lt;br /&gt;The sequence of events goes something like this: a request comes in, an ICP request is sent to all the origin servers and the results are used to direct the request.  If a server has handled a request for that site before, it sends back a HIT, if not, then a MISS.&lt;br /&gt;&lt;br /&gt;If a server would otherwise send a HIT but is too busy at the moment, it'll send a MISS instead, hoping that another server HITs.  If none do, then the fastest MISS will get the request, which may mean that a new server gains an affinity for that site.&lt;br /&gt;&lt;br /&gt;When used like this ICP can provide dynamic load balancing and data set partitioning in a simple, scalable fashion.   If you want to play with ICP you'll need a forward proxy that supports ICP, like &lt;a href="http://www.squid-cache.org/"&gt;Squid&lt;/a&gt; and an ICP server like my Python implementation: &lt;a href="http://pypi.python.org/pypi/zc.icp"&gt;zc.icp&lt;/a&gt; (developed at Zope Corporation, but not Zope-specific).</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/3610032705853919678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=3610032705853919678' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/3610032705853919678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/3610032705853919678'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2008/03/icp-for-faster-web-apps.html' title='ICP for Faster Web Apps'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-6553134087862337442</id><published>2008-02-23T10:25:00.000-05:00</published><updated>2008-02-23T10:38:37.720-05:00</updated><title type='text'>Programmable Python Syntax via Source Encodings</title><content type='html'>Because of my recent forays into Common Lisp and Haskell this recent &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/546539"&gt;recipe&lt;/a&gt; on ASPN piqued my interest.  It demonstrates using Python source file encodings as a hook for introducing alternate Python syntax.   Here's the simplest example of the technique I could come up with:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;codec.py&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;import codecs&lt;br /&gt;&lt;br /&gt;class StreamReader(codecs.StreamReader):&lt;br /&gt;   def decode(self, input, errors='strict'):&lt;br /&gt;       output = input.replace('until ', 'while not ')&lt;br /&gt;       output = output.replace('++', '+= 1')&lt;br /&gt;       return unicode(output), len(input)&lt;br /&gt;&lt;br /&gt;def get_my_codec(name):&lt;br /&gt;   if name == 'play-language':&lt;br /&gt;       return (codecs.utf_8_encode, None, StreamReader, None)&lt;br /&gt;&lt;br /&gt;codecs.register(get_my_codec)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;The above creates a codec called "play-language" and defines a very, very simple-minded source code transformation.  For actual use, you'd need to work harder at parsing the code.&lt;br /&gt;&lt;br /&gt;Now, if you create a file named play1.py with these contents:&lt;br /&gt;&lt;pre&gt;# coding=play-language&lt;br /&gt;&lt;br /&gt;c = 0&lt;br /&gt;until c == 10:&lt;br /&gt;   print c&lt;br /&gt;   c++&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;And execute this from a command line:&lt;br /&gt;&lt;pre&gt;python -c 'import codec1;import play1'&lt;/pre&gt;&lt;br /&gt;You'll get this output:&lt;br /&gt;&lt;pre&gt;0&lt;br /&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/6553134087862337442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=6553134087862337442' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/6553134087862337442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/6553134087862337442'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2008/02/programmable-python-syntax-via-source.html' title='Programmable Python Syntax via Source Encodings'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-117672733745129493</id><published>2007-04-16T08:05:00.000-04:00</published><updated>2007-04-17T13:00:38.066-04:00</updated><title type='text'>Sleep considered harmful</title><content type='html'>Even though I'm not a big fan of biological sleep, in this post I'm talking about the "sleep" function available in Python.  While we've all been &lt;a href="http://python.org/doc/current/lib/module-time.html"&gt;warned&lt;/a&gt; that sleep may take longer to return than requested, most people don't realize just how course-grained sleep is on their operating system.&lt;br /&gt;&lt;br /&gt;Here's a quiz: What is the minimum sleep interval on your operating system (other than 0)?&lt;br /&gt;&lt;br /&gt; a) more than 10ms&lt;br /&gt; b) 10ms&lt;br /&gt; c) 4ms&lt;br /&gt; d) 1ms&lt;br /&gt; e) 0.1ms&lt;br /&gt; f) less than 0.1ms&lt;br /&gt;&lt;br /&gt;The answer: it depends. :)&lt;br /&gt;&lt;br /&gt;On most flavors of Windows the answer is probably "a" (see below of a script to measure this for yourself).  On operating systems with the Linux kernel the answer is one of 10, 4, or 1ms.&lt;br /&gt;&lt;br /&gt;Why the variability on Linux?  Linux uses a programmable timer to tick at a certain frequency, and then performs periodic tasks on each tick.  The more ticks the more often it can task switch between processes (among other things), but there's also overhead with handling the interrupt, so higher tick rates reduce throughput.&lt;br /&gt;&lt;br /&gt;Some distributions think a "server" kernel should have a tick frequency of 100Hz to allow for more to be done between interrupts, others think the clock should tick at 1000Hz to allow for more rapidly switching between tasks.  Then there's the middle ground of 250Hz that some distributions use for desktop machines (giving 4ms sleep granularity).  This isn't a simple issue, &lt;a href="http://kerneltrap.org/node/5411"&gt;much discussion&lt;/a&gt; has taken place over the default setting and what the consequences are.&lt;br /&gt;&lt;br /&gt;This is all very interesting, but what does it have to do with sleep?  Python (indirectly) implements sleep based on the OS tick frequency.  So if your OS has a frequency of 100Hz and you ask for a 15ms sleep, on the first tick you still have 5ms left on your sleep so you won't get woken up until the next tick.  You asked for 15ms and got 20.  What do you think would have happened if you'd asked for 1 or even 0.01ms instead?  That's right, you'd have gotten 10ms.&lt;br /&gt;&lt;br /&gt;Now, if you're waiting for a reply from a socket and the average round-trip time is around 1ms and you sleep for 1ms after sending the request, you just made your network app 10 times slower than it needs to be.  This is where everyone says "use select instead"; and they'd be right.  "select" represents the event-based approach that is generally superior to a poll-based approach involving sleep (&lt;a href="http://www.monkey.org/~provos/libevent/"&gt;libevent&lt;/a&gt; for example).&lt;br /&gt;&lt;br /&gt;What if you really do need to sleep for less time than the sleep will allow?  On unix-like operating systems there's a function (normally) available that will do what you want: "&lt;a href="http://www.opengroup.org/onlinepubs/007908799/xsh/nanosleep.html"&gt;nanosleep&lt;/a&gt;".  Using nanosleep you can request (and get) much smaller sleep times.  Windows also has APIs to do finer-grained sleeping.  Either should be accesible through ctypes (included in Python 2.5).&lt;br /&gt;&lt;br /&gt;Curious what your minimum sleep time is?  Here's a little Python script that will tell you:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import time&lt;br /&gt;&lt;br /&gt;LOOPS = 100&lt;br /&gt;&lt;br /&gt;def do_sleep(min_sleep):&lt;br /&gt;    total = 0.0&lt;br /&gt;    for i in range(LOOPS):&lt;br /&gt;        c = time.time()&lt;br /&gt;        time.sleep(min_sleep)&lt;br /&gt;        x = time.time()&lt;br /&gt;        total = total + x - c&lt;br /&gt;    return total / LOOPS&lt;br /&gt;&lt;br /&gt;min_sleep = 0.000001&lt;br /&gt;result = None&lt;br /&gt;while True:&lt;br /&gt;    result = do_sleep(min_sleep)&lt;br /&gt;    if result &gt; 2 * min_sleep:&lt;br /&gt;        break&lt;br /&gt;    min_sleep *= 2&lt;br /&gt;&lt;br /&gt;print result&lt;br /&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/117672733745129493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=117672733745129493' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117672733745129493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117672733745129493'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2007/04/sleep-considered-harmful.html' title='Sleep considered harmful'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-117211112720769096</id><published>2007-02-21T21:05:00.000-05:00</published><updated>2007-02-21T21:25:27.230-05:00</updated><title type='text'>Reverse Interviewing at PyCon</title><content type='html'>Other than participating in the &lt;a href="http://us.pycon.org/TX2007/TestingToolsPanel"&gt;Testing Tools Panel&lt;/a&gt; at PyCon I have a secret recruiting mission.  But, instead of trying to get a bunch of resumes I'm going to try to get as many smart people as possible to &lt;i&gt;interview me&lt;/i&gt; about whether or not they would like to work at Zope Corp.&lt;br /&gt;&lt;br /&gt;So, if you're going to PyCon and you're a talented programmer, find me (Benji York) or Jim Fulton and tell us you're interested and a bit about yourself and we'll answer your questions about the positions and the company.  Zope 3 knowledge isn't required (although it's a plus).&lt;br /&gt;&lt;br /&gt;If you don't get to talk with us (or aren't going to PyCon this year) and are interested, there's always the &lt;a href="http://www.zope.com/zopecom/about_us/careers.html"&gt;Zope Corp careers page&lt;/a&gt; and the ever popular &lt;a href="mailto:careers@zope.com"&gt;careers@zope.com&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/117211112720769096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=117211112720769096' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117211112720769096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117211112720769096'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2007/02/reverse-interviewing-at-pycon.html' title='Reverse Interviewing at PyCon'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-117181731202798092</id><published>2007-02-18T11:28:00.000-05:00</published><updated>2007-02-18T11:48:32.040-05:00</updated><title type='text'>Testing Tools Panel at PyCon plus some Sahi</title><content type='html'>For those attending PyCon this year and interested in testing, there's the &lt;a href="http://us.pycon.org/TX2007/TestingToolsPanel"&gt;Testing Tools Panel&lt;/a&gt;.  The panel is being moderated by &lt;a href="http://agiletesting.blogspot.com/"&gt;Grig Gheorghiu&lt;/a&gt;, who's done a great job of getting a nice mixture of people with different takes on testing and was nice enough to invite me to participate.  The &lt;a href="http://us.pycon.org/TX2007/TestingToolsPanel"&gt;panel info page&lt;/a&gt; also has an invitation for people to add their own questions, so feel free to contribute.&lt;br /&gt;&lt;br /&gt;While on the subject of testing, a coworker of mine introduced me to &lt;a href="http://sahi.co.in/"&gt;Sahi&lt;/a&gt; recently.  Sahi is a Selenium-like system for in-browser testing.  It seems to have at least one advantage over Selenium: the tests are written in (a slightly preprocessed) JavaScript, but isn't quite as well-known yet.  The site has a &lt;a href="http://sahi.co.in/static/sahi_tutorial.html"&gt;screencast&lt;/a&gt; which is a pretty good into to the system.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/117181731202798092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=117181731202798092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117181731202798092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/117181731202798092'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2007/02/testing-tools-panel-at-pycon-plus-some.html' title='Testing Tools Panel at PyCon plus some Sahi'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-114331363490140884</id><published>2006-03-25T13:45:00.000-05:00</published><updated>2006-03-25T14:07:14.953-05:00</updated><title type='text'>Zope 3 Quick Start updated for Zope 3.2</title><content type='html'>I've (finally) uploaded a version of the Zope 3 quick start guide that's been updated to match Zope 3.2.  This version includes pointers on installing from a release (as well as a checkout as before).  I've also fleshed out and reworked some of the text a bit.  As is customary, there are both the (source) &lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;ReST version&lt;/a&gt; and a (generated) &lt;a href="http://www.benjiyork.com/quick_start/"&gt;HTML version&lt;/a&gt; available.&lt;br /&gt;&lt;br /&gt;I'd like to write a follow-on to the quick start, but need to decide on one of two directions, so feedback would be nice.  Would people more like a "show me how to do simple stuff" recipe-like collection, or more of a "how to do sophisticated stuff with Zope 3" document?&lt;br /&gt;&lt;br /&gt;If the former, it would be a good exercise to see what is helpful and what needs to be tweaked in Zope 3 to make it easy for the "middle class" developers that aren't building highly complex apps.&lt;br /&gt;&lt;br /&gt;If the latter, it'll be more of a theoretical discussion of interfaces, adapters, views, schemas, utilities, etc. and how all of those things fit together.  It'd also probably talk about using (most) of those things outside of Zope 3, as several people are already.&lt;br /&gt;&lt;br /&gt;So, what do you want?  Maybe a bit of both?</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/114331363490140884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=114331363490140884' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/114331363490140884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/114331363490140884'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2006/03/zope-3-quick-start-updated-for-zope-32.html' title='Zope 3 Quick Start updated for Zope 3.2'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-113181863012930141</id><published>2005-11-12T16:03:00.000-05:00</published><updated>2005-11-16T13:51:49.356-05:00</updated><title type='text'>First Release of ZopeTestbrowser</title><content type='html'>I've put together the first stand-alone release of the &lt;a href="http://cheeseshop.python.org/pypi?:action=display&amp;name=zope.testbrowser"&gt;zope.testbrowser package&lt;/a&gt;.  It is used in Zope 3 for doing functional testing of web applications, but can also be used against any web site.  It uses John J. Lee's mechanize as the back-end but provides a redesigned API that is more suited to testing, and perhaps other uses as well.  For example usage look at the &lt;a href="http://svn.zope.org/*checkout*/Zope3/trunk/src/zope/testbrowser/README.txt?rev=40065"&gt;README&lt;/a&gt;.  I'll release a 1.0 version when Zope 3.2 ships (should be some time in December).</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/113181863012930141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=113181863012930141' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/113181863012930141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/113181863012930141'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/11/first-release-of-zopetestbrowser.html' title='First Release of ZopeTestbrowser'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-113011300245590123</id><published>2005-10-23T23:18:00.000-04:00</published><updated>2005-10-23T20:16:42.476-04:00</updated><title type='text'>New Zope 3 Quick Start Ready</title><content type='html'>Now that I've built a test framework for the quick start and fixed several bugs it and readers have found, it's time for an update.  Both the &lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;ReST source&lt;/a&gt; and a &lt;a href="http://www.benjiyork.com/quick_start/"&gt;generated HTML version&lt;/a&gt; are available.  I hope to retarget the quick start to be about building a simple blog in the near future.  At that point I'll start thinking of doing a movie version.  Hopefully it won't be as long and excruciating as the &lt;a href="http://rifers.org/rife_indepth_simple_blog/"&gt;Java version&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/113011300245590123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=113011300245590123' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/113011300245590123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/113011300245590123'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/10/new-zope-3-quick-start-ready.html' title='New Zope 3 Quick Start Ready'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-112878834519990734</id><published>2005-10-08T15:21:00.000-04:00</published><updated>2005-10-09T20:10:22.150-04:00</updated><title type='text'>Revised Quick Start</title><content type='html'>I've had a good response to the Zope 3 Quick Start Guide.  Baiju M. fixed my ReST errors so I can now generate an &lt;a href="http://www.benjiyork.com/quick_start/"&gt;HTML version&lt;/a&gt; (the &lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;text source&lt;/a&gt; is also available). Marius Gedminas pointed out several spelling errors and had several other good fixes/suggestions. I've had offers to do Spanish and Brazilian Portuguese translations, so watch this space for links to those when they're finished. I also want to thank all the other people that wrote with fixes and suggestions.&lt;br /&gt;&lt;br /&gt;Other additions include a version numer, and a Creative Commons license block.</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/112878834519990734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=112878834519990734' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112878834519990734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112878834519990734'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/10/revised-quick-start.html' title='Revised Quick Start'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-112838934858989022</id><published>2005-10-04T00:26:00.000-04:00</published><updated>2005-10-03T21:29:08.603-04:00</updated><title type='text'>First Draft of Zope 3 Quick Start</title><content type='html'>I've finished the first cut of my &lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;Zope 3 Quick Start Guide&lt;/a&gt;.  It attempts to be a "gentle" introduction.  I hope it will give people an idea of what developing with Zope 3 is all about, and get them ready to learn Zope 3 in earnest (perhaps via one of these &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/3540223592"&gt;two&lt;/a&gt; &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0672326175"&gt;books&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Feedback welcome.&lt;br /&gt;&lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/112838934858989022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=112838934858989022' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112838934858989022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112838934858989022'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/10/first-draft-of-zope-3-quick-start.html' title='First Draft of Zope 3 Quick Start'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-112796750578916146</id><published>2005-09-29T10:20:00.000-04:00</published><updated>2005-09-29T07:25:36.070-04:00</updated><title type='text'>Zope 3 Marketing</title><content type='html'>&lt;p class="MsoNormal"&gt;My last post generated some interesting comments (both here and email) about why people think Zope 3 hasn't generated the buzz some other web framworks have. The responses broke down into two basic categories:&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;   &lt;ol start="1" type="1"&gt; &lt;li class="MsoNormal" style=""&gt;Zope 2's legacy affects Zope      3&lt;o:p&gt;&lt;/o:p&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;It's too hard to get started      with Zope 3&lt;o:p&gt;&lt;/o:p&gt;&lt;/li&gt;  &lt;/ol&gt;I'll agree with both of these. First, Zope 3 is a very different thing than Zope 2; some people either don't like Zope 2 and assume Zope 3 is similar, or love Zope 2, and don't like that Zope 3 is different. I think both of these points of view are a result of the fact/perception that Zope 3 is hard to get started with. The very cool &lt;a href="http://codespeak.net/z3/five/"&gt;Five&lt;/a&gt; project has helped somewhat in building a bridge so heavy users of Zope 2 can migrate to Zope 3, but we still need to help people coming from another (or no) framework get started.&lt;br /&gt;&lt;br /&gt;I'm going to see if I can write up a "quick start" to show people how to get started. Here's a minimal first cut: &lt;a href="http://www.benjiyork.com/quick_start.txt"&gt;quick_start.txt&lt;/a&gt;. I'm very interested in feedback.&lt;br /&gt;  &lt;span style=""&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/112796750578916146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=112796750578916146' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112796750578916146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112796750578916146'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/09/zope-3-marketing.html' title='Zope 3 Marketing'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-17109643.post-112769250845271755</id><published>2005-09-25T19:31:00.000-04:00</published><updated>2005-09-25T20:06:06.463-04:00</updated><title type='text'>Web Framework Popularity Contest</title><content type='html'>While reading about all the emerging &lt;a href="http://www.djangoproject.com/"&gt;web&lt;/a&gt; &lt;a href="http://turbogears.org/"&gt;application&lt;/a&gt; &lt;a href="http://subway.python-hosting.com/"&gt;frameworks&lt;/a&gt; for Python I keep getting the feeling that they're converging on (and meanwhile reinventing) Zope 3. Not to say that each doesn't have its strong points and original innovations, it's just that the &lt;span style="font-style: italic;"&gt;vast&lt;/span&gt; majority of the groundwork has already been done, why keep doing it again?&lt;br /&gt;&lt;br /&gt;It seems that I'm not the only one with similar feelings:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;One final thought for today about the new wave of Python web frameworks: I really can't understand why Zope 3 seems to be entirely ignored in this respect. Zope 3 is a framework that was carefully developed taking into account the many lessons learned from Zope, which is without a doubt the most successful Python web framework to date. Zope 2 managed to get a reputation as an unpythonic framework, so maybe Zope 3, even with its painstakingly designed component architecture, is paying for it. Or perhaps there's a lack of influential bloggers touting it as the next big thing (&lt;a href="http://www.rubyonrails.com/"&gt;Rails&lt;/a&gt; anyone?) or the project's web page is so terrible that few people think it's worth checking out. Whatever the reason, I think Zope 3 should be taken into account when exploring web frameworks of the future, so I intend to look into this matter more thoroughly. -- &lt;a href="http://cguardia.blogspot.com/2005/09/frameworks-magaframeworks-and.html"&gt;Carlos de la Guardia&lt;/a&gt; &lt;/blockquote&gt;&lt;br /&gt;So, can anyone tell me why they don't like/don't know about/are afraid of Zope 3?</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/112769250845271755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=17109643&amp;postID=112769250845271755' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112769250845271755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/17109643/posts/default/112769250845271755'/><link rel='alternate' type='text/html' href='http://benjiyork.com/blog/2005/09/web-framework-popularity-contest.html' title='Web Framework Popularity Contest'/><author><name>Benji York</name><uri>http://www.blogger.com/profile/09142508749858616522</uri><email>noreply@blogger.com</email></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry></feed>