<?xml version="1.0" encoding="utf8" ?>
<rss version="2.0" 
   xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" 
   xmlns:html="http://www.w3.org/1999/html" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
   <title>Repoze Notes</title>
   <link>http://blog.repoze.org</link>
   <description>Notes on the Repoze platform</description>
   <language>en</language>
   <copyright>Copyright 2007 Agendaless Consulting, Inc.</copyright>
   <ttl>60</ttl>
   <pubDate>Tue, 01 Jul 2008 18:50 GMT</pubDate>
   <managingEditor>repoze-dev@lists.repoze.org</managingEditor>
   <generator>PyBlosxom http://pyblosxom.sourceforge.net/ 1.4.2 8/16/2007</generator>
<item>
   <title>Repozecast Number 2</title>
   <guid isPermaLink="false">repozecast-2</guid>
   <link>http://blog.repoze.org/repozecast-2.html</link>
   <description><![CDATA[
<h4>Repozecast #2, Plone Symposium Wrapup</h4>

<p>The <a
href="http://static.repoze.org/casts/repozecast-2-june08.mp3">second
episode</a> (mp3) is now up.  It contains ramblings about Repoze and
how it relates to:

<ul>
   <li>A wrapup of the Plone Symposium in New Orleans 2008</li>
   <li>The current state of Zope-related Repoze software</li>
   <li>Info about repoze.who</li>
   <li>Recent Zope/Plone/Python user group talks</li>
   <li>Thoughts about Deliverance</li>
</ul>

</p>
<p>
Enjoy!
</p>
<p><cite>-Chris</cite></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 01 Jul 2008 18:50 GMT</pubDate>
</item>
<item>
   <title>Authorization in Pylons with repoze.who</title>
   <guid isPermaLink="false">pylons-who-nym</guid>
   <link>http://blog.repoze.org/pylons-who-nym.html</link>
   <description><![CDATA[

<p>

Tom Longson (aka nym) has created a useful <a
href="http://truefalsemaybe.com/2008/06/repozewho-with-pylons-part-1-htaccess-authentication/">blog
post</a> where he details a very simple integration between the <a
href="http://blog.repoze.org/repozewho-1.0.html">repoze.who</a>
WSGI authentication framework and Pylons, including simple authorization.

</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 10 Jun 2008 18:46 GMT</pubDate>
</item>
<item>
   <title>repoze.who 1.0 Released</title>
   <guid isPermaLink="false">repozewho-1.0</guid>
   <link>http://blog.repoze.org/repozewho-1.0.html</link>
   <description><![CDATA[

<p>

Version 1.0 of the <a
href="http://svn.repoze.org/repoze.who/trunk">repoze.who</a> WSGI
authentication framework has been released.  You can get it via
<code>easy_install -i http://dist.repoze.org/who/latest/simple repoze.who</code>.

</p>

<p>

Version 1.0 has optional support for middleware configuration via a
config file (thanks to Tres).  Being a framework, <i>repoze.who</i> is
configuration-heavy, and it can provide a better separation of
concerns and more convenience to wire it up via a configuration file
than via Python code.  So rather than configuring the middleware and
attendant plugins via straight Python code, you can now wire who
configuration up in an .ini file:

</p>

<pre>
    # who.ini

    [plugin:form]
    # identification and challenge
    use = repoze.who.plugins.form:make_plugin
    login_form_qs = __do_login
    rememberer_name = cookie
    form = %(here)s/login_form.html

    [plugin:auth_tkt]
    # identification
    use = repoze.who.plugins.auth_tkt:make_plugin
    secret = s33kr1t
    cookie_name = oatmeal
    secure = False
    include_ip = False

    [plugin:basicauth]
    # identification and challenge
    use = repoze.who.plugins.basicauth:make_plugin
    realm = 'sample'

    [plugin:htpasswd]
    # authentication
    use = repoze.who.plugins.htpasswd:make_plugin
    filename = %(here)s/passwd
    check_fn = repoze.who.plugins.htpasswd:crypt_check

    [plugin:sqlusers]
    # authentication
    use = repoze.who.plugins.sql:make_authenticator_plugin
    query = "SELECT userid, password FROM users where login = %(login)s;"
    conn_factory = repoze.who.plugins.sql:make_psycopg_conn_factory
    compare_fn = repoze.who.plugins.sql:default_password_compare

    [plugin:sqlproperties]
    name = properties
    use = repoze.who.plugins.sql:make_metadata_plugin
    query = "SELECT firstname, lastname FROM users where userid = %(__userid)s;"
    filter = my.package:filter_propmd
    conn_factory = repoze.who.plugins.sql:make_psycopg_conn_factory

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

    [identifiers]
    # plugin_name;classifier_name:.. or just plugin_name (good for any)
    plugins =
          form;browser
          auth_tkt
          basicauth

    [authenticators]
    # plugin_name;classifier_name.. or just plugin_name (good for any)
    plugins =
          htpasswd
          sqlusers

    [challengers]
    # plugin_name;classifier_name:.. or just plugin_name (good for any)
    plugins =
          form;browser
          basicauth

    [mdproviders]
    plugins =
          sqlproperties
</pre>

<p> Then you can use a constructor to create the configuration based
on the .ini file, e.g.: </p>

<pre>
from repoze.who.config import WhoConfig

app = {next app in pipeline}
here = os.path.dirname(__file__)
config_file = os.path.join(here, 'who.ini')
parser = WhoConfig(here)
parser.parse(open(config_file))
middleware = PluggableAuthenticationMiddleware(app,
             parser.identifiers,
             parser.authenticators,
             parser.challengers,
             parser.mdproviders,
             parser.request_classifier,
             parser_challenge_decider,
             log_stream = sys.stdout,
             log_level = logging.DEBUG,
             )
</pre>

<p> There is a PasteScript-compatible constructor available via the
egg name <code>egg:repoze.who#config</code> that does just this, so
you can also just wire it up via a paste config file equivalently,
ala: </p>

<pre>
[filter:who]
use = egg:repoze.who#config
config_file = %(here)s/etc/who.ini
log_level = debug
log_stream = stdout
</pre>

<p>You can read the <a
href="http://svn.repoze.org/repoze.who/trunk/README.txt">documentation</a>
for more information about configuration.</p>

<p> - Chris </p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 10 Jun 2008 18:46 GMT</pubDate>
</item>
<item>
   <title>Plone Symposium New Orleans Talks</title>
   <guid isPermaLink="false">nola_symposium_talks</guid>
   <link>http://blog.repoze.org/nola_symposium_talks.html</link>
   <description><![CDATA[

<p> We've had good feedback on our WSGI and repoze-related talks at the
    2008 Plone Symposium in New Orleans:</p>

<ul>
 <li><a href="http://static.repoze.org/presentations/wsgipresentation-2008plonesymposium.pdf"
     >Chris McDonough's "Intro to WSGI" talk.</a></li>
 <li><a href="https://agendaless.com/Members/tseaver/events/PloneSymposium-NOLA-2008/PloneSymposium2008-Turplango.pdf"
     >Tres Seaver's "Turplango:  Playing Nice with Others" talk.</a></li>
 <li><a href="https://agendaless.com/Members/tseaver/events/PloneSymposium-NOLA-2008/PloneSymposium2008-plone_gs.pdf"
     >Tres Seaver's "GenericSetup for Fun and Profit (redux)"
      lightning talk.</a></li>
</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 05 Jun 2008 21:41 GMT</pubDate>
</item>
<item>
   <title>repoze.plone 2.5.5 and repoze.zope2 2.9.8 Released</title>
   <guid isPermaLink="false">repoze-plone-255</guid>
   <link>http://blog.repoze.org/repoze-plone-255.html</link>
   <description><![CDATA[

<p>

For the oldskool, we've released versions of repoze.plone and
repoze.zope2 which are capable of running Plone 2.5.5 and Zope 2.9.8.
Previously, folks who had wished to run Plone under repoze.zope2 were
limited to running either Plone 3.0.6 or 3.1.1.  There are plenty of
folks out there who can't move to any version of Plone 3 just yet.
These releases are for you.  Instructions are below about how to get
Plone 2.5.5 and/or Zope 2.9.8 installed so they run under
repoze.zope2.  We support both buildout and virtualenv-based installs,
so each is documented separately.

</p>

<h1>Installing Plone 2.5.5 (implies Zope 2.9.8)</h1>

<h2>Install repoze.plone 2.5.5 using Buildout</h2>

<pre>
$ svn co http://svn.repoze.org/buildouts/repoze.plone/branches/2.5.5
$ cd 2.5.5
$ python2.4 bootstrap.py
$ bin/buildout
.. follow instructions here on in ..
</pre>

<h2>... or install repoze.plone 2.5.5 using Virtualenv</h2>

<pre>
$ virtualenv24 --no-site-packages plone255
$ cd plone255
$ bin/easy_install -i http://dist.repoze.org/plone/2.5.5/simple repoze.plone
$ bin/mkzope2instance .
$ bin/addzope2user admin admin
$ bin/paster serve etc/zope2.ini
</pre>

<h1>Installing Zope 2.9.8 only (if you don't use Plone)</h1>

<h2>Install repoze.zope2 2.9.8 using Buildout</h2>

<pre>
$ svn co http://svn.repoze.org/buildouts/repoze.zope2/branches/2.9
$ cd 2.9
$ python2.4 bootstrap.py
$ bin/buildout
.. follow instructions here on in ..
</pre>

<h2>Install repoze.zope2 2.9.8 using Virtualenv</h2>

<pre>
$ virtualenv24 --no-site-packages zope298
$ cd zope298
$ bin/easy_install -i http://dist.repoze.org/zope2/2.9/simple repoze.zope2
$ bin/mkzope2instance .
$ bin/addzope2user admin admin
$ bin/paster serve etc/zope2.ini
</pre>

<p>

One good thing about doing this work is that it's becoming a little
clearer how we need to lay out our distribution site (dist.repoze.org)
to support multiple build revisions of the same piece of software.  I
haven't managed yet to clean it up entirely but I think I know how to
now.

</p>

<p>

Have fun!

</p>

<p>
-C
</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 09 May 2008 14:41 GMT</pubDate>
</item>
<item>
   <title>Martin Aspeli's "Rolling Out Repoze"</title>
   <guid isPermaLink="false">optilude-rolling-out-repoze</guid>
   <link>http://blog.repoze.org/optilude-rolling-out-repoze.html</link>
   <description><![CDATA[

<p>

Martin Aspeli writes a <a
href="http://martinaspeli.net/articles/rolling-out-repoze">fairly
lengthy article</a> detailing how he's moved his personal blog over to
running under repoze.plone as well as configuration of another set of
applications under repoze+plone + mod_wsgi + deliverance.

</p>



]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sun, 04 May 2008 18:17 GMT</pubDate>
</item>
<item>
   <title>Test Version of repoze.plone for Plone 3.1.1 released</title>
   <guid isPermaLink="false">repoze-dot-plone3110</guid>
   <link>http://blog.repoze.org/repoze-dot-plone3110.html</link>
   <description><![CDATA[

<p> To get it via <code>easy_install</code> (virtualenv suggested,
don't even bother trying a <code>-U</code> upgrade from an older
repoze.plone, it just won't work): </p>

<pre>
$ bin/easy_install -i http://dist.repoze.org/plone/3.1.1/simple repoze.plone
$ bin/addzope2user {username} {password}
.. ignore deprecation warnings ..
$ bin/paster serve etc/zope2.ini
</pre>

<p> To get it via <code>zc.buildout</code>, check out <a
href="http://svn.repoze.org/buildouts/repoze.plone/branches/3.1.1/">http://svn.repoze.org/buildouts/repoze.plone/branches/3.1.1/</a>
and run:</p>

<pre>
$ python2.4 bootstrap.py
$ bin/buildout
$ bin/supervisord
$ bin/addzope2user {username} {password}
</pre>

<p>In either case, visit the result on <b>http://localhost:8080/manage</b></p>

<p>
- C
</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 29 Apr 2008 18:01 GMT</pubDate>
</item>
<item>
   <title>Using repoze.who for Authentication with TurboGears 2</title>
   <guid isPermaLink="false">tgrepozewho</guid>
   <link>http://blog.repoze.org/tgrepozewho.html</link>
   <description><![CDATA[
<p>

Since PyCon 2008 in March, we've been working within the <a
href="http://www.turbogears.org/">TurboGears</a> community on an
authentication system based around <a
href="http://svn.repoze.org/repoze.who/trunk/README.txt">repoze.who<a>.
<i>repoze.who</i> is a WSGI middleware authentication framework
roughly modeled after Zope's <a
href="http://pypi.python.org/pypi/Products.PluggableAuthService/1.5.3">Pluggable
Authentication Service"</a>.  <i>repoze.who</i> does less than PAS and
shares no code with PAS, but it shares with PAS a fundamental model of
a pluggable framework with customizable identification,
authentication, and metadata plugins.  The goal of <i>repoze.who</i>
is to let us use the authentication features we've become accustomed
to under PAS when deploying other web frameworks under WSGI.  As such,
repoze.who is not tied to any particular web framework.  It operates
as its own framework, providing downstream applications with
consumable authentication and identity information.  In particular,
it's tied to neither TurboGears nor Zope in any way.  It's tied only
to WSGI, and could be used to provide similar functionality for
one-off WSGI apps, Django, or Pylons, or any other WSGI-capable web
framework.

</p>

<p>

The TurboGears trunk (which will at some point be released as
TurboGears 2) is very different from the released 1.X version of
TurboGears.  Instead of using CherryPy as a controller dispatch
mechanism as TG 1.X does; instead it uses Pylons.  One of the side
effects of this change is that the venerable TG 1.X authentication and
authorization code known as <a
href="http://docs.turbogears.org/1.0/Identity">identity<a> doesn't
work anymore under the TurboGears trunk.  So the identification,
authentication, and authorization features that TurboGears 1.X people
have become accustomed to are largely missing for people working off
the TurboGears trunk.  An effort named <a
href="http://groups.google.com/group/authority-wsgi">Authority</a> was
established to provide the TG trunk with these features, and code
exists in that project to that end.  We've worked a bit with the folks
who are creating Authority, and I hope there's some way to coalesce
the two efforts into one in the future.

</p>

<p>

In the meantime, I created <a
href="http://svn.repoze.org/tg2whoplugins/trunk/">a sample set of
repoze.who plugins and a repoze.who middleware configuration</a> "on
spec" for TG2 just for proof-of-concept.  This eventually served as a
template for <a href="http://www.linkedin.com/in/florentaide">Florent
Aide</a>, who subsequently developed a <a
href="http://svn.turbogears.org/projects/tgrepozewho/trunk/">more-or-less
feature complete set of <i>repoze.who</i> plugins and separate
authorization facilities named <i>tgrepozewho</i></a> to provide
functionality equivalent to TG 1.X's "identity" package for TG2 users.
Florent also created a <a
href="http://svn.turbogears.org/projects/tgrepozewho/examples/whotg/">sample
TG2 application named <i>whotg</i></a> that can make use of the
authentication and authorization features provided by the
<i>tgrepozewho</i> configuration package.

</p>

<p> The fundamentals of Florent's TG2 application which makes use of
repoze.who are these:</p>

<ul>

 <li>Sqlalchemy models for users, groups, and permissions were created
 in the <i>whotg</i> package's <code>model.__init__.py</code>, which
 is represented below in its entirety.  These models are used by the
 plugins to repoze.who that exist in the "tgrepozewho" package (shown
 later) which perform identification and authorization.  These are
 loaded into a database within the demo package by doing <code>paster
 setup-app development.ini</code> within a checkout of <a>whotg</i>.
 Some sample user and group data exists in the generated SQL when you
 load it this way.

<pre>
import datetime
from pylons import config

from sqlalchemy import Column, MetaData, Table, Integer, Unicode, DateTime
from sqlalchemy import ForeignKey

from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.orm import mapper, relation

import md5
import sha

# Global session manager.  DBSession() returns the session object
# appropriate for the current web request.
DBSession = scoped_session(sessionmaker(autoflush=True, transactional=True))

# Global metadata. If you have multiple databases with overlapping table
# names, you'll need a metadata for each database.
metadata = MetaData()

def init_model(engine):
    """Call me before using any of the tables or classes in the model."""
    
groups_table = Table('tg_group', metadata,
    Column('group_id', Integer, primary_key=True),
    Column('group_name', Unicode(16), unique=True),
    Column('display_name', Unicode(255)),
    Column('created', DateTime, default=datetime.datetime.now)
)

users_table = Table('tg_user', metadata,
    Column('user_id', Integer, primary_key=True),
    Column('user_name', Unicode(16), unique=True),
    Column('email_address', Unicode(255), unique=True),
    Column('display_name', Unicode(255)),
    Column('password', Unicode(40)),
    Column('created', DateTime, default=datetime.datetime.now)
)

permissions_table = Table('tg_permission', metadata,
    Column('permission_id', Integer, primary_key=True),
    Column('permission_name', Unicode(16), unique=True),
    Column('description', Unicode(255))
)

user_group_table = Table('tg_user_group', metadata,
    Column('user_id', Integer, ForeignKey('tg_user.user_id',
        onupdate="CASCADE", ondelete="CASCADE")),
    Column('group_id', Integer, ForeignKey('tg_group.group_id',
        onupdate="CASCADE", ondelete="CASCADE"))
)

group_permission_table = Table('tg_group_permission', metadata,
    Column('group_id', Integer, ForeignKey('tg_group.group_id',
        onupdate="CASCADE", ondelete="CASCADE")),
    Column('permission_id', Integer, ForeignKey('tg_permission.permission_id',
        onupdate="CASCADE", ondelete="CASCADE"))
)

# identity model
class Group(object):
    """An ultra-simple group definition.
    """
    def __repr__(self):
        return '<Group: name=%s>' % self.group_name

class User(object):
    """Reasonably basic User definition. Probably would want additional
    attributes.
    """
    def __repr__(self):
        return '<User: email="%s", display name="%s">' % (
                self.email_address, self.display_name)

    def permissions(self):
        perms = set()
        for g in self.groups:
            perms = perms | set(g.permissions)
        return perms
    permissions = property(permissions)

    def by_email_address(klass, email):
        """A class method that can be used to search users
        based on their email addresses since it is unique.
        """
        session = DBSession()
        return session.query(klass).filter(klass.email_address==email).first()

    by_email_address = classmethod(by_email_address)

    def by_user_name(klass, username):
        """A class method that permits to search users
        based on their user_name attribute.
        """
        session = DBSession()
        return session.query(klass).filter(klass.user_name==username).first()

    by_user_name = classmethod(by_user_name)

    def _set_password(self, password):
        """encrypts password on the fly using the encryption
        algo defined in the configuration
        """
        algorithm = config.get('authorize.hashmethod', None)
        self._password = self.__encrypt_password(algorithm, password)

    def _get_password(self):
        """returns password
        """
        return self._password

    password = property(_get_password, _set_password)

    def __encrypt_password(self, algorithm, password):
        """Hash the given password with the specified algorithm. Valid values
        for algorithm are 'md5' and 'sha1'. All other algorithm values will
        be essentially a no-op."""
        hashed_password = password

        if isinstance(password, unicode):
            password_8bit = password.encode('UTF-8')

        else:
            password_8bit = password

        if "md5" == algorithm:
            hashed_password = md5.new(password_8bit).hexdigest()

        elif "sha1" == algorithm:
            hashed_password = sha.new(password_8bit).hexdigest()

        if not isinstance(hashed_password, unicode):
            hashed_password = hashed_password.decode('UTF-8')

        return hashed_password

    def validate_password(self, password):
        """Check the password against existing credentials.
        """
        algorithm = config.get('authorize.hashmethod', None)
        return self.password == self.__encrypt_password(algorithm, password)

class Permission(object):
    """A relationship that determines what each Group can do
    """
    pass

mapper(User, users_table,
        properties=dict(_password=users_table.c.password))

mapper(Group, groups_table,
        properties=dict(users=relation(User,
                secondary=user_group_table, backref='groups')))

mapper(Permission, permissions_table,
        properties=dict(groups=relation(Group,
                secondary=group_permission_table, backref='permissions')))


</pre>

</li>

  <li>

   Florent created a set of <i>repoze.who</i> plugins that work with
   SQLAlchemy model data to do identification and authentication.  In
   this case, Florent created an "authenticator" plugin that examines
   SQLAlchemy model data to compare the identity information found by
   repoze.who against SQL data, and a "metadata" plugin which adds
   permission and group information to the identity.  He reuses stock
   repoze.who plugins for "identificaton" duties, including an
   auth_tkt based cookie identification plugin and a form login
   identification plugin.  The code that defines and configures these
   plugins can be viewed <a
   href="http://svn.turbogears.org/projects/tgrepozewho/trunk/tgrepozewho/middleware.py">here</a>.
   In that module is also a helper function named
   <i>make_who_middleware</i> which serves as a constructor for
   a configuration of middleware which uses these plugins.

 </li>

 <li>

   Florent also coded up some functions in <a
   href="http://svn.turbogears.org/projects/tgrepozewho/trunk/tgrepozewho/authorize.py">the
   authorize.py module of <i>tgrepozewho</i></a> that can serve as
   decorators for controller methods that perform authorization
   against <i>repoze.who</i>-provided data.  <i>repoze.who</i> doesn't
   perform any authorization itself, it leaves that up to the web
   framework, so this was required.

 </li>

 <li>

   He then added the middleware generated by his helper function
   to his <i>whotg</i> demo package's middleware pipeline in in
   "config/middleware.py".  This sets up the repoze.who middleware in
   the TG2 WSGI stack, so that when you start the TG2 server, it's
   present in the call chain.

<pre>
    ...
    # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
    from whotg.model import User, DBSession
    user_criterion = User.user_name
    # the name of the column which is used as a unique identifier
    user_id_col = 'user_id'
    from tgrepozewho.middleware import make_who_middleware
    app = make_who_middleware(app, config, User, user_criterion, user_id_col,
            DBSession)
    ...
</pre>

</li>

<li> Then he created two methods on his root controller's class
named <code>manage_permission_only</code> and
<code>editor_user_only</code>.  He protects the
<code>manage_permission_only</code> method with a decorator which
ensures that the user provided by the middleware has the 'manage'
permission (as per the data in the model tables, via his group).  He
protects the <code>editor_user_only</code> with a decorator that
ensures that the user provided by the middleware has the username
'editor'.  When these methods are asked for (e.g. via
<b>http://locahost:8080/manage_permission_only</b> or via
<b>http://localhost:8080/editor_user_only</b>), if the user possesses the
proper permission or username (respectively), the TG "about" page will
be shown; if he does not, the user will be redirected to a login form.
Only the relevant parts of the <a
href="http://svn.turbogears.org/projects/tgrepozewho/examples/whotg/whotg/controllers/root.py">entire
module</a> are shown below.

<pre>
from datetime import datetime
now=datetime.now()

from tg import expose
from whotg.lib.base import BaseController

from tgrepozewho import authorize

class RootController(BaseController):

   ...

    @expose('whotg.templates.about')
    @authorize.require(authorize.has_permission('manage'))
    def manage_permission_only(self, **kw):
        return dict(now=now, page='about')

    @expose('whotg.templates.about')
    @authorize.require(authorize.is_user('editor'))
    def editor_user_only(self, **kw):
        return dict(now=now, page='about')

</pre>

</li>

</ul>


<p>

The result is a functional, customizable authentication and
authorization system for TurboGears 2 that reuses the
<i>repoze.who</i> framework.  Hats off to Florent!  This appears to be
real evidence that we can move towards a "fourth generation" of Python
web frameworks where coding framework-specific subsystems from scratch
isn't always the norm, because the work that Florent did could be
recast pretty easily for just about any TurboGears 2 or Pylons
application (or Django application, etc).

</p>

<p>
- Chris
</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sun, 27 Apr 2008 19:24 GMT</pubDate>
</item>
<item>
   <title>repoze.zope2 Updates</title>
   <guid isPermaLink="false">repozezope2updates-apr</guid>
   <link>http://blog.repoze.org/repozezope2updates-apr.html</link>
   <description><![CDATA[

<p>

<a href="http://svn.repoze.org/repoze.zope2">repoze.zope2</a> (the
reimplementation of Zope2's ZPublisher that allows Zope2 to run as a
WSGI application) has been updated quietly over the last few months,
with the latest release, 0.3.6, posted today.  Below is the changelog
for the releases performed in March and April of this year.  If you
haven't already given it a roll, and you're interested in WSGI, you
might want to <a href="http://repoze.org/quickstart.html">try it
out.</a>

</p>

<pre>

0.3.6 (2008-04-16)

  - "http" exceptions (like Redirect and Unauthorized) weren't handled
    properly anywhere except in the repoze.zope2 obob helper's
    'invoke' step.  In-the-wild code uses these exceptions before the
    published object has been located (e.g. during traverse() or
    before_traverse()).  We now depend on repoze.obob >=0.3 to get
    extended exception handling behavior, and we implement a
    'handle_exception' method on our z2bob helper which will turn
    Zope2 Unauthorized and Redirect exceptions into their
    "httpexception" equivalents for consumption by upstream
    middleware.  This was prompted by code found in the wild in
    Plone's OpenId implementation which raises a redirect during
    traversal.

0.3.5 (2008-04-16)

  - "Legacy" virtual hosting (via Virtual Host Monster) did not work
    properly.  Symptom: if you set up proxy-rewrite rules in Apache
    pointing at the Zope root a repoze.zope2 server running under a
    separate paster server, and tried to visit the ZMI via the Apache
    virtualhost's /manage URL, you'd be presented with the
    VirtualHostMonster ZMI configuration page instead of the ZMI's
    framed root UI.  Reason: the PARENTS[0] item was not set up early
    enough (it was set up in traverse rather than
    before_traverse). Since it was depended on by Zope API's which VHM
    called out to to set the virtual root, this didn't work, and the
    resulting traversal name stack was incorrect.

0.3.4 (2008-03-24)

  - Bump ez_setup.py version.

  - When Zope 2 starts, it potentially writes data to the database
    during product initialization.  When multiple clients talk to the
    same ZEO storage at startup, they often simultaneously try to
    write (the same) information to the database concurrently.  This
    causes startup failure due to conflict errors.  We now retry
    product initialization up to five times to work around this issue.

0.3.3 (2008-03-10)

  - repoze.zope2 now properly respects virtual host directives
    provided to it by repoze.vhm xheaders middleware >= 0.4.  Zope's
    VHM can still be used as necessary, but is no longer required.

0.3.2 (2008-03-03)

  - Fix bug reported by Martin Aspeli: repoze.zope2 would choke on
    large images and files (symptom: broken images when images were
    large).  This was due to the fact that the Zope File- and
    Image-rendering machinery used HTTPResponse.write, which
    repoze.zope2's response handling didn't handle properly.  We now
    subclass HTTPResponse (as RepozeHTTPResponse) to solve the issue.

0.3.1 (2008-03-02)

  - mkzope2instance now:

    o takes no arguments, only options.  '-d' replaces the single
      argument path.

    o creates a "log" directory

    o writes out a zeo.conf into "etc" (unconditionally); you can
      start a ZEO instance after installation now via 'bin/runzeo -C
      etc/zeo.conf', after ensuring that the 'address' in the ZEO
      section is correct.

    o allows the specification of 'sandbox' (-s) (replaces
      single-argument instancedir), 'zeo-port' (-z) , 'zope-port'
      (-p), and 'use-zeo' (-z) options.  If 'use-zeo' is specified,
      the zope.conf that's written will use a ClientStorage by
      default.

    o writes a zope.conf with a zodb cache-size of 50000 rather than
      10000.

  - addzope2user, runzope2script, and debugzope2 now respect a
    "ZOPE_CONF" environment variable, which can be used to specify the
    zope.conf configuration file to use.

  - Add a sample <zodb_db main> section to the generated zope.conf
    that can be uncommented if the installer wants to use ZEO instead
    of FileStorage or vice versa.

  - Added an (experimental) 'zope2testrunner' script that sets up
    stuff in the environment before running
    'zope.testing.testrunner.run'.  It accepts the same arguments as
    the Zope 3 testrunner.  E.g. 'bin/zope2testrunner -m
    Products.faster'.  This also respects the ZOPE_CONF envvar.

  - Depend on Zope 2.10.5 (zopelib-2.10.5.0) instead of 2.10.4.2 and
    various other updated repoze libraries.
</pre>

<p><cite>-Chris</cite></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 17 Apr 2008 02:15 GMT</pubDate>
</item>
<item>
   <title>Tomster.org:  Nginx + WSGI</title>
   <guid isPermaLink="false">tom_lazar-nginx_and_wsgi</guid>
   <link>http://blog.repoze.org/tom_lazar-nginx_and_wsgi.html</link>
   <description><![CDATA[

<p>Tom Lazar has written an <a
href="http://tomster.org/blog/archive/2008/04/16/nginx-mod-wsgi-python2.4"
> informative article</a> on running WSGI applications under
<a href=http://wiki.codemongers.com/Main">nginx</a>.  Check it out!</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 16 Apr 2008 19:28 GMT</pubDate>
</item>
<item>
   <title>Tom Lazar Investigates Deliverance and Repoze</title>
   <guid isPermaLink="false">tomlazar-deliverance-blogentry</guid>
   <link>http://blog.repoze.org/tomlazar-deliverance-blogentry.html</link>
   <description><![CDATA[

<p><a href="http://tomster.org/blog/archive/2008/04/08/deliverance-a-la-wsgi-for-plone"><i>Deliverance is the New Kid on the Block[tm] in the Plone world. I find the whole concept very intriguing and have decided to give it a try on both of my current new projects. (No risk, no fun, eh!?)</i></a>
</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sat, 12 Apr 2008 22:58 GMT</pubDate>
</item>
<item>
   <title>Video of Repoze Talk by Tim Knapp</title>
   <guid isPermaLink="false">duffyd-presents-repoze</guid>
   <link>http://blog.repoze.org/duffyd-presents-repoze.html</link>
   <description><![CDATA[

<p>Tim Knapp of Emerge Technology <a
href="http://plone.tv/media/2077881216">presents repoze.zope2</a> in
Christchurch NZ last week.  Nice job Tim!
</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 10 Apr 2008 03:23 GMT</pubDate>
</item>
<item>
   <title>Upcoming Repoze Talk Down Under</title>
   <guid isPermaLink="false">duffyd-christchurch-presentation</guid>
   <link>http://blog.repoze.org/duffyd-christchurch-presentation.html</link>
   <description><![CDATA[

<p>Fun for all as Tim Knapp <a
href="http://nzpug.org/MeetingsChristchurch/April2008">presents
Repoze</a> in Christchurch NZ on Friday Apr. 4, 5:30 - 7:30PM.  The
title of the talk is <i>The Repoze project and best practices for
deployment of Python code (ie. eggs, buildout)</i>.
</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 03 Apr 2008 04:25 GMT</pubDate>
</item>
<item>
   <title>Six Months of Repoze</title>
   <guid isPermaLink="false">sixmonthsofrepoze</guid>
   <link>http://blog.repoze.org/sixmonthsofrepoze.html</link>
   <description><![CDATA[

<p> <a href="http://repoze.org">Repoze</a> is now roughly six months
old and it's a pretty good time for some self-analysis.  What have we
done?  What are we doing?  What do we want to do?  </p>

<h5> What have we done? </h5>

<ul>

  <li>We've <a
  href="http://svn.repoze.org/repoze.zope2/trunk/">reimplemented the
  Zope 2 publisher</a>, so Zope 2 applications such as Plone can be
  run without modification within a WSGI environment</li>

  <li>We've successfully externalized features Zope such as <a
  href="http://svn.repoze.org/repoze.tm/trunk/">transaction
  management</a>, <a
  href="http://svn.repoze.org/repoze.retry/trunk/">conflict error
  retry</a>, <a href="http://svn.repoze.org/repoze.vhm/trunk/">virtual
  hosting services</a>, and <a
  href="http://svn.repoze.org/repoze.who/trunk/">identification and
  authentication</a>, <a
  href="http://svn.repoze.org/repoze.errorlog/trunk/">error
  logging</a>, and <a
  href="http://svn.repoze.org/repoze.profile/trunk/">profiling</a>
  into WSGI middleware, so they can be reused outside the Zope stack
  in a way that's largely familiar to Zope and non-Zope users
  alike.</li>

  <li>We've packaged up <a
  href="http://svn.repoze.org/repoze.plone/trunk/">Plone</a>, <a
  href="http://svn.repoze.org/repoze.grok/trunk/">Grok</a>, <a
  href="http://svn.repoze.org/repoze.trac/trunk/">Trac</a>, and <a
  href="http://svn.repoze.org/repoze.django/trunk/">Django</a> so they
  can be used without much effort in a Repoze WSGI environment.</li>

  <li>We've created bridges to traditionally-CGI applications like <a
  href="http://svn.repoze.org/repoze.mmwsgi/trunk/">Mailman</a> so
  they can be served up via WSGI servers.</li>

  <li>We've created applications like <a
  href="http://svn.repoze.org/repoze.kiss/trunk/">repoze.kiss</a>,
  which are "Zope-like", but do not use any ZODB.</li>

  <li>We've evangelized <a
  href="http://www.openplans.org/projects/deliverance/introduction">Deliverance</a>
  as a theming mechanism.</li>

  <li>We've reached out to other Python web projects like TurboGears,
  Pylons, and Django, attempting to reuse some of their components,
  and we've made them aware of ours.</li>

  <li>We've given many, many talks at Zope/Plone/Python user groups
  and conferences, attempting to bring more folks into the fold </li>

  <li>We've created <a
  href="http://svn.repoze.org/buildouts/">buildouts</a> using
  zc.buildout for Plone and Trac.</li>

</ul>

<h5> What are we doing? </h5>

<ul>

  <li>We're playing around with exernalizing <a
  href="http://svn.repoze.org/repoze.decsec/trunk/">declarative
  security</a>, so we can better integrate dissimilar WSGI applications using the same security model.</li>

  <li>We're attempting to create alternate <a href="http://svn.repoze.org/repoze.browserid/trunk/">sessioning</a> components for use under WSGI stacks.</li>

  <li>We're working Repoze into our (Agendaless') own customer deployments</li>

</ul>

<h5>What we intend to do </h5>

<ul>

  <li>We intend to do more evangelism via presenting to
  Python/Zope/Plone user groups and conferences.</li>

  <li>We intend to reach out more to other web projects by helping
  them integrate Repoze code into their own projects.</li>

  <li>We intend to push for Plone (and possibly Zope 2) to base a
  release on Repoze technologies.</li>

</ul>

<h5> Where we need help </h5>

<p> We need help a) evangelizing, b) bringing things to ground and c)
maintaining our various web presences.  On the evangelism front, we
need Python folks to understand that Repoze is <b>not</b> just about
Zope, instead it's a generically useful set of WSGI components
inspired by features of Zope.  We need to get Zope people excited
about a future that allows them to make use of best-of-breed
components created by Python web developers that are not Zope
developers.  We need to get Python folks excited about the fact that
the Zope community is reaching out to the larger Python web
development community by making it possible for them to use components
that Zope folks have been using for years without knowing anything
whatsoever about Zope itself.  We need to improve Deliverance's
conditional theming support.  We need Zope and Plone folks to start
using repoze.zope2 and Deliverance "in anger" to start to bring things
to ground.  We need help maintaining repoze.org, mainly to keep
content fresh.  We need more developers to start contributing code to
the Repoze repository.  </p>

<p> If
you want to help doing any of these things, please join the <a
href="http://lists.repoze.org/">repoze-dev</a> maillist and the <a
href="irc://irc.freenode.net/#repoze">#repoze IRC channel on
freenode.net</a>, and yell! </p>

<p><cite>-Chris</cite></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 31 Mar 2008 23:04 GMT</pubDate>
</item>
<item>
   <title>Repozecast Number 1</title>
   <guid isPermaLink="false">repozecast-1</guid>
   <link>http://blog.repoze.org/repozecast-1.html</link>
   <description><![CDATA[
<h4> Zopecast is dead, long live Repozecast ... </h4>

<p> For several years now, we've been making and releasing podcasts
  that we've referred to as <a
  href="http://www.plope.com/zopecast">Zopecasts</a> when we felt like
  it.  The last few we've made have been more about Repoze than
  they've been about Zope, so we've decided to retitle the
  every-so-often podcast we do as "Repozecast".</p>

<p>The <a
href="http://static.repoze.org/casts/repozecast-1-20080305.mp3">inaugural
episode</a> (mp3) is now up.  It contains ramblings about Repoze and
how it relates to:

<ul>
   <li>The past Plone Strategic Planning Summit</li>
   <li>The upcoming Plone Symposium East</li>
   <li>The upcoming Python conference</li>
   <li>Recent Zope/Plone/Python user group talks</li>
   <li>New Repoze committers</li>
   <li>New repoze.* packages</li>
   <li>Buildout for repoze.plone</li>
   <li>Deliverance</li>
</ul>

</p>
<p>
Enjoy!
</p>
<p><cite>-Chris</cite></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 05 Mar 2008 19:22 GMT</pubDate>
</item>
<item>
   <title>repoze.profile 0.3 Released</title>
   <guid isPermaLink="false">repozeprofile-0.3-released</guid>
   <link>http://blog.repoze.org/repozeprofile-0.3-released.html</link>
   <description><![CDATA[

<p> Whoops.  The earlier release of repoze.profile 0.2 today had two issues
    (discovered by Zac Bir, thanks Zac!).</p>

<ul>
   <li>It didn't work properly under Python 2.5 due to a difference in the way the Python 2.5 <code>pstats</code> module works</li>
   <li>It didn't explicitly depend on <code>ElementTree</code>, which its templates require (but the templating package is not a setuptools package, so cannot name its own dependencies).</li>
</ul>

<p>
If you tried it and it didn't work, try it again.
</p>

<p>
<code>easy_install -i http://dist.repoze.org/simple repoze.profile</code>
</p>

<p>
Or if you've already got it installed..
</p>

<p>
<code>easy_install -i http://dist.repoze.org/simple -U repoze.profile</code>
</p>

<p>- Chris</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 20 Feb 2008 23:46 GMT</pubDate>
</item>
<item>
   <title>repoze.profile 0.2 Released</title>
   <guid isPermaLink="false">repozeprofile-0_2-released</guid>
   <link>http://blog.repoze.org/repozeprofile-0_2-released.html</link>
   <description><![CDATA[

<p> A couple weeks ago, Tres quietly created and released a useful
piece of middleware called <a
href="http://svn.repoze.org/repoze.profile/trunk">repoze.profile</a>.
This middleware sits in the WSGI pipeline and performs aggregate
Python profiling across all requests to the application(s) on its
"right hand side".  Ian had some profiling middleware in Paste, but it
performed profiling of a single request only.</p>

<p>Version 0.2 adds a (butt-ugly-and-utterly-ripped-off-from-Zope)
browser UI that allows you to sort and filter profiling results.  It
looks like the image below.</p>

<p><img src="http://static.repoze.org/repozeprofileui.png"/></p>

<p>To get it, do <code>easy_install -i http://dist.repoze.org/simple
repoze.profile</code>, then wire it up in your WSGI pipeline.  For
example:</p>

<pre>
 [pipeline:main]
 pipeline = egg:repoze.profile#profile
            egg:Paste#cgitb
            egg:Paste#httpexceptions
            myapp
</pre>

<p>You should then be able to visit <code>/__profile__</code> in your
browser while talking to your WSGI application to see the profile UI.
Note that the middleware (by default) discards the first request info,
so you will need to hit your application a few times to see meaningful
profile info.</p>

<p>See the <a
href="http://svn.repoze.org/repoze.profile/trunk/README.txt">README</a>
for more detailed configuration information.</p>

<p> - Chris </p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 20 Feb 2008 16:25 GMT</pubDate>
</item>
<item>
   <title>Plone Sitetheming Part 2: Why and What</title>
   <guid isPermaLink="false">what-sitetheming-2-20080218</guid>
   <link>http://blog.repoze.org/what-sitetheming-2-20080218.html</link>
   <description><![CDATA[

<p>Applying a high-quality design to Plone is more of a programming
task than it should be.  This proposal isolates the pure
look-and-feel, site-global part into something called a "sitetheme"
that tailors a radically simpler, re-usable facility for corporate
ID.</p>

<h2>Motivations</h2>

<p>Why pursue this facility? Who is it aimed at and what issues do
they have with the status quo?</p>

<p>In a nutshell, this proposal wants to make it radically simpler to
brand Plone.  The designer's "sitetheming" job will focus on saving
HTML to disk. No templating, with weird macro decomposition and API
calls.  No resource registries.  No buildout.  No restart.</p>

<ol>

<li>People that produce high-quality designs won't want to learn Plone
  templating.  Imagine if their HTML (and skills therein) was used,
  untouched.</li>

<li>Reducing the amount of "unique-to-Plone" stuff that is important
to getting started can help reduce fear-of-the-unknown and learning
curve.</li>

<li>Sometimes this design already exists and doesn't need to be
  "compiled" into ZPT/packages.</li>

<li>Web designers probably don't want to run a Plone install to
  maintain the the branding.</li>

<li>Theme resources, such as CSS and JS, will be served from the HTTP
  server directly.</li>

<li>Focusing Plone on the semantic information unique to a single
  resource/URL will promote other goals such as integration.</li>

<li>It is possible that performance improves, if less is done in ZPT
and Zope.</li>

<li>If Plone moves to a more Python-friendly (WSGI) philosophy, then
  theming non-Plone sites with the same artifacts is a benefit.</li>

</ol>

<p>Again, just to be clear: the single biggest goal is to be kind to
civilians.</p>

<h2>Sitetheming in a nutshell</h2>

<p>First, a point about nomenclature.  Since theming was introduced as
a Plone word that covers skinning, templating, and (to a degree)
programming, this proposal temporarily chooses a new word.  We will
call this new facility "sitetheming" to disambiguate jargon skew.
Perhaps at the end, we'll just call this "theming".</p>

<p>Most pages in a site share lots of common elements.  Logo, site
menu links, footer, links to CSS and JS, etc. This is usually referred
to "branding", "look-and-feel", or "corporate identity". On larger
projects, the people managing the branding have little desire to learn
a new system.  On smaller projects, with people just learning, they
haven't mastered enough yet to make the pages "their own".</p>

<p>Sitetheming is a facility for imposing a common look-and-feel on
most site pages using no templating.  Instead, the designer or
customizer maintains a pile of HTML/CSS/JS/PNG artifacts at some
reachable location.  The HTML is then used as an "overlay" on the
content coming out of the site.</p>

<p>More specifically:</p>

<ol>

<li>Save some HTML and other stuff.</li>

<li>Make a rule file that defines spots in the theme that need to be
replaced.  For example, the big block in the middle column.</li>

<li>Later, as content is being served, blocks are pulled out of the
content and merged into the theme.</li>

</ol>

<p>This diagram shows the basic idea:</p>

<p><img src="http://static.repoze.org/deliverancediagram.png" width="374" height="416"/></p>

<p>In this approach, HTML is the API.  As long as the theme continues
providing elements with the correct ID or class names, and as long as
the content coming in has a stable "REST API" of markup structure, the
rule file can do its job.</p>

<h2>Next</h2>

<p>That covers that background and basic information.  Next posts will
dive into how it will actually work, plus what is needed for Plone to
evaluate it as a way of doing branding.</p>

<p> - Paul</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 18 Feb 2008 20:29 GMT</pubDate>
</item>
<item>
   <title>Plone Sitetheming Part 1: Why Not</title>
   <guid isPermaLink="false">why-sitetheming-1-20080214</guid>
   <link>http://blog.repoze.org/why-sitetheming-1-20080214.html</link>
   <description><![CDATA[

<p>At the Plone Strategic Planning Summit, I signed up for work on <a
href="http://dev.plone.org/plone/ticket/7852">Promote Deliverance as
the branding/"corporate ID" mechanism</a>. In the next series of blog
posts, I'll try to cover the why, the what, and the how. Before
beginning, though, I'd like to be up-front about some of the "why not
to go in this direction."</p>

<p>This ticket is about putting a site's common look-and-feel on each
page. For the moment, I'll call this step "sitetheming".  Should we
have a special, simple facility for just this audience (integrators,
entry-level Plone customizers) and activity?</p>

<p>However, not all will agree on the basic premise, so I'd like to
anticipate some of these concerns up-front. If any of this sounds like
you, please speak up during this process. The goal is to make
something uniquely useful and simple for the non-core-developer
audience. We certainly don't want to do something that you won't
like!</p>

<p>(If you simply must read more about site themes, here is <a
href="http://wiki.zope.org/zope3/SiteThemes">a writeup</a> I made long
ago on the Zope wiki and here is the <a
href="http://www.openplans.org/projects/deliverance/project-home">introduction
to Deliverance</a>. Alternatively, wait until my next few posts.)</p>

<h2>Why Not</h2>

<ol>

<li><em>Plone 2.5 and/or Plone 3.0 is easy enough to theme</em>. Falls
into the "ain't broke, don't fix it" category.  My sense is that
"theming is hard" is a common complaint by the target audience, but
perhaps I'm mis-reading the tea leaves.</li>

<li><em>It's hard, but worth it.</em> Currently,
theming/skinning/templating/programming are all part of the same
facility. This lets you do just about anything.  Creating an isolated,
stripped-down "theme engine" thus breaks that proposition.</li>

<li><em>I'm both the developer and the UI person.</em> If you're
mostly a developer who also does the UI, you might not want to learn a
new facility, as you're still going to be the person doing the page
content generation.</li>

<li><em>People will invariably stray over the line.</em> We always
encourage a clear line between presentation and content.  However, the
moment you have something straddling the line (e.g. the contents of a
calenar portlet), that discipline feels restraining.</li>

<li><em>I'll never have non-Plone.</em> As part of this proposal, we'd
like to encourage moving stuff out the Zope stack, allowing it to be
applied across other Python stuff. However, that might not be your
itch.  Having a corporate ID that could be used with other Plone apps,
or potentitally non-Plone apps, might not be a meaningful upside for
you.</li>

<li><em>Plone needs to stop changing.</em> Integrators, and even some
core Plone folks, are feeling bumfuzzled by all the machinery
changes. They've reached their absorption limit. Thus, it wouldn't
matter if there <em>was</em> a problem, nor if this was a good
solution.  It's a new way to do old stuff, and that's bad on the face
of it.</li>

</ol>

<p>That's some of what I'm hearing so far.  Before we get into the
details of what's on the table, who should care, and even how we can
minimize these points, I want to make sure I'm listening to the
integrators and entry folks. Any other concerns about this proposal in
particular, or the strategic planning summit in general?</p>

<p> - Paul </p>



]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 18 Feb 2008 18:58 GMT</pubDate>
</item>
<item>
   <title>Repoze Talk at the Seattle Plone Gathering, February 12th</title>
   <guid isPermaLink="false">seattle_plone_gathering-20080212</guid>
   <link>http://blog.repoze.org/seattle_plone_gathering-20080212.html</link>
   <description><![CDATA[
<p> Chris McDonough will be making a presentation on Repoze to the
    <a href="http://www.seattleplone.org">Seattle Plone Gathering</a> this
    <a href="http://www.seattleplone.org/Members/andrewb/developing-with-repoze-seattle-plone"
    >Tuesday, February 12th, starting at 6:00 PM</a>.  Thanks very much
    to Andrew Burkhalter for organizing the event, and especially to
    Ned Schumann at Olympus.net and Veda Williams, who have sponsored the
    travel costs. </p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 11 Feb 2008 02:25 GMT</pubDate>
</item>
<item>
   <title>Package Updates, Carlos de la Guardia Updates Tutorials</title>
   <guid isPermaLink="false">carlos-updates-tutorials-20080206</guid>
   <link>http://blog.repoze.org/carlos-updates-tutorials-20080206.html</link>
   <description><![CDATA[

<p> New releases of repoze.plone (0.2.7), repoze.zope2 (0.3.0),
  repoze.grok (.0.1.5), and repoze.trac (0.3) were put up yesterday.
  The major change to all of them is that we made it easier to install
  these without relying on the "repozeproject" installer wrapper.
  Instead, the preferred installation mechanism is to create a
  virtualenv "by hand".  Their respective README.txt files have the
  new regime documented and Carlos has kindly updated his tutorials on
  getting both <a
  href="http://grok.zope.org/documentation/tutorial/installing-and-setting-up-grok-under-mod-wsgi">Grok</a>
  and <a
  href="http://plone.org/documentation/tutorial/install-plone-3-behind-apache-and-mod_wsgi-using-repoze">Plone</a>
  installed under mod_wsgi to reflect these new changes </p>

<p> The "old" installation procedure (using repozeproject) still works
for the new packages, which is fortunate, as the documented install
procedures on Repoze.org haven't yet been updated to describe the new
installation process.  I'm getting around to it, I swear... ;-) </p>

<p> - Chris </p>



]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 07 Feb 2008 04:25 GMT</pubDate>
</item>
<item>
   <title>Martin Aspeli Gazes into the Crystal Ball...</title>
   <guid isPermaLink="false">aspeli-crystal_ball-200800205</guid>
   <link>http://blog.repoze.org/aspeli-crystal_ball-200800205.html</link>
   <description><![CDATA[
<h4> ... and sees Repoze / Deliverance in Plone's Future </h4>

<p> In a fascinating
    <a href="http://martinaspeli.net/articles/pete-and-andy-try-plone-4"
    >bit of science fiction</a>, Martin Aspeli explores the possible user
    experience of Pete and Andy, the next generation of Plone newbies.
    His tale features both Repoze and Deliverance prominently, as the
    favored means for skinning and deploying Plone. </p>

<p> Martin then <a href="http://martinaspeli.net/articles/is-plone-too-hard"
    >follows up</a> by examining his flight of fancy as a roadmap forward
    for Plone, in particular highlighting the need for better "getting
    started" documentation, as well as careful attention to the usability
    of Plone for the "average" (non-core) developer. </p>

<p><em>Recommended reading.</em></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 05 Feb 2008 05:46 GMT</pubDate>
</item>
<item>
   <title>Continuous Integration via Buildbot</title>
   <guid isPermaLink="false">continuous_integration_via_buildbot-20080214</guid>
   <link>http://blog.repoze.org/continuous_integration_via_buildbot-20080214.html</link>
   <description><![CDATA[
<h4> Or, How I learned to stop worrying ... </h4>

<h5> Rationale </h5>

<p> After running across a portability / build problem with a distutils
    package recently, I realized that the testing we are doing for Repoze
    may not have adequately covered our needs to keep the various Repoze
    components running against all supported platforms (basically, anything
    where packages with "C" extensions can be built easily).</p>

<p> After casting around a bit, I decided to bite the bullet and try out
    <a href="http://buildbot.sourceforge.net">Buildbot</a>, the same tool
    used to run the Zope unit tests.</p>

<h5> Setting Up the Master </h5>

<p> First, I decided to set up the buildbot "master", running on the
    repoze.org server.  This process tracks all pending changes which
    require builds, and doles the builds out to one or more designated
    "buildslaves".</p>
    
<p> Because buildbot runs as one or more long-running
    daemon processes, I decided to create a new account for it, to enforce
    a bit of privilege isolation:</p>

<pre>
  $ sudo /usr/sbin/groupadd buildbot
  $ sudo /usr/sbin/useradd -g buildbot -c "Buildbot" -m -s /bin/bash \
    buildbot
</pre>
 
 Then, I set up the new user's home directory as a
 <a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>.

<pre>
  $ sudo su - buildbot
  $ /usr/bin/virtualenv ~
</pre>

<p> I then installed buildbot and its setuptools-compatible dependencies
    (note that those dependencies aren't spelled out in its
    <code>setup.py</code>, but are document in its <code>INSTALL.txt</code>.</p>

<pre>
  $ bin/easy_install buildbot zope.interface
</pre>

<p> The remaining dependency is <a href="twistedmatrix.org">Twisted</a>,
    which <a href="http://twistedmatrix.com/trac/ticket/1286"
    >can't be installed via <code>easy_install</code></a> (its setup is
    complex, and hasn't yet adapted to the setuptools regime).  So, I
    installed it the old-fashined distutils way:</p>

<pre>
  $ mkdir src
  $ cd src
  $ wget http://tmrc.mit.edu/mirror/twisted/Twisted/2.5/Twisted-2.5.0.tar.bz2
  $ tar xjf Twisted-2.5.0.tar.bz2
  $ cd Twisted-2.5.0
  $ ../../bin/python setup.py install
  ...
</pre>

<p> Now, I could verify that the buildbot application was working:</p>

<pre>
  $ bin/buildbot --version
  Buildbot version: 0.7.6
  Twisted version: 2.5.0
</pre>

<p> I then created and initiailzed the buildbot "master" work area, and
    set up a configuration (lots of iterative tweakage elided here): </p>

<pre>
  $ mkdir -p var/masters/repoze
  $ bin/buildbot create-master var/masters/repoze
  $ cp var/masters/repoze/master.cfg{.sample,}
  $ vim var/masters/repoze/master.cfg
  $ bin/buildbot start var/masters/repoze
</pre>

<h5> Setting up a "buildslave"</h5>

<p> Next, I could work on setting up the first "buildslave":<p>

<pre>
  $ mkdir -p var/slaves/repoze
  $ bin/buildbot create-slave var/slaves/repoze repoze.org:9980 \
    laguna <password>
</pre>

<p> I used the slavename / password which I had created in the
    <code>master.cfg</code> file.  Then, I edited the two "info" files
    identifying me and my host, and then started the buildbot "slave"
    daemon:</p>

<pre>
  $ vim slave/repoze/info/{admin,host}
  $ bin/buildbot start slave/repoze
</pre>

<p> It connected, and I could see it on the
    <a href="http://repoze.org:8010/buildslaves">status page</a>.</p>

<p> Now, I tried a "forced" build, which worked (after more iterative
    tweakage).  The "builder recipe" I'm using does the following whenever
    it is triggered, either manually or when its "change source" notices a
    change:</p>

<ol>
 <li> checks out the branch containing the change
      (e.g., 'repoze.kiss/trunk');</li>

 <li> runs 'bin/python setup.py test' in the checkout.</li>
</ol>

<p> The <a href="http://repoze.org:8010/waterfall">"waterfall"</a> page
    shows the build status.</p>

<p> I then set up another pair of buildslaves, one on my Ubuntu Gutsy laptop
    and one on a Centos4 server, and ensured that the builds worked with
    them.  Carlos de la Guardia has since volunteered an Ubunty Gutsy server,
    which is great, as my laptop may or may not be online when a change
    is triggered.</p>

<h5> Conclusions </h5>

<p> First, the product does what it is designed for:  it handles the complex
    process of dispatching asynchronous builds to the various platforms
    based on changes to the repository.</p>

<p> Second, the configuration format is an <code>execfile</code'ed Python
    file, which I consider a bit <strong>too</strong> powerful:  I would
    prefer a purely declarative configuration language.  Many users, however,
    won't need to write any really imperative code in this file, which
    mitigates the risk somewhat.  I chose to add some code here, rather
    than move it out to an importable module, largely to deal with having
    a single "scheduler" handle changes to any of the supported branches,
    and to arrange that each of those branches build in a separate
    subdirectory.</p>

<p> Third, the code is definitely "frameworky", with lots of base classes
    and policy objects.  It succeeds in hiding a lot of that from the
    user, however, which covers a lot of sins.</p>

<p> Overall, I like it for what it does, and wouldn't hesitate to use it
    in other settings.</p>

<p><cite>Tres.</cite></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 05 Feb 2008 05:46 GMT</pubDate>
</item>
<item>
   <title>Carlos de la Guardia's repoze.grok Tutorial on grok.zope.org</title>
   <guid isPermaLink="false">cguardia-repoze.grok-tutorial-20080130</guid>
   <link>http://blog.repoze.org/cguardia-repoze.grok-tutorial-20080130.html</link>
   <description><![CDATA[
<p> Carlos has written an excellent tutorial on running a Grok application
    under repoze.grok and mod_wsgi.
    <a href="http://grok.zope.org/documentation/tutorial/installing-and-setting-up-grok-under-mod-wsgi">Check it out!</a></p>

<p> <em>(Update, 2/4)</em> Carlos <a href="http://blog.delaguardia.com.mx/"
    >blogs</a> about this tutorial, along with
    <a href="http://plone.org/documentation/tutorial/install-plone-3-behind-apache-and-mod_wsgi-using-repoze">another about running Plone 3</a>
    behind Apache and mod_wsgi using Repoze.</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 30 Jan 2008 05:00 GMT</pubDate>
</item>
<item>
   <title>Video of PyATL Talk Online</title>
   <guid isPermaLink="false">pyatl-video-20071223</guid>
   <link>http://blog.repoze.org/pyatl-video-20071223.html</link>
   <description><![CDATA[
<p>We just got word from Noah Gift that he has gotten the video of
   the first 25 minutes or so of our <a href="http://pyatl.org/">PyATL</a>
   talk about <code>repoze.zope2</code>.  The video is just "talking heads"
   (you can't see slides, or anything), but cool nevertheless.</p>
   
<p>Relevant links:</p>

<ul>
 <li><a href="http://pyatl.org/presentations">PyATL Video</a></li>
 <li><a href="http://static.repoze.org/pyatl-slides.pdf">Slides</a></li>
 <li><a href="http://www.oreillynet.com/onlamp/blog/2007/12/wsgi_python_web_developments_h_1.html">Noah's post on WSGI as "Howard Roark" of Python web
     development</a></li>
 <li>Noah's post on <a href="http://www.oreillynet.com/onlamp/blog/2007/12/repoze_sprint_at_pyatl_aglue_i_1.html">the simplest possible WSGI app</a>
     as developed at the PyATL sprint</li>
</ul>


<p>Many thanks to Noah, Derek Richardson, Brandon Craig Rhodes (who most
   graciously put us up in his own home), and the PyATL and Atlanta Plone
   folks for their hospitality.  Thanks as well to all who helped sponsor
   travel costs, expecially to Mark Kalmes at
   <a href="http://www.ccpgames.com/">CCP</a> /
   <a href="http://www.white-wolf.com/">White Wolf </a> who matched the
   other contributions!</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 28 Dec 2007 17:06 GMT</pubDate>
</item>
<item>
   <title>Adding repoze.tm to a Pylons Application</title>
   <guid isPermaLink="false">repoze.tm_with_pylons-20071218</guid>
   <link>http://blog.repoze.org/repoze.tm_with_pylons-20071218.html</link>
   <description><![CDATA[

<p> After sprinting with the <a href="http://pyatl.org/">PyATL</a>
    folks in Atlanta last week, Chris and I decided to dive into
    the "share Zope stuff with Python web developers" story a little
    more.  We wanted to show that various bits of Zopeish middleware
    might be useful in the context of the other WSGI-enabled web
    frameworks.
</p>

<p> I worked through the
    <a href="http://wiki.pylonshq.com/display/pylonscookbook/Making+a+Pylons+Blog"
    >How to write a basic blog with Pylons</a> tutorial, using
    the <code>sqlite</code> backend for simplicity.  Once done,
    I looked at the code in the application which did manual / explicit
    transaction handline in the controller method for the blog
    add form POST:
</p>

<pre>

    def blog_add_process(self):
        # Create a new Blog object and populate it.
        newpost = model.Blog()
        newpost.date = datetime.datetime.now()
        newpost.content = request.params['content']
        newpost.author = request.params['author']
        newpost.subject = request.params['subject']
        # I didn't set ID because it will get an autoincrement value.
        
        # Attach the object to the session.
        model.Session.save(newpost)

        # Commit the transaction.
        # (This sends the SQL INSERT command due to autoflushing.)
        model.Session.commit()
        redirect_to("/blog")

</pre>

<h3>Using the <code>transaction</code> Framework in the Application</h3>

I decided to knock together a simple "data manager" for this application,
following Chris' <a href="http://repoze.org/tmdemo.html">Transactions
in WSGI</a> tutorial.  The class implements the <code>IDataManager</code>
API, using the ORM session to do the real work:
</p>

<pre>

class DataManager(object):

    transaction_manager = None

    def __init__(self, post):
        self.post = post

    def commit(self, transaction):
        """ See IDataManager.
        """
        model.Session.save(self.post)

    def abort(self, transaction):
        """ See IDataManager.
        """
        model.Session.rollback()

    def tpc_begin(self, transaction):
        """ See IDataManager.
        """

    def tpc_vote(self, transaction):
        """ See IDataManager.
        """

    def tpc_finish(self, transaction):
        """ See IDataManager.
        """
        model.Session.commit()

    def tpc_abort(self, transaction):
        """ See IDataManager.
        """
        model.Session.rollback()

    def sortKey(self):
        """ See IDataManager.
        """
        return 'myblog-sql'

</pre>

<p> I then modified the controller method such that it registers
    an instance of the DataManager class with the transaction.  Note
    the addition of pseudo-validation logic, which triggers an exception
    in order to demonstrate the "auto-rollback" feature of
    <code>repoze.tm</code>:
</p>

<pre>

import transaction
...
    def blog_add_process(self):
        # Create a new Blog object and populate it.
        newpost = model.Blog()
        newpost.date = datetime.datetime.now()
        newpost.content = request.params['content']
        newpost.author = request.params['author']
        newpost.subject = request.params['subject']

        # Register with the global two-phase transaction manager
        dm = DataManager(newpost)
        transaction.get().join(dm)

        # Trigger an error on "invalid" data, to trigger the abort.
        if newpost.subject.startswith('Abort'):
            raise ValueError('Invalid data')

        redirect_to("/blog")

</pre>

<h3>Configuring the Application</h3>

<p>First, I needed to install <code>repoze.tm</code> and its
   dependencies:</p>

<pre>

  $ ../bin/easy_install -i http://dist.repoze.org/simple repoze.tm

</pre>

<p>Then, I needed to wire the <code>repoze.tm</code> middleware into
   the <code>PasteDeploy</code> configuration.  In order to add
   middleware, I renamed the <code>[app:main]<code> section::</p>

<pre>

[app:myblog]
use = egg:MyBlog
# Let pipeline handle errors
full_stack = false
cache_dir = %(here)s/data
beaker.session.key = myblog
beaker.session.secret = somesecret
sqlalchemy.url = sqlite:///%(here)s/db.sqlite
sqlalchemy.convert_unicode = true

</pre>

<p>Note that I turned off the <code>full_stack</code> option, because
   I want errors to propagate out to the middleware, so that it can
   abort the transaction.</p>

<p>I then defined a <code>[pipeline:main]</code> section, adding both
   the transaction middleware and some error handling::</p>

<pre>

[pipeline:main]
pipeline =
           egg:Paste#cgitb
           egg:Paste#httpexceptions
           egg:repoze.tm#tm
           myblog

</pre>

<p>At this point, the application works as desired:</p>

<ul>
 <li> "Normal" posts get added to the table
 <li> "Invalid" posts (those whose subject starts with "Abort"),
       are blocked.</li>
</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 18 Dec 2007 22:36 GMT</pubDate>
</item>
<item>
   <title>Highway Jam:   Faster Application Restart</title>
   <guid isPermaLink="false">highway_jam</guid>
   <link>http://blog.repoze.org/highway_jam.html</link>
   <description><![CDATA[
<p>
   While driving back from North Carolina, Chris McDonough and I spent
   the time talking about ways to make WSGI developers more
   productive.
</p>

<p>
   We discussed, and then discarded, the idea of trying to fix Python's
   reload story:  it seems just too painful and error-prone (like the
   <code>refresh.txt</code> story in Zope).  Instead, we realized that
   making restarting the application go <strong>really</strong> fast would
   be a big win:  this observation was highlighted especially by the
   restart-inducde delays during the demos we did at UNc and CPCC.
</p>

<p>In no particular order, here are the ideas we came up with:</p>

<h4> Python-based </h4>

<ul>
 <li>Move the current profiling support out of Zope-the-application
     and make it middleware, so we can measure the various bits
     more cleanly.  Chris says Ian Bicking has some support already,
     but only for one request at a time.</li>

 <li>
     When doing a "fast" restart, signal first an event which allows
     listeners to dump any global state to a cache on the filesystem;
     then, on restarting, arrange to signal another event which allows
     listeners to reload that state, short-circuiting the whole application
     initialization phase.
 </li>

 <li>
     In development mode, maybe we can trigger the fast restart whenever
     any of
     <code> [getattr(x, '__file__', None) for x in sys.modules.values()]</code>
     changes.  Can we somehow arrange for the triggering request to be
     retried after the restart?  Does it matter?<br />
     
     Hmm, it looks like this is what <code>paste --reloadr</code>
     does already.  Cool. Score that: <strong>NIH, 0;  Ian Rocks!, 1</strong>
 </li>

</ul>

<h4> Zope-related Changes </h4>

<ul>

 <li>
     Maybe find a way to add all parsed ZCML files, to the "watched files"
     list too, so that changing ZCML will automagically restart the
     application.
 </li>

 <li>
     Finish making ZCML parsing side-effect free, so that we can cache
     the action list (to a ".pyc"-like file) across application runs
     (a "pickle file").
 </li>

 <li>
     Removing ZCML-parse-time side-effects implies removing the
     "eager validation / resolution" of dotted names.  Instead, the parser
     would create "deferreds" representing the target objects, which would
     then be resolved / replaced at the point of use.  We would presumably
     be able to serialize the deferreds in the "pickle file" mentioned above.
 </li>

 <li>
     One particularly interesting bit of global state is the set of
     pickles cached by each ZODB connection.  Repopulating those caches
     after a restart is one reason that Plone, for instance, takes so
     long to render the homepage after a restart.  So, check into whether
     it is feasible to dump and reload the pickles maintained by each
     ZODB database connection to disk during a "fast restart".
 </li>

 <li>
     As an alternative to dumping / reloading the ZODB Connection pickles,
     investigate whether multiple connections (or even appserver processes)
     might be able to shart them via a setup using
     <a href="http://danga.com/memcached/">memcached</a>
 </li>

 <li>
     Look into whether we can replace the ZEO disk cache with memcahed.
 </li>

 <li>
     Measure "slow" product initializations, and find ways to speed or
     bypass them on restart (e.g., PlacelessTranslationService).
 </li>

</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 07 Dec 2007 22:52 GMT</pubDate>
</item>
<item>
   <title>Theming Trac with Deliverance</title>
   <guid isPermaLink="false">theming_trac_with_deliverance</guid>
   <link>http://blog.repoze.org/theming_trac_with_deliverance.html</link>
   <description><![CDATA[

<blockquote>
<em>Click the screenshot images below to see them without scaling.</em>
</blockquote>

<p><a target="blank" href="http://static.repoze.org/secoora-theme.png"
   ><img width="50%" height="50%" align="right"
        src="http://static.repoze.org/secoora-theme.png" /></a>
   While in North Carolina to present Repoze to Zope and Python user
   groups, we worked with our host, Chris Calloway, to help wrap his
   trac instances within the theming and branding of his project site.</p>

<p>Chris supports <a href="http://secoora.org/">SECOORA</a>, a regional
   marine science collaboration, and needed a way to share branding
   for the <a href="http://trac.edgewall.org">Trac</a> instances he
   maintains for the various SECOORA software projects.</p>

<h3>Installing Trac as a WSGI app</h3>

<p>We first worked out how to make Trac installable under Paste.  Chris
   McDonough figured out how to get Trac installed via
   <code>repoze.project</code>, using a new dependency package,
   <code>repoze.trac</code>:</p>

<pre>
$ bin/repozeproject --path=/tmp/trac repoze.trac
</pre>

<h3>Paste configuration</h3>

<p>The standard Paste configuration that <code>repoze.trac</code> sets up
   looks like so:</p>

<pre>
$ cat etc/paste.ini
[app:trac]
paste.app_factory = repoze.trac:make_trac
path = %(here)s/../var

[pipeline:main]
pipeline = egg:Paste#cgitb
           demo
</pre>

<h3>Setting up the Trac Instance</h3>

<p>Before starting the server, we need to initialize the Trac
   instance in the <code>var</code> directory:</p>

<pre>
$ bin/trac-admin var initenv
...
</pre>

<p><a target="blank" href="http://static.repoze.org/trac-unthemed.png"
      ><img width="50%" height="50%" align="right"
        src="http://static.repoze.org/trac-unthemed.png" /></a></p>

<h3>Running Trac under Paste</h3>

<p>Now we can start the server:</p>

<pre>
$ bin/paster serve etc/paste.ini
</pre>

<p>And view the Trac homepage.
        </p>

<h3>Adding Deliverance to the Mix</h3>

<p>First, install Deliverance:</p>

<pre>
$ bin/easy_install Deliverance
...
</pre>

<p>Then add a minimal rules file defining how Deliverance will
   merge the application into the theme:
</p>

<pre>
$ cat /etc/minimal_rules.xml
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;rules xmlns="http://www.plone.org/deliverance" &gt;
  &lt;prepend theme="//head" content="//head/link" nocontent="ignore" /&gt; 
  &lt;prepend theme="//head" content="//head/style" nocontent="ignore" /&gt; 
  &lt;append theme="//head" content="//head/script" nocontent="ignore" /&gt;    
  &lt;append theme="//head" content="//head/meta" nocontent="ignore" /&gt;
  &lt;copy theme="//table[@id='portal-columns']"
      content="//div[@id='content']" /&gt;
&lt;/rules&gt;
</pre>

<p> <a target="blank" href="http://static.repoze.org/trac-minimal.png"
      ><img width="50%" height="50%" align="right"
        src="http://static.repoze.org/trac-minimal.png" /></a>
    And configure Deliverance into the pipeline, using those rules:</p>

<pre>
$ cat /etc/paste.ini
...
[filter:deliverance]
paste.filter_app_factory = deliverance.wsgimiddleware:make_filter
theme_uri = http://secoora.org/
rule_uri = file:///%(here)s/minimal_rules.xml
...
[pipeline:main]
pipeline = egg:Paste#cgitb
           deliverance
           trac
</pre>


<h3>Making Trac's Nav Fit into the Theme</h3>

<p>
   As you can see, the minimal site does not expose any of the standard
   Trac navigation links:  instead, its navigation is thet from the
   theme (a Plone site).  We modified the rules file to merge the Trac
   links into the theme, along with the search form. </p>

<pre>
$ cat /etc/trac_rules.xml
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;rules xmlns="http://www.plone.org/deliverance" &gt;
  &lt;prepend theme="//head" content="//head/link" nocontent="ignore" /&gt; 
  &lt;prepend theme="//head" content="//head/style" nocontent="ignore" /&gt; 
  &lt;append theme="//head" content="//head/script" nocontent="ignore" /&gt;    
  &lt;append theme="//head" content="//head/meta" nocontent="ignore" /&gt;
  &lt;drop theme="//ul[@id='portal-siteactions']" /&gt;
  &lt;append-or-replace theme="//head" content="//head/title" nocontent="ignore" /&gt;
  &lt;replace theme="//form[@name='searchform']" content="//form[@id='search']" /&gt;
  &lt;copy theme="//ul[@id='portal-globalnav']"
           content="//div[@id='ctxtnav']/ul/*" nocontent="ignore" /&gt;
  &lt;copy theme="//ul[@id='portal-personaltools']"
           content="//div[@id='mainnav']/ul/*" /&gt;
  &lt;append theme="//ul[@id='portal-personaltools']"
           content="//div[@id='metanav']/ul/*" /&gt;
  &lt;drop theme="//div[@id='portal-breadcrumbs']" /&gt;
  &lt;copy theme="//table[@id='portal-columns']"
      content="//div[@id='content']" /&gt;
&lt;/rules&gt;
</pre>

<p><a target="blank" href="http://static.repoze.org/trac-themed.png"
      ><img width="50%" height="50%" align="right"
        src="http://static.repoze.org/trac-themed.png" /></a>
    We then swtich the Deliverance Paste configuration to use the new
    rules.</p>

<pre>
$ cat /etc/paste.ini
...
[filter:deliverance]
paste.filter_app_factory = deliverance.wsgimiddleware:make_filter
theme_uri = http://secoora.org/
rule_uri = file:///%(here)s/trac_rules.xml
</pre>

<p>Now, we see the fully-themed site.  Notice that:</p>

<ul>
 <li>The "tabs" in the Plone theme are now the "global" navigation
     links from the Trac application.</li>
 <li>The "personal tools" in the theme now contains the "main" and "meta"
     nav links from Trac.</li>
 <li>The search form is now the Trac version</li>
 <li>the Plone "breadcrumbs" are gone. </li>
</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 06 Dec 2007 16:31 GMT</pubDate>
</item>
<item>
   <title>Dueling Banjos:  Two Repoze Presentations Tonight</title>
   <guid isPermaLink="false">dueling_banjos-20071204</guid>
   <link>http://blog.repoze.org/dueling_banjos-20071204.html</link>
   <description><![CDATA[
<p>Repoze fans have two chances to hear about Repoze, Deliverance
   wnd WSGI this evening:</p>

<ul>

  <li> Paul Everitt will be presenting a talk on ""
       to the <a href="http://zpug.org/">D.C. Zope / Python Users'
       Group</a>, meeting at the <a
       href="http://zpugdc.org/meetings/mtg58">TNC Boardroom</a>
       at 7:00 PM</li>

  <li> Chris McDonough and Tres Seaver are presenting a talk,
       "Plumbing Zope through WSGI", to the <a
       href="http://trizpug.org">Triangle Zope / Plone Users' Group</a>
       in Chapel Hill, North Caroline, meeting on the UNC campus,
       Chapman 435, at 7:00.</li>

</ul>

<p> Tres and Chris will recap the same talk tomorrow for the
    <a href="http://groups.google.com/group/charpy">Charlotte
    Python Users' Group</a> in Charlotte, North Carolina.</p>

<p> We hope to see as many of you as possible at one of the talks!</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 04 Dec 2007 20:41 GMT</pubDate>
</item>
<item>
   <title>Upcoming Repoze User Group Talks</title>
   <guid isPermaLink="false">december_usergroups</guid>
   <link>http://blog.repoze.org/december_usergroups.html</link>
   <description><![CDATA[
<p>We have beein invited to present Repoze at several Python / Zope / Plone
   user group meetings in December:</p>

<ul>

 <li>Paul Everitt is presenting a talk on
     <a href="http://www.openplans.org/projects/deliverance/project-home"
     >Deliverance</a> and Repoze to the <a href="http://zpug.org"
     >D.C. ZPUG group</a> on December 4th.</li>

 <li>Chris McDonough and Tres Seaver will be doing back-to-back presentations
     on Repoze to the <a href="http://trizpug.org">Triangle ZPUG</a>, on
     December 4th, and to the
     <a href="http://groups.google.com/group/charpy">Charlotte Python
     Group</a> on December 5th.  It looks as though we will be able to
     do some sprinting on the day of the 5th, as well.</li>

 <li>Chris and Tres have also been invited to present Repoze to the
     <a href="http://python.meetup.com/46/calendar/6705977/">Atlanta
     Python Meetup</a>.  We will be sprinting with several members of that
     group and te <a href="http://atlantaplone.org/">Atlanta Plone Group</a>
     on Friday the 14th somewhere on the Georgia Tech camplus.</li>

</ul>

<p>Thanks to the groups for the invitations!  We are really excited to have
   the chance to talk about Repoze.</a></p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 20 Nov 2007 19:47 GMT</pubDate>
</item>
<item>
   <title>0.2.8 Release of repoze.zope2</title>
   <guid isPermaLink="false">releases-20071120</guid>
   <link>http://blog.repoze.org/releases-20071120.html</link>
   <description><![CDATA[
<p>A new releases of repoze.zope2, 0.2.8, is available. This release fixes some minor redirect bugs when adding content via Zope's ZMI.</p>

<p><a href="http://dist.repoze.org/repoze.zope2-0.2.8.tar.gz"
      >repoze.zope2 0.2.8</a>
</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 20 Nov 2007 19:46 GMT</pubDate>
</item>
<item>
   <title>Integrating Transactions into WSGI Applications Using repoze.tm</title>
   <guid isPermaLink="false">tmdemo-20071107</guid>
   <link>http://blog.repoze.org/tmdemo-20071107.html</link>
   <description><![CDATA[

<p> We've created a <a
href="http://repoze.org/tmdemo.html">tutorial</a> about integrating
transactions into WSGI applications using <a
href="http://dist.repoze.org/simple/repoze.tm/">repoze.tm</a>.
repoze.tm is a transaction manager implemented as WSGI middleware that
uses the ZODB transaction machinery.  It can be used independently of
ZODB or Zope. </p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 07 Nov 2007 18:17 GMT</pubDate>
</item>
<item>
   <title>"Developing With repoze.zope2"</title>
   <guid isPermaLink="false">devwrepoze-zope2-pdf</guid>
   <link>http://blog.repoze.org/devwrepoze-zope2-pdf.html</link>
   <description><![CDATA[

<div>
<p> We've just created and released <a href="http://static.repoze.org/misc/developingwithrepoze-zope2.pdf">Developing With repoze.zope2</a> which is a short 10-page PDF that explains the benefits of and differences between developing Zope 2 applications using Repoze and "stock" Zope 2.  It might be helpful to folks developing under Plone and CMF.  If you have comments or questions about it, please <a href="mailto:chrism@plope.com">contact me</a> or send a message to the <a href="mailto:repoze-dev@lists.repoze.org">mailing list</a>.
</p>
<p>
Note also that I'll be <a href="http://zpugdc.org/meetings/mtg57">introducing Repoze</a> at the Washington DC Zope and Python User's Group tonight at 7:00pm, see the meeting description for more info.
</p>
</div>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 06 Nov 2007 16:39 GMT</pubDate>
</item>
<item>
   <title>repoze.zope2 0.2.6 and repoze.plone 0.2.6 Released</title>
   <guid isPermaLink="false">026_released</guid>
   <link>http://blog.repoze.org/026_released.html</link>
   <description><![CDATA[

<p> We've just released repoze.zope2 0.2.6
which has the following new features:

<ul>

<li>WebDAV support (repoze has not supported Zope's webdav until
now)</li>

<li>An error log view which can be accessed at
<code>/__error_log__</code> (the Zope error_log object does not
function under repoze.</li>
</ul>
</p>

<p>repoze.plone 0.2.6 is just a dependency release</p>

<p> If you don't already have repoze.zope2 or repoze.plone installed,
you can get started at <a href="http://repoze.org/quickstart.html">the
Quickstart page</a>.  If you already have them installed, you should
be able to get the latest revisions by doing <code>easy_install -i
http://dist.repoze.org/simple -U repoze.zope2</code> or
<code>easy_install -i http://dist.repoze.org/simple -U
repoze.plone</code>, respectively.  </p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 02 Nov 2007 21:24 GMT</pubDate>
</item>
<item>
   <title>Mike Naberezny Posts About Repoze</title>
   <guid isPermaLink="false">mikenaberezny-20071102</guid>
   <link>http://blog.repoze.org/mikenaberezny-20071102.html</link>
   <description><![CDATA[

<p> Mike Naberezny, who runs <a
href="http://www.maintainable.com">Maintainable Software</a>, <a
href="http://mikenaberezny.com/archives/83">posts about Repoze on his
blog</a>. Maintainable Software designed the Repoze website and is a
vendor and customer for Agendaless.  Mike writes production software
in all of PHP, Rails, Python, TCL and JavaScript on a regular basis (I
kid you not).  </p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 02 Nov 2007 19:06 GMT</pubDate>
</item>
<item>
   <title>In the Fitting Room:  Trying on WSGI Servers</title>
   <guid isPermaLink="false">fitting_room-20071029</guid>
   <link>http://blog.repoze.org/fitting_room-20071029.html</link>
   <description><![CDATA[
<p>There's a funny rumor going around that somehow repoze is tied in
   some way to the <a href="http://svn.zope.org/Zope/trunk/lib/python/ZServer/"
   >ZServer</a> implementation in Zope2 (or maybe its the somewhat equivalent
   <a href="http://svn.zope.org/zope.server">zope.server</a> implementation
   in Zope3.</p>

<p> Nothing could be farther from the truth:  one of the driving goals
    for repoze is to allow interoperation with any
    <a href="http://www.wsgi.org/wsgi/servers">WSGI-conformant server
    implementation</a>, as well as conforming middleware.  In particular, we
    wanted to take advantage of Graham Dumpleton's
    <a href="http://code.google.com/p/mod_wsgi">mod_wsgi</a>, as well as
    the servers provided by other Python web frameworks such as the
    <a href="http://www.cherrypy.org/browser/trunk/cherrypy/wsgiserver">CherryPy
    server</a>.  In fact, this site consists of multiple WSGI applications
    running under <code>mod_wsgi</code>, as a proof of the concept.
</p>

<h2> Kicking the Tires </h2>

<p> Back before we had actually released anything, We did some
    preliminary benchmarking of the various WSGI servers available.</p>


<h3> Benchmark <code>paste.ini</code> File </h3>

<pre>
[DEFAULT]
debug = True

[app:test]
use = egg:Paste#test

[server:paste]
use = egg:Paste#http
host = 127.0.0.1
port = 8080

[server:wsgiutils]
use = egg:PasteScript#wsgiutils
host = 127.0.0.1
port = 8080

[server:zserver]
use = egg:repoze.zope2#zserver
host = 127.0.0.1
port = 8080

[server:cherrypy]
use = egg:Paste#cherrypy
host = 127.0.0.1
port = 8080
</pre>

<h3> Twisted Starter Script </h3>

<pre>
# Twisted.web2 WSGI application setup
from twisted.application import service
from twisted.application import strports
from twisted.internet import reactor
from twisted.web2 import channel
from twisted.web2 import server
from twisted.web2 import wsgi
from twisted.web2.channel import http

from paste.deploy import loadapp

my_app = loadapp('config:/home/tseaver/tmp/repoze-twisted/etc/zope2.ini',
                 'zope')
resource = wsgi.WSGIResource(my_app)
site = server.Site(resource)
application = service.Application('web')
service = strports.service('tcp:8080', channel.HTTPFactory(site))
service.setServiceParent(application)
</pre>

<h3> Best-Case Test</h3>

<p>On my box, I get the following:</p>

<table>
 <tr><td>Twisted.Web2</td>     <td align="right">  ~700 req/s</td></tr>
 <tr><td>wsgiutils</td>        <td align="right">  ~900 req/s</td></tr>
 <tr><td>paste</td>            <td align="right"> ~1500 req/s</td></tr>
 <tr><td>zope.server</td>      <td align="right"> ~1500 req/s</td></tr>
 <tr><td>cherrypy</td>         <td align="right"> ~2200 req/s</td></tr>
</table>

<p>I ran the twisted server with the attached server descriptor:</p>

<pre>
  $ bin/twistd -ny bin/twisty.py
</pre>

<p>The others I ran under paster:</p>

<pre>
  $ bin/paster --server-name=<name> --app-name test etc/zope2.ini
</pre>

<p>The endpoint in each case is egg:Paste#test (I wanted 'pony', but Chris
   talked me out of it).</p>

<h3>Zope Quickstart</h3>

<p> Running against the Zope quickstart page (editing the name in
    'twisty.py', switching --app-name to 'zope'):</p>

<table>
  <tr><td>Twisted.Web2</td>     <td align="right">~160 req/s</td></tr>
  <tr><td>wsgiutils</td>        <td align="right">~165 req/s</td></tr>
  <tr><td>paste</td>            <td align="right">~220 req/s</td></tr>
  <tr><td>zope.server</td>      <td align="right"> ~225 req/s</td></tr>
  <tr><td>cherrypy</td>         <td align="right">~240 req/s</td></tr>
</table>

<p>Tests run against all settings via:</p>

<pre>
  $ ab -n 1000 -c 10 http://localhost:8080/
</pre>

<h3> References </h3>

<p> The original mailing list thread where we tried this stuff out: </p>

<ul>
 <li><a href="http://lists.repoze.org/pipermail/repoze-dev/2007-September/000487.html"
     >http://lists.repoze.org/pipermail/repoze-dev/2007-September/000487.html</li>
</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 29 Oct 2007 19:26 GMT</pubDate>
</item>
<item>
   <title>Repoze Presentation at ZPUG-DC November 6, 2007</title>
   <guid isPermaLink="false">zpug-dc-nov-6-20071028</guid>
   <link>http://blog.repoze.org/zpug-dc-nov-6-20071028.html</link>
   <description><![CDATA[

<p>I (Chris McDonough) will be presenting an introduction to Repoze at
a meeting of the Washington DC Zope and Python User's Group on
Tuesday, November 6 2007 in the 
<a href="http://zpugdc.org/meetings/where/rfa">Radio Free Asia boardroom</a> .  Sadly this is also
election day.  If you should need to choose between coming to see this
presentation or voting, you should vote instead. ;-) </p>

<p>For more information, see <a
href="http://zpugdc.org/meetings/mtg57">the ZPUG DC announcement.</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sun, 28 Oct 2007 15:45 GMT</pubDate>
</item>
<item>
   <title>Martin Aspeli Cheers On Repoze</title>
   <guid isPermaLink="false">optilude-cheers-20071027</guid>
   <link>http://blog.repoze.org/optilude-cheers-20071027.html</link>
   <description><![CDATA[
<p> Martin Aspeli, better known in Ploneland as "optilude", has a new
    <a href="http://martinaspeli.net/articles/repoze-rocks">blog post up</a>
    which is <strong>really</strong> favorable to Repoze.  Check it out! </p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sun, 28 Oct 2007 02:38 GMT</pubDate>
</item>
<item>
   <title>repoze.zope2 0.2.5 and repoze.plone 0.2.5 Released</title>
   <guid isPermaLink="false">repoze-zope2-and-plone-0.2.5-released-20071027</guid>
   <link>http://blog.repoze.org/repoze-zope2-and-plone-0.2.5-released-20071027.html</link>
   <description><![CDATA[
<p>Plone's Kupu and KSS Javascript wasn't working up to 0.2.5, now it is.  You can update to the newest release by doing (in your sandbox):</p>

<pre>
$ bin/easy_install -U repoze.zope2
</pre>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sat, 27 Oct 2007 16:47 GMT</pubDate>
</item>
<item>
   <title>Screencast 1: Installing Repoze</title>
   <guid isPermaLink="false">installing-repoze-screencast-20071025</guid>
   <link>http://blog.repoze.org/installing-repoze-screencast-20071025.html</link>
   <description><![CDATA[
<p>Want to watch how to get started with Repoze? 7.5 Mb, 3m33s of viewing, and a 
fairly recent QuickTime installation is all you need for 
<a href="http://static.repoze.org/movies/installingrepoze.mov" target="_new">Screencast 1: 
Installing Repoze</a>.</p>

<p>This screencast shows:</p>

<ul>

<li>Snipping the right commands from the Repoze site</li>

<li>Using <code>easy_install</code> to get a <code>repozeproject</code> script</li>

<li>Running <code>repozeproject</code> to produce a Paste-driven, WSGI/virtualenv Zope2/Plone
install. <em>(To paraphrase <a href="http://imdb.com/title/tt0372588/">Team America</a>, <a
href="http://www.youtube.com/watch?v=O3ZuNBUBmcM">Hell Yeh!</a>.)</em></li>

<li>Using the <em>easy_install</em> in your virtual Python to add <a href="http://www.openplans.org/projects/deliverance">Deliverance</a>.</li>

</ul>

<p>Notes and caveats:</p>

<ul>

<li>Sure, I should write a bit more material on this. I plan to, honest. I know some folks (see
Geir, I'm listening to you!) prefer reading and static images to movies. I'd like to produce a
guide that combines both. But no need to hold this up until perfection arrives.</li>

<li>Not a lot of titling. I decided to try dumping Camtasia Studio, which meant authoring on
Windows. Instead, I used a Mac toolchain: iShowU -> iMovie 08. Let's just say the Steve giveth
and the Steve taketh away. Perhaps I'll brush things up later.</li>

<li>My plan is to have a series of screencasts (and text) that show how to really-really move
theming out of Plone and into Deliverance. Not just replace what Plone does, but instead, make
a Plone skin that doesn't do it in the first place.</li>

</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 25 Oct 2007 14:47 GMT</pubDate>
</item>
<item>
   <title>Screencast Two: Setting Up Deliverance</title>
   <guid isPermaLink="false">setting-up-deliverance-screencast-20071025</guid>
   <link>http://blog.repoze.org/setting-up-deliverance-screencast-20071025.html</link>
   <description><![CDATA[
<p>Want to theme Plone without learning the stack?  Want to use an existing HTML 
look-and-feel, without touching it, to give the basic style to your content...Plone or 
otherwise?</p>

<p><a href="http://static.repoze.org/movies/setupdeliverance.mov">Screencast 2: Setting Up
Deliverance</a> shows you how to use WSGI middleware and boring old web standards to theme your
content. (3.6 Mb, 3m18s duration, Quicktime 7-ish.)  This demo shows:</p>

<ul>

<li>Inspecting the theme and the content for merge points</li>

<li>Editing the Paste config file to insert the WSGI middleware (Deliverance). One word plus 3
lines of change!</li>

<li>Writing a simple rules file to merge the Plone content into the theme.</li>

<li>Restarting the server and seeing your newly-themed site.</li>

</ul>

<p>I have waited a long, long time to be able to give this screencast. Years ago, in the
original Zope 3 wiki, I wrote a proposal for <a
href="http://wiki.zope.org/zope3/SiteThemes">Zope Site Themes</a>. I worked on a couple of
mod_python implementations. Then Ian and Luke at OpenPlans picked up the idea and converted it
from a useless toy into a real-deal software package as WSGI middleware.</p>

<p>Unfortunately there was always a piece missing. If you wanted to do Plone, you wanted to do
Zope2. And that <em>mostly</em> meant no WSGI. Ian had a publisher hack you could use, but it
wasn't really a mainstream option. And not everyone would be willing to roll up their sleeves
and get mod_python going.</p>

<p>With Repoze, Chris and Tres have now made all of this not just possible, but probable.</p>

<p>As an example, we spent money on a <a
href="http://repoze.maintainable.com/index.html">theme</a> produced by some cools guys to the
west of here. They delivered HTML, CSS, etc., just as the Deliverance theory anticipates.
Instead of hacking into a ZPT with macros/slots, we used it as-is, fronting:</p>

<ul>

<li>www.repoze.org, a WSGI app that converts STX on the filesystem on-the-fly using a
Zope-publisher-like thing</li>

<li>blog.repoze.org, running pyblosxom</li>

<li>bugs.repoze.org, running Roundup</li>

<li>And soon, demo.repoze.org (a Plone) and lists.repoze.org (Mailman) will get themed</li>

</ul>

<p>All of these use exactly the same, untouched HTML/CSS/JS/PNG for the theme. It took Tres
around 20 minutes to "theme" Roundup...without touching Roundup either!</p>

<p>Me likey.</p>
]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Thu, 25 Oct 2007 14:47 GMT</pubDate>
</item>
<item>
   <title>Announcement: repoze.tempita 0.2 Released</title>
   <guid isPermaLink="false">repoze.tempita-initial-20071024</guid>
   <link>http://blog.repoze.org/repoze.tempita-initial-20071024.html</link>
   <description><![CDATA[
<p> repoze.tempita is a very early cut at creating a middleware filter
    which causes <a href="http://pythonpaste.org/tempita/">Tempita</a>
    syntax returned by a downstream application to be conditionally expanded
    using replacement configuration within a paste.deploy file</p>
<p>
For more information, see the <a href="http://svn.repoze.org/repoze.tempita/trunk/README.txt">repoze.tempita README.txt file</a>
</p>

<p>
To install, do <code>bin/easy_install -f http://dist.repoze.org repoze.tempita</code>
</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 24 Oct 2007 18:05 GMT</pubDate>
</item>
<item>
   <title>Announcement: repoze.zope2 0.2.3 and repoze.plone 0.2.3 Released</title>
   <guid isPermaLink="false">repoze.install-process-changed-20071022</guid>
   <link>http://blog.repoze.org/repoze.install-process-changed-20071022.html</link>
   <description><![CDATA[
<h4> repoze.zope2 0.2.3 and repoze.plone 0.2.3 now use repoze.project </h4>

<p> You can (indeed, must) now install repoze.plone or repoze.zope2 sandboxes 
    using <code>repoze.project</code>.  As of this release the old 
    "setup.py sandbox" sandbox creation mechanism is no longer supported in
    these packages.</p>

<p>Here's an example of using repoze.project to install repoze.plone</p>

<pre>

 $ bin/easy_install -i http://dist.repoze.org/simple/ repoze.project
 ...
 $ bin/repozeproject --target-path=/tmp/ptest repoze.plone

</pre>

<p>
This will cause a sandbox to be create in /tmp/ptest including all
"instance" files (such as etc/zope.conf, etc).
</p>


]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Mon, 22 Oct 2007 22:27 GMT</pubDate>
</item>
<item>
   <title>Announcement: repoze.project 0.0.2 Released</title>
   <guid isPermaLink="false">repoze.project-released-20071020</guid>
   <link>http://blog.repoze.org/repoze.project-released-20071020.html</link>
   <description><![CDATA[
<h4> What is repoze.project? </h4>

<p> <code>repoze.project</code> is a Python distribution which installs a
    script, <code>repozeprojectct</code>, into your Python environment.
    Ths intent of the script is to make it simple to create a new
    repoze application deployment environment, in somewhat the same manner
    as <a href="http://pypi.python.org/pypi/zopeproject">zopeproject</a>
    does for Zope3, and
    as <a href="http://pypi.python.org/pypi/grokproject">grokproject</a>
    does for Grok applications.</p>

<p> However, rather than using Jim Fulton's
    <a href="http://pypi.python.org/pypi/zc.buildout">zc.buildout</a>
    to drive the creation of a new environment, we chose to use Ian
    Bicking's 
    <a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>,
    because we like the concept of "standalone" environments with
    custom software in their own <code>site-packages</code> directories.</p>

<h4> Trying it Out </h4>

<p> As the version number implies, this is a pretty early version of the
    <code>repoze.project</code>.  Neverthless, the package does enable the
    following method of installing Plone-under-repoze:</p>

<pre>

 $ bin/easy_install -i http://dist.repoze.org/simple/ \
   repoze.project
 ...
 $ bin/repozeproject --target-path=/tmp/ptest repoze.plone

</pre>

<p> One caveat about the example:  the <code>repoze.plone</code> project has
    not yet been updated to add the
    <a href="http://peak.telecommunity.com/DevCenter/setuptools#dynamic-discovery-of-services-and-plugins"
    >entry point</a> which <code>repoze.project</code> looks for when
    initizlizing the environment.</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sat, 20 Oct 2007 19:29 GMT</pubDate>
</item>
<item>
   <title>Announcement: repoze.grok 0.1 Released</title>
   <guid isPermaLink="false">repoze.grok-working-20071018</guid>
   <link>http://blog.repoze.org/repoze.grok-working-20071018.html</link>
   <description><![CDATA[
<p>We've been working on getting a repoze wrapper for Zope3 apps, and
   <a href="http://grok.zope.org/">Grok</a> in particular, up and running.</p>

<p>I'm pleased to say that we have a
    <a href="http://dist.repoze.org/repoze.grok-0.1.1.tar.gz">distribution</a>
    available for testing. </p>

<h4> Installing from the Tarball </h4>

<pre>
 $ wget http://dist.repoze.org/repoze.grok-0.1.1.tar.gz
 $ tar xzf repoze.grok-0.1.1.tar.gz
 $ cd repoze.grok-0.1.1
 $ ../../bin/python setup.py sandbox \
   --admin-login=admin --admin-password=123
 ...
 $ bin/paster serve etc/grok.ini
</pre>

<h4> Installing via easy_install </h4>

<pre>
 $ easy_install -f http://dist.repoze.org repoze.grok
 $ bin/init_configs --admin-login=admin --admin-password=123
 $ mkdir var  # directory for the ZODB.
 $ bin/paster serve etc/grok.ini
</pre>

<h4> Browsing the Application </h4>

<p> You can then connect
    to the <a href="http://localhost:8080/">Grod Admin UI</a>.  Of course,
    there won't be any applications you can add (yet), but you can
    browse the application control UI and the documentation.</p>

<h4> Adding a Grokkified Application </h4>

<p> You can download and install one of the
    <a href="http://svn.zope.org/grokapps/">sample grok apps</a>,
    or even roll your own based on the
    <a href="http://grok.zope.org/">tutorial examples</a>.</p>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Fri, 19 Oct 2007 01:30 GMT</pubDate>
</item>
<item>
   <title>New Releases of repoze.zope2 and repoze.plone</title>
   <guid isPermaLink="false">releases-20071013</guid>
   <link>http://blog.repoze.org/releases-20071013.html</link>
   <description><![CDATA[
<p>New releases of repoze.plone and repoze.zope2 are available.  The latest releases (0.2.2, for both), allow usage of the Plone login portlet (which did not work up until this release).</p>

<ul>

 <li><a href="http://dist.repoze.org/repoze.plone-0.2.2.tar.gz"
      >repoze.plone 0.2.2</a></li>

 <li><a href="http://dist.repoze.org/repoze.zope2-0.2.2.tar.gz"
      >repoze.zope2 0.2.2</a></li>

</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Sat, 13 Oct 2007 20:32 GMT</pubDate>
</item>
<item>
   <title>IRC Channel for Repoze</title>
   <guid isPermaLink="false">irc_channel-20071003</guid>
   <link>http://blog.repoze.org/irc_channel-20071003.html</link>
   <description><![CDATA[
<p>We've set up an IRC channel for discussing repoze developement, and
   answering questions:</p>

<blockquote>
  <a href="irc://irc.freenote.net/#repoze">irc://irc.freenote.net/#repoze</a>
</blockquote>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Wed, 03 Oct 2007 17:13 GMT</pubDate>
</item>
<item>
   <title>Announcing Repoze</title>
   <guid isPermaLink="false">announce-20071001</guid>
   <link>http://blog.repoze.org/announce-20071001.html</link>
   <description><![CDATA[
<p>&quot;Whisky. Champagne.  Mickey's.&quot;</p>
<p>But seriously.... This blog is for news and updates concerning
   the <a href="http://repoze.org">Repoze</a> project.</p>
   
<p>Repoze is a refactoring / rewrite of portions of the
   <a href="http://www.zope.org/">Zope</a> application server, to make
   it possible to run Zope and Zope-like applications behind a
   <a href="http://www.wsgi.org/">WSGI-compliant</a> server.</p>

<h4>Other Repoze Resources</h4>

<ul>

 <li><a href="http://repoze.org/viewcvs">Browse the CVS repository</a></li>

 <li><a href="http://dist.repoze.org/"
      >Browse repoze packages</a></li>

 <li><a href="http://bugs.repoze.org/"
      >Report bugs against repoze packages</a></li>

</ul>

]]></description>
   <category domain="http://blog.repoze.org"></category>
   <pubDate>Tue, 02 Oct 2007 00:22 GMT</pubDate>
</item>
</channel>
</rss>
