Derniers billets de blog

Expert Python/Django/Plone et chef de projet agile, j'aime coder et découvrir de nouvelles technologies.

Grok 1.0 released !

L'équipe de développement "Grok" vient tout juste de publier Grok 1.0 ! Grok 1.0 est l'aboutissement de 3 années de travail depuis le démarrage du projet fin 2006. Grok offre une plateforme de développement stable et puissante permettant de développer toutes sortes d'applications web en mettant l'accent sur l'extensibilité et la réutilisabilité.

[Ce post est une traduction partielle et adaptée de l'annonce officielle de la publication de Grok 1.0]

Introduction

Puisque Grok est extensible, de nombreuses et puissantes fonctionnalités ont été développées par la communauté et sont disponibles en tant qu'extensions. L'équipe de développement de Grok travaille déjà sur toute une série de nouvelles fonctionnalités et améliorations pour les futures versions de Grok. Citons par exemple le support de Python 2.6, l'intégration du ZTK (Zope Toolkit) ou encore l'intégration de z3c.hashedresource et hurry.resource pour une meilleure gestion des ressources statiques, sans oublier biensûr l'amélioration de la documentation !

Site officiel de Grok

À propos de Grok

Un framework construit sur Python

Grok est un framework moderne construit sur Python. Les développeurs expert trouveront dans Grok un outil très puissant qui excelle dans les domaines de la réutilisablité et de l'extensibilité grâce à l'utilisation du modèle de développement par composant. En parallèle, Grok a également pour objectif de permettre aux développeurs moins expérimentés d'être immédiatement productif en leur offrant une courbe d'apprentissage assez douce.

Compatible avec la ZODB et les bases de données relationnelles

Grok permet de stocker tous les objets Python d'une application au sein de la célèbre base de données object ZODB. Les adeptes des bases de données SQL trouveront également leur bonheur puisque Grok supporte également les bases de données relationnelles grâce à l'extension megrok.rdb et l'excellent ORM (Object Relational Mapper) SQLAlchemy.

megrok.rdb

SQLAlchemy

Grok est construit sur les technologies Zope

Grok est développé au sein de la communauté Zope et est construit sur les technologies Zope. Grok s'appuit en particulier sur le Zope Toolkit qui offre une collection de librairies réutilisables basées sur le modèle de développement par composant, le "Zope Component Architecture". La communauté Zope a plus de dix ans d'expérience dans le développement d'applications web en Python, et le Zope Toolkit en est le remarquable résultat.

Zope Toolkit

Grok est compatible WSGI

Grok est compatible WSGI et peut par conséquent être intégré avec toutes les autres applications Python WSGI-compatibles.

La réutilisabilité des technologies Grok font qu'elles s'exportent pour être réutilisées dans d'autres applications. Le CMS Plone (contruit sur le serveur d'applications Zope 2) et Silva ont fait ce pari.

chameleon.zpt versus standard Zope page templates

Chameleon.zpt is a fast Zope Page Template implementation based on the Chameleon template compiler. It's largely compatible with zope.pagetemplate. Some benchmarks says Chameleon is 16x faster ! Chameleon page templates differ from standard Zope page templates in a few simple aspects which I propose to discover.

chameleon.zpt

The default expression type is Python

With zope.pagetemplate

<div tal:content="python:2+2" />

With chameleon.zpt

<div tal:content="2+2" />

Tuple unpacking is allowed when defining variables

With zope.pagetemplate

<tal:vars define="a python:1; b python:2; c python:3">
...
</tal:vars>

With chameleon.zpt

<tal:vars define="(a, b, c) [1, 2, 3]">
...
</tal:vars>

Generators are allowed in tal:repeat statements

Note that the repeat variable is not available in this case.

With chameleon.zpt

<div tal:repeat="i <some generator>">
...
</some>

Attribute-access to dictionary entries is allowed in Python-expressions

With zope.pagetemplate

<span tal:define="mydict python:{'e1': 'one', 'e2': 'two'}"
      tal:context="python:mydict['e1']"> using dictionary['key'] </span>

With chameleon.zpt

<span tal:define="mydict {'e1': 'one', 'e2': 'two'}"
      tal:content="mydict.e1"> using dictionary.key </span>

Genshi expression interpolation syntax is supported outside tags and inside static attributes

With zope.pagetemplate

<span tal:define="world string:'css'"
      class="" tal:attributes="class string:hello-$world"
      tal:content="string:Hello, $world!">
   Hello, css!
</span>

With chameleon.zpt

<span tal:define="world 'css'"
      class="hello-${'world'}">
   Hello, ${'world'}!
</span>

Notes

Chameleon templates and macros/slots for Grok Views

Posté par Sylvain
The main template: mymacro.cpt: 

<html metal:define-macro="mypage"> 
<head></head> 
<body> 
The content: 
<div metal:define-slot="mycontent"> 
Put your content here... 
</div> 
</body> 
</html> 

Use the "mypage" in a new template: mypage.cpt: 
<html metal:use-macro="path:context/@@mymacros/template/macros/mypage"> 
<!-- slot 'mycontent' was defined in the macro above --> 
<div metal:fill-slot="mycontent"> 
... 
</div> 
</html>

Using Chameleon in debug mode

Posté par Sylvain
$ export CHAMELEON_DEBUG=True 
$ export CHAMELEON_CACHE=False

Installez Google Chrome sur Ubuntu, ça rocks !

Google Chrome ouvre les pages Web et les applications à une vitesse fulgurante, et il est Open Source !!! Essayez le sur votre Ubuntu, il est disponible sur Launchpad en tant que "daily build".

Ajouter les dépôts Launchpad de Chromium, ici pour Jaunty

$ sudo vi /etc/apt/sources.list
+ deb http://ppa.launchpad.net/chromium-daily/ppa/ubuntu jaunty main
+ deb-src http://ppa.launchpad.net/chromium-daily/ppa/ubuntu jaunty main

Installer la clée GPG

En mettant à jour la liste de vos paquets, un message d'erreur indiquera qu'il vous manque la clé GPG pour apt. L'erreur nous indique le nom de la clé à installer, ci-dessous 5A9BF3BB4E5E17B5.
$ sudo apt-get update
...
W: GPG error: http://ppa.launchpad.net jaunty Release: Les signatures suivantes 
n'ont pas pu être vérifiées car la clé publique n'est pas disponible : 
NO_PUBKEY 5A9BF3BB4E5E17B5
$ gpg --keyserver subkeys.pgp.net --recv 5A9BF3BB4E5E17B5
$ gpg --export --armor 5A9BF3BB4E5E17B5 | sudo apt-key add -

Installer Google Chrome

$ sudo apt-get update
$ sudo apt-get install chromium-browser
Mais aussi si vous le souhaitez:
$ sudo apt-get install chromium-codecs-ffmpeg-nonfree
$ sudo apt-get install chromium-browser-inspector

Liens

Python Agility: be careful ;)

Python is a very powerful dynamic programming language. Python is fun, yes!, but be careful it allows to do hair-raising thinks !!!
silvio@serv:~$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> tmp = True
>>> True = False
>>> False = tmp
>>> True
False
>>> False
True
>>>
>>> file
<type 'file'>
>>> file = 'Hi!'
>>> file
'Hi!'
>>>

Create an archetype content type with Paster and ZopeSkel

ZopeSkel provides a collection of skeletons for quickstarting Zope and Plone projects. These skeletons are available as PasteScript templates and can be used via the "paster" command line tool. This how-to describes how-to create a plone egg with an archetype content type in a fiew command lines.

1. Install ZopeSkel

$ easy_install -U ZopeSkel

2. Create the archetype Plone egg

$ paster create --list-template
Available templates:
[...]
      archetype: A Plone project that uses Archetypes
[...]

$ paster create -t archetype
[...]
Enter project name: myproject.contenttypes
[...]

3. Create the content-type

$ cd myproject.contenttypes
$ paster addcontent --list
Available templates:
[...]
       contenttype:  A content type skeleton
[...]
$ paster addcontent contenttype
[...]
Enter contenttype_name (Content type name ) ['Example Type']: MyContentType
[...]

4. Add an archetype field to the new content-type

$ paster addcontent --list
Available templates:
[...]
    atschema: A handy AT schema builder
[...]
$ paster addcontent atschema
[...]
Enter content_class_filename (What is the module (file)name of your content class?) 
['exampletype']: mycontenttype
Enter field_name (What would you like to name this field?) ['newfield']: myfield
Enter field_type (What kind of field should I make for you?
Some examples: [computed,cmfobject,reference,text,image,float,lines,datetime,boolean,
file,integer,fixedpoint,string]) ['string']:
Enter widget_type (What kind of widget do you want to use 
(example: Password)?) ['default']:
[...]

5. Links

6. Thanks

Thank you to Jean-Michel François aka toutpt who introduced me to this very handy tool, and of course to the authors of PasteScript and ZopeSkel!

Posté par David le 07:37
Many thanks; it's pretty straight forward in itself but certainly is handy to see what options are coming up for schema etc.
Posté par Dan Thomas le 06:37
This worked for me in Windows, and this may be useful to others:
1) after cd to my product, I had to run paster with "..\paster"
2) I could install the product by doing this from the product folder: "..\..\python.exe setup.py install"
3) The message about Cheetah can apparently be ignored.

Thanks for a great write-up.

Using timezones in your Python scripts

pytz allows accurate and cross platform timezone calculations using Python. Here is a small example on how to display date and time for differents timezones using a Zope Utility.

pytz - World Timezone Definitions for Python

1. Create an utility which provides a getCurrentTimes fonction (file utils.py)

# Python imports
from datetime import datetime
import pytz

# Zope imports
from zope.interface import Interface, implements
from zope.component import provideUtility

class ITimezoneUtils(Interface):
    """ Utilities for timezone calculations """

    def getCurrentTimes(timezones, fmt=None):
        """ Return current time for a list of timezones.

        >>> getCurrentTimes(['Europe/London', 'Asia/Tokyo'])
        {'Europe/London': datetime.datetime(2009, 7, 9, 20, 29, 26, 603590, 
                          tzinfo=<DstTzInfo 'Europe/London' BST+1:00:00 DST>),
        'Asia/Tokyo': datetime.datetime(2009, 7, 10, 4, 29, 26, 603590, 
                          tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)}

        >>> getCurrentTimes(['Europe/London', 'Asia/Tokyo'], fmt='%Y-%m-%d %H:%M')
        {'Europe/London': '2009-07-09 20:31',
         'Asia/Tokyo': '2009-07-10 04:31'}
        """

class TimezoneUtils(object):

    implements(ITimezoneUtils)

    def getCurrentTimes(self, timezones, fmt=None):

        # Get UTC current time
        now_utc = datetime.now(pytz.timezone('UTC')) 

        # Compute current time for each timezone
        result = {}

        for tz in timezones:
            now_tz = now_utc.astimezone(pytz.timezone(tz))

            if fmt is not None:
                now_tz = now_tz.strftime(fmt)

            result[tz] = now_tz

        return result

provideUtility(TimezoneUtils(), ITimezoneUtils)

2. Use this utility to compute date and time for multiple timezones

>>> # Zope imports
>>> from zope.component import getUtility

>>> from utils import ITimezoneUtils
>>> tz_utils = getUtility(ITimezoneUtils)
>>> timezones = ['Europe/London', 'Asia/Tokyo', 'America/New_York']

>>> tz_utils.getCurrentTimes(timezones)
{'America/New_York': datetime.datetime(2009, 7, 9, 15, 32, 18, 910813, 
                          tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>), 
 'Europe/London': datetime.datetime(2009, 7, 9, 20, 32, 18, 910813, 
                          tzinfo=<DstTzInfo 'Europe/London' BST+1:00:00 DST>), 
 'Asia/Tokyo': datetime.datetime(2009, 7, 10, 4, 32, 18, 910813, 
                          tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)}

>>> tz_utils.getCurrentTimes(timezones, fmt='%Y-%m-%d %H:%M')
{'America/New_York': '2009-07-09 15:32', 
 'Europe/London': '2009-07-09 20:32', 
 'Asia/Tokyo': '2009-07-10 04:32'}