<?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://nathanvangheem.com/news/aggregator/RSS">
  <title>Posts</title>
  <link>http://nathanvangheem.com</link>

  <description>
    
      Site News
    
  </description>

  

  
            <syn:updatePeriod>daily</syn:updatePeriod>
            <syn:updateFrequency>1</syn:updateFrequency>
            <syn:updateBase>2008-05-11T20:50:31Z</syn:updateBase>
        

  <image rdf:resource="http://nathanvangheem.com/logo.png"/>

  <items>
    <rdf:Seq>
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/nginx-with-built-in-load-balancing-and-caching"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/running-plone-4b4-with-zope-2.13.0a1"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/pysourcesearch"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/running-plone-4-with-a-zope2-wsgi"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/plone-4-upgrade"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/repoze.zope2-with-deliverance-locking-up"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/add-eject-button-to-boxee"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/buildout-to-compile-install-apache-mysql-and-php"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/installing-pil-on-mac-os-x-leopard-virtualenv-with-easy_install"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/moving-to-picasa-update"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/moving-from-flickr-to-picasa-web-albums"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/site-update"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/upgrades-to-collective.plonetruegallery"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/creating-and-subscribing-to-events-in-zope"/>
      
      
        <rdf:li rdf:resource="http://nathanvangheem.com/news/using-a-browserview-as-a-traversable-adapter-utility-in-plone"/>
      
    </rdf:Seq>
  </items>

</channel>


  <item rdf:about="http://nathanvangheem.com/news/nginx-with-built-in-load-balancing-and-caching">
    <title>nginx with built in load balancing and caching</title>
    <link>http://nathanvangheem.com/news/nginx-with-built-in-load-balancing-and-caching</link>
    <description>nginx can do it all. Short example to get nginx going with buildout to provide load balancing and caching.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2>Introduction</h2>
<p>Why muck around with HAProxy and Varnish when you can have nginx do it all for you. The setup is easy and it's a lot easier to maintain.</p>
<h2>Installing nginx with buildout</h2>
<p>You can setup nginx fairly easily with buildout. The only fancy part of our setup is that we're going to include the nginx cache purge module.</p>
<ol>
<li>Add the cache purge part to your buildout <br />
<pre>[ngx_cache_purge]
recipe = hexagonit.recipe.download
url = http://labs.frickle.com/files/ngx_cache_purge-1.1.tar.gz
strip-top-level-dir = true</pre>
</li>
<li>I needed the pcre source to compile also<br />
<pre>[pcre-source]
recipe = hexagonit.recipe.download
url = ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.00.tar.gz
strip-top-level-dir = true
</pre>
</li>
<li>and the nginx part<br />
<pre>[nginx-build]
recipe = hexagonit.recipe.cmmi
url = http://nginx.org/download/nginx-0.8.45.tar.gz
configure-options =
    --with-http_stub_status_module
    --conf-path=${buildout:directory}/settings/nginx.conf
    --error-log-path=${buildout:directory}/var/log/nginx-error.log
    --pid-path=${buildout:directory}/var/nginx.pid
    --lock-path=${buildout:directory}/var/nginx.lock
    --with-pcre=${pcre-source:location}
    --with-http_ssl_module
    --add-module=${ngx_cache_purge:location}
</pre>
</li>
<li>and finally, add it all to the parts directive<br />
<pre>parts =
    ...
    pcre-source
    ngx_cache_purge
    nginx-build
    ...

</pre>
</li>
<li>After you re-run buildout, you'll be able to run nginx by issuing a command like this:<br />
<pre>./parts/nginx/sbin/nginx -c /path/to/configuration/nginx.conf</pre>
</li>
</ol>
<h2>nginx configuration</h2>
<p>Here is a simple sample configuration for nginx configured with load balancing and caching. It can obvious get as complicated as you want it, but I definitely think this is easier than managing haproxy, varnish and nginx.</p>
<pre>pid /path/to/buildout/var/nginx.pid;
lock_file /path/to/buildout/var/nginx.lock;

worker_processes 2;
daemon off;

events {
    worker_connections 1024;
}

error_log /path/to/buildout/var/log/nginx-error.log warn;

# HTTP server

http {
    server_names_hash_bucket_size 64;

    # this is how you do simple round robin load balancing with nginx.
	# you can define as many backup servers as you'd like here.
    upstream plone {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }
    
    access_log /path/to/buildout/var/log/main-access.log;


 	# can specify multiple cache paths for different resources/paths/proxies
    # if needed..
    # the levels=1:2 just means it'll store the cache'd files 2 levels down in
    # the folder structure
    proxy_cache_path  /var/www/cache  levels=1:2 keys_zone=thecache:100m max_size=1000m inactive=600m;
    proxy_temp_path /var/www/cache/tmp;

    # Here is the caching purge handling. Purge request come in here
    server {
        listen 8089;
        server_name www.example.com;

        access_log /path/to/buildout/var/log/purge.log;

        location / {
      	  allow			127.0.0.1;
      	  deny			all;
      	  proxy_cache_purge thecache $scheme$proxy_host$request_uri;
        }
    }
    
    server {
        listen 80;
        server_name www.example.com;


		# log for cache hits.
		log_format cache '***$time_local '
		                             '$upstream_cache_status '
		                             'Cache-Control: $upstream_http_cache_control '
		                             'Expires: $upstream_http_expires '
		                             '"$request" ($status) '
		                             '"$http_user_agent" ';

		access_log /path/to/buildout/var/log/cache.log cache;

        # Enable gzip compression
        gzip             on;
        gzip_min_length  1000;
        gzip_proxied     any;
        gzip_types       text/xml text/plain application/xml;

        # Show status information on /_main-status
        location = /_main_status_ {
            stub_status on;
            allow 127.0.0.1;
            deny all;
        }

		# do not cache when users are logged in..
        proxy_cache_bypass $cookie___ac;

	    location / {
	        proxy_redirect                  off;
			proxy_set_header                Host $host;
			proxy_set_header                X-Real-IP $remote_addr;
			proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
			client_max_body_size            0;
			client_body_buffer_size         128k;
			proxy_send_timeout              120;
			proxy_buffer_size               4k;
			proxy_buffers                   4 32k;
			proxy_busy_buffers_size         64k;
			proxy_temp_file_write_size      64k;
			proxy_connect_timeout           75;
			proxy_read_timeout              205;   
	        http://plone/VirtualHostBase/http/www.example.com:80/Plone	/VirtualHostRoot/;

	        proxy_cache_bypass $cookie___ac;
	        proxy_cache thecache;
	        proxy_cache_key $scheme$proxy_host$request_uri;
	    }
    }
}
</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2010-07-31T04:11:15Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/running-plone-4b4-with-zope-2.13.0a1">
    <title>Running Plone 4b4 with Zope 2.13.0a1</title>
    <link>http://nathanvangheem.com/news/running-plone-4b4-with-zope-2.13.0a1</link>
    <description>Just some guidelines on getting Plone 4b4 to work with the new Zope 2.13 release to save you some time.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p> </p>
<div style="padding-left: 0px; ">
<h2 style="padding-left: 0px; ">Introductions</h2>
<p style="padding-left: 0px; ">I'm not going to go into detail of the wheres and hows everything is done. This post expects you to know a bit about plone, zope and buildout. Maybe I'll be more detailed later. Use this if you want to save yourself a lot of time in getting a working setup with Plone 4 and Zope 2.13. Zope 2.13 adds native WSGI support in Zope. I tested it a bit and seems to work well but results may vary and I'm sure there will be a more supported way to do this soon.</p>
<h2 style="padding-left: 0px; ">Extends</h2>
<p style="padding-left: 0px; ">Make sure your buildout extends the http://download.zope.org/Zope2/index/2.13.0a1/versions.cfg versions file.</p>
<h2 style="padding-left: 0px; ">Checkouts</h2>
<p style="padding-left: 0px; ">You'll need to checkout Products.CMFCore, Products.PluggableAuthService, Products.TinyMCE and plone.locking from svn. You can use these locations right now until there is a new release,</p>
<pre style="padding-left: 1em; "><p style="padding-left: 0px; ">http://svn.zope.org/repos/main/Products.CMFCore/branches/2.2/ Products.CMFCore</p><p style="padding-left: 0px; ">http://svn.zope.org/repos/main/Products.PluggableAuthService/trunk Products.PluggableAuthService</p><p style="padding-left: 0px; ">http://svn.plone.org/svn/collective/Products.TinyMCE/trunk/ Products.TinyMCE</p><p style="padding-left: 0px; ">http://svn.plone.org/svn/plone/plone.locking/trunk/ plone.locking</p></pre>
<p style="padding-left: 0px; ">You'll also need to add these packages to your develop buildout section.</p>
<h2 style="padding-left: 0px; ">Extra Versions Pins</h2>
<p style="padding-left: 0px; ">You'll need to pin these versions since Zope 2.13 doesn't pin version that plone's setup used to assume were pinned,</p>
<p style="padding-left: 0px; ">Add these extra version pins</p>
<pre id="_mcePaste" style="padding-left: 1em; "><div id="_mcePaste" style="padding-left: 0px; ">Products.CMFCore =
Products.PluggableAuthService = 
Products.TinyMCE = 
plone.locking = 

five.formlib = 1.0.2
zope.formlib = 3.7.0
zope.app.apidoc = 3.6.2
zope.app.applicationcontrol = 3.5.0
zope.app.appsetup = 3.11
zope.app.authentication = 3.6.0
zope.app.basicskin = 3.4.1
zope.app.broken = 3.5.0
zope.app.cache = 3.6.0
zope.app.catalog = 3.8.0
zope.app.component = 3.8.3
zope.app.container = 3.8.0
zope.app.content = 3.4.0
zope.app.dav = 3.5.1
zope.app.debug = 3.4.1
zope.app.dependable = 3.4.0
zope.app.dtmlpage = 3.5.0
zope.app.error = 3.5.2
zope.app.exception = 3.5.0
zope.app.file = 3.5.0
zope.app.folder = 3.5.1
zope.app.form = 3.8.1
zope.app.generations = 3.5.0
zope.app.http = 3.6.0
zope.app.i18n = 3.6.1
zope.app.interface = 3.5.0
zope.app.intid = 3.7.0
zope.app.locales = 3.6.1
zope.app.localpermission = 3.7.2
zope.app.pagetemplate = 3.7.1
zope.app.principalannotation = 3.7.0
zope.app.publication = 3.8.1
zope.app.publisher = 3.8.4
zope.app.renderer = 3.5.1
zope.app.rotterdam = 3.5.0
zope.app.schema = 3.5.0
zope.app.security = 3.7.3
zope.app.securitypolicy = 3.5.1
zope.app.server = 3.4.2
zope.app.session = 3.6.1
zope.app.testing = 3.7.3
zope.app.traversing = 3.4.0
zope.app.undo = 3.5.0
zope.app.wsgi = 3.6.0
zope.app.zapi = 3.4.1
zope.app.zcmlfiles = 3.5.5
zope.app.zopeappgenerations = 3.5.0
zope.app.zptpage = 3.5.0

plone.app.form = 2.0b6
plone.app.contentrules = 2.0b4
plone.app.portlets = 2.0b11
plone.app.users = 1.0b9
plone.app.contentmenu = 2.0b3
</div><div style="padding-left: 0px; "></div><div style="padding-left: 0px; "></div></pre>
<div style="padding-left: 0px; "></div>
<h2 style="padding-left: 0px; ">Extra Eggs</h2>
<p style="padding-left: 0px; ">You'll also need to add extra add dependencies to your buildout that the Plone 4b4 egg doesn't require and should.</p>
<pre style="padding-left: 1em; "><p style="padding-left: 0px; ">    zope.formlib</p><p style="padding-left: 0px; ">    five.formlib</p><p style="padding-left: 0px; ">    zope.app.schema</p></pre>
<p style="padding-left: 0px; "><br style="padding-left: 0px; " /></p>
<h2 style="padding-left: 0px; ">WSGI</h2>
<p style="padding-left: 0px; ">You can take a look at my previous post for doing WSGI Zope2 for guidelines on how to setup the paste config and such.</p>
</div>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>Zope2</dc:subject>
    
    
      <dc:subject>installation</dc:subject>
    
    
      <dc:subject>python</dc:subject>
    
    
      <dc:subject>buildout</dc:subject>
    
    
      <dc:subject>plone</dc:subject>
    
    <dc:date>2010-06-25T19:35:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/pysourcesearch">
    <title>pysourcesearch</title>
    <link>http://nathanvangheem.com/news/pysourcesearch</link>
    <description>A simple repoze.bfg application for searching python packages and sets of packages utilizing repoze.catalog.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2>Overview</h2>
<p>Sometimes grep or TextMate's find can take a long time so I decided to give a mini search engine a try using repoze.bfg, repoze.catalog and Pygments. The result is that it works rather well and is very fast. The catalog ends up being rather large once you add groups of packages from Plone and such so this ends up making the RAM usage be very high unfortunately.</p>
<p>It gives you the ability to easily search methods, classes, filenames and full text and then give allows you to view the file with pygments.</p>
<p>You can take a look at <a class="external-link" href="http://search.nathanvangheem.com">search.nathanvangheem.com</a> to see it working with repoze.bfg and Plone 4 being indexed.</p>
<p>You can <a class="external-link" href="http://pypi.python.org/pypi/pysourcesearch">checkout the pypi page</a> if you're interested in it and I also <a class="external-link" href="http://bitbucket.org/vangheem/pysourcesearch">have it on bitbucket.</a></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2010-06-09T12:44:43Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/running-plone-4-with-a-zope2-wsgi">
    <title>Running Plone 4 with a Zope2 WSGI</title>
    <link>http://nathanvangheem.com/news/running-plone-4-with-a-zope2-wsgi</link>
    <description>Guide to running Plone 4 with the Zope2 WSGI branch</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2>Update</h2>
<p>Tres has managed to merge his WSGI branch into trunk and Hanno tells me the unofficial plan is to include this in a release for Zope 2.13, in time for Plone 4.1. This is not decided upon yet though.</p>
<h2>Overview</h2>
<p>I was planning on implementing WSGI for Zope2 during the Penn State Symposium Sprints, and I did a few things to help out; however, Tres Seaver did most of the work on his own before and during part of the Sprint :) The rest of the time I spent just testing it out and helping with the Theme Editor sprint.</p>
<p>Now, it's really quite trivial to get it working now and makes all of the repoze.zope2 nonsense unneeded now. This article is just here for a reference if anyone else is interested in getting it going on their setup.</p>
<h2>Guide</h2>
<p>This guide assumes you have an existing Plone 4 installation to work from. I don't provide any buildouts here--just modifying an existing buildout to make it work with a branch of Zope2 and creating an ini that Paste can consume to serve WSGI.</p>
<h3>Supplying the WSGI'd Zope2</h3>
<p>First off, go to the src directory of the installation. If you've installed using the unified installer, that will bin in <i>instance-home/zinstance/src </i>or if you just used straight buildout, it'll be in <i>instance/src.</i> Then checkout the Zope2 branch:</p>
<pre>svn co http://svn.zope.org/repos/main/Zope/branches/tseaver-fix_wsgi/ Zope2</pre>
<h3 class=" ">Stringing up buildout</h3>
<p class=" ">Next thing you'll need to do is modify your <i>buildout.cfg</i> file to add the checked out Zope 2 to the develop section:</p>
<pre class=" ">develop = <br />  ...<br />  Zope2<br />  ...</pre>
<p class=" ">Still modifying your <i>buildout.cfg</i>, add Paste, PasteScript, repoze.tm2 and repoze.retry to your eggs section:</p>
<pre class=" ">eggs =<br />  Plone<br />  Paste<br />  PasteScript<br />  repoze.tm2<br />  repoze.retry </pre>
<p class=" ">Again, editing your <i>buildout.cfg, </i>add a <i>paster</i> part for the paster script:</p>
<pre class=" ">parts =<br />  ...<br />  paster<br />  ...<br /><br /><div id="_mcePaste">[paster]</div><div id="_mcePaste">recipe = repoze.recipe.egg</div><div id="_mcePaste">scripts = paster</div><div id="_mcePaste">eggs = ${instance:eggs}</div></pre>
<p class=" ">Then, you'll need to add the updated Zope2 versions for the WSGI branch. To do this, basically, just add the <i>versions.cfg</i> file provided in the branch after every other version file listed in the extends directive. It'll look like this:</p>
<pre class=" ">extends =<br />  ...<br />  src/Zope2/versions.cfg</pre>
<p class=" ">Then run your buildout like normal:</p>
<pre class=" ">./bin/buildout</pre>
<h3 class=" ">Creating a WSGI Configuration File</h3>
<p>You'll now need to create a WSGI configuration file. Right now, we'll just server it using the Paste server and wsgi ini configuration way. You can also do this to string up Apache's WSGI implementation but that is beyond the scope of this article.</p>
<p>Create a file in the instance directory called, <i>zope2.ini</i> with the contents of:</p>
<pre>[app:zope]
use = egg:Zope2#main
zope_conf = %(here)s/parts/instance/etc/zope.conf

[pipeline:main]
pipeline =
    egg:paste#evalerror
    egg:repoze.retry#retry
    egg:repoze.tm2#tm
    zope

[server:main]
use = egg:paste#http
host = localhost
port = 8080
</pre>
<p class=" ">The <i>zope_conf</i> value in the <i>app:zope</i> section can be the path to any <i>zope.conf</i> file. I'm just exampling the standard location of it and not going through the configuration of that file itself.</p>
<h3 class=" ">Fire it up!</h3>
<p class=" ">If all went well, you should now be able to start up your Plone 4 instance on WSGI like this:</p>
<pre class=" ">./bin/paster serve zope2.ini</pre>
<p class=" ">Your server should now be able to visit your site on http://localhost:8080</p>
<h2 class=" ">Caveats</h2>
<p>I did run into a snag with the Mac OS X unified installer and the version of python it has configured. Basically, it wouldn't compile the Zope2 dependencies so I had to use my own version of python that I had compiled with the <a class="external-link" href="http://svn.plone.org/svn/collective/buildout/python/">python buildout</a> found in the plone collective svn. The bug is sort of referenced in the <a class="external-link" href="https://bugs.launchpad.net/zodb/+bug/427323">zope bug tracker</a>.</p>
<h2 class=" ">Future Considerations</h2>
<p>I'm hoping to maybe get a release with this branch implementation out--maybe as an alpha or beta release since I don't think they are planning on merging this to core any time soon; although, I really have no understanding of what that whole process is.</p>
<p>I'd like to see the Zope2 package implement mkzope2instance and other convenience methods so it'd be possible to install Plone 4/Zope2 without buildout at all maybe using pip. I'm looking into how this might be able to happen with a pip versions file and other things. Maybe more on this later.</p>
<p> </p>
<p>Post any comments if you run into any issues.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>sprint</dc:subject>
    
    
      <dc:subject>Zope2</dc:subject>
    
    
      <dc:subject>plone</dc:subject>
    
    <dc:date>2010-05-31T04:20:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/plone-4-upgrade">
    <title>Plone 4 Upgrade</title>
    <link>http://nathanvangheem.com/news/plone-4-upgrade</link>
    <description>Thoughts on moving the server to Plone 4.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Last night I decided to take some time to move this site over to Plone 4. The repoze.zope2 build I had previously was buggy and I am starting to dislike Deliverance a bit.</p>
<h2>Snags</h2>
<ul>
<li>the search didn't work because of this migration issue http://dev.plone.org/plone/ticket/10360</li>
<li>old file types aren't migrated to blob http://dev.plone.org/plone/ticket/10365</li>
<li>archetypes don't want to use the new add views--should probably report this</li>
<li>If you have the jquery UI package installed, it'll mess with some of Plone's JS for some reason--I just disabled it.</li>
<li>some other control panel entries and menu items were not fully migrated, still pointing to old templates</li>
</ul>
<p> </p>
<h2>Benefits</h2>
<ul>
<li>FAST--running this on a linode with 512MB of ram. 2 zeo clients and with CacheSetup, this thing is very fast. Much faster than Plone 3.</li>
<li>Just more polished than Plone 3--with usability enhancements and a new theme, it's great.</li>
<li>I haven't found a product that wasn't compatible with Plone 4 yet--although, sometimes I needed to do some digging or use an svn checkout to get the compatible version</li>
</ul>
<p> </p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>plone</dc:subject>
    
    
      <dc:subject>upgrades</dc:subject>
    
    <dc:date>2010-05-15T17:40:10Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/repoze.zope2-with-deliverance-locking-up">
    <title>repoze.zope2 with Deliverance locking up</title>
    <link>http://nathanvangheem.com/news/repoze.zope2-with-deliverance-locking-up</link>
    <description>How to make sure your repoze.zope2 wsgi setup with Deliverance will not lock up on you.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<p>I was having issues with my repoze.zope2 and Deliverance setup locking up on me. Turns out, since I had some of sub-requests in my Deliverance rules, it was occasionally causing a race condition where all the wsgi server threads were taken up and an existing thread was making a sub-request.</p>
<p>The fix is to remove all sub-requests in the deliverance rules file if possible, add more threads threads in the repoze.zope2 wsgi server configuration, or use a different wsgi server that doesn't restrict the amount of threads--so it'll add a new thread if needed. A better solution, IMO, would be to just have a different server, serve the theme files. Anything to make it not make sub-requests against the same wsgi server.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2010-03-21T01:52:19Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/add-eject-button-to-boxee">
    <title>Add Eject Button To Boxee</title>
    <link>http://nathanvangheem.com/news/add-eject-button-to-boxee</link>
    <description>Boxee is great, but how could they have forgotten the eject button?</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<p>For some very odd reason, <a class="external-link" href="http://www.boxee.tv/">boxee</a>&nbsp;did not include an eject button in their version of the app. Luckily it is pretty easy to add your own eject button. Well, looking back it is easy; however, it took me a while to figure it out...</p>
<p>First off, find a nice fancy eject button and place it into boxee's skin images folder, "<strong>skin/boxee/media/icons/". </strong>I used&nbsp;<a class="external-link" href="http://irumors.files.wordpress.com/2007/05/eject-copy.png">this one</a> and found it on google image search.</p>
<p>Next insert these lines after line number <strong>231</strong> of the file <strong>skin/boxee/720p/boxee_main_menu.xml</strong></p>
<pre>&lt;item&gt;
    &lt;visible&gt;System.HasMediadvd&lt;/visible&gt;
    &lt;controlid&gt;1300&lt;/controlid&gt;
    &lt;thumb&gt;icons/eject.png&lt;/thumb&gt;
    &lt;label&gt;Eject DVD&lt;/label&gt;
    &lt;onclick&gt;XBMC.EjectTray()&lt;/onclick&gt;
&lt;/item&gt;</pre>
<p>And you're set. You should now have an eject button for your DVDs.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>admin</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>media</dc:subject>
    
    <dc:date>2010-02-15T17:45:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/buildout-to-compile-install-apache-mysql-and-php">
    <title>Buildout to compile and install Apache, MySQL and PHP</title>
    <link>http://nathanvangheem.com/news/buildout-to-compile-install-apache-mysql-and-php</link>
    <description>I created a buildout that will compile and install Apache2, MySQL5 and PHP5 together.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<p>I like to make my work environments contained and repeatable. <a class="external-link" href="http://pypi.python.org/pypi/zc.buildout">Buildout</a>&nbsp;is tool that can help you do that. While buildout is a python tool, with buildout recipes you can compile and install other types of applications relatively easily.&nbsp;</p>
<p>You can download <a title="Buildout files to install Apache, MySQL and PHP" class="internal-link" href="../files/buildout-amp.zip">my buildout here</a>. It also contains patches for it to work on Mac OS X. You'll need python installed for this to work.</p>
<p>If you're not familiar with <a class="external-link" href="http://pypi.python.org/pypi/zc.buildout">buildout</a>, these are the steps to get it working after you've extracted it...</p>
<pre>python bootstrap.py
./bin/buildout</pre>
<p>Then wait for a long time. Then read the README.txt for instructions on how to configure and start apache</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>installation</dc:subject>
    
    
      <dc:subject>python</dc:subject>
    
    
      <dc:subject>databases</dc:subject>
    
    
      <dc:subject>mysql</dc:subject>
    
    
      <dc:subject>apache</dc:subject>
    
    
      <dc:subject>buildout</dc:subject>
    
    
      <dc:subject>php</dc:subject>
    
    <dc:date>2010-02-15T13:25:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/installing-pil-on-mac-os-x-leopard-virtualenv-with-easy_install">
    <title>Installing PIL on Mac OS X Leopard virtualenv with easy_install</title>
    <link>http://nathanvangheem.com/news/installing-pil-on-mac-os-x-leopard-virtualenv-with-easy_install</link>
    <description>What do you do when you need to install PIL in a virtualenv on Mac OS X and it won't build for you? I'll walk through getting it to work.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<h3>First off</h3>
<div>If when you try installing PIL, you get an error like this</div>
<pre>collect2: ld returned 1 exit status
lipo: can't open input file: /var/folders/nO/nOf0lGB+GlGrFGnhcyaFPE+++TI/-Tmp-//ccqHwR4o.out (No such file or directory)
error: Setup script exited with error: command 'gcc' failed with exit status 1</pre>
<p>Then it's failing because it doesn't have the universal versions of some packages installed.&nbsp;</p>
<p>You'll first need to install <a class="external-link" href="http://www.macports.org/">MacPorts</a>. You can download the <a class="external-link" href="http://distfiles.macports.org/MacPorts/MacPorts-1.8.2-10.5-Leopard.dmg">dmg install file</a>&nbsp;or just go to the <a class="external-link" href="http://www.macports.org/install.php">MacPorts installation page</a> for instructions on how to get it setup on your system.</p>
<h3>Installing Universal Packages</h3>
<div>&nbsp;</div>
<div>Open up a terminal window and run these commands,</div>
<pre>sudo port install libiconv +universal
sudo port upgrade --enforce-variants zlib +universal
sudo port install jpeg +universal
sudo port install freetype2<span class="Apple-tab-span">	</span> +universal</pre>
<h3>Now Install PIL&nbsp;</h3>
<div>&nbsp;</div>
<div>Now you should be able to run</div>
<pre>./bin/easy_install <span class="Apple-style-span"><a href="http://dist.repoze.org/PIL-1.1.6.tar.gz" rel="nofollow">http://dist.repoze.org/PIL-1.1.6.tar.gz</a></span></pre>
<p>&nbsp;This is a version of PIL that plays nice with setuptools.</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>PIL</dc:subject>
    
    
      <dc:subject>setuptools</dc:subject>
    
    <dc:date>2010-02-11T12:20:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/moving-to-picasa-update">
    <title>Moving to Picasa Update</title>
    <link>http://nathanvangheem.com/news/moving-to-picasa-update</link>
    <description>Everything didn't go as well as I hoped, but I fixed all the problems I was coming across...</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<p>While moving all my photos from flickr over to Picasa Web Albums I ran into some problems. The <a title="Moving from Flickr to Picasa Web Albums" class="internal-link" href="moving-from-flickr-to-picasa-web-albums">original post</a> explained how the whole process works.&nbsp;</p>
<ul><li>Picasa albums have 1000 photos limits</li><li>the python gdata api didn't support video uploads</li><li>Picasa trimmed&nbsp;whitespace&nbsp;from&nbsp;Album names</li><li>other small things</li></ul>
<div>&nbsp;</div>
<div>The <a title="Migrate from Flickr to Picasa Web Albums" class="internal-link" href="../scripts/migrate-flickr-to-picasa-nokey.py">new script</a>&nbsp;includes creates a new InsertVideo method to support video uploads, moves multiple photos at a time, automatically creates multiple albums if there are more than 1000 photos in a set and fixes other small issues. You'll need to install the flickrapi, gdata and ThreadPool packages.</div>
<div>&nbsp;</div>
<div>It completely works and is done now though. :)</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>photo-management</dc:subject>
    
    <dc:date>2010-02-06T15:15:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/moving-from-flickr-to-picasa-web-albums">
    <title>Moving from Flickr to Picasa Web Albums</title>
    <link>http://nathanvangheem.com/news/moving-from-flickr-to-picasa-web-albums</link>
    <description>The Picasa Desktop Client has made me decide to move back to using Picasa Web Albums. It is superior to Flickr in many ways. Here is my experience in switching... 
</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<h2>Introduction</h2>
<div>I used to use Picasa Web Albums and then moved to Flickr more than a year ago. Since then, I've realized that the flickr online editor just does not cut it, especially since the Picasa desktop client is in great shape now--a great application. The best feature of the newer Picasa desktop client is the ability to synchronize with your online albums. The only the that flickr has over picasa is flickr allows an unlimited amount of photos to be uploaded with the premium membership. Picasa's pricing is dependent on disk usage and can end up being much more expensive.&nbsp;</div>
<div>&nbsp;</div>
<h2>Moving</h2>
<div>To facilitate the move, I created a <a title="Migrate from Flickr to Picasa Web Albums" class="internal-link" href="../scripts/migrate-flickr-to-picasa-nokey.py">simple python script</a> that uses the flickr and picasa apis to move the photo sets, photos, and photo information over to Picasa.</div>
<div>&nbsp;</div>
<div>Before you can run the script, you'll need to install flickrapi and gdata. To do that, issues these commands..</div>
<pre>easy_install flickrapi
easy_install gdata</pre>
<div>You may need to prefix those commands with "sudo" or run as root for them to install.</div>
<div>&nbsp;</div>
<div>You'll also need a flickr api key and secret to use this. I'm not going to provide my own...</div>
<div>&nbsp;</div>
<div>The script can be found at&nbsp;<a title="Migrate from Flickr to Picasa Web Albums" class="internal-link" href="../scripts/migrate-flickr-to-picasa-nokey.py">Migrate from Flickr to Picasa Web Albums</a>.</div>
<div>&nbsp;</div>
<div>When you run it, you'll get prompts for your picasa authentication credentials, flickr api secret and key, and you will be directed by your web browser to authenticate flickr.</div>
<div>&nbsp;</div>
<div>That's it. It will run through all of your photos, moving them over to Picasa.</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2010-01-05T05:33:18Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/site-update">
    <title>Site Update</title>
    <link>http://nathanvangheem.com/news/site-update</link>
    <description>I just updated my server with a new and improved buildout. I am now using repoze.zope2, Deliverance and Zine in the setup to make it wsgi'd. In this post I provide an overview of the setup.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<h2>previous<br /></h2>
<p>On this server, I run my web site and a few free sites that I do for friends and family. Previously, I was just running a zope instance for <a class="external-link" href="http://www.plone.org/">Plone</a> and a couple separate Paste served apps. It is also running Ubuntu and <a class="external-link" href="http://nginx.net/">nginx</a> on a <a class="external-link" href="http://www.linode.com/index.cfm">Linode</a> shared host.</p>
<h2>updates</h2>
<p>While working with a client on Deliverance and <a class="external-link" href="http://repoze.org/">repoze.zope2</a>, I realized it was about time to eat my own dog food and implement the new technologies on my own server. Since I've done a lot of the implementation and research for my client already, it was pretty easy to move over to the new setup. The setup was closely borrowed from <a class="external-link" href="http://www.martinaspeli.net/">Martin Aspeli</a>'s <a class="external-link" href="http://svn.plone.org/svn/collective/buildout/uber/plone3.x-repoze/">uber bulidout</a> in the <a class="external-link" href="http://svn.plone.org/svn/collective/">plone collective svn</a>. Here are some quick notes on updates of the setup:</p>
<ul><li><a class="external-link" href="http://repoze.org/">repoze.zope2</a></li><li><a class="external-link" href="http://www.coactivate.org/projects/deliverance/project-home">Deliverance</a></li><li><a class="external-link" href="http://wsgi.org/wsgi/">wsgi</a></li><li><a class="external-link" href="http://nginx.net/">nginx</a></li><li>new site design themed with Deliverance<br /></li><li>everything built using <a class="external-link" href="http://www.buildout.org/">buildout</a> include <a class="external-link" href="http://codespeak.net/lxml/">lxml</a> and nginx</li><li>move to zeo cluster with only one back end. This allows me to attach debug instances to the zeo server and turn one client on while the other is restarting.</li><li><a class="external-link" href="http://zine.pocoo.org/">Zine</a> blogging software built in</li><li><a class="external-link" href="http://supervisord.org/">supervisor</a> managed - <a class="external-link" href="http://supervisord.org/">supervisor</a> allows you to monitor processes and http servers. It includes starting and stopping processes, tools to monitor the memory and availability and a web server to monitor them.<br /></li></ul>
<h2>highlights</h2>
<ul><li><a class="external-link" href="http://pypi.python.org/pypi/collective.recipe.template">collective.recipe.template</a> is a great buildout recipe for various tasks to generate configuration files for nginx served sites configuration and Paste serve ini files</li><li><a class="external-link" href="http://pypi.python.org/pypi/collective.recipe.backup">collective.recipe.backup</a> provides easy to use backup and restore scripts for ZODB storage</li><li><a class="external-link" href="http://pypi.python.org/pypi/collective.recipe.filestorage">collective.recipe.filestorage</a> easily adds new mount point configuration to the plone.recipe.zope2zeoserver and plone.recipe.zope2instance recipes</li><li><a class="external-link" href="http://pypi.python.org/pypi/collective.recipe.supervisor">collective.recipe.supervisor</a> add <a class="external-link" href="http://supervisord.org/">supervisor</a> to the setup in a configurable way</li><li><a class="external-link" href="http://pypi.python.org/pypi/z3c.recipe.staticlxml">z3c.recipe.staticlxml</a> allows you to compile <a class="external-link" href="http://codespeak.net/lxml/">lxml</a> statically</li><li><a class="external-link" href="http://pypi.python.org/pypi/hexagonit.recipe.cmmi">hexagonit.recipe.cmmi</a> provides mechanisms to easily build non-python software</li><li><a class="external-link" href="http://repoze.org/">repoze.zope2</a> allows me to serve <a class="external-link" href="http://www.plone.org/">Plone</a> via a <a class="external-link" href="http://wsgi.org/wsgi/">wsgi</a> pipeline, which also allows me to add <a class="external-link" href="http://www.coactivate.org/projects/deliverance/project-home">Deliverance</a> to that pipeline<br /></li><li><a class="external-link" href="http://pypi.python.org/pypi/zinebuildout">zinebuildout</a> integration so I can, with ease, provide multiple <a class="external-link" href="http://zine.pocoo.org/">zine</a> blogs<br /></li></ul>
<h2>&nbsp;conclusion</h2>
<p>Overall, it was a great update. The only thing I'm concerned about is the size of my virtual host, which only has 512 MB of RAM right now. So far it seems to be holding up okay, but I'm not running <a class="external-link" href="http://varnish.projects.linpro.no/">Varnish</a> or load balancing(I don't get that many hits)....</p>
<p>&nbsp;</p>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2009-12-10T11:10:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/upgrades-to-collective.plonetruegallery">
    <title>Upgrades to collective.plonetruegallery</title>
    <link>http://nathanvangheem.com/news/upgrades-to-collective.plonetruegallery</link>
    <description>With the advent of the collective.plonetruegallery 0.8 series, a lot of improvements have been introduced.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<p>The new version of collective.plonetruegallery brings a lot of improvements both within the code and visually. This article will just highlight some of the advantages the 0.8 series brings and introduce some images to help you see the improvements.</p>
<h3>Features</h3>
<div>
<ul><li><span class="Apple-style-span">No more Gallery type = getting prepared for dexterity</span></li><li><span class="Apple-style-span">custom gallery and display type story is much improved so it is very simple for people to add on to the product</span></li><li><span class="Apple-style-span">the classic display type is removed</span></li><li><span class="Apple-style-span">the addition of fancybox and highslide display types</span></li><li><span class="Apple-style-span">more visually pleasing through out</span></li><li><span class="Apple-style-span">un-intrusive</span></li><li><span class="Apple-style-span">Collections are now supported!</span></li></ul>
<div>&nbsp;</div>
<div>First thing, in any folder or collection, change to the "Gallery View"&nbsp;</div>
<div><img class="image-inline" src="../images-used/collective.plonetruegallery/copy3_of_copy2_of_copy_of_Picture1.png/image_preview" alt="apply gallery" /></div>
<div>Once the "Gallery View" is selected, a "Gallery Settings" tab is enabled. You can clicked there to start customizing your gallery.</div>
<div><img class="image-inline" src="../images-used/collective.plonetruegallery/copy3_of_copy2_of_copy_of_Picture2.png/image_preview" alt="settings" /></div>
<div>The default display type for galleries is Slideshow 2 now.&nbsp;</div>
<div><img class="image-inline" src="../images-used/collective.plonetruegallery/copy2_of_copy_of_Picture3.png/image_large" alt="slideshow 2" /></div>
<div>This release also contains Fancybox display type with batching.</div>
<div><img class="image-inline" src="../images-used/collective.plonetruegallery/copy_of_Picture4.png/image_preview" alt="fancybox" /></div>
<div>and finally, Highslide</div>
<div><img class="image-inline" src="../images-used/collective.plonetruegallery/copy2_of_copy_of_Picture5.png/image_preview" alt="highslide" /></div>
<div>&nbsp;</div>
<div>For more information, check out <a class="external-link" href="http://pypi.python.org/pypi/collective.plonetruegallery/0.8a1">the pypi entry</a>.</div>
</div>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2009-11-20T15:10:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/creating-and-subscribing-to-events-in-zope">
    <title>Creating and subscribing to events in Zope</title>
    <link>http://nathanvangheem.com/news/creating-and-subscribing-to-events-in-zope</link>
    <description>This will show you how to create events and subscribe to them using Zope 3 approaches.  These methods will also work in Plone.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<h2>Creating your event</h2>
<ul><li>An event is just an interface definition and the event object declaration<br />
<pre>import zope.component.interfaces
from zope.interface import implements

class IMyNewEvent(zope.component.interfaces.IObjectEvent):
&nbsp;&nbsp;&nbsp; """An object has been modified"""

class MyNewEvent(zope.component.interfaces.ObjectEvent):
    """An object has been modified"""
    implements(IMyNewEvent)
</pre>
</li></ul>
<ul><li>The real magic happens when fire off the event<br />
<pre>from zope.event import notify

notify(MyNewEvent(context))</pre>
</li><li>Now to subscribe to the event do something like this,<br />
<pre>&lt;subscriber
  for="myproduct.myobject
       myproduct.interfaces.IMyNewEvent"
  handler=".subscribers.event_handler"
  /&gt;</pre>
</li><li>Now in a file subscribers.py add the method event_handler like this,<br />
<pre>def event_handler(obj, event):
  # do something interesting here...
  pass</pre>
&nbsp;&nbsp; <br /></li></ul>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2009-02-01T01:35:00Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>


  <item rdf:about="http://nathanvangheem.com/news/using-a-browserview-as-a-traversable-adapter-utility-in-plone">
    <title>Using a BrowserView as a traversable adapter utility in Plone</title>
    <link>http://nathanvangheem.com/news/using-a-browserview-as-a-traversable-adapter-utility-in-plone</link>
    <description>This will show you how to make a traversable multi-adapter on the context and request object that can be called within tal expressions and used as utilities elsewhere.  It is done the exact same way as the plone_tools, plone_context_state, plone_portal_state BrowserViews you see used often throughout Plone viewlets and tal expressions.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
<ul><li>First off, you'll have to add this in one of your own Plone products.&nbsp; I will not go through creating a product in this tutorial.<br /></li><li>Next, create a few files. Remember you can customize these to your liking.&nbsp; I will call this BrowserView "tool."</li>
<ul><li>tool.py</li><li>interfaces.py</li></ul>
<li>In the tool.py file do something like this,<br />
<pre>from zope.interface import implements
from zope.component import getMultiAdapter
from plone.memoize.view import memoize, memoize_contextless

from Acquisition import aq_inner
from Products.CMFCore.utils import getToolByName
from Products.Five.browser import BrowserView

from interfaces import ITool

class Tool(BrowserView): 

  implements(IUWOshTools)

  @memoize_contextless
  def hello_world(self):
    return "Hello, World!"</pre>
</li><li>Now in interfaces.py do something like this,<br />
<pre>from zope.interface import Interface

class ITool(Interface):
  def hello_world(self):
    pass</pre>
</li><li>In the interfaces.py file you'll need to declare each method you'll create in the Tool BrowserView</li><li>Now add this to your configure.zcml<br />
<pre>&lt;browser:page
  name="tool"
  for="*"
  permission="zope2.View"
  class=".tool.Tool"
  allowed_interface=".interfaces.ITool"
  /&gt;

&lt;!-- We need to make the request annotatable for this to work --&gt;
  &lt;class class="ZPublisher.BaseRequest.BaseRequest"&gt;
    &lt;implements interface="zope.annotation.interfaces.IAttributeAnnotatable" /&gt;
  &lt;/class&gt;</pre>
</li><li>Now in a tal expression you can do things like this,<br />
<pre>here/@@tool/hello_world
python: here.restrictedTraverse("@@tool").hello_world()</pre>
</li><li>Or in code you can do something like this,<br />
<pre>from zope.component import getMultiAdapter

tool = getMultiAdapter((self.context, self.request), name=u'tool')</pre>
</li><li>and you're done.&nbsp; SWEET!<br /></li></ul>
]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nathan Van Gheem</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2009-02-01T01:19:03Z</dc:date>
    <dc:type>News Item</dc:type>
  </item>





</rdf:RDF>
