Weblog

published Nov 03, 2021, last modified Nov 04, 2021

Rok Garbas: Complex Forms with z3c.form

published Oct 28, 2009, last modified Oct 29, 2009

By Rok Garbas, Slovenia

Rok Garbas talks about the z3c.form form framework. Everybody is talking about is, using it, so it is time you learn how to (ab)use it and step into the Plone future. Tricks and things you might want to hear again. I won't speak about the internal structure, or why you would want to use it, or compare it with other frameworks.

For code examples, see his talk once it is uploaded to the Plone Conference 2009 website.

On the form you can set ignoreContext and ignoreRequest to control whether the form displays any values and where it gets it from.

Don't forget to package="plone.app.z3c.form" /> in your zcml when you use z3c.form in Plone.

You can register zope vocabularies and use that in your forms.

You can change the form layout. For that you create a layout factory, inheriting from plone.z3cform.templates.ZopeTwoFormTemplateFactory.

You can define your own widgets, for example to combine three inputs into one field.

You can create a custom data converter. It converts from the field to the widget (e.g. split fullname field into first name and last name inputs in the widget) or the other way around.

Within the form normally the default widgets are used. If you want to use your own widgets, you need to override the widgetFactory for that field in the form definition.

You can create group forms, which can be compared to Archetypes forms with tabs. Inherit from z3c.form.group.GroupForm.

In form wizards you can combine steps, so you can link different forms. Use collective.z3cform.wizard.

For more information, see http://docs.zope.org/z3c.form and http://pypi.python.org/pypi/plone.app.z3cform

Read Rok Garbas blog.

Alexander Limi: The future of Plone

published Oct 28, 2009, last modified Oct 29, 2009

Plone conference 2009 keynote by Alexander Limi

Alan Runyan is not here because he just had a baby (applause). The first South American Plone conference will be held this year.

Plone Foundation has been kicking ass this year; Jon Stahl did good work there (and is also having a baby). A lot of money was raised and spent to help more core people go to other conferences, also bigger industry events to represent Plone. Also some packages have been relicensed to make it easier to use them in other projects. Hosting of http://plone.org is now done by Six Feet Up. We are putting money into paying people to go to sprints. Dogin more marketing and evangelism.

Plone 4 is estimated to be released at the end of 2009. Release manager is Eric Steele. An amazing 26 new features (plips). We hope to have an alpha release at the end of the conference. It is the "Snow Leopard" of Plone releases, fixing lots of stuff in the background. Speedup, blob file storage, better memory management (partly because of using python 2.6), scales better.

Plone 5. Expected mid 2010 (well, maybe). I see Hanno Schlichting smiling, the release manager. Focus areas:

  • Approachability. New content framework: Dexterity; but Archetypes is not going away. Dexterity is thorugh the web schema editing, with round trip support. Theming has become too hard; Deliverence: theming done right. We will use xdv for this. There will be talks about Deliverance this conference. We use this on the http://plone.org website already, so we believe in this.
  • Plone needs to be faster. Partly we do this by using less code, Plone trunk plus all dependencies was at some point about 800,000 lines, instead of the 1 million lines of Plone 3.2. Using Chameleon for templating will make Plone faster. You can already use that on Plone 3.3 today. So more speed coming to you soon. We are going to run performance tests to see if Plone is not suddenly getting slower without us noticing.
  • Simplicity. New layout system called Deco. It is a new approach to page editing. You will have page layouts composed of tiles, small boxes of text, images, lists, forms, polls, anything. "Tiles are the new apps." Where you would currently create a new content type you could probably create a new tile instead.

Deco: full page editing interface. What you edit is what you get. Separates layout from format. There will be no need for grid management, so not something like "add a row", "add a column". (Alex now does a Deco demo. Hey, Plone has a pony!)

Opportunities. Plone 4 and 5 are solving some basic problems. I want us to change the world again. Community: we want new talent, new web sites, new add-ons; it should be easier to get more people involved in Plone. We are not doing enough shouting from the roof tops. We know some of the weaknesses of Plone so we keep quiet; but all other system have their weaknesses as well. Be proud of Plone! What is our identity? Collaboration? Publishing? Simple apps? Using something like Amazon EC2 will help us as it makes it easier to run a Plone site. It should be simple to create small applications with Plone; Dexterity should help there. Going after Drupal, Wordpress we will lose, as they will always be cheaper. We are more up against frameworks like Alfresco and Documentum.

The Plone software needs to be more performant, self-documenting (sphinx, amberjack), more quality assurance (I will be running my blog on Plone 4 and when that is stable enough I will switch to Plone 5; the site might be down sometimes, but that is okay, it makes Plone better).

Be great. Talk more about Plone. Improve http://plone.org. It used to be a great driver of innovation.

Widen participation. Please start a Plone user group in your area. Evangelize Plone. It's all about you. Thank you for making Plone better!

Don't just complain. Complain and then try to make it better.

Plone Conference 2009 Intro

published Oct 28, 2009

Short intro about the plone conference 2009.

The Plone Conference 2009 has just started. I am there with my Zest Software colleagues Jean-Paul and Fred. Location is Budapest, capital city of Hungary. It is the biggest Plone conference so far, with about 400 attendees.

Thomas Moroz talked a bit about KARL. He works for the Open Society Institute (OSI) that helped organize the conference. KARL is one of the largest sites built with Plone; a knowledge management system. He will talk about it in more dpeth later this week.

Python User group Netherlands meeting

published Sep 25, 2009

The three-monthly meeting of the Dutch python user group was held Thursday 24 September 2009 in Amsterdam, in the Beurs van Berlage, organised by Go2People. First a half-hour presentation about Phatch, then some lightning talks, another half-hour presentation on MonetDB and moving from python 2 to python 3, then a few more lightning talks.

My brother Reinout was also there and of course he wrote a summary too.

Stani: Phatch - Batch photo processing for everyone

Lots of photo data, including metadata. You have ImageMagick. Phatch allows you to resize images, do colour profiling. Combine actions. Prefabricated recipes. You don't need to know how to do graphics manipulation. You can remove metadata so you can upload photos anonymously to sites. You can have a droplet on your desktop; just drop an image on it and it will do the actions you specified. Safe and unsafe mode. Safe restricts you; in unsafe mode you have the full power of python. It's a command line tool, but also a UI. Uses open source fonts. Phatch can do anything Gimp and ImageMagick does and more as they are the back ends, including PIL and blender. Its goal is to unite all open source graphics tools. Anyone can submit new objects. Works on Linux and mostly on Windows and Mac, but we need more developers there. About six developers now. Someone has plans to work on Django integration. Link: http://photobatch.stani.be/

Jasper Spaans, Fox-IT: Pycuda - massively parallel computing

Calculating with the GPU (Graphical Processing Units). GPU's are incredibly fast for parallel computations compared to their price. Cuda is only nor Nvidia. OpenCL does that too, and that can also use ATI/AMD. Use it for parallel algorithms. PyCuda is a python interface for cuda. Slides in Dutch: http://jasper.es/talks/pun2009-09

Wim Feijen, Go2People: Bazaar (and mercurial and git)

Bazaar: you can have one or more repositories. You can work and commit locally. It's simple. It tracks movements. You can branch projects. Look at http://github.com (not only for git users) and http://bitbucket.org, for free project hosting.

Remco Wendt, Maykin Media: libraries that you love

Does anyone know of a library that is cool to use? Speak up about it!

Jan Jaap Driessen (Health Agency) and Sylvain Viollon (Infrae): Grok

Web framework, based on Zope. Even cavemen can use Zope. Just had a sprint about Grok. Takes the pain out of working with Zope. Zope has lots of layers, configuration, zcml, adapters, whatever. With Grok you do not register your stuff in zcml. Set of default settings. Grok "groks" your code, understands your code without needing a separate configuration language. Grok 1.0 is due for release this or next week. We have been using it for three years already. http://grok.zope.org

Gijs Molenaar, UvA, CWI: MonetDB and python 3

DBMS, developed by CWI, open source, BSD, platform for scientific research, not only SQL, http://www.monetdb.nl. Good for big databases; SkyServer is 6TB. For query intensive apps that are mostly read-only. For complex data models beyond SQL. Sometimes outperforms other databases by a hundred times for big tables.

It is a column based storage database. All columns are shown separately. Flexible kernel, which is easily extensible. SQL front end, but not limited to SQL; can use Xquery.

You can store xml documents in your database. Monet takes the document apart and stores it in several tables.

There are APIs for Ruby, PHP, python, perl (needs a rewrite but nobody wants to touch it), C, java. The CWI at the University of Amsterdam wanted me to rewrite the python API. MonetDB API is the wire protocol. Basic functions: set up connection, execute commands, parse the response, chop queries and responses in blocks. python.sql is the implementation of all DBAPI 2.0 functionality. Bridge between this and MonetAPI (mapi).

There were tests available for the MySQL python API, so I borrowed those for Monet. We looked at supporting python 2 and 3. We did not want to use two trees. We decided to do a 2+3 hybrid, though Guido van Rossum tells us not to do that. In python 3 there is a new IO layer with bytes and strings. New IO layer is used in the mapi layer. We made two versions here, mapi2.py and mapi3.py as it was too hard to combine, with exceptions that were no longer there in python 3. We do a python 3 version check in only two places, like conditionally importing mapi2 or mapi3, so not too bad. Tip: don't use print, use logging.

The hybrid python2-3 model works quite well in our case as the API is quite small. We minimised code duplication. Not advised for all projects.

Future work: bug fixes, port the xquery api, currently I am rewriting the C api (mapilite), unit tests in python using ctypes, having problem with structs.

Something completely different. http://pythonic.nl non-profit amateur web hosting provider for python web development. Focus on django.

Question: How mature is MonetDB? Well, there have been cases of data loss, but it has gotten better the last few years and it has been used in various projects.

Slides: http://gijs.pythonic.nl/static/pun-090924.pdf

Tim Molendijk: debugging

I usually just hunt for a bug, kill it and forget how I did the debugging and not improve it next time. But I am learning. I should probably use the python debugger, but usually I start with adding a few print statements. But with WSGI applications that normally does not work. So yes, next step is (i)pdb. For Django: Django debug toolbar.

Suggestions from the crowd: post mortem debugger, Twill, zc.testbrowser, mechanize, Selenium, winpdb, pydev for eclipse (you can still use vim for writing the code if you have to), werkzeug (for django).

Maurits van Rees: international emails

Short version of a presentation I gave at my employer Zest Software and that I blogged about recently. Suggestion from Jasper Spaans: use lamson (mentioned above), an smtp server framework in python.

International emails

published Sep 08, 2009, last modified Sep 08, 2009

Sending emails with strange characters to strange people, or at least people with non-ascii names.

Every few months at my employer Zest Software we have an evening of "eten en weten". Literally that is Dutch for "eating and knowing". Let's call it "Food for thought". We eat together and several of us hold presentations on subjects that are in some way related to our work. For example: Django, common Dutch language mistakes, how we use subversion, or local site hooks and the many interesting ways in which they can break when migrating from Plone 2.5 to 3. I managed to squeeze that last one into a lightning talk of a few minutes; you really don't want to know. ;-) (In case you do want to know, take a look at Products.Plone3Cleaners).

It is probably about time for a new "eten en weten" so it is probably also about time I uploaded my talk from last time about international emails. I talked about some base terminology, what can go wrong, pointed to the python email module and showed how to send a complete message, including some details that you can forget as long as you use the proper methods. After all, foreign languages are difficult enough already:

http://engrishfunny.files.wordpress.com/2009/03/engrish-funny-no-flush.jpg?w=500&h=375

i18n/l10n

Two terms widely used are:

internationalization
i       18         n

localization
l    10    n

Roughly said, in a Plone context, internationalization is making sure the content or the UI is translated into several languages. Localization is making sure that 3 May 2009 is 05-03-2009 in the USA and 03.05.2009 in Germany.

These two terms are not really the focus here though. The point is: how do you make sure that an email sent from Plone (or any python application really, if you ignore some details) with a Chinese name as From address, a Japanese name as To address, a Russian Subject and a Korean body text is delivered without errors.

Now do not think: "I live and work in America, I only need ascii." Don't you have Spanish colleagues? Some friends from your year abroad at that French university? A few Chinese clients? You could use only ascii, but you might regret that:

http://punditkitchen.files.wordpress.com/2009/01/political-pictures-hello-usa-copy.jpg

utf-8 is not unicode

Repeat after me: "utf-8 is not unicode", "utf-8 is not unicode", "utf-8 is not unicode":

>>> type('ascii')

>>> type('utf-8')

>>> type(u'unicode')

Basics

Sending an email in Plone goes something like this:

charset = portal.getProperty(
  'email_charset', 'ISO-8859-1')
mailhost = getToolByName(portal, 'MailHost')

mailHost.send(message = msg,
              mto = address,
              mfrom = mfrom,
              subject = subject,
              charset = charset)

What can go wrong with that?

  • Hard to read headers:

    From: RenXX Artois
    
  • Hard to read body text:

    lettere accentate: ò ùâ
    
  • Unrecognized addresses:

    To: undisclosed recipients
    
  • No email body: C

  • UnicodeDecodeErrors/UnicodeEncodeErrors

Some examples can be found in Poi issues 146 and 161.

Parsing/formatting addresses

The To and From fields should have something like this:

Maurits van Rees 

The standard python email package has nice utilities for this:

>>> from email.Utils import parseaddr
>>> from email.Utils import formataddr
>>> formataddr(('Maurits van Rees',
                'maurits@example.org'))
'Maurits van Rees '
>>> parseaddr(
      'Maurits van Rees ')
('Maurits van Rees', 'maurits@example.org')

These functions can get confused by strange characters. You can guard against that by parsing the address that you have just formatted and seeing if the parsed information still makes sense:

from_address = portal.getProperty(
  'email_from_address', '')
from_name = portal.getProperty(
  'email_from_name', '')
mfrom = formataddr((from_name, from_address))
if parseaddr(mfrom)[1] != from_address:
    # formataddr probably got confused
    # by special characters.
    mfrom = from_address

Character sets

The python email.Charset module has interesting information about how email headers and body text should be encoded depending on the input character set. Some examples (QP is quoted printable):

input         header enc  body enc  output conv
iso-8859-1:   QP          QP        None 
iso-8859-15:  QP          QP        None 
windows-1252: QP          QP        None 
us-ascii:     None        None      None 
big5:         BASE64      BASE64    None 
euc-jp:       BASE64      None      iso-2022-jp 
iso-2022-jp:  BASE64      None      None 
utf-8:        SHORTEST    BASE64    utf-8 
...

If that does not make sense, perhaps this helps:

http://icanhascheezburger.files.wordpress.com/2008/12/funny-pictures-this-kitten-is-confused.jpg

This information is used when creating email headers:

>>> from email.Charset import Charset
>>> latin = Charset('iso-8859-1')
>>> utf = Charset('utf-8')
>>> latin.header_encode('René Artois')
u'=?iso-8859-1?q?Ren=C3=A9_Artois?='
>>> utf.header_encode('René Artois')
'=?utf-8?q?Ren=C3=A9_Artois?='

and encoding body text:

>>> latin.get_body_encoding()
'quoted-printable'
>>> latin.body_encode('René Artois')
'Ren=C3=A9 Artois'
>>> utf.get_body_encoding()
'base64'
>>> utf.body_encode('René Artois')
'UmVuw6kgQXJ0b2lz\n'

This may look confusing. Surely if you get an email with a text or subject like this it is unreadable? No, your email program should be smart enough to display this to you in a readable fashion. No need for the funny face:

http://www.alloallo.yoyo.pl/img/01_rene_artois.jpg

Formatting headers

Instead of using email.Charset for formatting headers you normally use the email.Header module:

>>> from email.Header import Header
>>> subject = 'Re: René'.decode('latin-1')
>>> subject
u'Re: Ren\xc3\xa9'
>>> subject = Header(subject, 'latin-1')
>>> subject

>>> print subject
=?iso-8859-1?q?Re=3A_Ren=C3=A9?=

Formatting the body

You will need to know which character set the body text has, or at least in which character set it can be encoded without errors. This snipped tries three character sets:

charset = portal.getProperty(
  'email_charset', 'ISO-8859-1')
for body_charset in 'US-ASCII', charset, 'UTF-8':
    try:
        message = message.encode(body_charset)
    except UnicodeError:
        pass
    else:
        break

If the message only contains ascii characters, then at the end of this snippet the message is encoded in ascii and the body_charset variable is 'US-ASCII'.

Send it

We have done all the hard work with the Headers so now we can use the 'send' method:

# Create the message.
# 'plain' stands for Content-Type: text/plain
from email.MIMEText import MIMEText
msg = MIMEText(message, 'plain', body_charset)
msg['From'] = email_from
msg['To'] = email_to
msg['Subject'] = subject
msg = msg.as_string()
mailhost = getToolByName(portal, 'MailHost')
mailhost.send(message=msg)

Using secureSend

Easier is to use the secureSend method; using with the Header class is not needed then, as secureSend takes care of that:

email_msg = MIMEText(message, 'plain', body_charset)
mailhost.secureSend(
  message = email_msg,
  mto = email_to,
  mfrom = email_from,
  subject = subject,
  charset = header_charset)

Now international email sending should work:

http://icanhascheezburger.files.wordpress.com/2009/07/funny-pictures-cat-is-indisposed.jpg

Images courtesy of: