Archive for the 'Uncategorized' Category


simple ZODB performance settings

The use of the database can be optimized by using a bigger cache in the client.

For a single zope instance without a zeo server this can be done by increasing the number of cached objects.

The cache.size parameter in etc/local.conf must be set (default is 5000) :


cache-size 50000
path $DATADIR/Data.fs

The default size of 5000 is no longer usefull for a database with 200000 objects.

For a zeo client it is possible to configurate the client cache memory size :

server localhost:8101 storage 1
# ZEO client cache, in bytes
cache-size 300MB
# Uncomment to have a persistent disk cache
#client zeo1

The size should be set to a high value because otherwise a lot of network traffic is created between zeo and the client, this is also true if the client and zeo is on the same machine using localhost for the connection.

speed up your Apple Mail app

I found a good tipp for fasten up your email application in mac os x with an easy trick:

open Terminal
cd ~/Library/Mail
sqlite3 Envelope\ Index
vacuum subjects;
press Control-D to leave sqlite3

thanks to hawkwings.net for the tipp
http://www.hawkwings.net/2007/03/01/a-faster-way-to-speed-up-mailapp/

Using plone.app.form in Plone 2.5

It’s really nice that so much zope 3 stuff is available already in Plone 2.5 and Five 1.4. I use formlib and plone.app.form with success. I found three issues, but after solving them it works nicely.

  1. I had an “AttributeError: debug” error when trying to use formlib. The cause was that Zope 3 has a debug attribute on requests, while Zope 2 doesn’t. When my widget (in the form) rendered itself, which is zope 3 code, it tried to use the debug attribute on the request, but as the request is a Zope 2 request it couldn’t be found. I fixed this by monkey patching ZPublisher.HTTPRequest and setting the debug attribute to zope.publisher.base.DebugFlags(). I’m told this will be fixed, but as I want this to work now I’ll use the patch for now.
  2. If using latest trunk of plone.app.form one should inherit from Five’s EditForm. In earlier versions one needed to inherit directly from zope.formlib’s EditForm, otherwise you couldn’t save forms. plone.app.form did some monkey patching. I’m glad Daniel Nouri changed this behaviour. One should now inherit from Five’s base classes, not directly from zope.formlib’s base classes.
  3. formlib is supposed to work, but not all widgets are supported. The OrderedMultiSelectWidget is rendering itself and therefore it’s using the Zope 3 page template engine. The Zope 3 page template engine is not supported in Zope 2. When a path expression (which the template for the widget contains) is traversed it tries to adapt to ITraversable. This will not work in Five as this traverses the url, not path expressions. So the solution is to provide another adapter. The result is that the default Zope 3 adapter for traversing path expressions will be used (for input widgets).

<adapter

for=”zope.app.form.browser.interfaces.IInputWidget”
provides=”zope.app.traversing.interfaces.ITraversable”
factory=”zope.app.traversing.adapters.DefaultTraversable”

/>

Not sure if 1 and 3 are still valid for Five 1.5.

i18n - error msgfmt not found

if msgfmt (which is something you need for developing in zope3 with i18n) is not found and you want to install this on your mac, just use darwin ports with the command:

sudo port install gettext

Browser crashes when using Flash FileReference Object

If you are using a File Reference Object withing Flash 8 or higher, you need to make shure, that Flash does NOT make JavaScript calls when the browse window is opended. If you do so, your browser will crash

Strange behavior with Javascript to Flash Communication

I had hard troubles to actualy make it run in all browsers for communicating between Flash and Javascript. Some browsers allways hat the trouble that the Flash var was not set because they where not able to connect correctly to the flash object via the DOM.

I found out, that you need to take care, that your object tag which embeds the Flash file should have an ID, but no NAME attribute. But your EMBED tag should have a NAME, but no ID. After that it worked just fine in Windows IE/Firefox and Mac Safari/Firefox

code example:

<sc ript language="JavaScript">
<!–

function startBrowsing(){
// tells flash to start with browsing
if(window.fuploader) window.document["fuploader"].SetVariable("startBrowse", "go");
if(document.fuploader) document.fuploader.SetVariable("startBrowse", "go");
}
//–>
</scr ipt>

<input type="button" value="browse" onclick="JavaScript:startBrowsing()" />
<br />

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="fpdownload.macromedia.com—swflash.cab <http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0>" width="220" height="300" id="fuploader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie"
value="upload.swf <http://localhost:8080/@@/flash_resources/upload.swf>" />
<param name="quality" value="high" />
<param name="bgcolor" value="#f8f8f8" />
<param name="wmode" value="transparent" />
<param name="FlashVars"
value="target_path=uploadfile <http://localhost:8080/uploadfile>" />
<embed src="upload.swf <http://localhost:8080/@@/flash_resources/upload.swf>"
flashvars="target_path=uploadfile <http://localhost:8080/uploadfile>"
quality="high" bgcolor="#f8f8f8" width="220"
height="300" name="fuploader" align="middle"
allowscriptaccess="sameDomain"
type="application/x-shockwave-flash"
wmode="transparent"
pluginspage="www.macromedia.com—getflashplayer <http://www.macromedia.com/go/getflashplayer>" />
</object>

Conditional adapters

There are use cases when you just want to adapt an object if some condition is true. For instance I wanted to adapt xml-rpc requests only if they were meant for my application, so I wouldn’t interfere with other packages that may use xml-rpc. I found it was rather easy (after figuring out how :) to make a conditional adapter. Here’s a simple example that can be run in a zope prompt (zopectl debug).

First we have some imports, basic interfaces and classes.

from zope.interface import Interface, implements, implementer
from zope.component import adapts, adapter, provideAdapter
class IA(Interface):
pass
class A(object):
implements(IA)
x=7
class IB(Interface):
pass

An adapter class for adapting objects providing IA to IB would typically look like this:

class AdapterAtoB(object):
implements(IB)
adapts(IA)
def __init__(self, context):
....self.context = context

After registering this adapter one would be able to adapt objects providing IA to IB:

provideAdapter(AdapterAtoB)
>>> a = A()
>>> b = IB(a)

But let’s say you want the adapter lookup to succeed only when A.x = 7, then you would need to do something like this:

class AdapterAtoB(object):
implements(IB)
#we don't need adapts anymore
def __init__(self, context):
....self.context = context
@adapter(IA)
@implementer(IB)
def a_to_b(obj):
if obj.x == 7:
....return AdapterAtoB(obj)
else:
....return None
>>> provideAdapter(a_to_b)
>>> a = A()
>>> b = IB(a)
>>> a.x = 2
b = IB(a)
TypeError: ('Could not adapt', <A object at ...>, <InterfaceClass IB>)

Mission accomplished.

(had problems with indenting, that’s why the dots are there)

The Skin Browser and Lovely Systems’ new Development Workflow

I just checked in the new Skin Browser APIDOC module and started to write a
huge check in message justifying and explaining the this new package. But then
I thought this would be a great opportunity to write my first blog entry
ever. So here we go.

In recent months Lovely Systems has had significant growth in human
resources. While this is really great, it also adds engineering
overhead. Lovely Systems now employs people that do either design, templating
or Zope 3 development. Thus we needed ways to effectively communicate between
the different types of developers and allow them to work independently without
having much overhead.

Zope’s Page Templates (specifically the TAL standard) promised from the
beginning to allow the separation of template and view code
development. However, over the years common (lazy) patterns developed that
made this separation impossible. Also, other resources such as style sheets,
images and JavaScript files were not templatable and it was thus impossible to
reuse those resources without modification on the server.

To solve this problem, the Lovely developers/consultants (mainly Juergen
Kartnaller, Bernd Dorn, Roger Ineichen, Jodok Batlogg and I) developed a set
of packages. The first package was the z3c.zrtresource, which is a very
simple, but very versatile template language that was designed to do string
replacements in style sheets and JavaScript files. Zope Resource Templates
(ZRT) allow JavaScript scripters and CSS template designers to map local path
descriptions to valid server URLs. ZRT allows by default simple, regex and
TAL-based string replacement. Here are some examples:

/* Replace "foo" with "bar", but only 3 times */
/* zrt-replace: "foo" "bar" 3 */

/* Do a group regex string substitution */
/* zrt-replace: re"(?P<prefix>[a-z]*)foo" "barg<prefix>" */

/* Replace the strng "foo: with the resource URL at runtime, everywhere */
/* zrt-replace: "foo" tal"string:${context/@@absolute_url}/@@/foo" */

This was a real success with our designers. Instead of regularly scheduling
meetings with the designers to integrate the latest version of resources into
the code base, they are no able to test offline and in the system at the same
time!

After some progress with the development, we noticed that there was a far too
tight connection between the Python view code and the templates. After some
discussion we were convinced that the Python view code belongs into the layer
and the page templates into the skin. But the big problem was that templates
and view code always had to be combined to a page together using the
browser:page directive. To solve this problem, we developed
z3c.viewtemplate which allows you to define a view on one hand and use a
second directive to register templates for this view. While this requires two
instead of one directive per view (a clear development overhead), it allowed
us to completely separate template from Python view code development. As
Juergen said: “I finally do not have to care about templates at all anymore;
when my tests pass I am happy.” Here is an example of the ZCML:

<browser:page
    name="blog.html"
    for="myproject.interfaces.IBlog"
    class="myproject.browser.blog.BlogList"
    layer="myproject.browser.skin.IProjectSkin"
    permission="zope.Public"
    />

<browser:template
    template="blog.pt"
    layer="myproject.browser.IProjectLayer"
    for="myproject.browser.blog.BlogList"
    />

The BlogList view class only has to inherit
z3c.viewtemplate.baseview.BaseView. This finally allowed us to work
completely separately. To take this new approach even further, we also exiled
macros from our development. We are only using one master template that simply
calls all sorts of content providers and viewlet managers. Then we register
viewlets for particular view combinations. This appraoch effectively reduced
pages to a traversal step in the URL and a hook to register content
providers/viewlets. Jodok reasoned for this approach saying that it was very
confusing to a template developer to know at what point the “view” TAL
namespace would represent what object. After having set up a complete project
using this appraoch to UI Zope 3 development, we are confident that this
approach works. Here is a final example at how we work the configuration:

<!-- And example of a page. You really only need the class to have a
     registration point. -->
<browser:page
    name="blog.html"
    for="myproject.interfaces.IBlog"
    class="myproject.browser.blog.BlogPage"
    layer="myproject.browser.IProjectLayer"
    permission="zope.Public"
    />

<!-- The main template used by all pages. It only contains the very basic
     structure and a bunch of viewlet managaer calls. -->
<browser:template
    template="main.pt"
    layer="myproject.browser.skin.IProjectSkin"
    for="myproject.browser.IProjectPage"
    />

<!-- This is a typical main content viewlet that actually implements
     functionality for the blog page. -->
<browser:viewlet
    name="bloglist"
    for="myproject.interfaces.IBlog"
    manager="myproject.browser.interfaces.IContent"
    view="myproject.browser.blog.BlogPage"
    class="myproject.browser.blog.BlogList"
    layer="myproject.browser.IProjectLayer"
    permission="zope.Public"
    />

<!-- This is the template is registered for the blog list viewlet. -->
<browser:template
    template="bloglist.pt"
    layer="myproject.browser.skin.IProjectSkin"
    for="myproject.browser.blog.BlogList"
    />

This is almost the final version, actually. Eventually the template designer
came back saying that he would like to define multiple viewlets in one page
template. But how to select snippets in a template? Aha! The revival of
macros. So eventually we have the following:

<!-- This is the template contains all possible blog views, and we just
     select the blog list. -->
<browser:template
    template="blog.pt"
    macro="bloglist"
    layer="myproject.browser.skin.IProjectSkin"
    for="myproject.browser.blog.BlogList"
    />

Okay, this is the current state of the art at Lovely Systems. We have a clear
separation among designers, scripters, template coders and Zope 3
programmers. In fact, a meeting a few minutes ago went like this:

Michel (Project Manager):
How do we display a list of users and what info is shown?
Juergen (Zope Programmer):
Don’t look at me, I do everything you tell me to.
Olli (Designer):
I have already developed a mockup for lists, let’s use that.
Jodok (Template Developer):
Michel, let’s talk about that. We define what we want. Then I am going to
use Olli’s design and make a template. From this template I will provide
Juergen with an API to implement.

From conversations like that one, it became evident that we needed a tool that
let us discover the views of the system and communicate that API. And so I
developed the Skin Browser APIDOC module (lovely.skinbrowser), which
allows us to discover all view template driven views. This tool does not only
reconnect the view code to the template for comprehension, but also gives
reports on the existing and desired API of the view code. The desired API is
communicated to the Zope developer via the interface of the view class.

While this process is total overkill for a one or two man shop, it provides
all the necessary human and programming interfaces to allow independent,
separated development of the different groups, while documenting the code in a
formal and “standard” manner that can be easily viewed.

Okay, that’s all for now. I will be back with more stuff I did in a little
while.