<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Planet TurboGears</title>
	<link>http://planet.turbogears.org/</link>
	<language>en</language>
	<description>Planet TurboGears - http://planet.turbogears.org/</description>

<item>
	<title>Alessandro Molina: Mastering the TurboGears EasyCrudRestController</title>
	<guid>http://blog.axant.it/?p=423</guid>
	<link>http://blog.axant.it/archives/423</link>
	<description>&lt;p&gt;One of the key features of &lt;a href=&quot;http://www.turbogears.org&quot;&gt;TurboGears2&lt;/a&gt; is the great &lt;a href=&quot;http://pypi.python.org/pypi/tgext.crud&quot;&gt;CRUD extension&lt;/a&gt;. Mastering the CRUD extension can really make the difference between spending hours or just a few minutes on writing a web app prototype or even a full application.&lt;/p&gt;
&lt;p&gt;The CRUD extension provides two main features, the &lt;a href=&quot;http://www.turbogears.org/2.1/docs/main/Extensions/Crud/index.html#creating-our-own-crudrestcontroller&quot;&gt;CrudRestController&lt;/a&gt; which is meant to help creating totally custom CRUDs and the &lt;a href=&quot;http://www.turbogears.org/2.1/docs/main/Extensions/Crud/index.html#easycrudrestcontroller&quot;&gt;EasyCrudRestController&lt;/a&gt; which provides a quick and easy way to create CRUD interfaces.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll focus on the EasyCrudRestController as it is the easiest and more productive one, moving forward to the CrudRestController is quite straightforward after you feel confident with the Easy one.&lt;/p&gt;
&lt;p&gt;The target will be to create, in no more than 40 lines of controller code, a full featured photo gallery application with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiple Albums&lt;/li&gt;
&lt;li&gt;Uploads with Thumbnails Generation&lt;/li&gt;
&lt;li&gt;Authenticated Access, only users in group &amp;#8220;photos&amp;#8221; will be able to manage photos&lt;/li&gt;
&lt;li&gt;Contextual Management, manage photos of one album at time instead of having all photos mixed together in a generic management section&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2012/01/photos.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-426&quot; src=&quot;http://blog.axant.it/wp-content/uploads/2012/01/photos.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you don&amp;#8217;t already know how to create a new TurboGears project, start by giving a look at &lt;a href=&quot;http://www.turbogears.org/2.1/docs/main/DownloadInstall.html#installation-for-the-impatient&quot;&gt;TurboGears Installation for The Impatient&lt;/a&gt; guide. Just remember to add &lt;code&gt;tgext.datahelpers&lt;/code&gt; to dependencies inside your project &lt;code&gt;setup.py&lt;/code&gt; before running the &lt;code&gt;setup.py develop&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll start by providing a Gallery and Photo model. To store the images I&amp;#8217;ll use &lt;a href=&quot;http://pypi.python.org/pypi/tgext.datahelpers&quot;&gt;tgext.datahelpers&lt;/a&gt; to avoid having to manage the attachments. Using datahelpers also provides the advantage of having thumbnails support for free.&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; tgext.&lt;span&gt;datahelpers&lt;/span&gt;.&lt;span&gt;fields&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; Attachment, AttachedImage
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Gallery&lt;span&gt;&amp;#40;&lt;/span&gt;DeclarativeBase&lt;span&gt;&amp;#41;&lt;/span&gt;:
    __tablename__ = &lt;span&gt;'galleries'&lt;/span&gt;
&amp;nbsp;
   uid = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Integer, autoincrement=&lt;span&gt;True&lt;/span&gt;, primary_key=&lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
   name = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Unicode&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, nullable=&lt;span&gt;False&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Photo&lt;span&gt;&amp;#40;&lt;/span&gt;DeclarativeBase&lt;span&gt;&amp;#41;&lt;/span&gt;:
    __tablename__ = &lt;span&gt;'photos'&lt;/span&gt;
&amp;nbsp;
    uid = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Integer, autoincrement=&lt;span&gt;True&lt;/span&gt;, primary_key=&lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    name = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Unicode&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, nullable=&lt;span&gt;False&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    description = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Unicode&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;2048&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, nullable=&lt;span&gt;False&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    image = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Attachment&lt;span&gt;&amp;#40;&lt;/span&gt;AttachedImage&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    author_id = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Integer, ForeignKey&lt;span&gt;&amp;#40;&lt;/span&gt;model.&lt;span&gt;User&lt;/span&gt;.&lt;span&gt;user_id&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    author = relation&lt;span&gt;&amp;#40;&lt;/span&gt;app_model.&lt;span&gt;User&lt;/span&gt;, backref=backref&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    gallery_id = Column&lt;span&gt;&amp;#40;&lt;/span&gt;Integer, ForeignKey&lt;span&gt;&amp;#40;&lt;/span&gt;Gallery.&lt;span&gt;uid&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    gallery = relation&lt;span&gt;&amp;#40;&lt;/span&gt;Gallery, backref=backref&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos'&lt;/span&gt;, cascade=&lt;span&gt;'all, delete-orphan'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now to be able to start using our galleries we will have to provide a place where to view them and a gallery management controller to create and manage them. Viewing them should be quite straightforward, I&amp;#8217;ll just retrieve the galleries from the database inside my &lt;code&gt;index&lt;/code&gt; method and render them. To access a single gallery I&amp;#8217;ll rely on the datahelpers &lt;code&gt;SQLAEntityConverter&lt;/code&gt; which will retrieve the gallery for us ensuring it exists and is valid. For the management part I&amp;#8217;ll create an &lt;code&gt;EasyCrudRestController&lt;/code&gt; mounted as &lt;code&gt;/manage_galleries&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; tgext.&lt;span&gt;crud&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; EasyCrudRestController
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; GalleriesController&lt;span&gt;&amp;#40;&lt;/span&gt;EasyCrudRestController&lt;span&gt;&amp;#41;&lt;/span&gt;:
    allow_only = predicates.&lt;span&gt;in_group&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    title = &lt;span&gt;&amp;quot;Manage Galleries&amp;quot;&lt;/span&gt;
    model = model.&lt;span&gt;Gallery&lt;/span&gt;
&amp;nbsp;
    __form_options__ = &lt;span&gt;&amp;#123;&lt;/span&gt;
        &lt;span&gt;'__hide_fields__'&lt;/span&gt; : &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'uid'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;,
        &lt;span&gt;'__omit_fields__'&lt;/span&gt; : &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'photos'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;
    &lt;span&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; RootController&lt;span&gt;&amp;#40;&lt;/span&gt;BaseController&lt;span&gt;&amp;#41;&lt;/span&gt;:
    manage_galleries = GalleriesController&lt;span&gt;&amp;#40;&lt;/span&gt;DBSession&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    @expose&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos.templates.index'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; index&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, &lt;span&gt;*&lt;/span&gt;args, &lt;span&gt;**&lt;/span&gt;kw&lt;span&gt;&amp;#41;&lt;/span&gt;:
        galleries = DBSession.&lt;span&gt;query&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;Gallery&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;order_by&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;Gallery.&lt;span&gt;uid&lt;/span&gt;.&lt;span&gt;desc&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;all&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;dict&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;galleries=galleries&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    @expose&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos.templates.gallery'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    @validate&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;dict&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;gallery=SQLAEntityConverter&lt;span&gt;&amp;#40;&lt;/span&gt;Gallery&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, error_handler=index&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;def&lt;/span&gt; gallery&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, gallery&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;return&lt;/span&gt; &lt;span&gt;dict&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;gallery=gallery&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Logging in with an user inside the &lt;code&gt;photos&lt;/code&gt; group and accessing the &lt;code&gt;/manage_galleries&lt;/code&gt; url we will be able to create a new gallery and manage the existing ones. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2012/01/gallerylisting.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2012/01/gallerylisting.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;220&quot; class=&quot;alignnone size-full wp-image-444&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To configure how the crud controller forms should appear and behave the &lt;code&gt;__form_options__&lt;/code&gt; property of the &lt;code&gt;EasyCrudRestController&lt;/code&gt; can be used. This property relies on the same options as &lt;a href=&quot;http://packages.python.org/sprox/modules/sprox.formbase.html#module-sprox.formbase&quot;&gt;Sprox FormBase&lt;/a&gt; and customizes both the &lt;strong&gt;Edit&lt;/strong&gt; and &lt;strong&gt;Add&lt;/strong&gt; forms.&lt;br /&gt;
The next part is probably to be able to upload some photos inside our newly created galleries. To perform this we will create a new &lt;code&gt;EasyCrudRestController&lt;/code&gt; for gallery photos management.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; tgext.&lt;span&gt;crud&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; EasyCrudRestController
&lt;span&gt;from&lt;/span&gt; tw.&lt;span&gt;forms&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; FileField
&lt;span&gt;from&lt;/span&gt; tw.&lt;span&gt;forms&lt;/span&gt;.&lt;span&gt;validators&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; FieldStorageUploadConverter
&lt;span&gt;from&lt;/span&gt; webhelpers &lt;span&gt;import&lt;/span&gt; html
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; PhotosController&lt;span&gt;&amp;#40;&lt;/span&gt;EasyCrudRestController&lt;span&gt;&amp;#41;&lt;/span&gt;:
    allow_only = predicates.&lt;span&gt;in_group&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'photos'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    title = &lt;span&gt;&amp;quot;Manage Photos&amp;quot;&lt;/span&gt;
    model = model.&lt;span&gt;Photo&lt;/span&gt;
    keep_params = &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'gallery'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;
&amp;nbsp;
    __form_options__ = &lt;span&gt;&amp;#123;&lt;/span&gt;
        &lt;span&gt;'__hide_fields__'&lt;/span&gt; : &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'uid'&lt;/span&gt;, &lt;span&gt;'author'&lt;/span&gt;, &lt;span&gt;'gallery'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;,
        &lt;span&gt;'__field_widget_types__'&lt;/span&gt; : &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'image'&lt;/span&gt;:FileField&lt;span&gt;&amp;#125;&lt;/span&gt;,
        &lt;span&gt;'__field_validator_types__'&lt;/span&gt; : &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'image'&lt;/span&gt;:FieldStorageUploadConverter&lt;span&gt;&amp;#125;&lt;/span&gt;,
        &lt;span&gt;'__field_widget_args__'&lt;/span&gt; : &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'author'&lt;/span&gt;:&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;'default'&lt;/span&gt;:&lt;span&gt;lambda&lt;/span&gt;:request.&lt;span&gt;identity&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'user'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;.&lt;span&gt;user_id&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;
    &lt;span&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    __table_options__ = &lt;span&gt;&amp;#123;&lt;/span&gt;
        &lt;span&gt;'__omit_fields__'&lt;/span&gt; : &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'uid'&lt;/span&gt;, &lt;span&gt;'author_id'&lt;/span&gt;, &lt;span&gt;'gallery_id'&lt;/span&gt;, &lt;span&gt;'gallery'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;,
        &lt;span&gt;'__xml_fields__'&lt;/span&gt; : &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'image'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;,
        &lt;span&gt;'image'&lt;/span&gt;: &lt;span&gt;lambda&lt;/span&gt; filler,row: html.&lt;span&gt;literal&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'‹img src=&amp;quot;%s&amp;quot;/›'&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; row.&lt;span&gt;image&lt;/span&gt;.&lt;span&gt;thumb_url&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Mounting this inside the RootController as &lt;code&gt;manage_photos = PhotosController(DBSession)&lt;/code&gt; it will be possible to upload new photos inside any gallery. To manage the photos inside the first gallery for example we will have to access &lt;code&gt;/manage_photos?gallery=1&lt;/code&gt;url.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2012/01/photoslisting.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2012/01/photoslisting.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;294&quot; class=&quot;alignnone size-full wp-image-445&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each parameter passed to the &lt;code&gt;EasyCrudRestController&lt;/code&gt; is used to filter the entries to show inside the management table and the &lt;code&gt;keep_params&lt;/code&gt; option provides a way to keep the filter around. This makes possible to edit the photos of only one gallery at the time instead of having all the photos mixed together. Also when a new photo is created it will be created in the current gallery.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;PhotosController&lt;/code&gt; got more customization than the &lt;code&gt;GalleriesController&lt;/code&gt;, through the &lt;code&gt;__field_widget_types__&lt;/code&gt; and &lt;code&gt;__field_validator_types__&lt;/code&gt; options we force the image field to be a file field and using the &lt;code&gt;__field_widget_args__&lt;/code&gt; we ensure that the newly uploaded photos have the current user as the author.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;__table_options__&lt;/code&gt; provide a way to customize the management table. The available options are the same as the &lt;a href=&quot;http://packages.python.org/sprox/modules/sprox.tablebase.html#sprox.tablebase.TableBase&quot;&gt;Sprox TableBase&lt;/a&gt; and &lt;a href=&quot;http://packages.python.org/sprox/modules/sprox.fillerbase.html#sprox.fillerbase.TableFiller&quot;&gt;Sprox TableFiller&lt;/a&gt; objects. in this case we hide the indexes of the rows on the database and the gallery itself, as we are managing the photos of a specific gallery we probably don&amp;#8217;t need to know which galleries the photos belong to. Using the &lt;code&gt;__xml_fields__&lt;/code&gt; we also specify that the &lt;strong&gt;image&lt;/strong&gt; field provides HTML and so doesn&amp;#8217;t have to be escaped. The &lt;code&gt;image&lt;/code&gt; entry forces the table to show the image thumbnail for the image column of the table instead of printing the &lt;code&gt;AttachedImage.__repr__&lt;/code&gt; as it would by default.&lt;/p&gt;
&lt;p&gt;At first sight it might sound a bit complex, but once you start feeling confident, the CRUD extension makes possible to create entire applications in just a bunch of code lines. With just a few lines of code we created a photo gallery with multiple albums support and we can now focus on the &lt;strong&gt;index&lt;/strong&gt; and &lt;strong&gt;gallery&lt;/strong&gt; templates to make the gallery as pleasant as possible for our visitors.&lt;/p&gt;
&lt;p&gt;The complete implementation of the photo gallery is available as a pluggable application on &lt;a href=&quot;https://bitbucket.org/_amol_/tgapp-photos&quot;&gt;bitbucket&lt;/a&gt;, feel free to use it in your TurboGears projects.&lt;/p&gt;</description>
	<pubDate>Tue, 31 Jan 2012 20:22:06 +0000</pubDate>
</item>
<item>
	<title>Mengu Kagan: 2011 At A Glance</title>
	<guid>http://www.mengu.net/post/2011-at-a-glance</guid>
	<link>http://www.mengu.net/post/2011-at-a-glance</link>
	<description>&lt;p&gt;I can call 2011 quite a good year on my behalf however when I look at things I've done, I feel I've done much less than I could. Here is a list of what I have done in 2011.&lt;/p&gt;

&lt;h2&gt;Things I've Done in 2011&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Executed an idea we had with my brother, &lt;a href=&quot;http://compector.com&quot;&gt;http://compector.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built the start-up above with Ruby on Rails so I became more familiar with Ruby world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have made the switch to PostgreSQL from MySQL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Got a job in one of Turkey's top web sites where we deal with thousands of concurrent users...&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Sat, 31 Dec 2011 19:07:11 +0000</pubDate>
</item>
<item>
	<title>Mengu Kagan: Subqueries With SQLAlchemy</title>
	<guid>http://www.mengu.net/post/subqueries-with-sqlalchemy</guid>
	<link>http://www.mengu.net/post/subqueries-with-sqlalchemy</link>
	<description>&lt;p&gt;I have been developing the new version of www.osesturkiye.com for the Turkish version of the show called &quot;The Voice&quot;. It's already built with TurboGears, mako and SQLAlchemy. In the new version we have a gallery and many photos in it. My SQLAlchemy model is like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class GalleryPhoto(DeclarativeBase):
    __tablename__ = 'gallery_photo'

    id = Column(Integer, primary_key=True)
    photo_image = Column(UnicodeText)
    photo_description = Column(UnicodeText)
    dateline = Column(DateTime, default=datetime.now)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem I have is, in the photo detail page I will display &quot;Previous&quot; and &quot;Next&quot; links. I can implement this with two ways..&lt;/p&gt;</description>
	<pubDate>Wed, 21 Dec 2011 20:28:11 +0000</pubDate>
</item>
<item>
	<title>Ralph Bean: threebean</title>
	<guid>http://threebean.wordpress.com/?p=447</guid>
	<link>http://threebean.wordpress.com/2011/12/13/hacking-tw2-resource-injection/</link>
	<description>&lt;p&gt;Tonight, &lt;em&gt;VooDooNOFX&lt;/em&gt; was asking in IRC in #turbogears how to disable the injection of jquery.js by tw2.jquery into her/his TG2 app.  Using the &lt;code&gt;inject_resources=False&lt;/code&gt; middleware config value wouldn&amp;#8217;t cut it, since she/he wanted tw2 to inject all &lt;em&gt;other&lt;/em&gt; resources, they were loading jQuery via google CDN beforehand and tw2&amp;#8242;s injection was clobbering their code.&lt;/p&gt;
&lt;p&gt;I came up with the following hack to &lt;code&gt;myapp/lib/base.py&lt;/code&gt; which will remove tw2.jquery.jquery_js from the list of resources tw2 would inject into each page served by a TG2.1 app.&lt;/p&gt;
&lt;p&gt;At the top of &lt;code&gt;myapp/lib/base.py&lt;/code&gt; import:&lt;br /&gt;
&lt;pre class=&quot;brush: python;&quot;&gt;
import tw2.core.core
import tw2.jquery
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and then replace:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
        return TGController.__call__(self, environ, start_response)
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;with the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
        stream = TGController.__call__(self, environ, start_response)

        # Disable the injection of tw2.jquery
        offending_link = tw2.jquery.jquery_js.req().link
        local = tw2.core.core.request_local()
        local['resources'] = [
            r for r in local.get('resources', None) if r.link != offending_link
        ]

        return stream
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The two tricks to this are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simply knowing that tw2 resources register themselves with the &amp;#8216;request_local&amp;#8217; object and that during the return-phase of the WSGI pipeline, the tw2 middleware refers to that list when injecting resources&lt;/li&gt;
&lt;li&gt;Figuring out where in a TG2 app&amp;#8217;s request flow to place the call to alter that object &lt;strong&gt;after&lt;/strong&gt; all widgets that might register jquery have declared their resources but &lt;strong&gt;before&lt;/strong&gt; the resources list is injected into the output stream.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We came out of it with &lt;a href=&quot;https://bitbucket.org/paj/tw2core/issue/94/jquery-resource-injection&quot;&gt;a bug filed in the tw2 issue tracker&lt;/a&gt; so we can take care of it properly in the future.&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/threebean.wordpress.com/447/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/threebean.wordpress.com/447/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=threebean.wordpress.com&amp;blog=8850237&amp;post=447&amp;subd=threebean&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Tue, 13 Dec 2011 05:44:53 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing TurboGears 2.1.4 Release</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-1826534574273761418</guid>
	<link>http://codersbuffet.blogspot.com/2011/12/announcing-turbogears-214-release.html</link>
	<description>&lt;div&gt;The TurboGears team is proud to announce the release of TurboGears 2.1.4!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This release has many new features and bugfixes, all of them listed below. The most important one, though, is that this is the final 2.1.x release, and the final release that will support Python 2.4.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Please make sure to update your code to work on Python 2.5, as that will be the next supported Python version.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I would like to take a moment to thank Alessandro Molina especially. His work made this release possible, and as large as it is. He's been a great asset to the team, and I'm glad to have him on board.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Deprecated Python 2.4 support. In 2.2, Python 2.4 support will be removed, and only 2.5-2.7 will be supported&lt;/li&gt;&lt;li&gt;TurboGears extension architecture enhanced. Better support for hooks before and after configuration&lt;/li&gt;&lt;li&gt;Performance enhancements in tg module and in default templates&lt;/li&gt;&lt;li&gt;Enhancements to lazy_url&lt;/li&gt;&lt;li&gt;WebOb version locked in. The change of virtualenv to &quot;distribute&quot; by default has broken dependency_links and allow_hosts in the config files, and this works around that issue.&lt;/li&gt;&lt;li&gt;Jinja2 filters are now automatically loaded&lt;/li&gt;&lt;li&gt;Work arounds for best_match, which was not producing the expected behavior with IE7 and IE8&lt;/li&gt;&lt;li&gt;Add &quot;auto_reload_template&quot; as an .ini option&lt;/li&gt;&lt;li&gt;Performance tuning the default size of the Genshi cache&lt;/li&gt;&lt;li&gt;Added Genshi advanced i18n support&lt;/li&gt;&lt;li&gt;Better compatibility with SQLAlchemy 0.7&lt;/li&gt;&lt;li&gt;Changed default quickstart options to help ensure that some model is always available&lt;/li&gt;&lt;li&gt;Documentation enhancements&lt;/li&gt;&lt;li&gt;Nested RestControllers now work as expected (no longer required to implement &quot;_custom_actions&quot;)&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-1826534574273761418?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 12 Dec 2011 20:18:23 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Curia: An rsync-like interface for Amazon S3 and Google Storage</title>
	<guid>http://blog.curiasolutions.com/?p=1101</guid>
	<link>http://blog.curiasolutions.com/2011/12/an-rsync-like-interface-for-amazon-s3-and-google-storage/</link>
	<description>&lt;p&gt;Every so often I find myself working on that odd job that requires syncing files with Amazon&amp;#8217;s S3. In the beginning, I tried some of the various S3 FUSE interfaces—hoping for something that would play nice with rsync—but FUSE&amp;#8217;s stability always left something to be desired and more often than not I&amp;#8217;d be left with that one transfer that never would quite finish correctly.&lt;/p&gt;
&lt;p&gt;Eventually I discovered &lt;a href=&quot;http://github.com/boto/boto&quot; target=&quot;_blank&quot;&gt;boto&lt;/a&gt; and settled in to using a crude (yet stable) Python/boto solution for these type of tasks—all the while wondering why nobody took the time to write a &amp;#8220;real&amp;#8221; rsync-like client for S3.&lt;/p&gt;
&lt;p&gt;Well, this last time around I finally decided to stop whining and take matters into my own hands. After a couple of late nights fleshing out my basic boto solutions, I&amp;#8217;m happy to announce what I&amp;#8217;m calling &amp;#8220;boto rsync&amp;#8221;—an rsync like wrapper for boto&amp;#8217;s cloud storage interfaces (S3 &lt;em&gt;and&lt;/em&gt; Google Storage).&lt;/p&gt;
&lt;p&gt;Please take a look at the project on github and let me know what you think: &lt;a href=&quot;http://github.com/seedifferently/boto_rsync&quot; target=&quot;_blank&quot;&gt;http://github.com/seedifferently/boto_rsync&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 12 Dec 2011 00:55:06 +0000</pubDate>
</item>
<item>
	<title>Mengu Kagan: What's Going On With TurboGears?</title>
	<guid>http://www.mengu.net/post/whats-going-on-with-turbogears</guid>
	<link>http://www.mengu.net/post/whats-going-on-with-turbogears</link>
	<description>&lt;p&gt;If you are using Python and looking for a web framework or if you are just looking to do web programming with Python, you will look out your options and among Django, web2py and pyramid you will notice TurboGears. As a Python developer and TurboGears user, I will let you guys know what is going on with TurboGears lately and will let you have a chance with TurboGears.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/DvvDP.png&quot; alt=&quot;TurboGears Introduction&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;A Short Introduction First&lt;/h2&gt;

&lt;p&gt;TurboGears is a full stack MVC web framework that is built on top of Pylons and which includes an ORM, a templating system, database migration tool, web helpers, authentication and authorization system by default just like Django. If you are wondering, there are two main differences between Django and TurboGears. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;TurboGears is using class based controllers and object dispatch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TurboGears is built using external Python libraries such as Pylons, WebOB, paster whereas everything in Django is built for Django.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Sat, 19 Nov 2011 23:55:28 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: TurboGears2 DebugBar</title>
	<guid>http://blog.axant.it/?p=405</guid>
	<link>http://blog.axant.it/archives/405</link>
	<description>&lt;p&gt;Recently some work has been done to extend the hooks support in TurboGears, to play a little with the new hooks I decided to try creating the famous and envied Django Debug Toolbar. I&amp;#8217;m quite happy of the result and most of the features are there. In a few days I&amp;#8217;ll be able to place it on a public repository and I&amp;#8217;ll release it concurrently with the 2.1.4 release of TurboGears.&lt;/p&gt;
&lt;div id=&quot;attachment_409&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2011/11/debugbar.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2011/11/debugbar-300x223.png&quot; alt=&quot;Debug Toolbar&quot; width=&quot;300&quot; height=&quot;223&quot; class=&quot;size-medium wp-image-409&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Debug Toolbar&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_411&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2011/11/timings.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2011/11/timings-300x223.png&quot; alt=&quot;Timings&quot; width=&quot;300&quot; height=&quot;223&quot; class=&quot;size-medium wp-image-411&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Timings&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_412&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2011/11/request.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2011/11/request-300x223.png&quot; alt=&quot;Request and Headers&quot; width=&quot;300&quot; height=&quot;223&quot; class=&quot;size-medium wp-image-412&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Request and Headers&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_413&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2011/11/queries.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2011/11/queries-300x223.png&quot; alt=&quot;SQLAlchemy Queries&quot; width=&quot;300&quot; height=&quot;223&quot; class=&quot;size-medium wp-image-413&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;SQLAlchemy Queries&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;attachment_414&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;a href=&quot;http://blog.axant.it/wp-content/uploads/2011/11/controllers.png&quot;&gt;&lt;img src=&quot;http://blog.axant.it/wp-content/uploads/2011/11/controllers-300x233.png&quot; alt=&quot;Mounted Controllers&quot; width=&quot;300&quot; height=&quot;233&quot; class=&quot;size-medium wp-image-414&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Mounted Controllers&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The code has been heavily inspired by the Pyramid Debug Toolbar and have to thank the Pyramid team for the good job they did at making the Toolbar code clean and simple.&lt;/p&gt;</description>
	<pubDate>Sat, 12 Nov 2011 19:30:47 +0000</pubDate>
</item>
<item>
	<title>Cliff Wells: FreeSWITCH on Scientific Linux 6.1</title>
	<guid>http://www.enemyofthestatement.com/freeswitch-on-scientific-linux-6-1</guid>
	<link>http://www.enemyofthestatement.com/freeswitch-on-scientific-linux-6-1</link>
	<description>&lt;div class=&quot;document&quot;&gt;
&lt;p&gt;SL 6.1 (and I assume RHEL and CentOS 6.1 as well) has introduced an issue for building and running FreeSWITCH.  Apparently a lot of stuff now relies on dynamically linking to libnss3.  libnss3, in turn, depends on libnspr4.so, which depends on libplds4.so.  Seemingly, this should not be an issue (stuff depends on chained shared objects all over the place), but somehow it is.&lt;/p&gt;
&lt;p&gt;What happens is first you can't compile FreeSWITCH. You get complaints about unresolved symbols in /usr/lib64/libnss3.so.  The solution is to run the following commands:&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
yum install nspr-devel
env LIBS=&amp;quot;-lnss3 -lnspr4 -lplds4&amp;quot; ./configure
make &amp;amp;&amp;amp; make install
&lt;/pre&gt;
&lt;p&gt;This will get you a compiled version of FreeSWITCH.  However, when you actually run it, you'll find that several modules won't load at runtime (including the ODBC driver, should you happen to be using it).  The solution for this is similar.  Assuming you are using an init script to launch FreeSWITCH, you can add the following line to the top of /etc/init.d/freeswitch:&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
export LD_PRELOAD=&amp;quot;/usr/lib64/libnss3.so /usr/lib64/libnspr4.so /usr/lib64/libplds4.so&amp;quot;
&lt;/pre&gt;
&lt;p&gt;Voila.  Everything works.  Hopefully the FreeSWITCH devs get on RHEL6 support soon, but meanwhile this should get you by.&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 23 Oct 2011 15:27:44 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Request For Ideas for Hiring Pond</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-4474799999076339015</guid>
	<link>http://codersbuffet.blogspot.com/2011/10/request-for-ideas-for-hiring-pond.html</link>
	<description>So, a favor to ask of people: I'm working on a web application to help people manage their resumes. As I've gotten further in, I've realized I don't have an actual todo list for it. So, since I'm making this to be used by others, I'll ask everybody here:&lt;br /&gt;&lt;br /&gt;What would you want to see? Currently, I've added enough code to allow the program to output something very close to my online resume ( http://www.icelus.org/ ). Next up, I have the following features on my todo list already:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;add docutils to output strings where appropriate (everywhere?)&lt;/li&gt;&lt;li&gt;add login&lt;/li&gt;&lt;li&gt;add ability to edit own resume&lt;/li&gt;&lt;li&gt;add ability to compile new custom resumes&lt;/li&gt;&lt;li&gt;add ability to output PDF&lt;/li&gt;&lt;li&gt;add ability to output ODT&lt;/li&gt;&lt;li&gt;add ability to output DOC&lt;/li&gt;&lt;li&gt;add generic logo&lt;/li&gt;&lt;li&gt;add generic photo / head (shadow) shot&lt;/li&gt;&lt;li&gt;add ability to login using Google, Yahoo, Facebook, etc&lt;/li&gt;&lt;li&gt;add ability to send resumes directly from Hiring Pond&lt;/li&gt;&lt;li&gt;add ability to track where resumes have gone&lt;/li&gt;&lt;li&gt;add ability to track job hunt progress&lt;/li&gt;&lt;li&gt;add ability to display current employment status (employed, unemployed, contracting)&lt;/li&gt;&lt;li&gt;add ability to display current employment seeking status (not at all, active, passive)&lt;/li&gt;&lt;li&gt;add logo to qrcode&lt;/li&gt;&lt;li&gt;change colors of qrcode&lt;/li&gt;&lt;li&gt;change color scheme for all of hiring pond to sunset and water&lt;/li&gt;&lt;li&gt;add fisherman silhouette as hiring pond logo&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;What else would you all want to see in order to make you want to use this?&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-4474799999076339015?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 18 Oct 2011 20:44:25 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Alessandro Molina: TurboGears2 Performance Improvements</title>
	<guid>http://blog.axant.it/?p=400</guid>
	<link>http://blog.axant.it/archives/400</link>
	<description>&lt;p&gt;As recently some effort has been involved in improving the performances of TurboGears2, I was curious to see how much things improved. As usually, the test isn&amp;#8217;t really reliable in any way and was just for fun.&lt;/p&gt;
&lt;p&gt;All the graphs report the request/sec the application has been able to perform on my computer with only 1 concurrent client. So higher is better.&lt;/p&gt;
&lt;p&gt;Here is the comparison between TG2.0 and TG2dev (will be 2.1.4)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://docs.google.com/spreadsheet/oimg?key=0AuIJBJ437w0BdHNHdUlwclF4WWtJcTBxZzJId0hLT0E&amp;oid=2&amp;zx=lp41836o721b&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I also compared various setups with different template engines on TG2dev &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://docs.google.com/spreadsheet/oimg?key=0AuIJBJ437w0BdHNHdUlwclF4WWtJcTBxZzJId0hLT0E&amp;oid=1&amp;zx=tjwtm6ymhmbj&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The comparison happened on an application similar to the quickstarted one.&lt;br /&gt;
Actually as there is no database involved in this application the template engine impacts a lot and so was a good benchmark for the template engines themselves.&lt;/p&gt;</description>
	<pubDate>Tue, 04 Oct 2011 15:35:48 +0000</pubDate>
</item>
<item>
	<title>Ralph Bean: threebean</title>
	<guid>http://threebean.wordpress.com/?p=424</guid>
	<link>http://threebean.wordpress.com/2011/10/03/raptorizemw-fact-every-wsgi-app-is-better-with-a-raptor/</link>
	<description>&lt;p&gt;It&amp;#8217;s done.  An over-engineered &lt;a href=&quot;http://wsgi.readthedocs.org/en/latest/&quot; target=&quot;_blank&quot;&gt;WSGI middleware&lt;/a&gt; component that adds a velociraptor to every page served.  Fact:  Every WSGI app is better with a raptor.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s called &lt;a href=&quot;http://pypi.python.org/pypi/raptorizemw&quot;&gt;raptorizemw&lt;/a&gt; (pronounced &amp;#8220;awesome&amp;#8221;) and the only way to use it is in production.&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/threebean.wordpress.com/424/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/threebean.wordpress.com/424/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=threebean.wordpress.com&amp;blog=8850237&amp;post=424&amp;subd=threebean&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Mon, 03 Oct 2011 20:35:34 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcement: TurboGears2 2.1.3 Released!</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-7595285113976133518</guid>
	<link>http://codersbuffet.blogspot.com/2011/09/announcement-turbogears2-213-released.html</link>
	<description>We are pleased to announce the latest release of &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt;, 2.1.3!&lt;br /&gt;&lt;br /&gt;This release adds support for the &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;Mongo object database&lt;/a&gt; and the &lt;a href=&quot;http://merciless.sourceforge.net/&quot;&gt;Ming ORM&lt;/a&gt; for it, in addition to bringing in some small bugfixes. The full changelog is below&lt;br /&gt;&lt;br /&gt;The number of changes is, admittedly, small, but don't underestimate the importance: &lt;a href=&quot;http://en.wikipedia.org/wiki/NoSQL&quot;&gt;NoSQL databases&lt;/a&gt; are an important tool for the web, and adding the support for Mongo brings &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; into the group of frameworks that not only supports it, but supports it well.&lt;br /&gt;&lt;br /&gt;We're already looking forward to expanding support and closing even more issues for 2.1.4, so we'll see you next month for that release!&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Added support for MongoDB into the quickstart template&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Added lurl (lazy_url) support for late evaluation&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Adding tests module back into source distribution. Solves ticket 115&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Template caching is now manageable by TG applications&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Clean up output for flash() in default quickstart&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Performance enhancements&lt;br /&gt;&lt;span class=&quot;Apple-tab-span&quot;&gt; &lt;/span&gt;* Fixed missing dependencies in TG quickstart on Python 2.4&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-7595285113976133518?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 28 Sep 2011 21:22:07 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Ralph Bean: threebean</title>
	<guid>http://threebean.wordpress.com/?p=409</guid>
	<link>http://threebean.wordpress.com/2011/09/24/turbogears-2-1-and-foreclosures-more-empty-houses-than-homeless-people/</link>
	<description>&lt;p&gt;I wrote an app that scrapes foreclosure data from my county of residence and plots it six ways from Sunday in a TurboGears2.1 app.  You can find it at &lt;a href=&quot;http://monroe-threebean.rhcloud.com/&quot;&gt;http://monroe-threebean.rhcloud.com/&lt;/a&gt;, hosted on redhat&amp;#8217;s openshift cloud.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s used by activists with &lt;a href=&quot;http://takebackroc.rocus.org/&quot;&gt;Take Back the Land, Rochester&lt;/a&gt; and my local branch of the &lt;a href=&quot;http://rochesteriso.org&quot;&gt;ISO&lt;/a&gt; to find upcoming evictions before they happen and organize the neighborhoods to stop the shuttering of homes.  Get a hundred people at the door of the house before the cops come, and no-one is getting evicted (we&amp;#8217;ve had &lt;a href=&quot;http://socialistworker.org/2011/05/11/activist-takes-back-her-home&quot;&gt;some&lt;/a&gt; &lt;a href=&quot;http://socialistworker.org/2011/08/23/no-eviction-for-cathy-lennon&quot;&gt;successes&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re living in some absurd times where banks got bailed out by the trillions yet still get to collect on our student debt and mortgages.  Most of us are being ruined.  If you&amp;#8217;re not, then your neighbor is.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re in Boston, check out &lt;a&gt;&lt;/a&gt;Vida Urbana&lt;/p&gt; or if you&amp;#8217;re in Chicago, check out the &lt;a href=&quot;http://chicagoantieviction.org/&quot;&gt;Chicago Anti-Eviction Campaign&lt;/a&gt;.  Anywhere you go, check out the &lt;a href=&quot;http://internationalsocialist.org&quot;&gt;ISO&lt;/a&gt;.
&lt;p&gt;&lt;a href=&quot;http://github.com/ralphbean/monroe&quot;&gt;Fork my code&lt;/a&gt;, port it to your home town, and start organizing!&lt;/p&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/threebean.wordpress.com/409/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/threebean.wordpress.com/409/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=threebean.wordpress.com&amp;blog=8850237&amp;post=409&amp;subd=threebean&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Sat, 24 Sep 2011 16:01:21 +0000</pubDate>
</item>
<item>
	<title>Christpher Arndt: Hurra, hurra, der Herbst ist da!</title>
	<guid>http://blog.chrisarndt.de/?p=612</guid>
	<link>http://blog.chrisarndt.de/article/612</link>
	<description>Warum man zur Zeit beim Spazierengehen immer große Taschen mitnehmen sollte...</description>
	<pubDate>Thu, 22 Sep 2011 20:38:46 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: TurboGears and Ming/Mongo</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-6641951277180466211</guid>
	<link>http://codersbuffet.blogspot.com/2011/09/turbogears-and-mingmongo.html</link>
	<description>I know that my followers are few, and my posts are too infrequent. I'm looking for ways to change my posting frequency.&lt;br /&gt;&lt;br /&gt;But, even still, I have an important request: &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; 2.1.3 is getting ready to be released. We're adding &lt;a href=&quot;http://merciless.sourceforge.net/tour.html&quot;&gt;Ming&lt;/a&gt;/&lt;a href=&quot;http://www.mongodb.org/&quot;&gt;Mongo&lt;/a&gt; support in this release. Anybody who can, please review the changes (&lt;a href=&quot;http://sourceforge.net/p/turbogears2/tg2/&quot;&gt;core&lt;/a&gt;, &lt;a href=&quot;http://sourceforge.net/p/turbogears2/tg2devtools/&quot;&gt;devtools&lt;/a&gt;, and &lt;a href=&quot;http://sourceforge.net/p/turbogears2/tg2docs/&quot;&gt;docs&lt;/a&gt;), run tests, etc. We need to make sure we've got this as correct as possible for everybody.&lt;br /&gt;&lt;br /&gt;Thank you for your time!&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-6641951277180466211?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Sun, 18 Sep 2011 21:29:30 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Curia: The long overdue “Shootout” update</title>
	<guid>http://blog.curiasolutions.com/?p=1079</guid>
	<link>http://blog.curiasolutions.com/2011/09/the-long-overdue-shootout-update/</link>
	<description>&lt;p&gt;It&amp;#8217;s been several months since I&amp;#8217;ve had a chance to update &lt;em&gt;&lt;a title=&quot;The Great Web Framework Shootout&quot; href=&quot;http://blog.curiasolutions.com/the-great-web-framework-shootout/&quot;&gt;The Great Web Framework Shootout&lt;/a&gt;&lt;/em&gt;, but this weekend I decided that it was time to dig in and freshen things up a bit.&lt;/p&gt;
&lt;p&gt;Not only have most of the frameworks seen new releases since the last revision, but I finally decided to move all of the tests over to Amazon&amp;#8217;s &amp;#8220;release&amp;#8221; version of the Ubuntu LTS AMI.&lt;/p&gt;
&lt;p&gt;Below is a quick summary of what&amp;#8217;s new in this revision:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All tests were performed on the updated Ubuntu LTS AMI (ami-fbbf7892 ubuntu-images-us/ubuntu-lucid-10.04-amd64-server-20110719.manifest.xml)&lt;/li&gt;
&lt;li&gt;The updated AMI was configured with Python 2.6.5, PHP 5.3.2, Ruby 1.9.2p290, Apache 2.2.14 (default config), mod_wsgi 2.8 (embedded mode), and mod_passenger 3.0.9&lt;/li&gt;
&lt;li&gt;Rails 2.x and 3.0 were dropped from the &amp;#8220;full stack(ish)&amp;#8221; tests in favor of Rails 3.1.&lt;/li&gt;
&lt;li&gt;CakePHP 1.2 was dropped from the PHP tests in favor of 1.3, but Symfony and Yii were added as they seem to have considerable market share.&lt;/li&gt;
&lt;li&gt;CakePHP&amp;#8217;s caching engine was incorrectly configured during the last round of tests, and this has been corrected.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://profiles.google.com/seedifferently&quot; target=&quot;_blank&quot;&gt;Circle me on Google+&lt;/a&gt; to keep track of further updates, and feel free to contact me there with any questions or comments.&lt;/p&gt;</description>
	<pubDate>Mon, 12 Sep 2011 19:08:06 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcement: TurboGears2 2.1.2 Released!</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-7443864970469834568</guid>
	<link>http://codersbuffet.blogspot.com/2011/08/announcement-turbogears2-212-released.html</link>
	<description>&lt;br /&gt;&lt;br /&gt;We are pleased to announce the latest release of TurboGears, 2.1.2!&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This is a maintenance/bugfix release for the 2.1 series which also adds some new features. The full changelog is below.&lt;br /&gt;&lt;br /&gt;Highlights for this release include the beginnings of our new book &quot;TurboGears2 Web Applications: Batteries Included&quot;, Python 2.7 support, improved Jinja2 support, and quite a few bug fixes.&lt;br /&gt;You can see the book as it stands right now at http://www.turbogears.org/book/ . We're working towards getting more details and more of the older documentation updated to go into the book.&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;&lt;br /&gt;We took longer to reach this release milestone than we had planned, but Real Life(tm) takes its toll on everybody during the summer months, it seems.&lt;br /&gt;&lt;br /&gt;Even still, I can speak for the whole team when I say that we look forward to continuing to serve the community with quality code, and we look forward to your continued support!&lt;br /&gt;&lt;br /&gt;Full Change Log Here:&lt;br /&gt;&lt;br /&gt;For TG2.x Core:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Improved content-type handling ( https://sourceforge.net/p/turbogears2/tickets/73/ )&lt;/li&gt;
&lt;li&gt;Fixed dotted filename support for Genshi and Chameleon.Genshi&lt;/li&gt;
&lt;li&gt;Removed lxml dependency; now preparation of virtualenv is much easier on 64 bit systems&lt;/li&gt;
&lt;li&gt;Upgraded Chameleon.Genshi support to Chameleon1.3rc&lt;/li&gt;
&lt;li&gt;Set up render_genshi on demand only, improves Google App Engine support&lt;/li&gt;
&lt;li&gt;Support for Python 2.7&lt;/li&gt;
&lt;li&gt;Improved Jinja2 and Jinja2 filters support ( https://sourceforge.net/p/turbogears2/tickets/107/ )&lt;/li&gt;
&lt;li&gt;Added option to prevent auto-saving sessions ( https://sourceforge.net/p/turbogears2/tickets/83/ )&lt;/li&gt;
&lt;li&gt;Fixed crash where multiple templates were registered and user called override_template ( https://sourceforge.net/p/turbogears2/tickets/82/ )&lt;/li&gt;
&lt;li&gt;Fixed problem with &quot;:&quot; in error messages ( https://sourceforge.net/p/turbogears2/tickets/86/ )&lt;/li&gt;
&lt;li&gt;Improved i18n support&lt;/li&gt;
&lt;li&gt;Improved pagination support ( https://sourceforge.net/p/turbogears2/tickets/99/ )&lt;/li&gt;
&lt;li&gt;Fixed warning resets when in debug mode ( https://sourceforge.net/p/turbogears2/tickets/84/ )&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For TG2.x Devtools:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Improved Genshi support in quickstart template&lt;/li&gt;
&lt;li&gt;Improved content-type handling ( https://sourceforge.net/p/turbogears2/tickets/73/ )&lt;/li&gt;
&lt;li&gt;Improved bootstrap if database is under version control&lt;/li&gt;
&lt;li&gt;Changed default password hashing to SHA256 ( https://sourceforge.net/p/turbogears2/tickets/94/ )&lt;/li&gt;
&lt;li&gt;New &quot;--minimal&quot; quickstart template&lt;/li&gt;
&lt;li&gt;Separated password hashing mechanism to make it more easily usable ( https://sourceforge.net/p/turbogears2/tickets/67/ )&lt;/li&gt;
&lt;li&gt;Fixed Unicode return type in auth.py ( https://sourceforge.net/p/turbogears2/tickets/89/ )&lt;/li&gt;
&lt;li&gt;Added missing dependencies for Python 2.4 and the quickstart app ( https://sourceforge.net/p/turbogears2/tickets/100/ )&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For TG2.x Docs:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Introduced new book beginnings&lt;/li&gt;
&lt;li&gt;Rewrote 20 Minute Wiki, brought it forward to working with TG2.1.2&lt;/li&gt;
&lt;li&gt;Rewrote installation instructions, much simplified&lt;/li&gt;
&lt;li&gt;Began description of new application for tutorial/book&lt;/li&gt;
&lt;li&gt;Improved documentation on how to contribute&lt;/li&gt;
&lt;li&gt;Made all standard modules autodocumented in the appendices&lt;/li&gt;
&lt;li&gt;&quot;ignore_parameters&quot; documented ( https://sourceforge.net/p/turbogears2/tickets/15/ )&lt;/li&gt;
&lt;li&gt;&quot;tg_avoid_touch&quot; (method to avoid saving sessions) documented ( https://sourceforge.net/p/turbogears2/tickets/83/ )&lt;/li&gt;
&lt;li&gt;Updated references regarding _default and _lookup ( https://sourceforge.net/p/turbogears2/tickets/5/ )&lt;/li&gt;
&lt;li&gt;Documented custom filters for Jinja2&lt;/li&gt;
&lt;li&gt;&quot;migrate&quot; command is now documented ( https://sourceforge.net/p/turbogears2/tickets/106/ )&lt;/li&gt;
&lt;li&gt;Documented pagination parameters&lt;/li&gt;
&lt;li&gt;Documented &quot;--minimal&quot; quickstart option ( https://sourceforge.net/p/turbogears2/tickets/102/ )&lt;/li&gt;
&lt;li&gt;Changed references to &quot;aptitude&quot; to &quot;apt-get&quot; ( https://sourceforge.net/p/turbogears2/tickets/104/ )&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-7443864970469834568?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 24 Aug 2011 20:58:33 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Ralph Bean: You should be all gravy.</title>
	<guid>http://threebean.wordpress.com/?p=380</guid>
	<link>http://threebean.wordpress.com/2011/07/19/using-repoze-who-plugins-ldap-in-a-turbogears-2-1-app/</link>
	<description>&lt;p&gt;Often, you will need to authenticate against &lt;code&gt;ldap&lt;/code&gt; in your webapp.  Here&amp;#8217;s how to make that happen in a freshly quickstarted TurboGears 2.1 app.&lt;/p&gt;
&lt;h2&gt;Setting up your environment&lt;/h2&gt;
&lt;p&gt;&lt;pre class=&quot;brush: bash;&quot;&gt;
mkvirtualenv --no-site-packages repoze-ldap-app
pip install tg.devtools
paster quickstart   # call the app repoze-ldap-app, yes to mako and auth
cd repoze-ldap-app
python setup.py develop
pip install genshi  # This is a workaround.
paster setup-app development.ini
paster serve development.ini  # To test if the basic app works.
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Point your browser at &lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt; just to make sure everything is cool.&lt;/p&gt;
&lt;h2&gt;Setting up &lt;code&gt;repoze.who.plugins.ldap&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Add&lt;/strong&gt; the following line to the &lt;code&gt;install_requires&lt;/code&gt; list in &lt;code&gt;setup.py&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
    &amp;quot;repoze.who.plugins.ldap&amp;quot;,
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Run &lt;code&gt;python setup.py develop&lt;/code&gt; to install the newly listed repoze plugin.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Add&lt;/strong&gt; the following four lines to &lt;code&gt;development.ini&lt;/code&gt; which reference an as yet unwritten secondary configuration file.  Place them just above the &lt;code&gt;sqlalchemy.url=...&lt;/code&gt; lines:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: plain;&quot;&gt;
# Repoze.who stuff
who.config_file = %(here)s/who.ini
who.log_level = INFO
who.log_stream = stdout
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create&lt;/strong&gt; a new file &lt;code&gt;who.ini&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: plain;&quot;&gt;
# This file is adapted from:
# http://threebean.wordpress.com/2011/07/19/using-repoze-who-plugins-ldap-in-a-turbogears-2-1-app/
# which has been adapted from:
# http://static.repoze.org/whodocs/#middleware-configuration-via-config-file
# which has been adapted from:
# http://code.gustavonarea.net/repoze.who.plugins.ldap/Using.html

[plugin:friendlyform]
use = repoze.who.plugins.friendlyform:FriendlyFormPlugin
login_form_url= /login
login_handler_path = /login_handler
logout_handler_path = /logout_handler
rememberer_name = auth_tkt
post_login_url = /post_login
post_logout_url = /post_logout

[plugin:auth_tkt]
use = repoze.who.plugins.auth_tkt:make_plugin
secret = omg_this_is_so_secret_lololololol_2938485#butts

[plugin:ldap_auth]
# Here I use my own ldap_auth, since by default ldap allows affirmative
# authentication with *no password specified*.  That is lame; I override it.
use = repozeldapapp.lib.auth:ReconnectingAuthenticatorPlugin

# This is the URI of wherever you want to connect to.  I work at RIT.
ldap_connection = ldap://ldap.rit.edu

# This is the base of the 'distinguished names' (DNs) of persons in your
# particular LDAP instance.  It will vary from server to server.
base_dn = ou=People,dc=rit,dc=edu

[plugin:ldap_attributes]
# I also do some overriding for more security in how I get attributes for
# users.
use = repozeldapapp.lib.auth:ReconnectingLDAPAttrsPlugin
ldap_connection = ldap://ldap.rit.edu

[general]
request_classifier = repoze.who.classifiers:default_request_classifier
challenge_decider = repoze.who.classifiers:default_challenge_decider

[mdproviders]
plugins =
    ldap_attributes

[identifiers]
plugins =
    friendlyform;browser
    auth_tkt

[authenticators]
plugins =
    ldap_auth

[challengers]
plugins =
    friendlyform;browser
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create&lt;/strong&gt; another new file &lt;code&gt;repozeldapapp/lib/auth.py&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
from repoze.who.plugins.ldap import (
    LDAPAttributesPlugin, LDAPAuthenticatorPlugin
)
import ldap


class URISaver(object):
    &amp;quot;&amp;quot;&amp;quot; Saves the ldap_connection str given to repoze authn and authz &amp;quot;&amp;quot;&amp;quot;
    def __init__(self, *args, **kw):
        self.uri = kw['ldap_connection']
        super(URISaver, self).__init__(*args, **kw)


class ReconnectingLDAPAttrsPlugin(LDAPAttributesPlugin, URISaver):
    &amp;quot;&amp;quot;&amp;quot; Gets attributes from LDAP.  Refreshes connection if stale. &amp;quot;&amp;quot;&amp;quot;

    def add_metadata(self, environ, identity):
        &amp;quot;&amp;quot;&amp;quot; Add ldap attributes to the `identity` entry. &amp;quot;&amp;quot;&amp;quot;

        try:
            return super(ReconnectingLDAPAttrsPlugin, self).add_metadata(
                environ, identity)
        except Exception, e:
            print &amp;quot;FAILED TO CONNECT TO LDAP 1 : &amp;quot; + str(e)
            print &amp;quot;Retrying...&amp;quot;
            self.ldap_connection = ldap.initialize(self.uri)
            return super(ReconnectingLDAPAttrsPlugin, self).add_metadata(
                environ, identity)


class ReconnectingAuthenticatorPlugin(LDAPAuthenticatorPlugin, URISaver):
    &amp;quot;&amp;quot;&amp;quot; Authenticates against LDAP.

    - Refreshes connection if stale.
    - Denies anonymously-authenticated users

    &amp;quot;&amp;quot;&amp;quot;

    def authenticate(self, environ, identity):
        &amp;quot;&amp;quot;&amp;quot; Extending the repoze.who.plugins.ldap plugin to make it much
        more secure. &amp;quot;&amp;quot;&amp;quot;

        res = None

        try:
            # This is unbelievable.  Without this, ldap will
            #   let you bind anonymously
            if not identity.get('password', None):
                return None
            try:
                dn = self._get_dn(environ, identity)
            except (KeyError, TypeError, ValueError):
                return None

            res = super(ReconnectingAuthenticatorPlugin, self).authenticate(
                environ, identity)

            # Sanity check here (for the same reason as the above check)
            if &amp;quot;dn:%s&amp;quot; % dn != self.ldap_connection.whoami_s():
                return None

        except ldap.LDAPError, e:
            print &amp;quot;FAILED TO CONNECT TO LDAP 2 : &amp;quot; + str(e)
            print &amp;quot;Retrying...&amp;quot;
            self.ldap_connection = ldap.initialize(self.uri)

        return res
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Finally, do two things to &lt;code&gt;repozeldapapp/config/middleware.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt; it and at the top of the file add:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
from repoze.who.config import make_middleware_with_config
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Add&lt;/strong&gt; the following inside the &lt;code&gt;make_app(...)&lt;/code&gt; function, just below the comment line about Wrap your base TurboGears 2&amp;#8230;, like so:&lt;/p&gt;
&lt;p&gt;&lt;pre class=&quot;brush: python;&quot;&gt;
    # Wrap your base TurboGears 2 application with custom middleware here
    app = make_middleware_with_config(
        app, global_conf,
        app_conf['who.config_file'],
        app_conf['who.log_stream'],
        app_conf['who.log_level'])
&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;Give it a test&lt;/h2&gt;
&lt;p&gt;Restart the &lt;code&gt;paster&lt;/code&gt; server and reload &lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt;.  Try logging in as a user in your ldap instance and you should be all gravy.&lt;/p&gt;
&lt;div class=&quot;wp-caption aligncenter&quot;&gt;&lt;a href=&quot;http://www.flickr.com/photos/deathbeforedisco/3608101114&quot;&gt;&lt;img alt=&quot;You should be all gravy.&quot; src=&quot;http://farm4.static.flickr.com/3393/3608101114_22a355e9a5_b.jpg&quot; title=&quot;You should be all gravy.&quot; width=&quot;256&quot; height=&quot;192&quot; /&gt;&lt;/a&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;You should be all gravy.&lt;/p&gt;&lt;/div&gt;
&lt;br /&gt;  &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gocomments/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/comments/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godelicious/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/delicious/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gofacebook/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/facebook/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gotwitter/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/twitter/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/gostumble/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/stumble/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/godigg/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/digg/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;http://feeds.wordpress.com/1.0/goreddit/threebean.wordpress.com/380/&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://feeds.wordpress.com/1.0/reddit/threebean.wordpress.com/380/&quot; /&gt;&lt;/a&gt; &lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=threebean.wordpress.com&amp;blog=8850237&amp;post=380&amp;subd=threebean&amp;ref=&amp;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot; /&gt;</description>
	<pubDate>Tue, 19 Jul 2011 16:24:24 +0000</pubDate>
</item>
<item>
	<title>Mengu Kagan: Deploying TurboGears 2.1 Application With Nginx And uWSGI</title>
	<guid>http://www.mengu.net/post/deploying-turbogears-21-application-with-nginx-and-uwsgi</guid>
	<link>http://www.mengu.net/post/deploying-turbogears-21-application-with-nginx-and-uwsgi</link>
	<description>&lt;p&gt;I have developed a &lt;a href=&quot;http://www.turbogears.org&quot;&gt;TurboGears 2.1&lt;/a&gt; application and I was asked to deploy it today. I was planning to use Apache and mod_wsgi however on CentOS 5.6 both are painful. I was getting some errors that I really did not want to deal with so I have decided to use &lt;a href=&quot;http://www.nginx.org&quot;&gt;nginx&lt;/a&gt; and &lt;a href=&quot;http://projects.unbit.it/uwsgi/&quot;&gt;uWSGI&lt;/a&gt;. Great combination I believe. The thing is I had to deploy this application to 3 web servers as we are using a load balancer so I have created a deployment script to use on all 3 web servers but surely I won't let you figure out how to deploy from this script.&lt;/p&gt;

&lt;p&gt;Let's cut the chase and get to the point.&lt;/p&gt;</description>
	<pubDate>Fri, 15 Jul 2011 03:03:30 +0000</pubDate>
</item>
<item>
	<title>Christpher Arndt: ELKA PM 13 MIDI Basspedal (Version B)</title>
	<guid>http://blog.chrisarndt.de/?p=598</guid>
	<link>http://blog.chrisarndt.de/article/598</link>
	<description>Beschreibung, Anleitung und Kurzreview Das ELKA EM 13 MIDI Basspedal ist ein reiner MIDI-Controller ohne Klangerzeugung und dafür ausgelegt, mit den Füßen gespielt zu werden, um beide Hände zum Gitarre- oder Keyboardspielen oder Sonstigem freizuhaben. Die Pedale umfassen eine Oktave, von C bis C, ansonsten hat das Gerät keinerlei Klangsteuerungsmöglichkeiten und auch nur einen zusätzlichen [...]</description>
	<pubDate>Tue, 12 Jul 2011 13:23:58 +0000</pubDate>
</item>
<item>
	<title>Curia: Google+: It’s a bigger deal than Facebook, but not like you think</title>
	<guid>http://blog.curiasolutions.com/?p=1048</guid>
	<link>http://blog.curiasolutions.com/2011/07/google-its-a-bigger-deal-than-facebook-but-not-like-you-think/</link>
	<description>&lt;p&gt;I&amp;#8217;ve been on Google+ since week 1 and while the initial mood has been overwhelmingly positive, I couldn&amp;#8217;t help but notice the content of my stream becoming a bit skewed over the past few days as Google began opening it up more and more to &amp;#8220;the laypeople.&amp;#8221; Google was wise to restrict G+&amp;#8217;s initial membership base to the tech-savvy, because we&amp;#8217;re already on to Google about where it&amp;#8217;s going with this thing; but now that the rest of the world is jumping onboard there seems to be a bit of confusion about what it&amp;#8217;s good for.&lt;/p&gt;
&lt;p&gt;In response to this, I thought I&amp;#8217;d share a few of my own thoughts on G+, and why I believe it is a valuable and needed addition the online social ecosystem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;1. It&amp;#8217;s not Facebook, and it&amp;#8217;s not Twitter—it&amp;#8217;s a bit of both, and the key is Circles.&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;What Twitter does best is giving busy professionals, celebrities, and business entities an outlet to interact &lt;em&gt;publicly&lt;/em&gt; with their audience on a pseudo-personal level &lt;em&gt;in 140 characters or less&lt;/em&gt;. What Facebook does best is giving people an outlet to interact &lt;em&gt;somewhat privately&lt;/em&gt; with &lt;em&gt;people they trust&lt;/em&gt; on as personal of a level as they like. For many, the separation between Twitter vs. Facebook mirrors their own separation of business vs. personal. For example: A picture of your 2-year old squeezing the cat is more likely to wind up posted to a &lt;em&gt;limited audience&lt;/em&gt; on Facebook than publicly shared on Twitter, while a quick blurb updating &lt;em&gt;anyone interested&lt;/em&gt; on a recent professional achievement often &lt;em&gt;needs&lt;/em&gt; a more public forum such as Twitter to gain the visibility you want it to have. Even in each of their post boxes you can see the difference in what&amp;#8217;s expected to be shared: Twitter asks &amp;#8220;What&amp;#8217;s happening?&amp;#8221; expecting you to want the whole world to know, while Facebook asks &amp;#8220;What&amp;#8217;s on your mind?&amp;#8221; which is quite a bit more personal. &lt;span id=&quot;more-1048&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What Google+ gives you is both (and much more), through the power of a brilliant feature called Circles. No longer is it a question of public vs. private, but rather the much more honest and straightforward &amp;#8221;Who do you want to share this with?&amp;#8221; Through Circles, you now have complete control over who will and who wont see the content you are about to share. You may only want &amp;#8220;close friends&amp;#8221; to see how crazy that party was last night, while &amp;#8220;friends&amp;#8221; can be given access to pictures of your recent vacation to Hawaii, and &lt;em&gt;the whole world&lt;/em&gt; can have access to that presentation you did last week that received a standing ovation.&lt;/p&gt;
&lt;p&gt;(Note: Yes I am aware that Facebook offers something similar to Circles, but its integration is clumsy and inconvenient in comparison.)&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;2. For now, it may only be relevant to those who manage multiple online identities.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Sure, there are plenty of people who use Twitter and Facebook as practically the same outlet, and if you&amp;#8217;re one of those then Google+ is probably going to be little more than a redundant nuisance—one more social network to have to keep track of.&lt;/p&gt;
&lt;p&gt;Or perhaps you&amp;#8217;re the Facebook-only or Twitter-only type and simply don&amp;#8217;t see the point in jumping ship or picking up another service. I applaud you for your loyalty, but in this day and age resistance to &amp;#8220;the big G&amp;#8221; is futile. Which leads me to my final thought&amp;#8230;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;3. If you can look to the horizon, it might just be bigger than anything we&amp;#8217;ve seen yet!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The real thing to keep in mind in these early days is that G+ is just the beginning of Google&amp;#8217;s plan to bring a social element to many of its products and services. In the coming months, you are probably going to see the google.com ecosystem revolve more and more tightly around G+ to a point where involvement in the + will be unavoidable. They have already somewhat merged Picasa and there are whispers of a full-on integration with Gmail. What else could be coming? Well, just think about all of the services that Google currently offers and simply add a &amp;#8220;+&amp;#8221; to them: Music+, Calendar+, Maps+, Docs+, Checkout+, etc.—and I&amp;#8217;m not even going to take the time here to mention Android and the possible mobile implications!&lt;/p&gt;
&lt;p&gt;But what about speculative projects? Well, Google recently sank loads of cash into a little company called Zynga and not too long ago partnered with Rovio to bring Angry Birds to Chrome. Can you imagine playing &amp;#8220;Words With Friends+&amp;#8221; or &amp;#8220;Angry Birds+&amp;#8221; online with all your G+ friends?&lt;/p&gt;
&lt;p&gt;The future of Google is here folks, and it&amp;#8217;s as subtle as a +.&lt;/p&gt;</description>
	<pubDate>Tue, 12 Jul 2011 01:53:41 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: TurboGears 2.1.1 released!</title>
	<guid>http://blog.axant.it/?p=396</guid>
	<link>http://blog.axant.it/archives/396</link>
	<description>&lt;p&gt;After a reflection moment caused by the need to think what will follow after the pylons and repoze.bfg merge in pyramid the TurboGears2 team has decide to gather up all its forces and give to TurboGears2 its own independent life.&lt;/p&gt;
&lt;p&gt;The first steps have been oriented to improve the framework reliability and brought to life the &lt;a href=&quot;http://jenkins.turbogears.org/view/TurboGears%20Hosted/&quot;&gt;TurboGears&lt;/a&gt; continuous integrations system and a standard project release process.&lt;/p&gt;
&lt;p&gt;After a few months of work 2.1.1 has been released and it brings many fixes and improvements, 2.1.2 is under its way and a 2.2 release with major improvements is already planned!&lt;/p&gt;
&lt;p&gt;TG2 Core:&lt;br /&gt;
* Fixed dependencies for Python 2.4. Now any packages that are&lt;br /&gt;
needed are automatically installed.&lt;br /&gt;
* Updated package requirements as high as possible.&lt;br /&gt;
* Verified nested RestControllers work as expected&lt;br /&gt;
* Added/fixed Kajiki support&lt;br /&gt;
* Ignore repoze.who_testutil when running nosetests&lt;br /&gt;
* Fixed import order for pylons.middleware&lt;br /&gt;
* Fixed crash when PYTHONOPTIMIZE is enabled&lt;br /&gt;
* Report a warning about ErrorMiddleware is disabled&lt;br /&gt;
* Fixed concurrency issues with use_custom_format&lt;br /&gt;
* Fixed 404 errors if a controller uses only custom formats&lt;br /&gt;
* Verified that user object is available inside of the error controller/template&lt;br /&gt;
* Fixed expansion of arguments on before/after calls&lt;br /&gt;
* Fixed wrong header response for 405 error&lt;br /&gt;
* Fixed WebOb version requirment. Newer version required&lt;br /&gt;
* Added test case to check for replace_header when called from WSGIApp&lt;br /&gt;
* Fixed issues with Content-Type header appearing multiples times on 204/205 responses&lt;br /&gt;
* Removed redundant hasattr checks on override_template&lt;br /&gt;
* Improved support for pylons 1.0 strict_c&lt;br /&gt;
* Fixed post traceback, now reports to Pylons correctly&lt;br /&gt;
* Added test case to check for spurious content type removal on empty content&lt;br /&gt;
* Fixed crash when content type header is missing&lt;br /&gt;
* Fixed crash when response Content-Type is set to None&lt;br /&gt;
* Fixed support for etags. Pylons 1.0 changes slightly, we support the correct version now&lt;br /&gt;
* Added dependency_links and setup.cfg allow_hosts: easy_install TurboGears2 now works&lt;br /&gt;
* Fixed DecoratedController. should not call super(), 2.6 revealed a problem&lt;br /&gt;
* Fixed Genshi output method. Use XHTML if none specified, instead of XML&lt;/p&gt;
&lt;p&gt;TG2 Devtools:&lt;br /&gt;
* Fixed Python 2.4 compatibility issues. Dependencies are now automatically specified&lt;br /&gt;
* Updated package version requirements as high as possible&lt;br /&gt;
* Fixed about.html instructions about where the logo is found&lt;br /&gt;
* Set &amp;#8220;zip_safe=False&amp;#8221; by default in the templates now&lt;br /&gt;
* Tests fixed, now pass&lt;br /&gt;
* Added support for sqlalchemy-migrate&lt;br /&gt;
* Added option to choose config file&lt;br /&gt;
* Added archive_tw_resources command for projects&lt;br /&gt;
* Fixed deprecated redirect calls&lt;br /&gt;
* Set Genshi templating method by default to XHTML&lt;br /&gt;
* Adding dependency_links: easy_install tg.devtools now works&lt;/p&gt;</description>
	<pubDate>Sun, 19 Jun 2011 08:59:05 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcement: TurboGears 2.1.1 Released!</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-6534907918960539384</guid>
	<link>http://codersbuffet.blogspot.com/2011/06/announcement-turbogears-211-released.html</link>
	<description>We are pleased to announce the latest release of TurboGears, 2.1.1!&lt;br /&gt;&lt;br /&gt;This is a maintenance/bugfix release for the 2.1 series. The full changelog is below.&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;&lt;br /&gt;This release has been a long time in the making, and I would like to take a few minutes to thank the people who made it happen.&lt;br /&gt;&lt;br /&gt;Mark Ramm, Chris Perkins, and Kevin Dangoor, for supporting me in beginning this whole process back in January.&lt;br /&gt;&lt;br /&gt;Alessandro Molina, Christoph Zwerschke, and Diez Roggisch, for contributing much of their precious free time to writing code, making suggestions, and keeping me on track.&lt;br /&gt;&lt;br /&gt;Florent Aide and Jon Schemoul, for providing us with a server and tgext.pages to make the site work.&lt;br /&gt;&lt;br /&gt;And to everybody in the community that I did not name: Without you, I don't think I would have kept myself working. The results are here, and they belong to you as much as any of the people I named above.&lt;br /&gt;&lt;br /&gt;Thank you, everybody. Your support and help mean a great deal to me. I only hope I've lived up to some of your expectations.&lt;br /&gt;&lt;br /&gt;I can speak for the whole team when I say that we look forward to continuing to serve the community with quality code, and we look forward to your continued support!&lt;br /&gt;&lt;br /&gt;And I know I can say it most strongly for myself. We're back on the move. And I'm liking the results.&lt;br /&gt;&lt;br /&gt;Full Change Log Here:&lt;br /&gt;&lt;br /&gt;TG2 Core:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fixed dependencies for Python 2.4. Now any packages that are needed are automatically installed.&lt;/li&gt;&lt;li&gt;Updated package requirements as high as possible.&lt;/li&gt;&lt;li&gt;Verified nested RestControllers work as expected&lt;/li&gt;&lt;li&gt;Added/fixed Kajiki support&lt;/li&gt;&lt;li&gt;Ignore repoze.who_testutil when running nosetests&lt;/li&gt;&lt;li&gt;Fixed import order for pylons.middleware&lt;/li&gt;&lt;li&gt;Fixed crash when PYTHONOPTIMIZE is enabled&lt;/li&gt;&lt;li&gt;Report a warning about ErrorMiddleware is disabled&lt;/li&gt;&lt;li&gt;Fixed concurrency issues with use_custom_format&lt;/li&gt;&lt;li&gt;Fixed 404 errors if a controller uses only custom formats&lt;/li&gt;&lt;li&gt;Verified that user object is available inside of the error controller/template&lt;/li&gt;&lt;li&gt;Fixed expansion of arguments on before/after calls&lt;/li&gt;&lt;li&gt;Fixed wrong header response for 405 error&lt;/li&gt;&lt;li&gt;Fixed WebOb version requirment. Newer version required&lt;/li&gt;&lt;li&gt;Added test case to check for replace_header when called from WSGIApp&lt;/li&gt;&lt;li&gt;Fixed issues with Content-Type header appearing multiples times on 204/205 responses&lt;/li&gt;&lt;li&gt;Removed redundant hasattr checks on override_template&lt;/li&gt;&lt;li&gt;Improved support for pylons 1.0 strict_c&lt;/li&gt;&lt;li&gt;Fixed post traceback, now reports to Pylons correctly&lt;/li&gt;&lt;li&gt;Added test case to check for spurious content type removal on empty content&lt;/li&gt;&lt;li&gt;Fixed crash when content type header is missing&lt;/li&gt;&lt;li&gt;Fixed crash when response Content-Type is set to None&lt;/li&gt;&lt;li&gt;Fixed support for etags. Pylons 1.0 changes slightly, we support the correct version now&lt;/li&gt;&lt;li&gt;Added dependency_links and setup.cfg allow_hosts: easy_install TurboGears2 now works&lt;/li&gt;&lt;li&gt;Fixed DecoratedController. should not call super(), 2.6 revealed a problem&lt;/li&gt;&lt;li&gt;Fixed Genshi output method. Use XHTML if none specified, instead of XML&lt;/li&gt;&lt;/ul&gt;TG2 Devtools:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fixed Python 2.4 compatibility issues. Dependencies are now automatically specified&lt;/li&gt;&lt;li&gt;Updated package version requirements as high as possible&lt;/li&gt;&lt;li&gt;Fixed about.html instructions about where the logo is found&lt;/li&gt;&lt;li&gt;Set &quot;zip_safe=False&quot; by default in the templates now&lt;/li&gt;&lt;li&gt;Tests fixed, now pass&lt;/li&gt;&lt;li&gt;Added support for sqlalchemy-migrate&lt;/li&gt;&lt;li&gt;Added option to choose config file&lt;/li&gt;&lt;li&gt;Added archive_tw_resources command for projects&lt;/li&gt;&lt;li&gt;Fixed deprecated redirect calls&lt;/li&gt;&lt;li&gt;Set Genshi templating method by default to XHTML&lt;/li&gt;&lt;li&gt;Adding dependency_links: easy_install tg.devtools now works&lt;/li&gt;&lt;/ul&gt;TG2 Docs:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;New book doc project started.&lt;/li&gt;&lt;li&gt;Added note about how/why to set zip_safe to False&lt;/li&gt;&lt;li&gt;Fixed import statement in some examples&lt;/li&gt;&lt;li&gt;Fixed spelling errors&lt;/li&gt;&lt;li&gt;Fixed wiki tutorial errors about bootstrapping, also the missing setup.py&lt;/li&gt;&lt;li&gt;Removed dead references in modwsgi deployment documentation&lt;/li&gt;&lt;li&gt;Fixed warnings. None remain right now&lt;/li&gt;&lt;li&gt;Implemented new theme donated by Christoph Zwerschke&lt;/li&gt;&lt;li&gt;Added documentation on how to extract ToscaWidgets resources&lt;/li&gt;&lt;li&gt;Added tutorials for DataGrid, pagination, sorting, and custom columns&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-6534907918960539384?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 15 Jun 2011 21:21:10 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: Announcing TurboGears 2.0.4</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-5824563682787482418</guid>
	<link>http://codersbuffet.blogspot.com/2011/06/announcing-turbogears-204.html</link>
	<description>We are pleased to announce the latest release in the 2.0 series, TurboGears 2.0.4.&lt;br /&gt;&lt;br /&gt;This is a maintenance/bugfix release for the 2.0 series. The full changelog is below.&lt;br /&gt;&lt;br /&gt;Note that, unless security issues are found, this will be the final release of the 2.0.x line. As 2.1 is fully backwards compatible, and release of 2.1.1 is imminent, we strongly encourage everybody to upgrade as soon as possible.&lt;br /&gt;&lt;br /&gt;We look forward to continuing to serve the community with quality code, and we look forward to your continued support!&lt;br /&gt;&lt;br /&gt;The following changes were added for 2.0.4:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Python 2.4 compatibility was fixed.&lt;/li&gt;&lt;li&gt;Nested RestControllers had a bug preventing the proper&lt;/li&gt;&lt;li&gt;resolution of the &quot;delete&quot; method. This has been fixed.&lt;/li&gt;&lt;li&gt;When all @expose'd methods of a controller had a&lt;/li&gt;&lt;li&gt;CUSTOM_CONTENT_TYPE, a 404 would be returned. This has been fixed.&lt;/li&gt;&lt;li&gt;Problem existed with getting tuples into controllers. Patch from&lt;/li&gt;&lt;li&gt;bug 37 applied to fix this.&lt;/li&gt;&lt;li&gt;Brought the current TG2 private PyPI current. Getting installation&lt;/li&gt;&lt;li&gt;to work is now as easy as &quot;easy_install TurboGears2==2.0.4&quot;&lt;/li&gt;&lt;li&gt;Got automated testing working consistently.&lt;/li&gt;&lt;li&gt;Added tests for mixing positional args, keyword args, and pagination&lt;/li&gt;&lt;li&gt;dependency_links is now in place to make it easier to get the initial&lt;/li&gt;&lt;li&gt;setup done&lt;/li&gt;&lt;li&gt;Several other smaller bugs were fixed.&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-5824563682787482418?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Sat, 04 Jun 2011 21:55:59 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Cliff Wells: I joined Facebook</title>
	<guid>http://www.enemyofthestatement.com/i-joined-facebook</guid>
	<link>http://www.enemyofthestatement.com/i-joined-facebook</link>
	<description>&lt;div class=&quot;document&quot;&gt;
&lt;p&gt;I've been a long-time opponent of Facebook, and social networking sites in general (my opposition started way back when Orkut was the cool thing).  My reasons are simple: I value privacy and I feel these sites make too much information available to both civil authorities as well as corporations.  My canned summary of this position was to ask: &amp;quot;Are you, or have you ever been, a member of the Communist Party?&amp;quot;, quoting our infamous McCarthy, who would have absolutely adored Facebook, with its easy-to-navigate graphs of relationships.&lt;/p&gt;
&lt;p&gt;I still feel Facebook should have never existed and is simply too dangerous.&lt;/p&gt;
&lt;p&gt;So why did I join (and friend a lot of people)?  The reasons are myriad, but at the end of the day it comes down to this: the genie is out of the bottle and can't be put back in.  My wife is on Facebook, my friends are on Facebook.  Facebook &lt;em&gt;already knows who I am, and who my friends are&lt;/em&gt;.  Despite the fact that I chose not to engage, I have to finally admit I'm already part of the system.  At this point, I can either pretend this isn't the case, or I can choose to engage on my own terms, as best I can.&lt;/p&gt;
&lt;p&gt;We are all aware of the abuses of Facebook and its complete and utter disregard for its user's privacy.  But I've also seen Facebook used to empower people in ways previously unheard of.  The turning point for me came a couple of days ago when I read &lt;a class=&quot;reference external&quot; href=&quot;http://www.readwriteweb.com/archives/brazil_facebook_flash_mob.php&quot;&gt;this article&lt;/a&gt;, about a &amp;quot;flash mob&amp;quot; of 40,000 people who came together, mostly via Facebook, to protest against a wealthy neighborhood who wanted to keep them out.
This is something previously unheard of, and really, previously impossible.  The reality is that Facebook and friends are, like most powerful technologies, a double-edged sword; we can either allow it to be wielded against us, or we can wield it ourselves.&lt;/p&gt;
&lt;p&gt;In any case, I've decided that Facebook (and social networks in general), are little more than the culmination of the Internet as a whole.  Really, if we wanted to stop Facebook, we'd have needed to stop the Internet (and for many of the same reasons).  At the end of the day, for better or worse, the world is now networked. Anonymity is over and has been for some time.  While I'm still trying to wrap my head around it, I have a gut feeling that the only hope we have for privacy is to create such a glut of data that it can never be fully digested, that to parade our social networks is possibly the only protection we have left.  After all, if they know my wife, my friends, my family, what good is my own anonymity?&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Sun, 15 May 2011 23:30:49 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: Red Hat OpenShift Express &amp; The Leafy Miracle</title>
	<guid>http://lewk.org/blog/2011/05/07/leafy-miracle</guid>
	<link>http://lewk.org/blog/leafy-miracle.html</link>
	<description>&lt;p&gt;

&lt;a href=&quot;http://redhat.com&quot;&gt;Red Hat&lt;/a&gt; made a lot of awesome announcements
this week at &lt;a href=&quot;http://www.redhat.com/summit/&quot;&gt;The Red Hat Summit&lt;/a&gt;, one of which being &lt;a href=&quot;http://openshift.redhat.com/app/&quot;&gt;OpenShift&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
I had the opportunity to play with the internal beta for a little while now,
and I must say that as a developer I am extremely impressed with the service.
Just being able to &lt;code&gt;git push&lt;/code&gt; my code into to the cloud drastically simplifies
large-scale software deployment, and makes it so I don't even have
to leave my development environment.
&lt;/p&gt;

&lt;p&gt;
    I figured out a way to get &lt;a href=&quot;http://turbogears.org&quot;&gt;TurboGears2&lt;/a&gt; and &lt;a href=&quot;http://pylonsproject.com&quot;&gt;Pyramid&lt;/a&gt; running on OpenShift Express, and documented it &lt;a href=&quot;https://www.redhat.com/openshift/blogs/deploying-turbogears2-python-web-framework-using-express&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://www.redhat.com/openshift/blogs/deploying-a-pyramid-application-in-a-virtual-python-wsgi-environment-on-red-hat-openshift-expr&quot;&gt;here&lt;/a&gt;. After that, I proceeded to write my very first Pyramid application.
&lt;/p&gt;

&lt;p&gt;
    &lt;b&gt;[ The Leafy Miracle ]&lt;/b&gt;&lt;br /&gt;

&lt;p&gt;
    In memory of the proposed [and &lt;a href=&quot;http://lewk.org/beefy.txt&quot;&gt;rejected&lt;/a&gt;] Fedora 16 codename &quot;&lt;a href=&quot;http://beefymiracle.org&quot;&gt;Beefy Miracle&lt;/a&gt;&quot;, this little app
is called &quot;Leafy Miracle&quot;.
&lt;/p&gt;

&lt;center&gt;
    &lt;b&gt;&lt;a href=&quot;http://leafy-miracle.rhcloud.com&quot;&gt;leafy-miracle.rhcloud.com&lt;/a&gt;&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/center&gt;

&lt;center&gt;
    &lt;a href=&quot;http://leafy-miracle.rhcloud.com&quot;&gt;&lt;img src=&quot;http://lewk.org/img/leafy.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://pylonsproject.org/projects/pyramid/about&quot;&gt;&lt;img src=&quot;http://docs.pylonsproject.org/_images/pyramid_105x28_white.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;
&lt;/p&gt;
&lt;b&gt;[ Features &amp;amp; Tech ]&lt;/b&gt;&lt;br /&gt;

&lt;p&gt;
&lt;ul&gt;
&lt;li&gt;Written in &lt;a href=&quot;http://python.org&quot;&gt;Python&lt;/a&gt; using the &lt;a href=&quot;http://pylonsproject.org&quot;&gt;Pyramid&lt;/a&gt; web framework&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sqlalchemy.org&quot;&gt;SQLAlchemy&lt;/a&gt; database model of &lt;a href=&quot;http://yum.baseurl.org&quot;&gt;Yum&lt;/a&gt; Categories, Groups, Packages, Dependencies, and Dependants&lt;/li&gt;
&lt;li&gt;Interactive graph widget, using &lt;a href=&quot;http://toscawidgets.org/documentation/tw2.core&quot;&gt;ToscaWidgets2&lt;/a&gt; and the &lt;a href=&quot;http://thejit.org&quot;&gt;JavaScript InfoVis Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Package mouse-over menus linking to downloads (&lt;a href=&quot;https://admin.fedoraproject.org/community&quot;&gt;community&lt;/a&gt;), code (&lt;a href=&quot;http://pkgs.fedoraproject.org/gitweb&quot;&gt;gitweb&lt;/a&gt;), bugs (&lt;a href=&quot;http://bugzilla.redhat.com&quot;&gt;bugzilla&lt;/a&gt;), acls (&lt;a href=&quot;https://admin.fedoraproject.org/pkgdb&quot;&gt;pkgdb&lt;/a&gt;), builds (&lt;a href=&quot;http://koji.fedoraproject.org/koji&quot;&gt;koji&lt;/a&gt;) and updates (&lt;a href=&quot;https://admin.fedoraproject.org/updates&quot;&gt;bodhi&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Deep linking, which allows you to use the browser back/forward buttons while navigating the tree, as well as share or bookmark links to specific nodes&lt;/li&gt;
&lt;li&gt;Search bar with auto-completion of packages, categories, and groups&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt; under the hood, powering the widgets&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;b&gt;[ Running ]&lt;/b&gt;&lt;br /&gt;

&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;
sudo yum -y install python-virtualenv
git clone git://fedorapeople.org/~lmacken/leafymiracle &amp;amp;&amp;amp; cd leafymiracle
virtualenv env &amp;amp;&amp;amp; source env/bin/activate
python setup.py develop
python leafymiracle/populate.py
paster serve development.ini
&lt;/pre&gt;
&lt;/code&gt;
&lt;/blockquote&gt;

&lt;b&gt;[ Code ]&lt;/b&gt;&lt;br /&gt;

&lt;p&gt;
&lt;blockquote&gt;&lt;code&gt;
        git clone &lt;a href=&quot;http://fedorapeople.org/gitweb?p=lmacken/public_git/leafymiracle;a=summary&quot;&gt;git://fedorapeople.org/~lmacken/leafymiracle&lt;/a&gt;
&lt;/code&gt;&lt;/blockquote&gt;
&lt;/p&gt;

&lt;b&gt;[ Props ]&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;
    Mad props go out to &lt;a href=&quot;https://threebean.wordpress.com&quot;&gt;RJ Bean&lt;/a&gt;, who helped me write this app.  He is
responsible for writing a ton of amazing Python widgets for various
JavaScript visualization libraries.  You can see some demos of them
here: &lt;a href=&quot;http://craftsman.rc.rit.edu&quot;&gt;craftsman.rc.rit.edu&lt;/a&gt;.
&lt;/p&gt;</description>
	<pubDate>Sat, 07 May 2011 20:20:13 +0000</pubDate>
</item>
<item>
	<title>Cliff Wells: Ubuntu 11.04</title>
	<guid>http://www.enemyofthestatement.com/ubuntu-11-04</guid>
	<link>http://www.enemyofthestatement.com/ubuntu-11-04</link>
	<description>&lt;div class=&quot;document&quot;&gt;
&lt;p&gt;Despite misgivings about Unity, I upgraded to 11.04 on Monday night.&lt;/p&gt;
&lt;p&gt;Turns out my misgivings were entirely misplaced, since Unity won't even run (just hangs).  Shrugging that off, I proceeded to switch to the &amp;quot;classic&amp;quot; desktop, spent an hour fixing all the settings that are required for Compiz to work properly without Unity (moving and resizing windows, etc).  I finally got it into a pretty happy state and was set to move on.&lt;/p&gt;
&lt;p&gt;Issue #1: suspend/resume broken.  Oops.  This worked fine under 10.04 and 10.10.  Suspend works, resume doesn't.  I figured I could figure out a quirk or wait for an update to fix this, except...&lt;/p&gt;
&lt;p&gt;Issue #2: an update on Tuesday (not sure if it was kernel, compiz or xorg Intel drivers) seems to have permanently broken my desktop.  Now I can only log in using &amp;quot;classic desktop (no effects)&amp;quot; or &amp;quot;safe mode&amp;quot;.   Fiddled with it for another hour, before giving up.&lt;/p&gt;
&lt;p&gt;At the end of the day, I ended up reinstalling 10.04 and then upgrading to 10.10, where things are more-or-less sane again.  11.04 is an unmitigated disaster as far as I'm concerned.  I'll stick with 10.10 until 11.10 or 12.04 is released, but if the next release doesn't improve their QA considerably, I'm thinking I'll be moving to Debian Mint.&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Wed, 04 May 2011 03:50:20 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: Mobile devices detection with TurboGears2</title>
	<guid>http://blog.axant.it/?p=388</guid>
	<link>http://blog.axant.it/archives/388</link>
	<description>&lt;p&gt;We just released &lt;a href=&quot;http://bitbucket.org/_amol_/tgext.mobilemiddleware&quot;&gt;tgext.mobilemiddleware&lt;/a&gt; for turbogears2 to make easier to handle templates for mobile devices and detect mobile devices requests.&lt;/p&gt;
&lt;p&gt;Indeed it is quite simple to use as it makes possible just to register a different template by using &lt;em&gt;@expoe_mobile&lt;/em&gt; decorator which will be used for mobile devices, making possible to create mobile version of web page by using for example &lt;a href=&quot;http://jquerymobile.com/&quot;&gt;jquery mobile &lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 19 Apr 2011 23:00:19 +0000</pubDate>
</item>
<item>
	<title>Christpher Arndt: Tag der freien Dokumente</title>
	<guid>http://blog.chrisarndt.de/?p=563</guid>
	<link>http://blog.chrisarndt.de/article/563</link>
	<description>Die Free Software Foundation (FSF) hat für heute, den 30. März 2011, den Document Freedom Day (DFD) ausgerufen. Das nehme ich zum Anlass, den kurzen Informationstext der DFD-Webseite zum Open Document Format vom Englischen ins Deutsche zu übersetzen. Das &amp;#8220;Open Document Format&amp;#8221; Offene Dokumentformate sind offene Standards für Ihre Bürodokumente: Texte, Tabellen, Präsentationen usw. Wir [...]</description>
	<pubDate>Wed, 30 Mar 2011 15:33:50 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: git clone all of your Fedora packages</title>
	<guid>http://lewk.org/blog/2011/03/24/clone-all-my-fedora-pkgs</guid>
	<link>http://lewk.org/blog/clone-all-my-fedora-pkgs.html</link>
	<description>&lt;p&gt;
After doing a fresh &lt;a href=&quot;http://fedoraproject.org&quot;&gt;Fedora 15&lt;/a&gt; install on
my laptop last night, I wanted to quickly clone all of the packages that I
maintain. Here is a single command that does the job:
&lt;/p&gt;

&lt;code&gt;
&lt;blockquote&gt;
python -c &quot;import pyfedpkg; from fedora.client.pkgdb import PackageDB; [pyfedpkg.clone(pkg['name'], '$USER') for pkg in PackageDB().user_packages('$USER')['pkgs']]&quot;
&lt;/blockquote&gt;
&lt;/code&gt;</description>
	<pubDate>Thu, 24 Mar 2011 16:10:06 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: Fedora Photobooth @ SXSW</title>
	<guid>http://lewk.org/blog/2011/03/12/photobooth.py</guid>
	<link>http://lewk.org/blog/photobooth.py.html</link>
	<description>&lt;center&gt;&lt;img src=&quot;http://lewk.org/img/photobooth1.jpg&quot; align=&quot;right&quot; /&gt;&lt;/center&gt;
&lt;p&gt;
    This is the first year that Fedora will have a booth at &lt;a href=&quot;http://www.sxsw.com&quot;&gt;SXSW&lt;/a&gt;! Sadly, I am not going to be attending since it conflicts with &lt;a href=&quot;http://us.pycon.org&quot;&gt;PyCon&lt;/a&gt;.  However,
my code will be running at our booth. Usually the Fedora booth at conferences is comprised of a bunch of flyers, media, swag, and some people to help answer questions and tell the Fedora story. However at SXSW, things are going to be a little different.
&lt;/p&gt;
&lt;p&gt;
Aside from the &lt;a href=&quot;http://mairin.wordpress.com/2011/03/11/flyers-about-free-open-source-software-for-sxsw-creatives/&quot;&gt;amazing flyers&lt;/a&gt; that Máirín created, there will also be a &lt;a href=&quot;http://fedoraproject.org/wiki/SXSW_2011#Photobooth&quot;&gt;Fedora Photobooth&lt;/a&gt;. Someone (probably Spot or Jared) will be dressed in a full Tux costume, and people can come and get their photo taken with them.  Spot came to me the other day and asked if I could write some code to streamline the whole process.
&lt;/p&gt;
&lt;p&gt;
An hour or so later, photobooth.py was born. There are definitely lots of improvements that can be made, but here is what it currently does in its initial incarnation:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Uses gphoto2 to automatically detect your camera&lt;/li&gt;
	&lt;li&gt;When Enter is pressed, it snaps a photo and downloads it locally&lt;/li&gt;
	&lt;li&gt;A Fedora watermark is applied to the bottom right corner of the image&lt;/li&gt;
	&lt;li&gt;The photo is uploaded to a server&lt;/li&gt;
	&lt;li&gt;A QRCode is generated that points to the image URL&lt;/li&gt;
	&lt;li&gt;A TinyURL is generated for the image&lt;/li&gt;
	&lt;li&gt;HTML is generated that shows the image, the QRCode, and TinyURL&lt;/li&gt;
	&lt;li&gt;The page is then displayed in the web browser&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;In Action&lt;/b&gt;
&lt;br /&gt;
See Mo's blog for photos of this code in action at the Fedora SXSW booth!
&lt;blockquote&gt;
* &lt;a href=&quot;http://mairin.wordpress.com/2011/03/14/sxsw-expo-day-1-from-the-show-floor/&quot;&gt;SXSW Expo Day 1 from the show floor&lt;/a&gt;&lt;br /&gt;
* &lt;a href=&quot;http://mairin.wordpress.com/2011/03/15/sxsw-expo-day-2/&quot;&gt;SXSW Expo Day 2&lt;/a&gt;&lt;br /&gt;
* &lt;a href=&quot;http://mairin.wordpress.com/2011/03/16/a-beefy-miraculous-day-at-sxsw-expo-day-3/&quot;&gt;A Beefy, Miraculous Day at SXSW (Expo Day 3)&lt;/a&gt;&lt;br /&gt;
&lt;/blockquote&gt;

&lt;br /&gt;
&lt;center&gt;&lt;img src=&quot;http://lewk.org/img/photobooth0.jpg&quot; /&gt;&lt;/center&gt;
&lt;br /&gt;

&lt;b&gt;The Code&lt;/b&gt;

&lt;br /&gt;
I threw this in a git repo and tossed it up on GitHub:

&lt;blockquote&gt;
	&lt;a href=&quot;http://github.com/lmacken/photobooth.py&quot;&gt;github.com/lmacken/photobooth.py&lt;/a&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;


&lt;!--
/*pre { font-family: monospace; color: #657b83; background-color: #fdf6e3; }*/
pre { font-family: monospace; color: #657b83;}
.Special { color: #dc322f; }
.Type { color: #b58900; }
.Statement { color: #719e07; }
.Identifier { color: #268bd2; }
.Constant { color: #2aa198; }
.PreProc { color: #cb4b16; }
.Comment { color: #93a1a1; font-style: italic; }
--&gt;



&lt;pre&gt;
&lt;span class=&quot;Comment&quot;&gt;#!/usr/bin/python&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;# photobooth.py - version 0.3&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;# Requires: python-imaging, qrencode, gphoto2, surl&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;# Author: Luke Macken &amp;lt;lmacken@redhat.com&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;# License: GPLv3&lt;/span&gt;

&lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; os
&lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; surl
&lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; Image
&lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; subprocess

&lt;span class=&quot;PreProc&quot;&gt;from&lt;/span&gt; uuid &lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; uuid4
&lt;span class=&quot;PreProc&quot;&gt;from&lt;/span&gt; os.path &lt;span class=&quot;PreProc&quot;&gt;import&lt;/span&gt; join, basename, expanduser

&lt;span class=&quot;Comment&quot;&gt;# Where to spit out our qrcode, watermarked image, and local html&lt;/span&gt;
out = expanduser(&lt;span class=&quot;Constant&quot;&gt;'~/Desktop/sxsw'&lt;/span&gt;)

&lt;span class=&quot;Comment&quot;&gt;# The watermark to apply to all images&lt;/span&gt;
watermark_img = expanduser(&lt;span class=&quot;Constant&quot;&gt;'~/Desktop/fedora.png'&lt;/span&gt;)

&lt;span class=&quot;Comment&quot;&gt;# This assumes ssh-agent is running so we can do password-less scp&lt;/span&gt;
ssh_image_repo = &lt;span class=&quot;Constant&quot;&gt;'fedorapeople.org:~/public_html/sxsw/'&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;# The public HTTP repository for uploaded images&lt;/span&gt;
http_image_repo = &lt;span class=&quot;Constant&quot;&gt;'&lt;a href=&quot;http://lmacken.fedorapeople.org/sxsw/&quot;&gt;http://lmacken.fedorapeople.org/sxsw/&lt;/a&gt;'&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;# Size of the qrcode pixels&lt;/span&gt;
qrcode_size = &lt;span class=&quot;Constant&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;# Whether or not to delete the photo after uploading it to the remote server&lt;/span&gt;
delete_after_upload = &lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;# The camera configuration&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;# Use gphoto2 --list-config and --get-config for more information&lt;/span&gt;
gphoto_config = {
    &lt;span class=&quot;Constant&quot;&gt;'/main/imgsettings/imagesize'&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;Comment&quot;&gt;# small&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;'/main/imgsettings/imagequality'&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;Comment&quot;&gt;# normal&lt;/span&gt;
    &lt;span class=&quot;Constant&quot;&gt;'/main/capturesettings/zoom'&lt;/span&gt;: &lt;span class=&quot;Constant&quot;&gt;70&lt;/span&gt;, &lt;span class=&quot;Comment&quot;&gt;# zoom factor&lt;/span&gt;
}

&lt;span class=&quot;Comment&quot;&gt;# The URL shortener to use&lt;/span&gt;
shortener = &lt;span class=&quot;Constant&quot;&gt;'tinyurl.com'&lt;/span&gt;

&lt;span class=&quot;Statement&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;PhotoBooth&lt;/span&gt;(&lt;span class=&quot;Identifier&quot;&gt;object&lt;/span&gt;):

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;initialize&lt;/span&gt;(self):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Detect the camera and set the various settings &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        cfg = [&lt;span class=&quot;Constant&quot;&gt;'--set-config=%s=%s'&lt;/span&gt; % (k, v) &lt;span class=&quot;Statement&quot;&gt;for&lt;/span&gt; k, v &lt;span class=&quot;Statement&quot;&gt;in&lt;/span&gt; gphoto_config.items()]
        subprocess.call(&lt;span class=&quot;Constant&quot;&gt;'gphoto2 --auto-detect '&lt;/span&gt; +
                        &lt;span class=&quot;Constant&quot;&gt;' '&lt;/span&gt;.join(cfg), shell=&lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;)

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;capture_photo&lt;/span&gt;(self):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Capture a photo and download it from the camera &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        filename = join(out, &lt;span class=&quot;Constant&quot;&gt;'%s.jpg'&lt;/span&gt; % &lt;span class=&quot;Identifier&quot;&gt;str&lt;/span&gt;(uuid4()))
        cfg = [&lt;span class=&quot;Constant&quot;&gt;'--set-config=%s=%s'&lt;/span&gt; % (k, v) &lt;span class=&quot;Statement&quot;&gt;for&lt;/span&gt; k, v &lt;span class=&quot;Statement&quot;&gt;in&lt;/span&gt; gphoto_config.items()]
        subprocess.call(&lt;span class=&quot;Constant&quot;&gt;'gphoto2 '&lt;/span&gt; +
                        &lt;span class=&quot;Constant&quot;&gt;'--capture-image-and-download '&lt;/span&gt; +
                        &lt;span class=&quot;Constant&quot;&gt;'--filename=&amp;quot;%s&amp;quot; '&lt;/span&gt; % filename,
                        shell=&lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;)
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; filename

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;process_image&lt;/span&gt;(self, filename):
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Processing %s...&amp;quot;&lt;/span&gt; % filename
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Applying watermark...&amp;quot;&lt;/span&gt;
        image = self.watermark(filename)
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Uploading to remote server...&amp;quot;&lt;/span&gt;
        url = self.upload(image)
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Generating QRCode...&amp;quot;&lt;/span&gt;
        qrcode = self.qrencode(url)
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Shortening URL...&amp;quot;&lt;/span&gt;
        tiny = self.shorten(url)
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Generating HTML...&amp;quot;&lt;/span&gt;
        html = self.html_output(url, qrcode, tiny)
        subprocess.call(&lt;span class=&quot;Constant&quot;&gt;'firefox &amp;quot;%s&amp;quot;'&lt;/span&gt; % html, shell=&lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;)
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;Done!&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;watermark&lt;/span&gt;(self, image):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Apply a watermark to an image &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        mark = Image.&lt;span class=&quot;Identifier&quot;&gt;open&lt;/span&gt;(watermark_img)
        im = Image.&lt;span class=&quot;Identifier&quot;&gt;open&lt;/span&gt;(image)
        &lt;span class=&quot;Statement&quot;&gt;if&lt;/span&gt; im.mode != &lt;span class=&quot;Constant&quot;&gt;'RGBA'&lt;/span&gt;:
            im = im.convert(&lt;span class=&quot;Constant&quot;&gt;'RGBA'&lt;/span&gt;)
        layer = Image.new(&lt;span class=&quot;Constant&quot;&gt;'RGBA'&lt;/span&gt;, im.size, (&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;))
        position = (im.size[&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;] - mark.size[&lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;], im.size[&lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;] - mark.size[&lt;span class=&quot;Constant&quot;&gt;1&lt;/span&gt;])
        layer.paste(mark, position)
        outfile = join(out, basename(image))
        Image.composite(layer, im, layer).save(outfile)
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; outfile

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;upload&lt;/span&gt;(self, image):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Upload this image to a remote server &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        subprocess.call(&lt;span class=&quot;Constant&quot;&gt;'scp &amp;quot;%s&amp;quot; %s'&lt;/span&gt; % (image, ssh_image_repo), shell=&lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;)
        &lt;span class=&quot;Statement&quot;&gt;if&lt;/span&gt; delete_after_upload:
            os.unlink(image)
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; http_image_repo + basename(image)

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;qrencode&lt;/span&gt;(self, url):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Generate a QRCode for a given URL &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        qrcode = join(out, &lt;span class=&quot;Constant&quot;&gt;'qrcode.png'&lt;/span&gt;)
        subprocess.call(&lt;span class=&quot;Constant&quot;&gt;'qrencode -s %d -o &amp;quot;%s&amp;quot; %s'&lt;/span&gt; % (
            qrcode_size, qrcode, url), shell=&lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;)
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; qrcode

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;shorten&lt;/span&gt;(self, url):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Generate a shortened URL &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; surl.services.supportedServices()[shortener].get({}, url)

    &lt;span class=&quot;Statement&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;html_output&lt;/span&gt;(self, image, qrcode, tinyurl):
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Output HTML with the image, qrcode, and tinyurl &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        html = &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;            &amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;              &amp;lt;center&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                &amp;lt;table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                  &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                    &amp;lt;td colspan=&amp;quot;2&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                        &amp;lt;b&amp;gt;&amp;lt;a href=&amp;quot;%(tinyurl)s&amp;quot;&amp;gt;%(tinyurl)s&amp;lt;/a&amp;gt;&amp;lt;/b&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                    &amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                  &amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                  &amp;lt;tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                    &amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;%(image)s&amp;quot; border=&amp;quot;0&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                    &amp;lt;td&amp;gt;&amp;lt;img src=&amp;quot;%(qrcode)s&amp;quot; border=&amp;quot;0&amp;quot;/&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                  &amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;                &amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;              &amp;lt;/center&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;          &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;Constant&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt; % {&lt;span class=&quot;Constant&quot;&gt;'image'&lt;/span&gt;: image, &lt;span class=&quot;Constant&quot;&gt;'qrcode'&lt;/span&gt;: qrcode, &lt;span class=&quot;Constant&quot;&gt;'tinyurl'&lt;/span&gt;: tinyurl}
        outfile = join(out, basename(image) + &lt;span class=&quot;Constant&quot;&gt;'.html'&lt;/span&gt;)
        output = &lt;span class=&quot;Identifier&quot;&gt;file&lt;/span&gt;(outfile, &lt;span class=&quot;Constant&quot;&gt;'w'&lt;/span&gt;)
        output.write(html)
        output.close()
        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; outfile

&lt;span class=&quot;Statement&quot;&gt;if&lt;/span&gt; __name__ == &lt;span class=&quot;Constant&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;:
    photobooth = PhotoBooth()
    &lt;span class=&quot;Statement&quot;&gt;try&lt;/span&gt;:
        photobooth.initialize()
        &lt;span class=&quot;Statement&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;Identifier&quot;&gt;True&lt;/span&gt;:
            &lt;span class=&quot;Identifier&quot;&gt;raw_input&lt;/span&gt;(&lt;span class=&quot;Constant&quot;&gt;&amp;quot;Press enter to capture photo.&amp;quot;&lt;/span&gt;)
            filename = photobooth.capture_photo()
            photobooth.process_image(filename)
    &lt;span class=&quot;Statement&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;Type&quot;&gt;KeyboardInterrupt&lt;/span&gt;:
        &lt;span class=&quot;Statement&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;Exiting...&amp;quot;&lt;/span&gt;
&lt;/pre&gt;


&lt;/blockquote&gt;</description>
	<pubDate>Sun, 13 Mar 2011 02:57:39 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: A Git Script for Python</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-166156106022060867</guid>
	<link>http://codersbuffet.blogspot.com/2011/03/git-script-for-python.html</link>
	<description>Working on TurboGears, I found myself trying to run all the tests we provide. And then I found myself getting a failure even though I didn't change anything. I had simply switched to a different branch.&lt;br /&gt;&lt;br /&gt;Turns out the problem was left over .pyc files. Also turns out that the fix is extremely easy.&amp;nbsp; In your git repository, create a file named &quot;hooks/post-checkout&quot;. In that file, put the following lines, and make the script executable. All .pyc files will be scrubbed every time you switch, preventing the problem entirely.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;#!/bin/bash&lt;/div&gt;&lt;div&gt;find . -type f -print | grep -v ^.git | grep '\.pyc$' | xargs rm&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-166156106022060867?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 09 Mar 2011 07:27:37 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Luke Macken: FUDCon 2011 Tempe</title>
	<guid>http://lewk.org/blog/2011/02/16/FUDCon2011Tempe</guid>
	<link>http://lewk.org/blog/FUDCon2011Tempe.html</link>
	<description>&lt;p&gt;
I meant to get this summary out the door weeks ago, however, I didn't want to distract from my post-FUDCon productivity :)
&lt;br /&gt;
&lt;br /&gt;
Another FUDCon has come and gone. This time it was in gorgeous Tempe, Arizona.
It was my first time in AZ, and I must say that I was thoroughly impressed.  It
was truly a great location for FUDCon.  Thanks to the epic snowstorm of doom, I
also was stuck there for a few extra days
&lt;/p&gt;

&lt;p&gt;
    &lt;a href=&quot;http://lewk.org/img/fudstream.png&quot;&gt;&lt;img src=&quot;http://lewk.org/img/fudstream-thumb.png&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;b&gt;Live Widgetry&lt;/b&gt;&lt;br /&gt;

    Before the conference I decided to throw together a little &lt;a href=&quot;http://tinyurl.com/fudstream&quot;&gt;live widget&lt;/a&gt; that
scrolls all of the new identi.ca posts tagged with #FUDCon. Thanks to the mad design
skillz of mizmo, and the feed aggregation and real-time web sockets of 
&lt;a href=&quot;http://moksha.fedorahosted.org&quot;&gt;Moksha&lt;/a&gt;, I was able to throw it
together pretty quickly.  I plan on taking this code and integrating it in the
existing &lt;a href=&quot;https://admin.fedoraproject.org/community&quot;&gt;fedoracommunity dashboard&lt;/a&gt; and hooking up many different fedora-related feeds to it.
&lt;/p&gt;

&lt;h3&gt;Sessions&lt;/h3&gt;
&lt;p&gt;
&lt;b&gt;AutoQA&lt;/b&gt;&lt;br /&gt;
Day 1 of the FUDCon sessions were quite interesting.  I got a chance to learn a
bit more about the exciting &lt;a href=&quot;http://autoqa.fedorahosted.org&quot;&gt;AutoQA project&lt;/a&gt;, which is coming along
nicely.  You'll be seeing AutoQA commenting on bodhi updates soon
enough.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Security Lab&lt;/b&gt;&lt;br /&gt;
I caught &lt;a href=&quot;http://fedoraproject.org/wiki/JoergSimon&quot;&gt;Joerg Simon&lt;/a&gt;'s session on the &lt;a href=&quot;https://fedorahosted.org/security-spin/&quot;&gt;Fedora Security Lab&lt;/a&gt;.
It was exciting to see how the Security Spin has evolved ever since
&lt;a href=&quot;http://lewk.org/blog/securitylivecd&quot;&gt;I created it back in 2007&lt;/a&gt; for a project in my forensics class.  It was also interesting to learn more about &lt;a href=&quot;http://www.isecom.org/osstmm/&quot;&gt;OSSTMM&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Spins&lt;/b&gt;&lt;br /&gt;
The next session I attended was about the future of &lt;a href=&quot;http://spins.fedoraproject.org&quot;&gt;spins&lt;/a&gt;.  Almost everyone
agreed that Spins are useful and a valuable part of Fedora.  The problems seem
to mostly lie in governance/policy and a lack of communication and coordination
between the Spins SIG and QA/Releng/Infrastructure.  Once of my ideas below may
help with this a little bit.
&lt;/p&gt;

&lt;h3&gt;The Next Big Project&lt;/h3&gt;
&lt;p&gt;
Day 2 was comprised of more sessions, including my team's &quot;Next Big Project&quot; proposals.
Of course, the &lt;a href=&quot;http://fedoraproject.org/wiki/Fedora_RPG&quot;&gt;Fedora RPG&lt;/a&gt; that Spot and Mo talked about was definitely a hot topic, and got a lot of people excited.
&lt;br /&gt;&lt;br /&gt;
I talked about a handful of project ideas that I would like to work on in the
future (actually, I have code written for most of them already).  Here is a
quick rundown:
&lt;/p&gt;

&lt;p&gt;
    &lt;b&gt;Real-time Infrastructure&lt;/b&gt;&lt;br /&gt;
I want to see us deploy an AMQP message broker inside our production
infrastructure.  Then, we hook up all of our existing services and have them
fire off messages when various events occur (koji builds, bodhi updates,
pkgdb additions/removals/changes, git hooks, planet feeds, wiki edits, etc).
From here, using some realtime web technology that &lt;a href=&quot;http://moksha.fedorahosted.org&quot;&gt;we created&lt;/a&gt;, we could easily
expose these message queues via a live dashboard that lets you filter and navigate
the stream of activity, along with providing real-time metrics.  We can also create
desktop notification widgets, so you can get popup bubbles for things that you
care about.
&lt;br /&gt;
&lt;br /&gt;
This is also key to the whole RPG as well.  In order to build a game based on
Fedora workflows, we need an underlying expert system that knows what actions can be taken within fedora, how they are accomplished, and who is getting them done.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Meeting app&lt;/b&gt;&lt;br /&gt;
Currently after a meeting, our Meetbot
spits out the logs and an overview in txt/html/rst to a directory on &lt;a href=&quot;http://meetbot.fedoraproject.org/&quot;&gt;meetbot.fedoraproject.org&lt;/a&gt;.
Trying to track down who agreed to what when, or even to see what a given
team has been up to over the past couple of months, is very tedious.
&lt;br /&gt;
&lt;br /&gt;
The data is there, now we just need to make it useful.  I would love to see a
frontend for this sytem that tracked meetings by team/people/topics/projects, kept track
of actions and held people accountable for what they say they are going to do
(and make it easy for people to say &quot;I need help with this&quot;, or &quot;I don't have
time to finish this&quot;), making it simple to go from an #idea in a meeting to
implementation.  There is so much great data in these logs, and I think we can
do some awesome things with it.
&lt;/p&gt;

&lt;p&gt;
    &lt;b&gt;Improved upstream monitoring&lt;/b&gt;&lt;br /&gt;
Most Fedora developers probably don't even know that we already have an &lt;a href=&quot;http://fedoraproject.org/wiki/Upstream_Release_Monitoring&quot;&gt;Upstream release monitoring&lt;/a&gt; service buried in the wiki.
I added almost every package I maintain to it, and it will automatically open a bug when a new upstream version is released.  Extremely useful.
&lt;br /&gt;
&lt;br /&gt;
I wouldn't call this a &quot;big&quot; project, but I would like to see us integrate this
service into our existing infrastructure.  We could potentially store this
per-package upstream data in the pkgdb/bodhi, and when a new release comes out
write some code to automatically try doing a simple specfile bump, throw a
scratch build at koji, run it through AutoQA, queue up for testing in bodhi,
etc.  Ideally, this would minimize the massive amounts of effort that our
maintainers have to do to keep our packages up to speed with upstream.
&lt;/p&gt;

&lt;p&gt;
    &lt;b&gt;Discussions app&lt;/b&gt;&lt;br /&gt;
Last year, Máirín Duffy and I came up with some &lt;a href=&quot;https://mairin.wordpress.com/2010/03/16/a-rich-web-interface-for-mailing-lists/&quot;&gt;interesting ideas&lt;/a&gt; for improving our mailing lists.  I would like to make this a reality.
Since then, I have already written code that can successfully parse all of
fedora-devel.mbox (sounds much easier than it really is), populate it into a
SQLAlchemy database model, expose a JSON API for quering, and visualize threads
and various statistics with a basic widget.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Spin Master&lt;/b&gt;&lt;br /&gt;
One of the biggest problems with spins that we have right now is that there is
no easy way to track how they are evolving.  I would like to see us create a
system that took the nightly spins and analyzed them, tracking what packages
have been added/removed, which packages have grown/shrunk, etc.  We could
potentially get AutoQA involved here and make sure all spins pass a certain
level of sanity checks before they can even be released.  There are scripts
floating around that can do a lot of this already -- but I want to streamline
it and build a frontend.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Source-level package diff viewer&lt;/b&gt;&lt;br /&gt;
Fedora churns at such a fast pace, yet I can only imagine that a small subset
of maintainers actually look at the complete code changes between upstream
package releases.  The recent sourceforge intrusion should be seen as a reality
check to us distributions, and I think we need to step up our game quite a bit
to ensure we don't let any malicious code slip into Fedora.
&lt;br /&gt;
&lt;br /&gt;
I would like to see a web/cli interface for viewing full source diffs of
package updates in Fedora, allowing people to annotate/flag lines of code.
Having more eyes view the code changes that go into our distribution is
definitely a Good Thing, not just for Fedora, but for Open Source in general.
&lt;/p&gt;

&lt;h3&gt;Hackfests&lt;/h3&gt;
&lt;p&gt;
Now, on to my favorite part of any conference -- The Hackfests.
First off, I felt that the hackfests were a bit unorganized this year.
There was no opportunity to pitch hackfests, and it was not easy to figure out
who was doing what in which rooms.
Anyway, I had a fairly productive day of hacking...
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;bodhi&lt;/b&gt;&lt;br /&gt;
I integrated our package test cases into bodhi, which will now query the wiki for tests and display them in your updates, like so:
&lt;center&gt;
&lt;img src=&quot;http://lewk.org/img/bodhi-test-cases.png&quot; /&gt;
&lt;/center&gt;
Thanks to &lt;a href=&quot;http://fedoraproject.org/wiki/User:Jlaska&quot;&gt;James Laska&lt;/a&gt;
for the code to query the wiki, and to &lt;a href=&quot;http://ianweller.org/&quot;&gt;Ian
    Weller&lt;/a&gt; for python-simplemediawiki API.
&lt;br /&gt;
&lt;br /&gt;
I also sat down with &lt;a href=&quot;http://mairin.wordpress.com/&quot;&gt;Máirín Duffy&lt;/a&gt; and talked about &lt;a href=&quot;https://fedoraproject.org/wiki/Bodhi/2.0&quot;&gt;Bodhi v2.0&lt;/a&gt; interaction design.  We discussed what actions we want people to take when they arrive at bodhi's homepage, which essentially boils down to submitting, searching, browsing, and testing updates.  Mo quickly threw together an awesome mockup that portrays some of our initial ideas.
&lt;br /&gt;
&lt;br /&gt;
&lt;center&gt;
    &lt;a href=&quot;http://lewk.org/img/bodhi-20-frontpage.png&quot;&gt;&lt;img src=&quot;http://lewk.org/img/bodhi-20-frontpage-thumb.png&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;
&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Fedora Community Discussions&lt;/b&gt;&lt;br /&gt;
As mentioned above, I have already started implementing the mailing list interface that mizmo and I designed last year.  I worked with &lt;a href=&quot;http://screwyouenterpriseedition.blogspot.com/&quot;&gt;Casey Dahlin&lt;/a&gt; during the hackfests and helped him get a working &lt;a href=&quot;http://fedoracommunity.fedorahosted.org&quot;&gt;fedoracommunity&lt;/a&gt;/&lt;a href=&quot;http://moksha.fedorahosted.org&quot;&gt;moksha&lt;/a&gt; development environment up and running and become familiar with the existing code.
&lt;br /&gt;
&lt;br /&gt;
Even though he wasn't at FUDCon, Jan Hutar has also been working on a couple of
great graphs/grids of mailing list statistics for fedoracommunity as well.
We'll be hacking away at this stuff over the next few months, so stay tuned.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;kernel EFI framebuffer&lt;/b&gt;&lt;br /&gt;
I spun up a quick kernel patch to enable the EFI framebuffer on a
handfull of Macs.  I already wrote a patch that got &lt;a href=&quot;http://lkml.org/lkml/2010/9/2/30&quot;&gt;applied upstream&lt;/a&gt; that enables this framebuffer on 14 different mac models, but this new patch adds 5 more.  A lot of people, especially Sugar on a Stick users, are
desperate to get Fedora running on their mactel machines (assuming found in
may school labs), so I spun up a fresh
livecd with my kernel patch for testing.  See &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=528232&quot;&gt;Bug #528232&lt;/a&gt; for more information.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;liveusb-creator&lt;/b&gt;&lt;br /&gt;
I did a bunch of work on porting the liveusb-creator from HAL to UDisks.
Thankfully, Ubuntu's cleverly-named &quot;usb-creator&quot; already has UDisks support,
so I've been happily borrowing ideas from their code :)
&lt;br /&gt;
&lt;br /&gt;
I also had some great discussions with &lt;a href=&quot;http://fedoraproject.org/wiki/User:Pbrobinson&quot;&gt;Peter Robinson&lt;/a&gt; and &lt;a href=&quot;http://www.codewiz.org/&quot;&gt;Bernie Innocenti&lt;/a&gt;
about solving the persistent overlay problem with our Live USBs.  Right now, they
are essentially a ticking time bomb, and real world LiveUSB use-cases are
getting bit by this all of the time.  Over the past few years, the &quot;solution&quot;
has been to &quot;wait for unionfs to get merged into the kernel&quot;.  However, there
are a variety of other potential solutions that we are going to look into as well.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Pyramid&lt;/b&gt;&lt;br /&gt;

The future of Python web development is extremely exciting, innovative, and still evolving at a rapid pace.  As a &lt;a href=&quot;http://turbogears.org&quot;&gt;TurboGears&lt;/a&gt; developer, I'm still very impressed with TG2, which along with TG1 will be supported for a long time to come -- but I'm also very eager for the next generation framework that has just emerged.

&lt;br /&gt;
&lt;br /&gt;
Recently, the &lt;a href=&quot;http://pylonshq.com&quot;&gt;Pylons&lt;/a&gt; project has merged with &lt;a href=&quot;http://bfg.repoze.org/&quot;&gt;repoze.bfg&lt;/a&gt; to form &lt;a href=&quot;http://docs.pylonsproject.org&quot;&gt;Pyramid&lt;/a&gt;, which just released version 1.0.
I'm quite amazed by the quality of the code, docs, and tests, and benchmarks
already show it blowing rails/django/tg/pylons out of the water.  I'm looking
forward to the PyCon sprints, where all 3 communitites are going to be
sitting at the same table working together on this project.
&lt;br /&gt;
&lt;br /&gt;
So while I was stuck in Tempe during the snow storm, I wrote 7 RPMs for Pyramid and it's dependencies, which are currently &lt;a href=&quot;https://bugzilla.redhat.com/showdependencytree.cgi?id=674692&quot;&gt;waiting to be reviewed&lt;/a&gt;.  I plan on writing &lt;a href=&quot;https://fedoraproject.org/wiki/Bodhi/2.0&quot;&gt;Bodhi v2.0&lt;/a&gt; using Pyramid, so if this is something that interests you, let me know (and start reading the 600+ pages of docs ;)
&lt;/p&gt;

&lt;p&gt;
    &lt;b&gt;Good times&lt;/b&gt;&lt;br /&gt;
Technical stuff aside, I had a blast at FUDCon, and I feel like it was one of
the best.  FUDPub was great, as usual. I
played a lot of poker [poorly], ate a lot of tasty food, and had some great conversations.  I had caught a cold prior to coming to FUDCon, so instead of nursing it with
some nyquil and sleep, I decided to try to nurse it with a bottle of Jack,
which turned out to be a bad idea.
&lt;br /&gt;
&lt;br /&gt;
Also, no FUDCon would be complete without mentioning &lt;a href=&quot;http://thegreatestgameyouwilleverplay.com&quot;&gt;TheGreatestGameYouWillEverPlay.com&lt;/a&gt;.
Once the hackfests started winding down, I gave a quick session on nethack,
where I tought people various ways to steal from shops, using a bunch of screecasts that I had on my laptop.
&lt;/p&gt;</description>
	<pubDate>Wed, 16 Feb 2011 21:55:02 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: Fixing broken inline genshi tags on TG2.1</title>
	<guid>http://blog.axant.it/?p=352</guid>
	<link>http://blog.axant.it/archives/352</link>
	<description>&lt;p&gt;Turbogears 2.1 got a little issue with genshi templates being rendered as xml instead of xhtml. This causes the most various strange problems with tags nesting being closed in random points as the browser likes.&lt;/p&gt;
&lt;p&gt;This is caused by an improvement to the mechanism used to decide with rendering format to use that it is now based on the response content type. If your applications returns Content-Type &lt;strong&gt;text/xml&lt;/strong&gt; or &lt;strong&gt;text/plain&lt;/strong&gt; your templates will be rendered as xml or as plain text.&lt;/p&gt;
&lt;p&gt;But what happens with your application returns text/html which is the default case?&lt;/p&gt;
&lt;p&gt;Indeed in this case the application asks to your configuration file what to do, and as in your configuration file by default there isn&amp;#8217;t any &lt;em&gt;templating.genshi.method&lt;/em&gt; entry you get the default genshi behaviour, which is &lt;strong&gt;xml&lt;/strong&gt;. Your browser doesn&amp;#8217;t really like receiving some xml when he is expecting html and so handles the tags as not being closed.&lt;/p&gt;
&lt;p&gt;In the recent future it will probably be fixed, in the mean time you can work around this problem by declaring in your &lt;strong&gt;development.ini&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;[DEFAULT]
templating.genshi.method = xhtml&lt;/pre&gt;
&lt;p&gt;This will reassemble the default behaviour that was available in TG2.0 rendering your templates as xhtml and correctly showing them inside the browser. If you have specified in your template the html doctype instead of the default xhtml one, then you might also want to change that value to html.&lt;/p&gt;</description>
	<pubDate>Fri, 14 Jan 2011 03:49:20 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: liveusb-creator 3.9.3 windows release</title>
	<guid>http://lewk.org/blog/2011/01/06/liveusb-creator-3.9.3</guid>
	<link>http://lewk.org/blog/liveusb-creator-3.9.3.html</link>
	<description>&lt;img src=&quot;https://fedorahosted.org/liveusb-creator/attachment/wiki/img/fedorausb.png?format=raw&quot; align=&quot;right&quot; /&gt;
&lt;p&gt;
I spent the majority of yesterday at a DOS prompt.  Thankfully, it wasn't
as painful as it sounds, as git, vim and Python make Windows development
quite tolerable.
&lt;/p&gt;
&lt;p&gt;
Anyway, I was finally able to track down and fix a couple of major bugs in the
liveusb-creator on Windows XP and 7, and I pushed out a new build
yesterday with the following changes:
&lt;/p&gt;

&lt;p&gt;
&lt;ul&gt;
  &lt;li&gt;Rebuilt with Python 2.7 and the latest PyQt4/pywin32/py2exe/NSIS&lt;/li&gt;
  &lt;li&gt;Update to syslinux 4.03 in our Windows package, which works with Fedora 14&lt;/li&gt;
  &lt;li&gt;Determine if we are running with admin privs, and warn otherwise&lt;/li&gt;
  &lt;li&gt;Fix how and where we put our error logs&lt;/li&gt;
  &lt;li&gt;Update our list of Fedora &amp;amp; Sugar releases&lt;/li&gt;
  &lt;li&gt;Download releases to Downloads or My Documents&lt;/li&gt;
  &lt;li&gt;Various Windows path-related fixes&lt;/li&gt;
  &lt;li&gt;Translation updates&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
Windows users, download it here: &lt;a href=&quot;http://liveusb-creator.fedorahosted.org&quot;&gt;http://liveusb-creator.fedorahosted.org&lt;/a&gt;
&lt;/p&gt;</description>
	<pubDate>Thu, 06 Jan 2011 15:34:12 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: Workaround for empty helpers in Turbogears 2.1</title>
	<guid>http://blog.axant.it/?p=348</guid>
	<link>http://blog.axant.it/archives/348</link>
	<description>&lt;p&gt;Last release of TG2.1 has a subtle bug due to the changes helpers management to support in pylons 1.0, this makes the &amp;#8220;h&amp;#8221; object appear as an empty dict instead of your application helpers module.&lt;/p&gt;
&lt;p&gt;The bug is already tracked on &lt;a href=&quot;http://trac.turbogears.org/ticket/2488&quot;&gt;http://trac.turbogears.org/ticket/2488&lt;/a&gt; and as the fix is quite easy it will be probably fixed soon. In the mean time you can work around it by monkey patching the &lt;strong&gt;pylons.templating.pylons_globals&lt;/strong&gt; (I do it in lib/app_globals.py but any place is fine).&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;import&lt;/span&gt; tg.&lt;span&gt;render&lt;/span&gt;, pylons
&lt;span&gt;def&lt;/span&gt; patched_pylons_globals&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
    x = tg.&lt;span&gt;render&lt;/span&gt;.&lt;span&gt;my_pylons_globals&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;if&lt;/span&gt; x&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'h'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; == &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;:
        conf = pylons.&lt;span&gt;config&lt;/span&gt;._current_obj&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        x&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'h'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; = conf&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'package'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;.&lt;span&gt;lib&lt;/span&gt;.&lt;span&gt;helpers&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; x
pylons.&lt;span&gt;templating&lt;/span&gt;.&lt;span&gt;pylons_globals&lt;/span&gt; = patched_pylons_globals&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will make your helpers work again in TG2.1.&lt;br /&gt;
Please pay attention that this code is specific for TG2.1, TG2.0 didn&amp;#8217;t perform pylons_globals monkey patching and so the code won&amp;#8217;t work.&lt;/p&gt;</description>
	<pubDate>Tue, 04 Jan 2011 11:46:29 +0000</pubDate>
</item>
<item>
	<title>Compound Thinking: TurboGears Joins the Pylons Project</title>
	<guid>http://compoundthinking.com/blog/?p=890</guid>
	<link>http://compoundthinking.com/blog/index.php/2010/12/28/turbogears-joins-the-pylons-project/</link>
	<description>&lt;p&gt;After much debate, discussion, and contemplation, we&amp;#8217;ve made an important decision, that will best ensure the future of TurboGears, and of the ideas on which it was based.  TurboGears is merging into the Pylons Project.  &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A bit of background&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We built TurboGears 2 on top of a the Pylons framework, and I have been working with Ben and the Pylons folks for a couple of years now.&lt;/p&gt;
&lt;p&gt;Pylons is a lightweight framework that is neither full stack noropinionated. The Pylons team has recently joined up with the repoze.bfg folks to create a new low-level non-opinionated web application development library called Pyramid which is based on repoze.bfg and now part of the larger Pylons Project.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pyramid status&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can use Pyramid to build web applications right now. It has more plug points, and is in many ways more flexible and extendable than the original Pylons and will provide an even better foundation for a full stack framework like TurboGears. &lt;/p&gt;
&lt;p&gt;Pyramid has a strong, highly documented, well tested, approach,  is already starting to show the fruits of merging in ideas from TurboGears, and Pylons.   We expect it to be a great choice for those who want a flexible, non-opinionated and very fast framework for their projects. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The future of &amp;#8220;Full Stack&amp;#8221; frameworks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fortunately, that&amp;#8217;s not where the story ends.  The Pylons Project  leaders recognize that a &amp;#8220;low level&amp;#8221; framework is not enough. &lt;/p&gt;
&lt;p&gt;Most web developers need to get things done quickly, and want a full stack setup and ready to go, so they can immediately start developing features rather than infrastructure.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s where we come in.  TurboGears was the pioneer of the &amp;#8220;full stack&amp;#8221; set of integrated components approach among the modern Python web frameworks, and we have already developed many full stack tools.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, our first step will be to add the TurboGears2 package to the legacy support in the Pylons Project.  So, the Pylons 1.x  and Turbogears2 packages will be maintained side by side as part of a single overall project. This change won&amp;#8217;t impact the TG2 code, except that we will be officially acknowledging that both codebases are&lt;br /&gt;
tightly linked and now are part of a single project.&lt;/p&gt;
&lt;p&gt;Maintaining the existing Pylons1+tg code will only be one part of the larger Pylons Project.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Big Harry Audacious Goal&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ultimately, we will also be working with the Pylons Project folks to create a new generation of rapid application development tools on top of Pyramid, using the TurboGears &amp;#8220;Full Stack&amp;#8221; philosophy. We will help to pick default templating engines, default session support, default data persistence mechanisms, integrate widget libraries and build high level tools like OAuth or OpenID support.&lt;/p&gt;
&lt;p&gt;The main benifits of this merger will come when we reach across framework boundaries, work together with with Repoze, Pylons, and other web framework developers to build a set of high level tools that make building complex, modern web applications easier and faster. There&amp;#8217;s a lot we can learn from each-other, and even more that we can do if we work through our differences and find new ways to collaborate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There is no future but what we make&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been a great ride.   And, it looks like just when we thought things  were settling down, there&amp;#8217;s another drop, and the roller coaster  ride that is TurboGears isn&amp;#8217;t done yet.   I am forever grateful for the chance&lt;br /&gt;
to work with all the TurboGears developers, to face challenges, and to build something that&amp;#8217;s been so valuable to so many.  And I&amp;#8217;m looking forward to what we can do together with the Pylons and Repoze folks. &lt;/p&gt;</description>
	<pubDate>Tue, 28 Dec 2010 14:12:40 +0000</pubDate>
</item>
<item>
	<title>Compound Thinking: Technical Debt isn’t always Debt</title>
	<guid>http://compoundthinking.com/blog/?p=868</guid>
	<link>http://compoundthinking.com/blog/index.php/2010/10/05/technical-debt-isnt-always-debt/</link>
	<description>&lt;p&gt;After yesterday&amp;#8217;s posts about why you &lt;a href=&quot;http://compoundthinking.com/blog/index.php/2010/10/04/focusing-on-removing-technical-debt-is-a-dead-end/&quot;&gt;should not focus on reducing technical&lt;/a&gt; debt and why that&amp;#8217;s not an excuse to &lt;a href=&quot;http://compoundthinking.com/blog/index.php/2010/10/04/ignoring-%e2%80%9ctechnical-debt%e2%80%9d-is-like-playing-with-dynamite/&quot;&gt;ignore it&lt;/a&gt; either.   Dave brought up a good point in a comment.   &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Technical debt can be assessed like real debt, to a large degree. How much are you paying monthly because of the debt? An annoying little thing, or wanting to upgrade to a new version just for newness’ sake has a low interest rate.&lt;/p&gt;
&lt;p&gt;&amp;#8211; Dave Brondsema
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;But it got me thinking, perhaps &amp;#8220;debt&amp;#8221; isn&amp;#8217;t the right metaphor for this at all.   Annoying issues that don&amp;#8217;t cost anything, and don&amp;#8217;t technically need to be &amp;#8220;repaid&amp;#8221;  aren&amp;#8217;t properly debt at all.   &lt;/p&gt;
&lt;p&gt;Perhaps technical &lt;em&gt;warts&lt;/em&gt; would be a better term for those kind of things.   It feels good to fix them.   But rather than feel righteous for spending time fixing them all and &amp;#8220;paying down our debt,&amp;#8221; perhaps we ought to feel a little bit self indulgent for spending time and money on what amounts to cosmetic surgery for our code. &lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not saying cosmetic surgery is never valuable, or that warts are never painful, and certainly not that you should ignore them.  After all warts can be cancerous, and could perhaps kill you. But after investigating and discovering that they are benign, perhaps it&amp;#8217;s not worth the cost to have them removed. &lt;/p&gt;</description>
	<pubDate>Tue, 05 Oct 2010 03:15:39 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing gogo, The Bash Project Switcher</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-283110783693731884</guid>
	<link>http://codersbuffet.blogspot.com/2010/09/announcing-gogo-bash-project-switcher.html</link>
	<description>If you're a developer, then you've faced this problem: When you switch between multiple projects, you have to switch your shell, your editor, and possibly a lot more. If it's time to start a new project, then there's all the busy work of making a new project.&lt;br /&gt;&lt;br /&gt;Those problems are now ending.&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://bitbucket.org/pedersen/gogo&quot;&gt;gogo&lt;/a&gt; is a set of &lt;a href=&quot;http://www.gnu.org/software/bash&quot;&gt;bash&lt;/a&gt; functions that will enable you to more easily switch things around. Since I wrote it (first) for me, it supports my most common needs up front: &lt;a href=&quot;http://www.python.org/&quot;&gt;Python&lt;/a&gt;, &lt;a href=&quot;http://mercurial.selenic.com/&quot;&gt;Mercurial&lt;/a&gt;, &lt;a href=&quot;http://www.gnu.org/software/emacs&quot;&gt;Emacs&lt;/a&gt;, and &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt;. The only piece that is not trivially swappable is Mercurial. I'm sorry, that's on my todo list, but I wanted to let people see it and maybe start getting some value from it.&lt;br /&gt;&lt;br /&gt;I highly recommend checking out the &lt;a href=&quot;http://bitbucket.org/pedersen/gogo/src/tip/README.txt&quot;&gt;README&lt;/a&gt; file. It includes instructions on getting set up, along with instructions on how to use the tool. For now, a quick summary of usage:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make a new project: gogo -n myproject&lt;/li&gt;&lt;li&gt;Activate the new project (after having closed your current shell): gogo myproject&lt;/li&gt;&lt;li&gt;Make a new Python project: gogo -n -l python pyproject&lt;/li&gt;&lt;li&gt;Make a new TurboGears project: gogo -n -l python -t tg21 tgproject&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Switching between projects is downright trivial. gogo even supports tab completion of project names. It's already helping me, and hopefully it can help you.&lt;br /&gt;&lt;br /&gt;You can download the &lt;a href=&quot;http://v0.4%20release/&quot;&gt;v0.4 release&lt;/a&gt;, or clone the &lt;a href=&quot;http://bitbucket.org/pedersen/gogo&quot;&gt;latest repository&lt;/a&gt; (or even download a &lt;a href=&quot;http://bitbucket.org/pedersen/gogo/get/tip.tar.gz&quot;&gt;.tar.gz&lt;/a&gt; file of it).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-283110783693731884?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 14 Sep 2010 19:32:38 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Alessandro Molina: Lowering Tg2 memory usage by running multiple instances of an app inside same WSGI daemon process</title>
	<guid>http://blog.axant.it/?p=303</guid>
	<link>http://blog.axant.it/archives/303</link>
	<description>&lt;p&gt;I was recently trying to deploy one app multiple times inside the same&lt;br /&gt;
&lt;strong&gt; WSGIProcessGroup&lt;/strong&gt; and &lt;strong&gt;WSGIApplicationGroup %{GLOBAL}&lt;/strong&gt; to reduce memory&lt;br /&gt;
usage.&lt;br /&gt;
This works quite well except for all the SQLAlchemy sessions which end being&lt;br /&gt;
attached to the engine of the last wsgi script started.&lt;/p&gt;
&lt;p&gt;The best solution that I have been able to get so far is to create a proxy interface to the application engine. This way each wsgi script gets binded to the same engine, but the engine itself keeps track of all the available real engines and responds to the script requests sending them to the right real engine.&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;class&lt;/span&gt; MultiSiteEngine&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
   &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
       &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;engines&lt;/span&gt; = &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
   &lt;span&gt;def&lt;/span&gt; &lt;span&gt;__getattr__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, name&lt;span&gt;&amp;#41;&lt;/span&gt;:
       &lt;span&gt;if&lt;/span&gt; name == &lt;span&gt;'engines'&lt;/span&gt;:
           &lt;span&gt;return&lt;/span&gt; &lt;span&gt;object&lt;/span&gt;.&lt;span&gt;__getattribute__&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, name&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
       &lt;span&gt;if&lt;/span&gt; &lt;span&gt;not&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;engines&lt;/span&gt;.&lt;span&gt;has_key&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;config&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'sqlalchemy.url'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
           &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;engines&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;config&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'sqlalchemy.url'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt; = engine_from_config&lt;span&gt;&amp;#40;&lt;/span&gt;config, &lt;span&gt;'sqlalchemy.'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
       &lt;span&gt;return&lt;/span&gt; &lt;span&gt;getattr&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;.&lt;span&gt;engines&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;config&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;'sqlalchemy.url'&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;, name&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To make this work just allocate a &lt;strong&gt;multi_engine = MultiSiteEngine()&lt;/strong&gt; inside your tg2 app model &lt;em&gt;__init__&lt;/em&gt; and change &lt;strong&gt;init_model&lt;/strong&gt; method to pass &lt;em&gt;multi_engine&lt;/em&gt; instead of the engine itself.&lt;/p&gt;</description>
	<pubDate>Fri, 06 Aug 2010 15:01:29 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: Patched TG2 bootstrap script for python 2.6</title>
	<guid>http://blog.axant.it/?p=294</guid>
	<link>http://blog.axant.it/archives/294</link>
	<description>&lt;p&gt;As actually I end up installing Tg2 on various systems having python2.6 quite often I have patched the bootstrap script to work on it.&lt;/p&gt;
&lt;p&gt;If you had problems installing TG2 on python2.6 failing on Extremes or Zope dependencies you can try to use this script, it should work for you:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bitbucket.org/_amol_/tg-bootstrap-py2.6/src/tip/tg2-bootstrap.py&quot;&gt;https://bitbucket.org/_amol_/tg-bootstrap-py2.6/src/tip/tg2-bootstrap.py&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 28 Jul 2010 22:41:07 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing the Availability of tgext.menu v1.0b3</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-1676506875650196918</guid>
	<link>http://codersbuffet.blogspot.com/2010/07/announcing-availability-of-tgextmenu_26.html</link>
	<description>tgext.menu v1.0b3 is available for immediate download. It can be found on &lt;a href=&quot;http://pypi.python.org/pypi/tgext.menu/1.0b3&quot;&gt;PyPI&lt;/a&gt;&amp;nbsp;in an easy_install'able form. The source may be found at &lt;a href=&quot;http://bitbucket.org/pedersen/tgext.menu&quot;&gt;BitBucket&lt;/a&gt;. This release now allows specifying the icon for a menu entry in the decorators and functions, fixes an issue where an id could be duplicated, and allows for replacement of the default template.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-1676506875650196918?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 26 Jul 2010 21:21:26 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: TurboGears, SQLAlchemy, and Parent/Child Relations on the Same Model</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-5583575435408594300</guid>
	<link>http://codersbuffet.blogspot.com/2010/07/turbogears-sqlalchemy-and-parentchild.html</link>
	<description>Best thing to do is to read this post. I'm just posting it here to try to help it get more exposure to those who might need it.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.5dollarwhitebox.org/drupal/node/110&quot;&gt;http://www.5dollarwhitebox.org/drupal/node/110&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-5583575435408594300?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Thu, 15 Jul 2010 11:00:29 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: Announcing the Availability of tgext.menu v1.0b2</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-8244663227007723923</guid>
	<link>http://codersbuffet.blogspot.com/2010/07/announcing-availability-of-tgextmenu.html</link>
	<description>This is a minor update. It contains new installation instructions due to testing failures right after installation in a new quickstart, along with a fix for a menu display bug with jdMenu, and some new API enhancements from bitbucket user scottawilliams. It is already available on PyPI, and you may upgrade as soon as you are ready.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-8244663227007723923?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 12 Jul 2010 22:59:51 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: TurboGears and Amazon EC2 Benchmarking, Part 4: Conclusions</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-7836945089569503385</guid>
	<link>http://codersbuffet.blogspot.com/2010/07/turbogears-and-amazon-ec2-benchmarking_10.html</link>
	<description>Reviewing my methods, and the results I got, I found out quite a bit about TurboGears. I learned about how it will perform in real world scenarios, and I learned how to figure out the level of hardware I will need to accommodate a community. So, what does this mean for you?&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;For TurboGears, this is about answering the question: &quot;How well does this scale&quot;.&lt;br /&gt;&lt;br /&gt;The results of that question cover a very limited set of variables: How much hardware do you need to scale? What version of TG provides the best performance? Is Genshi or Mako the better performing template engine?&lt;br /&gt;&lt;br /&gt;That's it. No more, no less. By and large, the numbers speak for themselves. The only gotcha in this is that those numbers are for all the dynamic pages. They do not cover the static pages, and that is done deliberately. I configured Apache to handle serving static CSS and JavaScript files. You get the full speed of Apache when the files are static, and then you get the full benefits of TurboGears for all your dynamic pages.&lt;br /&gt;&lt;br /&gt;If you need to deploy and scale your TurboGears application, look at those numbers, use the definition of an Amazon EC2 Compute Unit (along with how many each instance provides), and then comes the hard part: You must estimate how many dynamic pages are going to be viewed at a time. I would then leave an additional 50% capacity, just as a buffer.&lt;br /&gt;&lt;br /&gt;So, if you expect your site to attract, at peak, 10 dynamic page views per second, and you're on TG2.1b2 with Genshi, then you can get away with the smallest instance. The requirements &lt;b&gt;sound&lt;/b&gt;&amp;nbsp;like you need something huge, but you really don't. Remember what I said in yesterday's post: 864,000 dynamic page views per day on something that small. That's a lot of page views, and will support a very active community.&lt;br /&gt;&lt;br /&gt;I'm glad to be working with TurboGears. Lots of power, lots of scalability, and it's all built in. I just have to use it.&lt;br /&gt;&lt;br /&gt;Now, as I close out this series, I'd just like to say thank you to the developers who work so long and hard with TurboGears. They make things like these posts possible.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-7836945089569503385?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Sat, 10 Jul 2010 23:52:53 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: TurboGears and Amazon EC2 Benchmarking, Part 3: What I was Testing</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-2582671340308916380</guid>
	<link>http://codersbuffet.blogspot.com/2010/07/turbogears-and-amazon-ec2-benchmarking.html</link>
	<description>&lt;div&gt;I actually learned a few things, some of which were surprising, some of which were not. One thing that I don't think I've communicated very well to my readers is that I most emphatically am&amp;nbsp;&lt;b&gt;not&lt;/b&gt;&amp;nbsp;comparing TurboGears to any of the other frameworks out there. I'm comparing TurboGears to itself, and finding out what I need to do to scale it up.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I could compare to Ruby on Rails, CakeWalk, CodeIgniter, WebCore, Django, and a host of others. The problem with doing so is that doing that sort of comparison is nearly impossible. Why? Each of these frameworks has their own particular pluses and minuses. PHP versus Python vs Ruby. Pure unadulterated speed vs size of community vs how much scaffolding you need to build vs how locked in you are after you start using it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For every developer, these are tradeoffs. Some will be okay with scaffolding. Some demand PHP. Others want the framework to put no demands on them. Comparing all of these frameworks in an unbiased fashion just is not feasible. That's why I didn't do it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All of these, from very very slow to very very fast, will serve the needs of a great many web sites. Even at a &quot;mere&quot; 10 requests per second,&amp;nbsp;that's 864,000 dynamic page views per day. I happen to participate in a forum which transfers around 3G of data every day, and it only gets 380,000 URL requests per day (both dynamic and static).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is part of why I've stressed that I'm testing the whole application stack so very much in these past few posts. Any of these frameworks are more than capable of serving a rather large and thriving community on very simple hardware.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, think about those numbers long and hard before you say that a &quot;mere&quot; 14 requests per second is not good enough. If you actually analyze your needs, you're likely to find that you're overly focused on a number that won't matter nearly as much as you think it does.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-2582671340308916380?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Fri, 09 Jul 2010 09:43:00 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: TurboGears and Amazon EC2 Benchmarking, Part 2: Requests per Second</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-5293307569046725398</guid>
	<link>http://codersbuffet.blogspot.com/2010/06/turbogears-and-amazon-ec2-benchmarking_09.html</link>
	<description>That all important question has been asked, and is now answered: How fast is &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt;? I started this &lt;a href=&quot;http://codersbuffet.blogspot.com/2010/06/turbogears-and-amazon-ec2-benchmarking.html&quot;&gt;series yesterday&lt;/a&gt; when I described my methodology. I conclude soon with my analysis of what I did, and what I found.&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;The numbers below are not what you might expect to see. Many people, when doing benchmarks, do the equivalent of writing &quot;hello world&quot;, and say &quot;That's how fast my web framework is.&quot; No, it's not. It's considerably slower than that. I've seen far too many benchmarks like that. I'll not link to any of them, as I don't wish to encourage more like that. I want to get an idea of how a full featured application will perform, not some dinky &quot;hello world&quot;.&lt;br /&gt;&lt;br /&gt;When looking at these numbers today, keep one thing in mind: These are not &quot;hello world&quot; requests. These requests include templating, caching, sessions, database requests and transactions, authentication, authorization, and all of the other little pieces that make an actual web application into an application versus something that manages to simply print &quot;hello world&quot; on the screen.&lt;br /&gt;&lt;br /&gt;I'll be back tomorrow with some analysis, both on the numbers, and my own biases in the whole process. For now, look these over. I think you'll find them interesting.&lt;br /&gt;&lt;br /&gt;In the below table, the columns have the following meanings:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;EC2 Instance Name&lt;/b&gt;: This is the marketing name of the instance as visible on &lt;a href=&quot;http://aws.amazon.com/ec2/&quot;&gt;Amazon's page about EC2&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;EC2 Instance Type&lt;/b&gt;: This is the instance name that you will see when you create a new instance on EC2.&lt;/li&gt;&lt;li&gt;&lt;b&gt;TG Version&lt;/b&gt;: The version of &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; that produced these results&lt;/li&gt;&lt;li&gt;&lt;b&gt;Genshi/Mako&lt;/b&gt;: When running these tests, I varied the template engine between these two where possible. This column indicates the template engine that produced these results.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Index or Database&lt;/b&gt;: The default index page for a quickstarted application does not hit the database. This column indicates whether I was forcing a database hit, or just hitting the index page.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Req/Second&lt;/b&gt;: How many requests per second were being processed. I truncated the results (so nothing after a decimal).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;2&quot; cellpadding=&quot;6&quot; cellspacing=&quot;0&quot; frame=&quot;hsides&quot; rules=&quot;groups&quot;&gt;&lt;caption&gt;TurboGears on EC2 Results&lt;/caption&gt; &lt;colgroup&gt;&lt;col align=&quot;left&quot; /&gt;&lt;col align=&quot;left&quot; /&gt;&lt;col align=&quot;left&quot; /&gt;&lt;col align=&quot;left&quot; /&gt;&lt;col align=&quot;left&quot; /&gt;&lt;col align=&quot;right&quot; /&gt; &lt;/colgroup&gt; &lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Name&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Type&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;TG Version&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Genshi/Mako&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Index or Database&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Req/Second&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;86&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;44&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;148&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;171&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;94&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;284&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;171&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;388&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;229&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;217&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.0.3&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Name&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Type&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;TG Version&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Genshi/Mako&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Index or Database&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Req/Second&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;124&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;58&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;96&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;41&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;168&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;70&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;196&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;86&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;349&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;468&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;194&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;283&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Genshi&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;126&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Name&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;EC2 Instance Type&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;TG Version&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Genshi/Mako&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Index or Database&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Req/Second&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;115&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Small Instance&lt;/td&gt;&lt;td&gt;m1.small&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;480&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Medium&lt;/td&gt;&lt;td&gt;c1.medium&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;93&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;282&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Large&lt;/td&gt;&lt;td&gt;m1.large&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;63&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;415&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Extra Large&lt;/td&gt;&lt;td&gt;m1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;94&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;630&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Extra Large&lt;/td&gt;&lt;td&gt;m2.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;131&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;976&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Double Extra Large&lt;/td&gt;&lt;td&gt;m2.2xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;220&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;1354&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Memory Quadruple Extra Large&lt;/td&gt;&lt;td&gt;m2.4xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;274&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Index&lt;/td&gt;&lt;td&gt;776&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-CPU Extra Large&lt;/td&gt;&lt;td&gt;x1.xlarge&lt;/td&gt;&lt;td&gt;2.1b2&lt;/td&gt;&lt;td&gt;Mako&lt;/td&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;181&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-5293307569046725398?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Fri, 09 Jul 2010 09:40:19 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Jorge Vargas: Hoy Dom Sagolla en RD, #sagollaRD y el futuro</title>
	<guid>http://blog.maetico.com/post/745572031</guid>
	<link>http://blog.maetico.com/post/745572031</link>
	<description>&lt;p&gt;El día ha llegado. Hoy se presenta Dom Sagolla (@dom) en Republica Dominicana y le deseo suerte. Esperemos que la audiencia logre sacarle todo el provecho que pueda y que @dom se lleve una muy buena impresión de la representación de nuestra comunidad que fue a escucharlo.&lt;/p&gt;
&lt;p&gt;Dicho eso, me parece mas interesante analizar el entorno, ya que al igual que las redes sociales, la huella de esta conferencia (a mi parecer) es mas importante que la conferencia en si. La punta de lanza de este entorno durante las pasadas semanas fue el tag #SagollaRD en twitter, aunque las ramificaciones son bastantes, desde replies públicos con y sin mention, DMs (mensajes directos), google buzz, emails públicos, privados y oficiales (de twitter inc.), llamadas telefónicas, almuerzos, discusiones de pasillo, reuniones para tratar el tema, temas varios después de las reuniones, mesas de tragos, conversaciones de bomba de gasolina, y hasta tema para romper esos silencios incómodos que ocurren de vez en cuando. &lt;/p&gt;
&lt;p&gt;En fin la cola es larga e interesante. A continuación una serie de puntos a resaltar sin orden de relevancia:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;El “old style” marketing, es decir publicidad masiva, medios de comunicación, rifas, un mensaje unificado, repetir hasta el cansancio, entre otros. Todavia sirve. Irónicamente sirve para mercadear el “new style” marketing, que aboga por como los métodos “tradicionales” son obsoletos. La prueba de esto es simple. Todas (casi?) las boletas del evento se vendieron. El conferencista ganara por su exposición y la compañía organizadora obtendrá el beneficio planificado. Por otro lado el publico pago el precio pactado y saldrá con un conocimiento que no tenia anteriormente.&lt;/li&gt;
&lt;li&gt;Los chistes, la ironía y el sarcasmo son una excelente forma de transmitir la información. Así como pueden ser malinterpretados y tomados demasiado en serio.&lt;/li&gt;
&lt;li&gt;El expositor responde a las inquietudes, discordancias y malentendidos mientras que los organizadores siguen con el mensaje original. Esto es nuevo e interesante ya que nunca antes se había tenido este nivel de contacto, me presento como ejemplo a mi mismo, ante la confusión, al igual que muchos de ustedes me hice las siguiente preguntas: vale la pena que yo vaya? ganare algo de este evento? el costo de la entrada vale lo que potencialmente ganare? si veo el evento online (o me lo cuentan) valdrá la pena economizar ese dinero? La solución fue simple preguntarle al conferencista. Hace 5 años eso hubiera sido una locura. Hoy en día me tomo unos cuantos minutos para pensar la pregunta http://twitter.com/elpargo/status/16699935795 y a el unos cuantos mas responderme &lt;a href=&quot;http://twitter.com/elpargo/status/16699935795.&quot;&gt;http://twitter.com/elpargo/status/16699935795.&lt;/a&gt; El análisis de la pregunta, la respuesta y de si estoy o no sentado en la sala*, es irrelevante aunque queda como un ejercicio para el lector. El punto es contrarrestar toda la inversión en tiempo y dinero del “old style” marketing con la del “new style” y medir su efectividad para cumplir la meta. &lt;/li&gt;
&lt;li&gt;El Cambio del bio de @dom, en la tarde del viernes 18 de junio, &lt;a href=&quot;http://twitter.com/dom&quot;&gt;http://twitter.com/dom&lt;/a&gt; cambio de “co-creator of twitter”** a el texto actual “H&lt;span&gt;elped create @&lt;a title=&quot;Twitter&quot; href=&quot;http://twitter.com&quot;&gt;Twitter&lt;/a&gt;.”&lt;/span&gt; este sutil cambio en si mismo es casi irrelevante, pero dado que gran parte de la controversia generada por #SagollaRD se enfocaba en el termino co-creador, lo vuelve muy importante. Lo mas importante a resaltar es la influencia de la red social y sus ramificaciones, los detalles no los tengo (ni realmente los quiero saber). Lo cierto es que aparentemente #sagollaRD fue la gota que desramo el vaso y influencio a las personas indicadas a que tomaran acción para cambiar rompiendo con el status quo.&lt;/li&gt;
&lt;li&gt;Otro dato curioso es medir la habilidad para adaptarse al cambio de las entidades involucradas, la fecha anterior es importante porque una semana después del cambio (24 junio), en las dos entrevistas realizadas a @dom todavía el termino era usado. Sera interesante ver durante la charla de @dom cuantas veces el utiliza el termino para referirse a si mismo.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Por ultimo me gustaría notar cuatro cosas negativas que salieron a relucir a lo largo de esta discusión.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Criticas a la persona no a la proyección de la imagen: se critico la habilidad de @dom de dar una excelente charla por ser presentado como un “co-creador de twitter” y la publicidad que sugería un rol mas importante del realmente jugado.&lt;/li&gt;
&lt;li&gt;Criticas a la persona no al argumento, se tacho de malo (o bueno) un argumento por venir de algunas personas con conflictos de interés, sin tomar en cuenta la validez del argumento.&lt;/li&gt;
&lt;li&gt;Se genero un ambiente de nosotros contra ellos, donde no se podía tener una opinión neutral y tener puntos a favor y en contra.&lt;/li&gt;
&lt;li&gt;Muchas personas aprovecharon la oportunidad para “saldar pleitos pasados”&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Todas las anteriores simplemente deterioran a la comunidad de personas interesadas en fomentar el avance tecnológico de la República Dominicana, y son practicas que debemos tratar de evitar, podemos discutir y estar radicalmente en desacuerdo sobre algún tema, esto no quiere decir que tengamos que llevar las cosas a titulo personal.&lt;/p&gt;
&lt;p&gt;Por ultimo a los que están/fueron al evento de @dom que lo disfruten y que aprendan, a los que no fueron, que también que se lo disfruten y que aprendan. &lt;/p&gt;
&lt;p&gt;El futuro? Quien sabe. Estamos aquí para crearlo.&lt;/p&gt;
&lt;p&gt;* revisar si he hecho checkin en foursquare es trampa (y la data puede ser alterada con el fin de confundir y ser irónico)&lt;/p&gt;
&lt;p&gt;** Si alguien tiene el texto original me encantaría ponerlo de ejemplo, por favor haganmelo llegar.&lt;/p&gt;
&lt;p&gt;&lt;a title=&quot;Enhanced by Zemanta&quot; href=&quot;http://www.zemanta.com/&quot;&gt;&lt;img class=&quot;zemanta-pixie-img&quot; src=&quot;http://img.zemanta.com/zemified_e.png?x-id=29350c57-fb88-4fa8-bb63-47c8181de2f8&quot; alt=&quot;Enhanced by Zemanta&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 28 Jun 2010 13:00:43 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: Professors' Open Source Summer Experience @ RIT</title>
	<guid>http://lewk.org/blog/2010/06/25/POSSE-RIT</guid>
	<link>http://lewk.org/blog/POSSE-RIT.html</link>
	<description>&lt;p&gt;
&lt;img src=&quot;http://www.teachingopensource.org/images/thumb/d/d1/Posse-logo.png/350px-Posse-logo.png&quot; align=&quot;right&quot; width=&quot;250&quot; /&gt;
Last week &lt;a href=&quot;http://redhat.com&quot;&gt;Red Hat&lt;/a&gt; put on a &lt;a href=&quot;http://teachingopensource.org/index.php/POSSE&quot;&gt;Professors' Open Source
Summer Experience&lt;/a&gt; (POSSE) at &lt;a href=&quot;http://rit.edu&quot;&gt;RIT&lt;/a&gt;. Being an
alumni, I was excited by the opportunity to be able to go back up to The ROC
and teach some of the people that taught me.  Going into it, I really had no
idea what to expect.  All I knew is that I was going to help lead the 'deep
dive' section of the course, where I would teach professors how to dive in head
first and get productively lost in a strange codebase.  This is not something
that can be accomplished with a set of powerpoint slides.  Teaching how to hack on open source
requires that you emerse yourself into a codebase, and bring your students with
you.
&lt;/p&gt;

&lt;p&gt;
The previous POSSE at Worcester State dove into the &lt;a href=&quot;http://sugarlabs.org&quot;&gt;Sugar&lt;/a&gt; &lt;a href=&quot;http://wiki.laptop.org/go/Measure&quot;&gt;Measure Activity&lt;/a&gt;, and we were going to do the same.
&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt;&lt;i&gt;
Measure is an activity that turns the computer into an oscilloscope. Signals
from the microphone (and sensors) can be plotted in time and frequency domains.
&lt;/i&gt;&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;
I had never used this activity, let alone hacked on it before.  I've also never
done any sugar activity development, aside from some tweaking of the &lt;a href=&quot;https://fedorahosted.org/OpenVideoChat&quot;&gt;OpenVideoChat&lt;/a&gt;, so I really
had no idea what I was getting myself into.  The obvious first step was to
get it running.  All of us were able to start the activity in virtual machines
or emulators, except for one install which hit some odd errors upon startup.
We were able to quickly track the bug down to a stray &lt;code&gt;return&lt;/code&gt;
statement in &lt;code&gt;__init__&lt;/code&gt; before some critical initialization code.
Right after we fixed the problem we noticed that Walter Bender had already 
fixed this issue a few hours earlier.  After a &lt;code&gt;git pull&lt;/code&gt;, we were
up and running.
&lt;/p&gt;

&lt;p&gt;
Once we all got the activity running, we took a look at the bug list to see if
there was any low-hanging fruit for us to tackle.  Since the previous POSSE
had already done some work on this activity the week before, there were not
any trivial tickets left in the queue.  So, in that case, we dove head first
into the hardest one, &quot;Measure activity gets stuck after recording&quot;.  This
ticket had very little information, and no log output, so we were on our own
to try and track it down.  We were able to reliably reproduce the issue on the
XO-1.5, but not on the 1.0.  In our virtual machines we hit it sporadically.
We all agreed that it felt like a race-condition, most likely due to
threading.  So we started instrumenting the code and adding some debugging
statements to try and figure out which line of code was the culprit.
&lt;/p&gt;

&lt;p&gt;
In our efforts to scatter &lt;code&gt;print&lt;/code&gt;
statements all over the place to try and determine the code path, we noticed
that none of our output was hitting the logs.  
When you have no idea if your code is even being run or not, don't be ashamed
to throw in a &lt;code&gt;raise Exception(&quot;WTF?!&quot;)&lt;/code&gt;.  We finally realized that since the activity would freeze, it was never able to flush stderr/stdout to the log.  A quick find/replace regex later, and we were using the proper &lt;code&gt;logging&lt;/code&gt; module and seeing our debugging output hit the logs.
&lt;/p&gt;

&lt;p&gt;
We were then able to track the bug down to a line of code that uses &lt;a href=&quot;http://www.gtk.org&quot;&gt;GTK&lt;/a&gt; to try and get
the coordinates of the parent window.  At this point, since none of us were GTK
experts, we had to go upstream.  So, I dropped into #fedora-devel and asked.
Within 10 minutes I had responses from 3 different GTK hackers.  One was a
typical &lt;a href=&quot;http://en.wikipedia.org/wiki/RTFM&quot;&gt;RTFM&lt;/a&gt; response, which humored the professors (who are very used to
hearing/saying this), but the others pointed us in the right direction.  One
mentioned that gtk.gdk calls probably should not be done in a seperate thread.
So, a suggested workaround was to add &lt;code&gt;gtk.threads_enter()/gtk.threads_leave()&lt;/code&gt;
calls before running any gtk.gdk code in the thread.  A &lt;a href=&quot;http://bugs.sugarlabs.org/attachment/ticket/1904/0001-Call-gtk.threads_-enter-leave-before-after-taking-th.patch&quot;&gt;2-line
patch&lt;/a&gt; later, and we had squashed the bug.
&lt;/p&gt;

&lt;p&gt;
We eventually bumped into the inevitable typo in some comments.  So, we made
the fix locally, and committed it to our git repo.  A few minutes later and we
found another one.  I saw this as a great opportunity to show off some of my
git-fu.  Instead of sending two &quot;Fix typo&quot; patches upstream, I showed the
professors how to use git interactive rebasing to squash multiple commits into
a single one.  They all followed along closely, and the workflow made sense to
them.
&lt;/p&gt;

&lt;p&gt;
While we were looking through the ticket queue, we saw an issue where Measure
would apparently leak memory and crash when running it for a long period of
time.  While keeping this in mind, we kept our eyes peeled while wandering
around the codebase to see if we could track the issue down.  When looking at
the code that takes screenshots of the waveform, I noticed that it created a
temporary file with &lt;code&gt;tempfile.mkstemp&lt;/code&gt;, saved the pixmap to it,
injected it into the Journal, and then deleted the directory.  This looked fine
at a first glance, until I realized that it never closed the temporary file descriptor.
Another &lt;a href=&quot;http://bugs.sugarlabs.org/attachment/ticket/2051/0001-Ensure-that-we-close-the-file-descriptors-of-our-tem.patch&quot;&gt;2-line patch&lt;/a&gt; later, and this issue was solved.
&lt;/p&gt;

&lt;p&gt;
The next day both of the patches that we sent upstream were applied by Walter Bender.
&lt;/p&gt;

&lt;p&gt;
Overall, POSSE definitely exceeded my expectations, and I'm extremely satisfied
with how the 'deep dive' section went.  I went into it feeling completely
unprepared to teach, but by trusting my &quot;hacker intuition&quot;, I feel that it
turned out to be a fantastic learning experience for all of us.
&lt;/p&gt;</description>
	<pubDate>Fri, 25 Jun 2010 19:59:33 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing tgext.xmlrpc v0.8</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-3490133342916353678</guid>
	<link>http://codersbuffet.blogspot.com/2010/06/announcing-tgextxmlrpc-v08.html</link>
	<description>This is an important update, and also one that is 100% backwards  compatible.&lt;br /&gt;&lt;br /&gt;This update allows you to have nice Python method signatures, as opposed  to the hacky &quot;*p, **kw&quot; trick that v0.6 required on all methods.&lt;br /&gt;&lt;br /&gt;To clarify, an example. v0.6 code required this:&lt;br /&gt;&lt;br /&gt;class MyXmlRpc(XmlRpcController):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @xmlrpc([['int', 'int', 'int']])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def sumthem(self, *p):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p[0] + p[1]&lt;br /&gt;&lt;br /&gt;v0.8 finally corrects this ugliness. This now works:&lt;br /&gt;&lt;br /&gt;class MyXmlRpc(XmlRpcController):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @xmlrpc([['int', 'int', 'int']])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def sumthem(self, i1, i2):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return i1+i2&lt;br /&gt;&lt;br /&gt;Note that any code written for v0.6 will work just fine with v0.8. This  is a purely cosmetic change, though a welcome one, I think.&lt;br /&gt;&lt;br /&gt;It is available via &lt;a href=&quot;http://pypi.python.org/pypi/tgext.xmlrpc/0.8&quot;&gt;PyPI&lt;/a&gt; and &lt;a href=&quot;http://bitbucket.org/pedersen/tgext.xmlrpc&quot;&gt;BitBucket&lt;/a&gt; (with documentation also on &lt;a href=&quot;http://bitbucket.org/pedersen/tgext.xmlrpc/wiki/Home&quot;&gt;BitBucket&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;Note that I did not forget to finish my Amazon EC2 benchmarking series. The next post in the series has been bugging me. I might not be William Shakespeare, but I do have some standards for my writing, and I've not been able to write up anything decent yet. I think I've finally figured out why I hated what I was writing, so will finish that series this week.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-3490133342916353678?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Tue, 15 Jun 2010 20:11:38 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Michael Pedersen: TurboGears and Amazon EC2 Benchmarking, Part 1: Methodology</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-7755221023120733208</guid>
	<link>http://codersbuffet.blogspot.com/2010/06/turbogears-and-amazon-ec2-benchmarking.html</link>
	<description>This is going to be a multi-part series. As of right now, I've got at least three parts, and I may be adding another one in. I've just gathered a lot of data from &lt;a href=&quot;http://www.amazon.com/&quot;&gt;Amazon&lt;/a&gt;, and the &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; &lt;a href=&quot;http://aws.amazon.com/ec2/&quot;&gt;EC2&lt;/a&gt; images I made. Enough of it, in fact, that I'm not sure how to present all of it. For now, I'll explain how I gathered the data.&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;First, I signed up for &lt;a href=&quot;http://aws.amazon.com/rds/&quot;&gt;Amazon's Relational Database Service&lt;/a&gt; (RDS). This allowed me to move the database off of my EC2 instances. It did subject me to the limits of their setup, and their network, but this provides two advantages:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Web servers and database servers are typically separated in real world deployments. Using RDS allows me to have a similar configuration.&lt;/li&gt;&lt;li&gt; This allows me to show the speed of &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt;. It's a fairly safe bet that Amazon has tuned their RDS service very well. Therefore, any speed issues that occur are likely to belong entirely to TurboGears.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;From there, I used the EC2 &lt;a href=&quot;http://codersbuffet.blogspot.com/2010/05/announcing-turbpgears-ec2-images.html&quot;&gt;Amazon Machine Images I announced last week&lt;/a&gt;. I would start up an instance, create a quickstarted application, and then test against both the index page (which produces no database hits) and against the index page with authentication cookies, which did produce database hits.&lt;br /&gt;&lt;br /&gt;That's the summary.&lt;br /&gt;&lt;br /&gt;For 2.0.3, I did the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Start up the instance of the TG 2.0.3 AMI I created. Use the correct one to get an instance size I've not yet measured.&lt;/li&gt;&lt;li&gt;ssh into the machine&lt;/li&gt;&lt;li&gt;Become the &quot;turbogears&quot; user&lt;/li&gt;&lt;li&gt;Create a quickstart app named &quot;tgtestapp&quot;&lt;/li&gt;&lt;li&gt;Run &quot;python setup.py develop&quot; to register the application&lt;/li&gt;&lt;li&gt;Copy development.ini to tgapp.ini, as expected by the AMI&lt;/li&gt;&lt;li&gt;Edit tgapp.ini: Set debug to False, and set the correct sqlalchemy.url to point to the RDS database.&lt;/li&gt;&lt;li&gt;Use &quot;paster setup-app tgapp.ini&quot; to initialize the database&lt;/li&gt;&lt;li&gt;Use &quot;tglinker tgtestapp 0.1dev&quot; to configure the remaining mod_wsgi files&lt;/li&gt;&lt;li&gt;Restart Apache&lt;/li&gt;&lt;li&gt;Visit the site in a browser to make sure the site is visible&lt;/li&gt;&lt;li&gt;Run the commands I made for benchmarking, and record the requests per second value from them.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;For 2.1b2, I did the following (very similar to 2.0.3):&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Start up the instance of the TG 2.1b2 AMI I created. Use the  correct one to get an instance size I've not yet measured.&lt;/li&gt;&lt;li&gt;ssh  into the machine&lt;/li&gt;&lt;li&gt;Become the &quot;turbogears&quot; user&lt;/li&gt;&lt;li&gt;Create a  quickstart app named &quot;tgtestapp&quot; using genshi templates&lt;/li&gt;&lt;li&gt;Run &quot;python setup.py develop&quot; to  register the application&lt;/li&gt;&lt;li&gt;Copy development.ini to tgapp.ini, as  expected by the AMI&lt;/li&gt;&lt;li&gt;Edit tgapp.ini: Set debug to False, and set  the correct sqlalchemy.url to point to the RDS database.&lt;/li&gt;&lt;li&gt;Use  &quot;paster setup-app tgapp.ini&quot; to initialize the database&lt;/li&gt;&lt;li&gt;Use  &quot;tglinker tgtestapp 0.1dev&quot; to configure the remaining mod_wsgi files&lt;/li&gt;&lt;li&gt;Restart  Apache&lt;/li&gt;&lt;li&gt;Visit the site in a browser to make sure the site  is visible&lt;/li&gt;&lt;li&gt;Run the commands I made for benchmarking, and record  the requests per second value from them.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Destroy the current quickstarted app (rm -rf)&lt;/li&gt;&lt;li&gt;Make a new one, using mako templates&lt;/li&gt;&lt;li&gt;Run &quot;python setup.py develop&quot; to  register the application&lt;/li&gt;&lt;li&gt;Use  &quot;tglinker tgtestapp 0.1dev&quot; to configure the remaining mod_wsgi files&lt;/li&gt;&lt;li&gt;Restart  Apache&lt;/li&gt;&lt;li&gt;Visit the site in a browser to make sure the site  is visible&lt;/li&gt;&lt;li&gt;Run the commands I made for benchmarking, and record  the requests per second value from them.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;I repeated all of the steps (for both 2.0.3 and 2.1b2) for all Amazon EC2 instance sizes.&lt;br /&gt;&lt;br /&gt;The commands I used for running the actual benchmarks are as follows:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ab -c 10 -n 400 http://localhost/&lt;/li&gt;&lt;li&gt;ab -c 10 -n 1000 http://localhost/&lt;/li&gt;&lt;li&gt;ab -c 10 -n 1000 -C 'tgtestapp=06c4a524f1a6c3196b1c491e95517c61c1770ef7efeaaacdcc29437c70cc8737438fc02d' -C 'authtkt=&quot;3a5c5890ea35f1bea327bf5b43123bbe4c0ef565manager!&quot;' -C 'authtkt=&quot;3a5c5890ea35f1bea327bf5b43123bbe4c0ef565manager!&quot;' http://localhost/&lt;/li&gt;&lt;/ul&gt;I have noticed a sometimes significant delay in mod_wsgi getting started serving the site. The first command overcomes that delay, and gets everything flowing as smoothly as possible. The second command focuses on raw rendering speed. The third looks at speed when the database server is in the mix, as it will generate hits.&lt;br /&gt;&lt;br /&gt;Many people insist on multiple runs when doing benchmarks. To a degree, they are right. They are looking to know the absolute values, and benchmarking is inherently non-absolute. I did not do multiple runs, because I was looking for approximations of real world performance. Any one run will provide that.&lt;br /&gt;&lt;br /&gt;Even those times when I said &quot;Wait, that can't be right&quot;, and re-ran the numbers, I found the results were always within a few percentage points of each other. I quickly figured out that, for the needs of this article, anything more than one run would be superfluous.&lt;br /&gt;&lt;br /&gt;You will note that the pages being retrieved are not simple &quot;hello world&quot; pages. The entire &lt;a href=&quot;http://turbogears.org/2.1/docs/main/RequestFlow.html&quot;&gt;TurboGears stack&lt;/a&gt; gets tried out here. This is a full, real world example of what you can expect to see from TurboGears on Amazon's EC2 service. As such, multiple runs are of questionable value in this case (at best). If enough people are bothered by this, I'll do re-runs, and average out the results (or get the median, whichever), but I really do not feel it is necessary for this particular test.&lt;br /&gt;&lt;br /&gt;Preparing the results for viewing on blogspot is actually taking a bit of time. I'll get them up in the next two days, so that everybody can see the numbers that I see.&lt;br /&gt;&lt;br /&gt;Next: &lt;a href=&quot;http://codersbuffet.blogspot.com/2010/06/turbogears-and-amazon-ec2-benchmarking_09.html&quot;&gt;Requests per Second&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-7755221023120733208?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Wed, 09 Jun 2010 20:23:49 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Luke Macken: Fedora Updates Report</title>
	<guid>http://lewk.org/blog/2010/06/08/bodhi-stats-20100608</guid>
	<link>http://lewk.org/blog/bodhi-stats-20100608.html</link>
	<description>&lt;p&gt;
&lt;img src=&quot;https://admin.fedoraproject.org/updates/static/images/bodhi-icon-48.png&quot; align=&quot;right&quot; /&gt;
I recently wrote some code to generate detailed statistics of Fedora &amp;amp; EPEL
updates within &lt;a href=&quot;https://fedorahosted.org/bodhi&quot;&gt;bodhi&lt;/a&gt;.  Eventually
this will be auto-generated and exposed within bodhi itself, but for now here are the initial metrics.
&lt;/p&gt;
&lt;p&gt;
This report definitely conveys the shortcomings in how we currently utilize
bodhi for &quot;testing&quot; updates, however, it does show us
improving with each release.  For Fedora 13, we implemented the &lt;a href=&quot;http://fedoraproject.org/wiki/No_Frozen_Rawhide_Proposal&quot;&gt;No Frozen
    Rawhide&lt;/a&gt; process with improved &lt;a href=&quot;http://fedoraproject.org/wiki/Critical_Path_Packages_Proposal&quot;&gt;Critical
    Path&lt;/a&gt; policies, which were definitely a success.  With these enhanced procedures, along with the upcoming implementation of &lt;a href=&quot;https://fedorahosted.org/autoqa/&quot;&gt;AutoQA&lt;/a&gt; and the new &lt;a href=&quot;https://fedoraproject.org/wiki/Package_update_acceptance_criteria&quot;&gt;Package
    update acceptance criteria&lt;/a&gt;, I think we'll see these numbers drastically improve in the future.
&lt;/p&gt;
&lt;p&gt;
You can find the code that generates these statistics here: &lt;a href=&quot;https://fedorahosted.org/bodhi/browser/bodhi/tools/metrics.py&quot;&gt;metrics.py&lt;/a&gt;, &lt;a href=&quot;https://fedorahosted.org/bodhi/browser/bodhi/tools/log_stats.py&quot;&gt;log_stats.py&lt;/a&gt;.  If you have any ideas or suggestions for different types of metrics to generate, or if you find any bugs in my code, please let me know.
&lt;/p&gt;
&lt;p&gt;
&lt;blockquote&gt;
&lt;code&gt;
&lt;pre&gt;
Bodhi Statistics Report (Generated on June 8th, 2010)
=====================================================

Out of 17412 total updates, 2958 received feedback (16.99%)
Out of 1045 total unique karma submitters, the top 30 are:
 * notting (424)
 * mclasen (366)
 * jkeating (321)
 * adamwill (283)
 * cwickert (161)
 * rdieter (159)
 * pbrobinson (141)
 * kevin (141)
 * cweyl (122)
 * tomspur (119)
 * mtasaka (110)
 * xake (97)
 * cschwangler (86)
 * kwright (84)
 * peter (83)
 * hadess (80)
 * michich (72)
 * tagoh (69)
 * pfrields (69)
 * bpepple (69)
 * iarnell (68)
 * lkundrak (66)
 * shinobi (65)
 * sundaram (64)
 * spot (62)
 * pravins (62)
 * markmc (62)
 * thomasj (61)
 * smooge (60)
 * fab (59)

================================================================================
     Fedora 13
================================================================================

 * 3562 updates
 * 3065 stable updates
 * 427 testing updates
 * 62 pending updates
 * 8 obsolete updates
 * 2371 bugfix updates (66.56%)
 * 745 enhancement updates (20.92%)
 * 89 security updates (2.50%)
 * 357 newpackage updates (10.02%)
 * 410 critical path updates (11.51%)
 * 333 critical path updates approved
 * 1155 updates received feedback (32.43%)
 * 12120 +0 comments
 * 2477 +1 comments
 * 155 -1 comments
 * 595 unique authenticated karma submitters
 * 133 anonymous users gave feedback (1.57%)
 * 2261 out of 3562 updates went through testing (63.48%)
 * 1317 testing updates were pushed *without* karma (58.25%)
 * 21 critical path updates pushed *without* karma
 * Time spent in testing:
   * mean = 11 days
   * median = 9 days
   * mode = 7 days
 * 4 updates automatically unpushed due to karma (0.11%)
   * 0 of which were critical path updates
 * 231 updates automatically pushed due to karma (6.49%)
   * 2 of which were critical path updates
 * Time spent in testing of updates that were pushed by karma:
   * mean = 11 days
   * median = 7 days
   * mode = 7 days
 * Time spent in testing of updates that were unpushed by karma:
   * mean = 9 days
   * median = 5 days
   * mode = 5 days
 * 2445 packages updated (top 10 shown)
    * selinux-policy: 13
    * jd: 12
    * openoffice.org: 12
    * gdb: 12
    * ibus-pinyin: 11
    * nautilus: 10
    * kernel: 10
    * evolution: 9
    * libfm: 9
    * libmx: 9

================================================================================
     Fedora 12
================================================================================

 * 4844 updates
 * 4291 stable updates
 * 371 testing updates
 * 113 pending updates
 * 69 obsolete updates
 * 2905 bugfix updates (59.97%)
 * 1054 enhancement updates (21.76%)
 * 201 security updates (4.15%)
 * 684 newpackage updates (14.12%)
 * 407 critical path updates (8.40%)
 * 960 updates received feedback (19.82%)
 * 16311 +0 comments
 * 1899 +1 comments
 * 554 -1 comments
 * 758 unique authenticated karma submitters
 * 576 anonymous users gave feedback (5.33%)
 * 2873 out of 4844 updates went through testing (59.31%)
 * 2138 testing updates were pushed *without* karma (74.42%)
 * 188 critical path updates pushed *without* karma
 * Time spent in testing:
   * mean = 14 days
   * median = 13 days
   * mode = 17 days
 * 12 updates automatically unpushed due to karma (0.25%)
   * 4 of which were critical path updates
 * 133 updates automatically pushed due to karma (2.75%)
   * 13 of which were critical path updates
 * Time spent in testing of updates that were pushed by karma:
   * mean = 11 days
   * median = 7 days
   * mode = 7 days
 * Time spent in testing of updates that were unpushed by karma:
   * mean = 9 days
   * median = 5 days
   * mode = 5 days
 * 2902 packages updated (top 10 shown)
    * qbittorrent: 25
    * gdb: 25
    * selinux-policy: 22
    * kernel: 15
    * xorg-x11-server: 14
    * ibus: 13
    * jd: 13
    * abrt: 11
    * gvfs: 11
    * gtk2: 11

================================================================================
     Fedora 11
================================================================================

 * 6987 updates
 * 6381 stable updates
 * 183 testing updates
 * 99 pending updates
 * 324 obsolete updates
 * 3649 bugfix updates (52.23%)
 * 1566 enhancement updates (22.41%)
 * 350 security updates (5.01%)
 * 1422 newpackage updates (20.35%)
 * 383 critical path updates (5.48%)
 * 729 updates received feedback (10.43%)
 * 23427 +0 comments
 * 1197 +1 comments
 * 448 -1 comments
 * 782 unique authenticated karma submitters
 * 481 anonymous users gave feedback (3.58%)
 * 4129 out of 6987 updates went through testing (59.10%)
 * 3620 testing updates were pushed *without* karma (87.67%)
 * 278 critical path updates pushed *without* karma
 * Time spent in testing:
   * mean = 15 days
   * median = 14 days
   * mode = 17 days
 * 7 updates automatically unpushed due to karma (0.10%)
   * 0 of which were critical path updates
 * 64 updates automatically pushed due to karma (0.92%)
   * 11 of which were critical path updates
 * Time spent in testing of updates that were pushed by karma:
   * mean = 11 days
   * median = 7 days
   * mode = 7 days
 * Time spent in testing of updates that were unpushed by karma:
   * mean = 9 days
   * median = 5 days
   * mode = 5 days
 * 3787 packages updated (top 10 shown)
    * libguestfs: 30
    * jd: 24
    * selinux-policy: 23
    * kdebase-workspace: 19
    * kernel: 18
    * gdb: 16
    * dovecot: 16
    * qemu: 16
    * kdebase-runtime: 16
    * kdenetwork: 16

================================================================================
     Fedora EPEL 5
================================================================================

 * 1572 updates
 * 1255 stable updates
 * 198 testing updates
 * 43 pending updates
 * 76 obsolete updates
 * 734 bugfix updates (46.69%)
 * 236 enhancement updates (15.01%)
 * 93 security updates (5.92%)
 * 509 newpackage updates (32.38%)
 * 20 critical path updates (1.27%)
 * 103 updates received feedback (6.55%)
 * 6076 +0 comments
 * 156 +1 comments
 * 19 -1 comments
 * 243 unique authenticated karma submitters
 * 41 anonymous users gave feedback (1.22%)
 * 1176 out of 1572 updates went through testing (74.81%)
 * 1092 testing updates were pushed *without* karma (92.86%)
 * 19 critical path updates pushed *without* karma
 * Time spent in testing:
   * mean = 24 days
   * median = 18 days
   * mode = 16 days
 * 0 updates automatically unpushed due to karma (0.00%)
   * 0 of which were critical path updates
 * 10 updates automatically pushed due to karma (0.64%)
   * 0 of which were critical path updates
 * Time spent in testing of updates that were pushed by karma:
   * mean = 11 days
   * median = 7 days
   * mode = 7 days
 * Time spent in testing of updates that were unpushed by karma:
   * mean = 9 days
   * median = 5 days
   * mode = 5 days
 * 1060 packages updated (top 10 shown)
    * libguestfs: 26
    * znc: 10
    * vrq: 8
    * cherokee: 8
    * 389-ds-base: 8
    * viewvc: 8
    * 389-admin: 7
    * pki-ca: 7
    * wordpress-mu: 7
    * Django: 7

================================================================================
     Fedora EPEL 4
================================================================================

 * 447 updates
 * 359 stable updates
 * 40 testing updates
 * 11 pending updates
 * 37 obsolete updates
 * 222 bugfix updates (49.66%)
 * 68 enhancement updates (15.21%)
 * 40 security updates (8.95%)
 * 117 newpackage updates (26.17%)
 * 5 critical path updates (1.12%)
 * 11 updates received feedback (2.46%)
 * 1592 +0 comments
 * 11 +1 comments
 * 2 -1 comments
 * 85 unique authenticated karma submitters
 * 2 anonymous users gave feedback (0.24%)
 * 320 out of 447 updates went through testing (71.59%)
 * 311 testing updates were pushed *without* karma (97.19%)
 * 5 critical path updates pushed *without* karma
 * Time spent in testing:
   * mean = 18 days
   * median = 16 days
   * mode = 16 days
 * 0 updates automatically unpushed due to karma (0.00%)
   * 0 of which were critical path updates
 * 1 updates automatically pushed due to karma (0.22%)
   * 0 of which were critical path updates
 * Time spent in testing of updates that were pushed by karma:
   * mean = 11 days
   * median = 7 days
   * mode = 7 days
 * Time spent in testing of updates that were unpushed by karma:
   * mean = 9 days
   * median = 5 days
   * mode = 5 days
 * 313 packages updated (top 10 shown)
    * cherokee: 8
    * globus-common: 7
    * R: 6
    * voms: 6
    * globus-gsi-proxy-ssl: 5
    * globus-openssl-module: 5
    * globus-gsi-proxy-core: 5
    * bitlbee: 5
    * flashrom: 5
    * viewvc: 5
&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;
&lt;/p&gt;</description>
	<pubDate>Tue, 08 Jun 2010 20:41:36 +0000</pubDate>
</item>
<item>
	<title>Gustavo Narea: Web Site Security With repoze.who and repoze.what</title>
	<guid>http://gustavonarea.net/?p=294</guid>
	<link>http://gustavonarea.net/blog/posts/repoze-auth/</link>
	<description>&lt;p&gt;&lt;em&gt;This article first appeared in the &lt;a href=&quot;http://pymag.phparch.com/c/issue/view/98&quot;&gt;May 2009 issue of Python Magazine&lt;/a&gt; and has been slightly updated. The contents of the article are only applicable to repoze.who 1.0 and repoze.what 1.0, &lt;strong&gt;not&lt;/strong&gt; repoze.who 2 and repoze.what 1.1 which are under development as of this writing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Have you ever created a Web application? If so, it&amp;#8217;s very likely that you have at one time or another faced &amp;#8220;the security problem&amp;#8221;; whether to create and maintain a homegrown security sub-system, or to learn to use framework-specific security mechanisms (which may not be as flexible as you wish).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Securing Web applications shouldn&amp;#8217;t be a problem&lt;/strong&gt;. This article explores a highly extensible alternative which you can learn once and use in arbitrary applications, regardless of the Web framework used (if any!).&lt;br /&gt;
&lt;span id=&quot;more-294&quot;&gt;&lt;/span&gt;&lt;br /&gt;
Application security is a broad field within software development, covering topics ranging from low-level network transmission security and encryption, up to application-level data security and input validation. In this article, we will focus on two of the most basic elements of application security: authentication and authorization.&lt;/p&gt;
&lt;h2&gt;Authentication vs. Authorization&lt;/h2&gt;
&lt;p&gt;Even experienced software developers often confuse these two related but not equivalent terms, so we&amp;#8217;ll start by explaining what they are.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authentication&lt;/em&gt;, often shortened as &amp;#8220;authn&amp;#8221;, is what you do when you check the credentials provided by the user to verify that he&amp;#8217;s really who he claims to be. The most widely-used credentials are a set made up of a user identifier (like user name, or email address) and a password.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authorization&lt;/em&gt;, often shortened as &amp;#8220;authz&amp;#8221;, is what you do when you check whether the user has permission to make the request or perform the transaction he&amp;#8217;s currently making. Most of the time this depends on &lt;strong&gt;who&lt;/strong&gt; the subject is, but it may also depend on &lt;strong&gt;what&lt;/strong&gt; is requested, &lt;strong&gt;when&lt;/strong&gt; it is requested, and/or &lt;strong&gt;how&lt;/strong&gt; it is requested.&lt;/p&gt;
&lt;p&gt;A common shortening for &amp;#8220;authentication and authorization&amp;#8221; is &amp;#8220;auth&amp;#8221;.&lt;/p&gt;
&lt;p&gt;And there&amp;#8217;s one more related term that comes into play: &lt;em&gt;Identification&lt;/em&gt;, which is to check whether he was successfully authenticated previously to avoid challenging him again unnecessarily.&lt;/p&gt;
&lt;h2&gt;Authentication, identification and authorization in Python Web applications&lt;/h2&gt;
&lt;p&gt;Web applications powered by Python may take advantage of &lt;a href=&quot;http://docs.repoze.org/who/1.0/&quot;&gt;repoze.who&lt;/a&gt; to handle authentication and identification, and &lt;a href=&quot;http://what.repoze.org/docs/1.0/&quot;&gt;repoze.what&lt;/a&gt; to handle authorization. Both are security frameworks that can be used on top of your application, or integrated with your application&amp;#8217;s Web framework if you are using one.&lt;/p&gt;
&lt;p&gt;You can use them as long as your application is WSGI-compliant. WSGI is a Python standard which defines an interface between HTTP servers and Python applications, similar to &lt;a href=&quot;http://en.wikipedia.org/wiki/Common_Gateway_Interface&quot;&gt;CGI&lt;/a&gt;, which eases the writing of cross Web server libraries (which can be framework-independent) and applications.&lt;/p&gt;
&lt;p&gt;The WSGI standard mandates the availability of a Python dictionary,  referred to as the &amp;#8220;WSGI environment&amp;#8221;.  This dictionary stores CGI environment variables, as well as others specific to the WSGI standard; other components used by your application may also use the WSGI environment to store data.&lt;/p&gt;
&lt;p&gt;Any framework or raw application that exposes the WSGI environment dictionary can use both repoze.who and repoze.what.  The popular WSGI-compliant frameworks &lt;a href=&quot;http://www.cherrypy.org/&quot;&gt;CherryPy&lt;/a&gt;, &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt;, &lt;a href=&quot;http://pylonshq.com/&quot;&gt;Pylons&lt;/a&gt;, &lt;a href=&quot;http://turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; and &lt;a href=&quot;http://werkzeug.pocoo.org/&quot;&gt;Werkzeug&lt;/a&gt; expose this variable.&lt;/p&gt;
&lt;h2&gt;How repoze.who and repoze.what work&lt;/h2&gt;
&lt;p&gt;Figure 1 illustrates how a typical request is processed in WSGI and when repoze.who comes into play.&lt;/p&gt;
&lt;div id=&quot;attachment_310&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-310&quot; title=&quot;Figure 1&quot; src=&quot;http://gustavonarea.net/uploads/Figure1.png&quot; alt=&quot;Figure 1&quot; width=&quot;800&quot; height=&quot;566&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Figure 1&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;repoze.who is a WSGI middleware. A WSGI middleware is a layer that wraps your application, processing each request before your application does. WSGI middleware can also post-process your application&amp;#8217;s response. WSGI applications can have zero or more of these middleware layers.&lt;/p&gt;
&lt;p&gt;As shown in Figure 2, when a request is made and before it reaches your application, repoze.who will try to check if the user is already logged in or if he&amp;#8217;s currently trying to log in. If the user is trying to log in and has supplied the right credentials, authentication will succeed and the user will be &amp;#8220;remembered&amp;#8221; in future requests by default. The request is then passed to the next WSGI middleware, if any, and eventually on to your WSGI application.&lt;/p&gt;
&lt;div id=&quot;attachment_313&quot; class=&quot;wp-caption alignnone&quot;&gt;&lt;img class=&quot;size-full wp-image-313&quot; title=&quot;Figure 2&quot; src=&quot;http://gustavonarea.net/uploads/Figure2.png&quot; alt=&quot;Figure 2&quot; width=&quot;566&quot; height=&quot;800&quot; /&gt;&lt;p class=&quot;wp-caption-text&quot;&gt;Figure 2&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;The following fully customizable components can be used at this stage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The request classifier: It matters if the agent is a browser, a Subversion client or a library which access a Web Service; you wouldn&amp;#8217;t want to display a login form if the agent is a Subversion client, for example. Thus, this component classifies the current request so that only the appropriate plugins (out of your pre-selected ones) are used.&lt;/li&gt;
&lt;li&gt;Identifier plugins: These are the components that &amp;#8220;identify&amp;#8221; the user. That is, they are able to tell if the user is already logged from in a previous request, or if he is trying to log in in the current request. When authentication succeeds, these plugins are in charge of &amp;#8220;remembering&amp;#8221; the user for future requests (e.g., by defining a session cookie). Likewise, when a challenge is required, they &amp;#8220;forget&amp;#8221; the user (discarding a session cookie).&lt;/li&gt;
&lt;li&gt;Authenticator plugins: When the user is trying to log in in the current request, these components verify the user-supplied credentials (such as username and password) against a database, LDAP server, .htaccess file, etc.&lt;/li&gt;
&lt;li&gt;Metadata provider plugins: If the user was authenticated, metadata providers can load data about the current user (email address, full name, etc.) so that such data is ready to be used by your application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After your application issues a response and before it reaches the HTTP server, as shown in Figure 3, repoze.who will check if a challenge is necessary; that is, ask the user in some way to identify himself.  If so and the user was previously authenticated, the previous authentication will be forgotten, and the related session cookie will be discarded. After the challenge is complete, your application&amp;#8217;s response will be replaced with a new response which will allow the user to log in (for example, sending a &amp;#8220;WWW-Authenticate&amp;#8221; header or displaying a login form).&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-full wp-image-365&quot; title=&quot;Figure 3&quot; src=&quot;http://gustavonarea.net/uploads/Figure3.png&quot; alt=&quot;repoze.who on egress&quot; width=&quot;566&quot; height=&quot;800&quot; /&gt;&lt;/p&gt;
&lt;p&gt;repoze.who&amp;#8217;s response-handling functionality is also driven by customizable components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The challenge decider: This is the component which will determine whether a challenge is required. The default challenge decider will order a challenge if and only if the response&amp;#8217;s HTTP status code is 401.&lt;/li&gt;
&lt;li&gt;Challenger plugins: When a challenge is required, those challenger plugins which support the current request type will be run until the first of them returns a valid response.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;repoze.who may seem hard to use at first sight, with all its components and terminology; so much flexibility comes at the cost of being a little hard to understand. But one of the goals of this article is to help people who had never heard of repoze.who to deal with basic and advanced authentication settings.&lt;/p&gt;
&lt;h2&gt;And how does repoze.what work?&lt;/h2&gt;
&lt;p&gt;repoze.what is mostly used inside of your application, where you define the access rules that must be met for a given routine to be performed.&lt;/p&gt;
&lt;p&gt;Access rules in repoze.what are made of atomic units called &amp;#8220;predicate checkers&amp;#8221;, re-usable objects that check whether a given condition is met.  Predicate checkers can be single or compound to form complex access rules. For example, a single condition (or predicate) might be &amp;#8220;The user is not anonymous&amp;#8221;, while a compound predicate could be &amp;#8220;The user is not anonymous &lt;em&gt;and&lt;/em&gt; their IP address is X.X.X.X&amp;#8221;. You can write your own predicate checkers, usually in just a few lines of code.&lt;/p&gt;
&lt;p&gt;repoze.what has built-in support for the widely-used authorization pattern whereby you assign groups to your users and then grant permissions to such groups; it ships with a comprehensive set of checkers for the relevant predicates (e.g., &amp;#8220;The current user belongs to the &amp;#8216;directors&amp;#8217; group&amp;#8221;, &amp;#8220;The current user is allowed to edit user accounts&amp;#8221;).  If you use this authorization pattern, the groups and permissions for the authenticated user will be loaded by a repoze.who metadata provider; in repoze.what 1.1, they&amp;#8217;ll be loaded on demand by repoze.what itself, so you wouldn&amp;#8217;t need repoze.who.  Nevertheless, it is entirely optional and you can use any authorization pattern that best suits your needs.&lt;/p&gt;
&lt;p&gt;Predicate checkers allow you to control access based not only on &lt;em&gt;who&lt;/em&gt; makes the request, but also on &lt;em&gt;how&lt;/em&gt; the request is made and &lt;em&gt;what&lt;/em&gt; exactly is requested. For example, if you have a blog application, you might use the simple predicate &amp;#8220;The user is allowed to remove posts&amp;#8221;, focusing on who the user is to control access to the post edition routine. Or you can have the more specific compound predicate &amp;#8220;The user is allowed to remove posts, as long as the user is the post&amp;#8217;s author&amp;#8221;.  This predicate focuses on both &lt;em&gt;who&lt;/em&gt; makes the request and &lt;em&gt;what&lt;/em&gt; is requested. You can have an even more complex access rule for the article edition routine, such as &amp;#8220;The user is allowed to remove posts, as long as the user is the post&amp;#8217;s author &amp;#8212; except post #1 which nobody can remove&amp;#8221;.&lt;/p&gt;
&lt;p&gt;repoze.what 1.0.X supports only blacklist-based authorization, that is, authorization is granted unless explicitly denied. Whitelist-based authorization, in which authorization is denied unless explicitly granted, will be supported as of version 1.1 (under development as of this writing).&lt;/p&gt;
&lt;h2&gt;Creating a Web application protected with repoze.who and repoze.what&lt;/h2&gt;
&lt;p&gt;It&amp;#8217;s time to go practical!  We&amp;#8217;re going to create a WSGI application powered by repoze.who and repoze.what.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll use the TurboGears 2 Web Application framework to make this simple application, but after reading the article you should be able to put what you just learned into practice in other frameworks, or standalone applications.&lt;/p&gt;
&lt;p&gt;(For the sake of demonstration, we will skip typical overhead features such as input validation, so we can focus the examples on the repoze.who and repose.what&amp;#8217;s integration of authentication and authorization.)&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s get started!&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to develop this application using an isolated Python environment using a rather famous utility called &amp;#8220;virtualenv&amp;#8221;. This is very handy because everything you install or remove won&amp;#8217;t affect your system-wide Python environment. To install it, run:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;easy_install virtualenv&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You may need administration rights to install it, depending on where you install it.&lt;/p&gt;
&lt;p&gt;Next, create an environment for our application and activate it; on Unix systems, the commands for this are:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;virtualenv --no-site-packages appenv&lt;br /&gt;
source appenv/bin/activate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On Windows systems, enter the following in a directory whose path doesn&amp;#8217;t contain spaces:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;C:\Python25\python.exe &quot;C:\Path-to-VE\virtualenv.py&quot; appenv&lt;br /&gt;
C:\Path-to-newly-created-environment\Scripts\activate.bat&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When you&amp;#8217;re done and want to deactivate it, you should run the command &amp;#8220;deactivate&amp;#8221; on Unix systems. For Windows, use &amp;#8220;C:\Path-to-newly-created-environment\Scripts\deactivate.bat&amp;#8221;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve called my virtual environment &amp;#8220;appenv&amp;#8221;, but you can use any name you like.&lt;/p&gt;
&lt;p&gt;For help installing virtualenv, you can check its documentation at  &lt;a href=&quot;http://pypi.python.org/pypi/virtualenv&quot;&gt;http://pypi.python.org/pypi/virtualenv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now to install TurboGears 2:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;easy_install -i http://www.turbogears.org/2.0/downloads/current/index tg.devtools&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Generating an application&lt;/h2&gt;
&lt;p&gt;TurboGears allows you to start coding using a minimal application, so that you don&amp;#8217;t have to start from scratch (unless you really want to).  We&amp;#8217;ll use just that minimal application so that we can get off to a quick start, which you can optionally &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/classifieds.zip&quot; title=&quot;Download the sample classifieds application&quot;&gt;download&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Web application we&amp;#8217;re going to create is a classifieds service, like craiglist.org or gumtree.com; for lack of imagination, I&amp;#8217;ll call it &amp;#8220;classifieds&amp;#8221;. To start coding it from a minimal application, we&amp;#8217;ll ask TurboGears to generate it with the following command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;paster quickstart classifieds&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then you&amp;#8217;ll be asked a couple of questions.  The first will ask you for the package name to be generated in this project; hit ENTER to accept &amp;#8220;classifieds&amp;#8221; as the default package name.  The second question will ask if you need authentication and authorization features for this project, hit ENTER to accept the default answer of &amp;#8220;yes&amp;#8221;.  By answering &amp;#8220;yes&amp;#8221; to the second question, repoze.who and repoze.what will be used in the application by default. Now switch to the application&amp;#8217;s directory, install it in development mode and set it up:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cd classifieds&lt;br /&gt;
python setup.py develop&lt;br /&gt;
paster setup-app development.ini&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re not going to start coding yet &amp;#8212; I&amp;#8217;d like you to try the generated application, so that you can see repoze.who and repoze.what in action. So, start the application (the &amp;#8220;reload&amp;#8221; switch will restart the application whenever one of its files is modified):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;paster serve --reload development.ini&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;and then open the following URL in your browser: &lt;a href=&quot;http://localhost:8080/&quot;&gt;http://localhost:8080/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You should keep this simple procedure in mind because we&amp;#8217;ll use it very often. Then, when you need to stop the development server, you have to hit Ctrl+C.&lt;/p&gt;
&lt;p&gt;Now try, at least, the following (in order):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Log in&lt;/strong&gt;: Visit &lt;a href=&quot;http://localhost:8080/login&quot;&gt;http://localhost:8080/login&lt;/a&gt; or click on the &amp;#8220;Login&amp;#8221; link in the upper-right side of any Web page of our application. Enter &amp;#8220;manager&amp;#8221; and &amp;#8220;managepass&amp;#8221; in the login and password fields. You&amp;#8217;ll get redirected to the main page and a welcome message will be displayed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visit a page you shouldn&amp;#8217;t see&lt;/strong&gt;: Like &lt;a href=&quot;http://localhost:8080/editor_user_only&quot;&gt;http://localhost:8080/editor_user_only&lt;/a&gt;; you should get a 403 page and a message which reads &amp;#8220;Only for the editor&amp;#8221;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log out&lt;/strong&gt;: Visit &lt;a href=&quot;http://localhost:8080/logout_handler&quot;&gt;http://localhost:8080/logout_handler&lt;/a&gt; or click on the &amp;#8220;Logout&amp;#8221; link in the upper-right side of any Web page of our application. You&amp;#8217;ll get redirected to the main page and a goodbye message will be displayed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visit a private page as anonymous&lt;/strong&gt;: If you&amp;#8217;re currently logged in, log out first. Then visit &lt;a href=&quot;http://localhost:8080/manage_permission_only&quot;&gt;http://localhost:8080/manage_permission_only&lt;/a&gt;; you should be redirected to the login form, where also the message &amp;#8220;Only for managers&amp;#8221; is displayed. Log in with the previous credentials (&amp;#8220;manager&amp;#8221;/&amp;#8221;managepass&amp;#8221;) and you&amp;#8217;ll be redirected to the page you requested initially.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What you&amp;#8217;ve seen is repoze.who, repoze.what and some of their official plugins in action; those notification messages are TurboGears-specific, though, but it shouldn&amp;#8217;t be hard to port them to other frameworks or raw applications.&lt;/p&gt;
&lt;p&gt;Before moving forward, I&amp;#8217;ll describe some of the files and directories that the &amp;#8220;paster quickstart&amp;#8221; command above generated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;devdata.db: The sqlite database file used for development.&lt;/li&gt;
&lt;li&gt;classifieds/: Your application&amp;#8217;s package itself.&lt;/li&gt;
&lt;li&gt;classifieds/config/middleware.py: The file where the extra WSGI middleware for your application is added.&lt;/li&gt;
&lt;li&gt;classifieds/controllers/root.py: Your application&amp;#8217;s root controller. Sub-controllers should be attached to the one defined in this file; below I&amp;#8217;ll explain how.&lt;/li&gt;
&lt;li&gt;classifieds/model/: The application&amp;#8217;s model definitions powered by &lt;a href=&quot;http://www.sqlalchemy.org/&quot;&gt;SQLAlchemy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;classifieds/model/auth.py: The model definitions specific to authentication, identification and authorization.&lt;/li&gt;
&lt;li&gt;classifieds/templates/: The application&amp;#8217;s XHTML templates powered by &lt;a href=&quot;http://genshi.edgewall.org/&quot;&gt;Genshi&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;classifieds/websetup.py: Contains the function which will get run when the application is set up (used by the &lt;em&gt;paster setup-app&lt;/em&gt; command). By default it just adds rows to the database.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the other hand, this is how authentication, identification and authorization is configured right now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have a table for our application&amp;#8217;s users (&lt;em&gt;tg_user&lt;/em&gt;), which contains the self-explanatory fields &lt;em&gt;user_name&lt;/em&gt; and &lt;em&gt;password&lt;/em&gt;, among others. repoze.who is configured to authenticate by using these two fields.&lt;/li&gt;
&lt;li&gt;repoze.what is configured to use its groups/permission-based pattern. The groups and permissions are stored in the database, in the &lt;em&gt;tg_group&lt;/em&gt; and &lt;em&gt;tg_permission&lt;/em&gt; tables.&lt;/li&gt;
&lt;li&gt;One user can belong to zero or more groups; one group can be granted zero or more permissions.&lt;/li&gt;
&lt;li&gt;Right now we have two users, &amp;#8220;manager&amp;#8221; and &amp;#8220;editor&amp;#8221; (with passwords &amp;#8220;managepass&amp;#8221; and &amp;#8220;editpass&amp;#8221;). &amp;#8220;manager&amp;#8221; belongs to the only group defined so far, &amp;#8220;managers&amp;#8221;. The  group &amp;#8220;managers&amp;#8221; is granted the only permission defined so far, &amp;#8220;manage&amp;#8221;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Let&amp;#8217;s start coding&lt;/h2&gt;
&lt;p&gt;&amp;#8220;At last!&amp;#8221;, I heard you say.&lt;/p&gt;
&lt;p&gt;While implementing repoze.who and repoze.what in an application which doesn&amp;#8217;t come with them enabled out-of-the-box, the first thing you have to do is add their middleware to your application.&lt;/p&gt;
&lt;p&gt;However, we&amp;#8217;ll skip that part and keep the default settings for now, so that we can go to fun part right away: Learning how to protect areas in your Web application. The setup will be addressed later on, where you&amp;#8217;ll learn how to configure repoze.who and repoze.what the TurboGears-independent way.&lt;/p&gt;
&lt;p&gt;This is what we&amp;#8217;re going to implement in our classifieds application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A simple user registration system.&lt;/li&gt;
&lt;li&gt;A classified visualization mechanism, for any user (anonymous or authenticated).&lt;/li&gt;
&lt;li&gt;A classified addition mechanism, for registered users.&lt;/li&gt;
&lt;li&gt;A classified edition mechanism, for registered users to edit their own classifieds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So it&amp;#8217;s finally time to fire up your Python editor, a terminal and a window of your browser!&lt;/p&gt;
&lt;p&gt;First of all, let&amp;#8217;s add groups and permissions for authorization in our application, instead of sticking to the ones created by default. We&amp;#8217;re going to add one more group called &amp;#8220;posters&amp;#8221; and the &amp;#8220;add-classifieds&amp;#8221; permission to be granted to posters. (Before continuing, you should stop the server running in the terminal &amp;#8212; With Ctrl+C).&lt;/p&gt;
&lt;p&gt;To add the posters group, add this code to the &lt;em&gt;setup_app()&lt;/em&gt; function, defined in &lt;em&gt;classifieds/websetup.py&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;posters = model.Group(group_name=u'posters', display_name=u'Classified posters')&lt;br /&gt;
model.DBSession.add(posters)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The addclassifieds permission is created with this code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;addclassifieds = model.Permission(permission_name=u'add-classifieds', description=u'Allowed to add classifieds')&lt;br /&gt;
addclassifieds.groups.append(posters)&lt;br /&gt;
model.DBSession.add(addclassifieds)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Add these sections &lt;strong&gt;right before&lt;/strong&gt; the following lines:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;model.DBSession.flush()&lt;br /&gt;
transaction.commit()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now, since we have a classifieds application, we have to define the SQLAlchemy model for the classifieds. To keep things simple, we&amp;#8217;ll define just four columns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;classified_id&lt;/em&gt;: The classified&amp;#8217;s identifier.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;poster_id&lt;/em&gt;: The poster&amp;#8217;s user id.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;classified_title&lt;/em&gt;: The classified title.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;classified_contents&lt;/em&gt;: The classified contents.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing1.py.txt&quot;&gt;Listing 1&lt;/a&gt; implements this model definition. You have to create &lt;em&gt;classifieds/model/posts.py&lt;/em&gt; and store that definition in there. Then you have to import that model at the end of &lt;em&gt;classifieds/model/__init__.py&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from classifieds.model.posts import Classified&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To apply the changes, let&amp;#8217;s remove the development database, re-create it with our new model and rows, and finally start the server again:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rm devdata.db&lt;br /&gt;
paster setup-app development.ini&lt;br /&gt;
paster serve --reload development.ini&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s it, now we have the model definition for the classifieds. Let the fun part begin!&lt;/p&gt;
&lt;h2&gt;Creating a user registration system&lt;/h2&gt;
&lt;p&gt;We&amp;#8217;re going to create a simple registration system made up of two controller actions: One to display the registration form and another to process the submitted form.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to implement them in the root controller for our application, the class &lt;em&gt;RootController&lt;/em&gt; found in the source file &lt;em&gt;classifieds/controllers/root.py&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To define the action for the registration form, first import the repoze.what predicate checker that verifies that the current user is anonymous:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from repoze.what.predicates import is_anonymous&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Next, add the following method in &lt;em&gt;RootController&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose('classifieds.templates.register')&lt;br /&gt;
@require(is_anonymous(msg='Only one account per user is allowed'))&lt;br /&gt;
def register(self):&lt;br /&gt;
    &quot;&quot;&quot;Display the user registration form&quot;&quot;&quot;&lt;br /&gt;
    return {'page': 'user registration'}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;What the two decorators above do is specify that the template for the &amp;#8220;register&amp;#8221; action is &lt;em&gt;classifieds/templates/register.html&lt;/em&gt; and that access is granted to users who don&amp;#8217;t have an account, respectively.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;@require&lt;/em&gt; is a TurboGears-specific decorator that evaluates a repoze.what predicate before calling the action in question. When such a predicate is not met, the action is not called and a 401 response is returned (403 if the user is already logged in). Then repoze.who&amp;#8217;s default challenge decider will find the 401 response and will replace it with the challenge.&lt;/p&gt;
&lt;p&gt;Internally, the predicate is evaluated by calling its &lt;em&gt;check_authorization()&lt;/em&gt; method (which raises the &lt;em&gt;repoze.what.predicates.NotAuthorizedError&lt;/em&gt; exception if the predicate isn&amp;#8217;t met, whose message is the user-friendly explanation) or &lt;em&gt;is_met()&lt;/em&gt; (which returns a boolean).  &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing2.py.txt&quot;&gt;Listing 2&lt;/a&gt; illustrates a fictitious implementation, using the &lt;em&gt;decorator&lt;/em&gt; package; you&amp;#8217;d find it useful if you want to use repoze.what in another framework or raw application (Pylons users may want to check &lt;a title=&quot;The Pylons plugin for repoze.what&quot; href=&quot;http://code.gustavonarea.net/repoze.what-pylons/&quot;&gt;repoze.what-pylons&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Going back to the creation of the action, you&amp;#8217;ll have to create the template that will display the form: Create &lt;em&gt;classifieds/templates/register.html&lt;/em&gt; with the contents of &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing3.html.txt&quot;&gt;Listing 3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now it&amp;#8217;s time to create the action which will process the contents of the submitted form by adding the user to the database, including them in the &amp;#8220;posters&amp;#8221; group and finally redirecting them to the login form so that they can use the newly created account. For that, you have to define the &lt;em&gt;add_user&lt;/em&gt; method shown in &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing4.py.txt&quot;&gt;Listing 4&lt;/a&gt; (in &lt;em&gt;RootController&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s it! Our registration system is done. Now you can try it by visiting &lt;a href=&quot;http://localhost:8080/register&quot;&gt;http://localhost:8080/register&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The classifieds visualization mechanism&lt;/h2&gt;
&lt;p&gt;We&amp;#8217;re going to write the part of the interface which will allow us to see the classifieds hosted by our service. This will be accomplished by means of two controller actions: One to see all the classifieds available, in the main page of the application, and another to see individual classifieds.&lt;/p&gt;
&lt;p&gt;For the first, we have to re-write the &amp;#8220;index&amp;#8221; action of the root controller, to make it look like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose('classifieds.templates.index')&lt;br /&gt;
def index(self):&lt;br /&gt;
    query = DBSession.query(model.Classified)&lt;br /&gt;
    all_classifieds = query.all()&lt;br /&gt;
    return dict(page='index', classifieds=all_classifieds)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then its template, &lt;em&gt;classifieds/templates/index.html&lt;/em&gt;, should be replaced with the contents of &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing5.html.txt&quot;&gt;Listing 5&lt;/a&gt;, which lists the available classifieds with a link to their individual pages.&lt;/p&gt;
&lt;p&gt;The second action, the one to show the classifieds individually, will be implemented as &amp;#8220;view&amp;#8221; and will be defined in the root controller too:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose('classifieds.templates.view')&lt;br /&gt;
def view(self, classified):&lt;br /&gt;
    query = DBSession.query(model.Classified)&lt;br /&gt;
    classified_obj = query.get(classified)&lt;br /&gt;
    # Is the user allowed to edit the classified?&lt;br /&gt;
    checker = user_is_poster()&lt;br /&gt;
    can_edit = checker.is_met(request.environ)&lt;br /&gt;
    return {'page': 'Classified page', 'classified': classified_obj, 'classified_id': classified, 'can_edit': can_edit}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Note that in the &amp;#8220;view&amp;#8221; action we do something new: Handle a predicate checker directly. Sometimes it is necessary to evaluate them directly and get a boolean result to know whether it&amp;#8217;s met or not thanks to the &lt;em&gt;is_met()&lt;/em&gt; method of the predicate checker. For example, right now we use it to display a link to edit that predicate, if and only if the current user is allowed to edit it.&lt;/p&gt;
&lt;p&gt;Then the template for &amp;#8220;view&amp;#8221;, &lt;em&gt;classifieds/templates/index.html&lt;/em&gt;, is defined as shown in &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing6.html.txt&quot;&gt;Listing 6&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Implementing the classified submission mechanism&lt;/h2&gt;
&lt;p&gt;To allow users publish classifieds, we&amp;#8217;ll write two controller actions (once again, one to display the form and the other to process it).&lt;/p&gt;
&lt;p&gt;The action that will display the form should first check that the user is allowed to add a classified; this is, we should use repoze.what&amp;#8217;s &lt;em&gt;has_permission&lt;/em&gt; predicate so that it checks whether they are granted the &amp;#8220;add-classified&amp;#8221; permission. You have to import it at the top of &lt;em&gt;classifieds/controllers/root.py&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from repoze.what.predicates import has_permission&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And then write the action as shown below:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose('classifieds.templates.add')&lt;br /&gt;
@require(has_permission('add-classifieds'))&lt;br /&gt;
def add(self):&lt;br /&gt;
    return {'page': 'Classified submission'}&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This action uses the template &lt;em&gt;classifieds/templates/add.html&lt;/em&gt;, which we have to create with the contents of &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing7.html.txt&quot;&gt;Listing 7&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing8.py.txt&quot;&gt;Listing 8&lt;/a&gt; shows how the action that processes the submitted form is implemented. There we use something we hadn&amp;#8217;t used before: The repoze.who identity dictionary. Do you remember that I said that repoze.who optionally uses so-called &amp;#8220;metadata providers&amp;#8221;, which are plugins that load data about the current user into the request? Well, that data is kept in the WSGI environment dictionary, under the &lt;em&gt;repoze.who.identity&lt;/em&gt; key.&lt;/p&gt;
&lt;p&gt;Then we use one of the items of that dictionary, &amp;#8220;user&amp;#8221;, which contains the database object for the current user. It is loaded by the metadata provider defined in the repoze.who SQLAlchemy plugin (repoze.who.plugins.sa), a component that is enabled by default in TurboGears.&lt;/p&gt;
&lt;h2&gt;Implementing the classified edition mechanism with custom predicate checkers&lt;/h2&gt;
&lt;p&gt;So far we&amp;#8217;ve used a few repoze.what predicate checkers, which are all very basic. Very often you have to write your own checkers. For example, if the URL where classifieds are edited looks like &lt;q&gt;http://localhost:8080/edit/&lt;em&gt;X&lt;/em&gt;&lt;/q&gt; (where &amp;#8220;X&amp;#8221; represents the classified identifier), and we want that classifieds can only be edited by their posters, we&amp;#8217;ll need a predicate checker that finds the poster of the &amp;#8220;X&amp;#8221; classified and checks if it is the current user.&lt;/p&gt;
&lt;p&gt;This predicate checker is implemented in &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing9.py.txt&quot;&gt;Listing 9&lt;/a&gt;, which should be stored in &lt;em&gt;classifieds/lib/authz.py&lt;/em&gt; (a file you should create). That&amp;#8217;s a good sample checker, which helps us to understand how a predicate checker is defined:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It must extend the &lt;em&gt;repoze.what.predicates.Predicate&lt;/em&gt; class.&lt;/li&gt;
&lt;li&gt;It must define a user-friendly explanation in the &lt;em&gt;message&lt;/em&gt; attribute, which may be shown to the user when the predicate is not met.&lt;/li&gt;
&lt;li&gt;Its logic is defined in the &lt;em&gt;evaluate()&lt;/em&gt; instance method, which must call the &lt;em&gt;unmet()&lt;/em&gt; method when the predicate is not met; keyword arguments passed to this method will replace the placeholders defined in &lt;em&gt;message&lt;/em&gt; (if any), although that message can be replaced on-the-fly with a string passed as the first positional argument. &lt;em&gt;evaluate()&lt;/em&gt; receives the WSGI environment and the repoze.what credentials dictionaries as arguments.&lt;/li&gt;
&lt;li&gt;If the checker relies on arguments such as GET or POST variables, or other arguments available in the URL, the &lt;em&gt;parse_variables()&lt;/em&gt; method should be used to retrieve them. It will return a dictionary whose items are: &amp;#8220;get&amp;#8221; for variables in the query string and &amp;#8220;post&amp;#8221; for POST variables, plus &amp;#8220;named_args&amp;#8221; and &amp;#8220;positional_args&amp;#8221; for named and positional arguments in the URL (which must be set by a routing software like Selector or Routes).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because this predicate relies on a named argument in the URL (&amp;#8220;classified&amp;#8221;), we have to use a URL router software compliant with the &lt;a href=&quot;http://wsgi.org/wsgi/Specifications/routing_args&quot;&gt;wsgiorg.routing_args&lt;/a&gt; standard; we&amp;#8217;ll use Routes. To configure Routes in TurboGears 2, you have to insert the following contents in &lt;em&gt;classifieds/config/app_cfg.py&lt;/em&gt; (right after the imports) and then replace the line &lt;em&gt;base_config = AppConfig()&lt;/em&gt; with &lt;em&gt;base_config = ClassifiedsConfig()&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;class ClassifiedsConfig(AppConfig):&lt;br /&gt;
def setup_routes(self):&lt;br /&gt;
    &quot;&quot;&quot;Customize routing&quot;&quot;&quot;&lt;br /&gt;
    from tg import config&lt;br /&gt;
    from routes import Mapper&lt;br /&gt;
    dir = config['pylons.paths']['controllers']&lt;br /&gt;
    map = Mapper(directory=dir, always_scan=config['debug'])&lt;br /&gt;
    # Defining our custom routes:&lt;br /&gt;
    map.connect('/{action}/{classified:\d+}', controller='root')&lt;br /&gt;
    # Required by TurboGears:&lt;br /&gt;
    map.connect('*url', controller='root', action='routes_placeholder')&lt;br /&gt;
    config['routes.map'] = map&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;At this point we&amp;#8217;re ready to use the &lt;em&gt;user_is_poster&lt;/em&gt; checker.&lt;/p&gt;
&lt;p&gt;Now import the custom checker into &lt;em&gt;classifieds/controllers/root.py&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from classifieds.lib.authz import user_is_poster&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Next, use the following contents to define the &amp;#8220;edit&amp;#8221; action and the contents of &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing10.html.txt&quot;&gt;Listing 10&lt;/a&gt; for its template (&lt;em&gt;classifieds/templates/edit.html&lt;/em&gt;):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose('classifieds.templates.edit')&lt;br /&gt;
@require(user_is_poster())&lt;br /&gt;
def edit(self, classified):&lt;br /&gt;
    query = DBSession.query(model.Classified)&lt;br /&gt;
    classified_obj = query.get(classified)&lt;br /&gt;
    return {'page': 'Classified edition page', 'classified': classified_obj, 'classified_id': classified}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Finally, for the action that processes the submitted form, we can use:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@expose()&lt;br /&gt;
@require(user_is_poster())&lt;br /&gt;
def edit_classified(self, classified, title, contents):&lt;br /&gt;
    # Fetching and updating the classified object:&lt;br /&gt;
    query = DBSession.query(model.Classified)&lt;br /&gt;
    classified_obj = query.get(classified)&lt;br /&gt;
    classified_obj.classified_title = title&lt;br /&gt;
    classified_obj.classified_contents = contents&lt;br /&gt;
    DBSession.update(classified_obj)&lt;br /&gt;
    # Notifying the user:&lt;br /&gt;
    flash('Classified &quot;%s&quot; updated!' % title)&lt;br /&gt;
    redirect(url('/view/%s' % classified))&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can now play with the classifieds edition mechanism, to see by yourself how authorization is denied when somebody tries to edit somebody else&amp;#8217;s classified, thanks to our &amp;#8220;user_is_poster&amp;#8221; checker.&lt;/p&gt;
&lt;h2&gt;Configuring it all by ourselves&lt;/h2&gt;
&lt;p&gt;At this point you&amp;#8217;re able to deal with identification (using the repoze.who identity dictionary, which contains user data) and control authorization in your application with repoze.what predicate checkers (even how to write your own!), and you should also be able to put this knowledge to the test in frameworks other than TurboGears.&lt;/p&gt;
&lt;p&gt;What we&amp;#8217;re missing now is to know how to configure repoze.who and repoze.what by ourselves, since we skipped that part initially because TurboGears configures them for us. But you have to know this to use both packages with other frameworks or even to continue with TurboGears in a more advanced setup.&lt;/p&gt;
&lt;p&gt;Therefore we&amp;#8217;re going to stop TurboGears from configuring repoze.who and repoze.what, so that we have full control on how they are configured and learn how to do it in other frameworks.&lt;/p&gt;
&lt;p&gt;To disable the automatic setup of repoze.who and repoze.what, go to &lt;em&gt;classifieds/config/app_cfg.py&lt;/em&gt; and set the variable &lt;em&gt;base_config.auth_backend&lt;/em&gt; to &lt;em&gt;None&lt;/em&gt;. Then all those variables that start by &lt;em&gt;base_config.sa_auth&lt;/em&gt; will be ignored, so you can remove them if you want.&lt;/p&gt;
&lt;p&gt;Now let&amp;#8217;s handle the configuration by adding the middleware to our WSGI application. I&amp;#8217;ll use a function called &lt;em&gt;add_auth()&lt;/em&gt; (defined in &lt;em&gt;classifieds/config/auth.py&lt;/em&gt;) which receives the WSGI application as the only argument and returns it with the middleware added, as shown in &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing11.py.txt&quot;&gt;Listing 11&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because &lt;em&gt;add_auth()&lt;/em&gt; configures repoze.who and repoze.what the same way we&amp;#8217;ve been using them, but with the hidden details revealed, we&amp;#8217;ll be able to identify their components.&lt;/p&gt;
&lt;p&gt;In this function we see that repoze.who is configured with the following plugins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;AuthTktCookiePlugin&lt;/em&gt;, an identifier which remembers and forgets authenticated users using cookies (using the string &amp;#8220;secret&amp;#8221; as the encryption key and &amp;#8220;authtkt&amp;#8221; as the cookie name).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;FriendlyFormPlugin&lt;/em&gt;, the component that handles our login form and logouts. As an identifier, when the user is logging in it extracts the &amp;#8220;login&amp;#8221; and &amp;#8220;password&amp;#8221; from the request so that the authenticator(s) can use such data, and when the user tries to log out, it asks &lt;em&gt;AuthTktCookiePlugin&lt;/em&gt; to forget the user. As a challenger, it redirects the user to the login form (at &amp;#8220;/login&amp;#8221;).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SQLAlchemyAuthenticatorPlugin&lt;/em&gt;, as the only authenticator used. It connects to the &amp;#8220;tg_user&amp;#8221; table to check if there&amp;#8217;s a match for the supplied &amp;#8220;login&amp;#8221; and &amp;#8220;password&amp;#8221;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SQLAlchemyUserMDPlugin&lt;/em&gt;, the metadata provider that loads the current user&amp;#8217;s SQLAlchemy object into the repoze.who identity item &amp;#8220;user&amp;#8221;.&lt;/li&gt;
&lt;li&gt;Because we didn&amp;#8217;t specified request classifiers or challenge deciders, the default ones will be used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Meanwhile, repoze.what is configured using the groups/permissions-based authorization pattern, where the groups and permissions are retrieved thanks to the following adapters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;SqlGroupsAdapter&lt;/em&gt;, which loads the groups from the &amp;#8220;tg_group&amp;#8221; table.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SqlPermissionsAdapter&lt;/em&gt;, which loads the groups from the &amp;#8220;tg_permission&amp;#8221; table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we don&amp;#8217;t use this authorization pattern, our &lt;em&gt;app_with_mw&lt;/em&gt; variable would have been defined without passing groups/permission adapters:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;app_with_mw = setup_auth(app, **who_args)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And what about using repoze.who but not repoze.what? &lt;a href=&quot;http://gustavonarea.net/files/articles/pymag-repoze-09/Listing12.py.txt&quot;&gt;Listing 12&lt;/a&gt; shows how to configure repoze.who just like we did above, but without repoze.what. Note that this time we had to pass the request classifier and challenge decider explicitly.&lt;/p&gt;
&lt;p&gt;The opposite, using repoze.what without repoze.who, is not yet possible as of this writing because repoze.what 1.0&amp;#8242;s credentials are loaded through a repoze.who metadata provider. repoze.what 1.1 will be completely repoze.who-independent, optionally.&lt;/p&gt;
&lt;p&gt;Finally, it&amp;#8217;s time to use &lt;em&gt;add_auth()&lt;/em&gt;. It can be used like any other WSGI middleware, so in the case of this TurboGears 2 application, it is in &lt;em&gt;classifieds/config/middleware.py&lt;/em&gt;; if using another framework, consult the relevant documentation to find the equivalent. First, you should import the function:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from classifieds.config.auth import add_auth&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And then use it inside the &lt;em&gt;make_app()&lt;/em&gt; function, under the specified line:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# Wrap your base TurboGears 2 application with custom (...)&lt;br /&gt;
app = add_auth(app)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And voila! Now our classifieds service behaves the same way as before, with its authentication, identification and authorization settings now being controlled by our own code instead of the generated defaults.&lt;/p&gt;
&lt;h2&gt;Going beyond with repoze.who and repoze.what&lt;/h2&gt;
&lt;p&gt;The topics covered in this article are just the tip of the iceberg. Both Repoze packages are created with extensibility in mind; their core is minimalist but they already have many ready-to-use plugins, not only the repoze.who and repoze.what SQLAlchemy plugins we used here.&lt;/p&gt;
&lt;p&gt;There are repoze.who plugins for OpenId, LDAP, &lt;em&gt;.htaccess&lt;/em&gt; and RADIUS authentication, as well as a built-in challenger plugin for HTTP authentication &amp;#8212; just to name some of the available plugins. And you can easily create your own plugins, following the patterns described in this article.&lt;/p&gt;
&lt;p&gt;Although repoze.what is a relatively new piece of software as of this writing, it has several ready-to-use plugins as well. It has plugins to store the groups and permissions in XML files or .ini files, not only in databases, as well as a plugin called &lt;em&gt;repoze.what-quickstart&lt;/em&gt; which allows us to have repoze.who and repoze.what working quickly (that&amp;#8217;s what TurboGears uses to set them up).&lt;/p&gt;
&lt;p&gt;Although they were not used in our classifieds service, just mentioned in the beginning, you can have so-called &lt;strong&gt;compound predicates&lt;/strong&gt;. Access rules aren&amp;#8217;t always as simple as &amp;#8220;The user must be logged in&amp;#8221; or &amp;#8220;The user belongs to the &amp;#8216;posters&amp;#8217; group&amp;#8221;. For example, in our classified edition mechanism we way want to allow administrators to edit classifieds, even those not posted by themselves; to do so, instead of using our &lt;em&gt;user_is_poster&lt;/em&gt; checker alone, we could use it along with the &lt;em&gt;Any&lt;/em&gt; and &lt;em&gt;in_group&lt;/em&gt; checkers:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;from repoze.what.predicates import Any, in_group&lt;br /&gt;
p = Any(in_group('manager'), user_is_poster())&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In this article we didn&amp;#8217;t even use half of the built-in repoze.what predicate checkers. A full list is available in the repoze.what manual.&lt;/p&gt;
&lt;p&gt;Settings are very flexible. It is even possible to configure repoze.who and repoze.what through .ini files, so that those settings can be adjusted while deploying the application (which would be a replacement for our &lt;em&gt;add_auth()&lt;/em&gt; function defined above).&lt;/p&gt;
&lt;p&gt;It is also worth noting that both projects are actively developed, well documented, well tested and supported by the Repoze community. As a result, it is most likely that you&amp;#8217;ll have a good experience using them.&lt;/p&gt;
&lt;p&gt;repoze.who and repoze.what aim to solve &amp;#8220;the security problem&amp;#8221; we Web developers face so often, and they have proved to be the right choice in many scenarios. The likelihood of them being the right choice for your next Web application is strong, specially now that you&amp;#8217;re familiar with them!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To ask questions about &lt;a href=&quot;http://docs.repoze.org/who/1.0/&quot;&gt;repoze.who&lt;/a&gt; and/or &lt;a href=&quot;http://what.repoze.org/docs/1.0/&quot;&gt;repoze.what&lt;/a&gt;, please use the &lt;a href=&quot;http://lists.repoze.org/listinfo/repoze-dev&quot;&gt;repoze-dev&lt;/a&gt; mailing list. For everything else that is related to this article, please leave a comment below.&lt;/em&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 01 Jun 2010 14:41:13 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing TurboGears EC2 Images</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-8580158938436684947</guid>
	<link>http://codersbuffet.blogspot.com/2010/05/announcing-turbpgears-ec2-images.html</link>
	<description>&lt;a href=&quot;http://www.amazon.com/&quot;&gt;Amazon&lt;/a&gt; has long offered a &lt;a href=&quot;http://aws.amazon.com/&quot;&gt;service&lt;/a&gt; whereby the community can purchase time on their clusters. Today, &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; is able to take advantage of this in a new way. It is now easier than ever before to get a &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; instance up, running, and viewable by you, allowing you to find out how that &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; based application really looks and functions.&lt;br /&gt;&lt;br /&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;The whole process is actually fairly simple. You will need to know the AMI ID of the version of &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; you wish to test. Here are the AMI IDs we have available now. This post will be updated when new versions of the AMIs are made available.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;TurboGears 2.0.3, 32 Bit - AMI ID: ami-c5648dac&lt;/li&gt;&lt;li&gt;TurboGears 2.0.3, 64 Bit - AMI ID:&amp;nbsp; &lt;span class=&quot;value&quot;&gt;ami-a17e97c8&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;TurboGears 2.1b2, 32 Bit - AMI ID:&amp;nbsp; &lt;/span&gt;&lt;span class=&quot;value&quot;&gt;ami-67678e0e&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;TurboGears 2.1b2, 64 Bit - AMI ID:&amp;nbsp; &lt;/span&gt;&lt;span class=&quot;value&quot;&gt;ami-7b719812&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class=&quot;value&quot;&gt;Installing your application and getting it live is very simple. If you don't know how to work with &lt;a href=&quot;http://aws.amazon.com/&quot;&gt;Amazon's EC2&lt;/a&gt; service, please read &lt;a href=&quot;http://aws.amazon.com/documentation/ec2/&quot;&gt;their documentation for it&lt;/a&gt;. Here's the process:&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Launch an instance of the AMI you have selected.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Log in to the instance:&lt;br /&gt;ssh ubuntu@public.dns.name&lt;br /&gt;sudo su - turbogears&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Install the application following whatever directions are provided by the application, but do not run &quot;paster setup-app&quot; yet.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Instead of making &quot;production.ini&quot; or &quot;deployment.ini&quot;, you will make &quot;/home/turbogears/app.ini&quot;. This is absolutely identical to the other files, it's just the name that is special. Yes, you can modify configuration to use one of the other names, but you do not have to.&lt;br /&gt;&lt;br /&gt;When you do make this file, don't forget to set &quot;debug=false&quot; in it. This is meant to be a production environment, and will break if &quot;debug=true&quot; is set.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Run the following two commands:&lt;br /&gt;cd $HOME&lt;br /&gt;paster setup-app tgapp.ini&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;If your configuration uses a SQLite database, don't forget to fix the permissions. Either make www-data the owner, or set the permissions to 0777.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;A couple of files need to be made, but will be made automatically for you. When you installed the application in step 3, a Python egg was installed. You will need the name of that egg (but can find it fairly easily). A command has been written to make this whole part of the process painless. Do this:&lt;br /&gt;&lt;br /&gt;tglinker eggname eggversion&lt;br /&gt;&lt;br /&gt;If you are unsure of the eggname, simply type &quot;tglinker&quot;, followed by a space, and then press the tab key twice. You will be given a list of all installed eggs, and can start typing the name in from that list. Once you get enough to be unique, press tab again, and the name will be completed.&lt;br /&gt;&lt;br /&gt;Once you have that, the eggversion will be even easier: Pressing tab twice will likely fill in the full version number. If not, simply type it in again usaing the tab completion as above.&lt;br /&gt;&lt;br /&gt;Press enter, and the required files will be generated.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class=&quot;value&quot;&gt;Finally, logout of the turbogears user account (either by using the &quot;exit&quot; command, or the &quot;logout&quot; command), and restart apache using this command:&lt;br /&gt;&lt;br /&gt;sudo /etc/init.d/apache2 restart&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;You're done, and by visiting &quot;http://public.dns.name&quot; in your browser, you will now see your web site function.&lt;br /&gt;&lt;br /&gt;A word of caution: If you are a new user of the &lt;a href=&quot;http://aws.amazon.com/&quot;&gt;EC2&lt;/a&gt; service, you might well terminate any instance that you create. All data on the local drive will be destroyed.&amp;nbsp; &lt;a href=&quot;http://aws.amazon.com/documentation/ec2/&quot;&gt;Their documentation&lt;/a&gt; covers how to preserve data. I recommend you read it.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-8580158938436684947?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 31 May 2010 20:00:07 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Luke Macken: liveusb-creator trojan in the wild</title>
	<guid>http://lewk.org/blog/2010/05/25/liveusb-creator-trojan</guid>
	<link>http://lewk.org/blog/liveusb-creator-trojan.html</link>
	<description>&lt;p&gt;
&lt;img src=&quot;https://fedorahosted.org/liveusb-creator/attachment/wiki/img/fedorausb.png?format=raw&quot; align=&quot;right&quot; /&gt;
I've been noticing many different copies of my Windows &lt;a href=&quot;http://liveusb-creator.fedorahosted.org&quot;&gt;liveusb-creator&lt;/a&gt; popping up on various sketchy-looking download sites.  The majority of these copies contain a variant of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Vundo&quot;&gt;Vundo&lt;/a&gt; Trojan.

&lt;blockquote&gt;&lt;i&gt;&quot;Vundo, or the Vundo Trojan (also known as Virtumonde  or Virtumondo and sometimes referred to as MS Juan) is a Trojan horse that is known to cause popups and advertising for rogue antispyware programs, and sporadically other misbehavior including performance degradation and denial of service with some websites including Google  and Facebook.&quot;&lt;/i&gt;&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
So, if you downloaded a copy of the Windows liveusb-creator from anywhere other than
&lt;a href=&quot;https://fedorahosted.org/liveusb-creator&quot;&gt;https://fedorahosted.org/liveusb-creator&lt;/a&gt; -- you could be infected.  Apparently
the latest variation of this trojan is undetectable by most antivirus
(although, clamav was able to recognize the one that I found), so you
may need to look around for some of the common symptoms.  There is apparently a
tool that will remove this trojan which can be found &lt;a href=&quot;http://vundofix.atribune.org&quot;&gt;here&lt;/a&gt;, however I have not tested it and
cannot vouch for its validity.
&lt;/p&gt;
&lt;p&gt;
If anyone was actually hit by this, I'd be interested to hear about
it.&lt;br /&gt;&lt;br /&gt;  Also,
to state the blatantly obvious: &lt;b&gt;only download the liveusb-creator from the &lt;a href=&quot;https://fedorahosted.org/liveusb-creator&quot;&gt;homepage&lt;/a&gt;!&lt;/b&gt;
&lt;/p&gt;</description>
	<pubDate>Tue, 25 May 2010 21:11:25 +0000</pubDate>
</item>
<item>
	<title>Michael Pedersen: Announcing tgext.xmlrpc</title>
	<guid>tag:blogger.com,1999:blog-1176744327252521223.post-3329216553413056372</guid>
	<link>http://codersbuffet.blogspot.com/2010/05/announcing-tgextxmlrpc.html</link>
	<description>One of the questions that we in the &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; community get asked is &quot;How can I have &lt;a href=&quot;http://www.xmlrpc.com/&quot;&gt;XMLRPC&lt;/a&gt; in my TurboGears application?&quot; Until now, we didn't have a useful answer beyond &quot;Write it up&quot;. Now we have &lt;a href=&quot;http://bitbucket.org/pedersen/tgext.xmlrpc&quot;&gt;tgext.xmlrpc&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://bitbucket.org/pedersen/tgext.xmlrpc&quot;&gt;tgext.xmlrpc&lt;/a&gt; allows you to have an XMLRPC hierarchy. Your code becomes a case of simply setting up your controller and working with it like any other controller. So, if you need to have &lt;a href=&quot;http://www.xmlrpc.com/&quot;&gt;XMLRPC&lt;/a&gt; in your &lt;a href=&quot;http://www.turbogears.org/&quot;&gt;TurboGears&lt;/a&gt; application, check it out (and don't forget to read the &lt;a href=&quot;http://bitbucket.org/pedersen/tgext.xmlrpc/wiki/Home&quot;&gt;docs&lt;/a&gt;!). I think you'll find it quite helpful.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/1176744327252521223-3329216553413056372?l=codersbuffet.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</description>
	<pubDate>Mon, 24 May 2010 10:43:57 +0000</pubDate>
	<author>noreply@blogger.com (Michael Pedersen)</author>
</item>
<item>
	<title>Jorge Vargas: Twittdo en 3923 caracteres (primera parte)</title>
	<guid>http://blog.maetico.com/post/533596909</guid>
	<link>http://blog.maetico.com/post/533596909</link>
	<description>&lt;p&gt;El dia comenzo triste, lloviendo y nublado. Sin embargo la gente llego desde temprano y todo el mundo madrugo (menos yo). Dato curioso cuando me levante y vi que eran las 9 y pico, lo primero que hice fue abrir &lt;a href=&quot;http://twitter.com/twettdeck&quot;&gt;@tweetdeck&lt;/a&gt; y el stream de &lt;a href=&quot;http://twitter.com/onlineteamdo&quot;&gt;@onlineteamDO&lt;/a&gt; cuando me di cuenta que me estaban esperando para comenzar me aliste lo mas rapido que pude y llegue cuando ya habia pasado “el incidente de la fila” asi que entre de una vez y le dieron permiso a &lt;a href=&quot;http://twitter.com/Ggroovin&quot;&gt;@ggroovin&lt;/a&gt; de que comenzara. Por lo tanto les pido disculpas a todos por el retraso en el comienzo del evento, fue 100% culpa mia. &lt;br /&gt;&lt;br /&gt;Dejando el chiste malo de lado la charla de Ricardo Guerrero fue interesante, me gusto el hecho de lo rapido que se dieron cuenta de la excelente herramienta que encontraron generalmente las empresas grandes tienen muchos problemas con eso, creo que les ayudo mucho el funcionar independiente. Creo que la mejor leccion de esa charla es que una gran empresa puede funcionar como una pequeña si se estructura bien.&lt;br /&gt;&lt;br /&gt;Luego el coffee break, la parte mas interesante de este fue el ponerse al lado de alguien aleatoreo y decir hola.&lt;br /&gt;&lt;br /&gt;El panel de las empresas me lo encontre 50/50 la tipa de @tricom sinceramente me durmio no recuerdo una sola palabra de lo que dijo. Por otro lado la presentacion de &lt;a href=&quot;http://twitter.com/yokomosushi&quot;&gt;@yokomosushi&lt;/a&gt; fue excelente como le mande a decir lastima que a mi el sushi no me gusta, voy a tener que cambiar eso, simplemente una ejemplo de lo que el servicio al cliente deberia de ser. La gente de @aeropaq y @diariolibre se manejaron bien pero no vi nada resaltable.&lt;br /&gt;&lt;br /&gt;La charla de @tpago fue interesante es un projecto excelente ya que cubre el tercer modelo de revenue que ha funcionado en Internet (siendo los otros dos ads y subscriptions) y si logran implementar los micropayments estoy seguro de que todos lo vamos a querer usar. Yo soy uno que cada vez que firmo la tarjeta uso &lt;a href=&quot;http://www.zug.com/pranks/credit_card/index5.html&quot;&gt;algo&lt;/a&gt; diferente. Y por otro lado me encantaria poder implementar micropayments en cualquiera de mis apps orientados a RD. Aunque tengo dos dudas que me tienen preocupado. #1 Quien paga por el sistema? La respuesta de @yaqui a la pregunta me dio a entender 3 cosas. a) Pagan los usuarios con una mensualidad (ya que hay que ser miembro) b) Pagan los bancos y empresas crediticias (por tener el pribilegio? de cobrar por ese sistema) c- el sistema es mantenido por GCSystems y se mantiene magicamente. El miedo es simplemente porque si nos apuntamos en este sistema queremos que funcione por los proximos 5 años y para eso se necesita un modelo de negocio valido y solido #2 Como yo cobro por aca? si yo tengo un app, un negocio, una fruteria (ejemplo que le molesto mucho a @cor3d) como cobro?? Lamentablemente en materia de $$$ hay que tener un plan solido y no estoy diciendo que no exista sino que no lo he visto, hay que publicar eso. Update: mientras escribia esto me llego un tweet de @tpago &lt;a href=&quot;http://twitter.com/tPago/status/12464325608&quot;&gt;http://twitter.com/tPago/status/12464325608&lt;/a&gt; diciendo que sea a, la pregunta entonces cambia es a+b o solo a? &lt;br /&gt;&lt;br /&gt;El panel de tasa cero me encanto. Lo unico que necesitamos es llevar eso a la realidad. QUe dicha que hay mas gente pensando “Hay que declarar el internet como bien público que de cáracter universal” Lo segundo que nos tenemos que llevar de esto es la burbuja en la que vivimos solo el 30% de los dominicanos tienen acceso a internet y tener internet en tu casa cuesta el 35% del sueldo minimo. &lt;br /&gt;&lt;br /&gt;Luego la foto de grupo (link ?) y el almuerzo &lt;br /&gt;&lt;br /&gt;La charla de Norberto Gobbi (&lt;a href=&quot;http://twitter.com/ngobbi&quot;&gt;@ngobbi&lt;/a&gt;) fue la que mas me gusto mucha informacion interesante y muchos pequeños detalles ese es un video que hay que verlo para tratar de captar todas los detalles que se perdieron.&lt;br /&gt;&lt;br /&gt;Luego la seccion de preguntas y respuestas no se de donde salio, ironicamente fue una de las que mas me aburrio aunque hubo una gran participacion. Eso estaba planeado?&lt;br /&gt;&lt;br /&gt;El #barcamp fue la parte mas interesante del evento entero, pero ya me harte de escribir :) asi que se quedara para un segundo post.&lt;/p&gt;</description>
	<pubDate>Mon, 19 Apr 2010 17:03:40 +0000</pubDate>
</item>
<item>
	<title>Alessandro Molina: ACR got support for user permissions</title>
	<guid>http://blog.axant.it/?p=253</guid>
	<link>http://blog.axant.it/archives/253</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://labs.axant.it/acr&quot;&gt;ACR&lt;/a&gt; opensource &lt;a href=&quot;http://www.turbogears.org&quot;&gt;Turbogears2&lt;/a&gt; CMS got support for user permissions to allow users to edit only some pages and create children only in some sections. This should permit to separate work between multiple people in ACR based sites.&lt;/p&gt;
&lt;p&gt;ACR also got support for blog/news slice template. This permits to create blogs in ACR with just two clicks instead of having to declare the ACR slicegroup youself.&lt;/p&gt;
&lt;p&gt;As usual you can download ACR from &lt;em&gt;http://repo.axant.it/hg/acr&lt;/em&gt; by using &lt;a href=&quot;http://mercurial.selenic.com/&quot;&gt;mercurial&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 07 Apr 2010 21:15:28 +0000</pubDate>
</item>
<item>
	<title>Luke Macken: Fedora Community Statistics</title>
	<guid>http://lewk.org/blog/2010/03/26/fedoracommunity-statistics</guid>
	<link>http://lewk.org/blog/fedoracommunity-statistics.html</link>
	<description>&lt;p&gt;
&lt;a href=&quot;http://fedoracommunity.fedorahosted.org&quot;&gt;&lt;img src=&quot;http://fedorapeople.org/groups/designteam/Projects/Fedora%20Community/Fedora%20Community%20Banners/fedora-community-plain.png&quot; align=&quot;right&quot; /&gt;&lt;/a&gt;
    I'm pleased to announce that version 0.4.0 of the &lt;a href=&quot;http://fedoracommunity.fedorahosted.org&quot;&gt;Fedora Community&lt;/a&gt; dashboard has just hit &lt;a href=&quot;https://admin.fedoraproject.org/community&quot;&gt;production&lt;/a&gt;.  Along with the usual batch of bugfixes, this release
contains a new '&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics&quot;&gt;Statistics&lt;/a&gt;' section that contains metrics from a variety of different pieces of Fedora Infrastructure.
&lt;/p&gt;
&lt;p&gt;
    Thanks goes to &lt;a href=&quot;http://ianweller.org/&quot;&gt;Ian Weller&lt;/a&gt; for the wiki stats, &lt;a href=&quot;http://skvidal.wordpress.com/&quot;&gt;Seth Vidal&lt;/a&gt; for the torrent
    stats, and &lt;a href=&quot;http://www.domsch.com/&quot;&gt;Matt Domsch&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://jspaleta.livejournal.com/&quot;&gt;Jef Spaleta&lt;/a&gt; for the map generation code.  I ended up writing the updates
metrics, package stats, and users/mirrors widgets.  Enjoy!
&lt;/p&gt;

&lt;p&gt;
    &lt;center&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/users&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-userstats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/mirrors&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-mirrorstats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/packages&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-packagestats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/accounts&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-accountstats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/updates&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-updatestats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/wiki&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-wikistats.png&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://admin.fedoraproject.org/community/statistics/torrents&quot;&gt;&lt;img src=&quot;http://lmacken.fedorapeople.org/img/fedoracommunity-torrentstats.png&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;/p&gt;</description>
	<pubDate>Sat, 27 Mar 2010 03:48:25 +0000</pubDate>
</item>

</channel>
</rss>

