Entries tagged “bluebream”

Discover new versions of your packages or dependencies

written by ccomb, on Aug 6, 2010 1:23:00 AM.

Python

z3c.checkversions

As part of my work on the the Zope Toolkit 1.0 and BlueBream 1.0, I've released several versions of z3c.checkversions. This package is part of the z3c (Zope 3 Community) namespace, but it does not depend on any Zope package and has zero dependencies (except setuptools). It provides you with a single checkversions script which can be used with any project. This is particularly useful, for instance, on large Plone projects, with many packages. The more packages you use, the more bugs you find. You shouldn't loose time on bugs that are already fixed by newer versions of packages! In the Zope community, it's generally safe to upgrade to the latest minor versions of packages. If you're using package foo version 1.0.2, and discover that version 1.0.6 and 1.1.0 are available, you can upgrade immediately to 1.0.6 without risk.

As a summary, versions are commonly formed with 3 numbers : X.Y.Z:

  • a new minor Z version only provides bugfixes. No new features are allowed.
  • a new intermediate Y version should provide new (backward compatible) features
  • a new major X version is expected to cause breakages and is probably backward-incompatible.

Discovering new versions on the system Python

Install z3c.checkversions as an administrator. This is safe because there is no dependencies, and you can uninstall it easily with pip afterwards:

$ sudo pip install z3c.checkversions  # or sudo easy_install z3c.checkversions
$ checkversions
# Checking your installed distributions
pida=0.6.2
python-dateutil=1.5
genshi=0.6
buildbot=0.8.1
pyparsing=1.5.3
(...)

If you add the -v option, all parsed versions will be displayed, as well as the current installed versions:

$ checkversions -v
# Checking your installed distributions
twisted-words=10.0.0
pida=0.6.2 # was: 0.5.0
foolscap=0.5.1
distribute=0.6.14
twisted-names=10.0.0
bicyclerepair=0.9
python-dateutil=1.5 # was: 1.4.1
genshi=0.6 # was: 0.5.1
buildbot=0.8.1 # was: 0.7.12
pyparsing=1.5.3 # was: 1.5.2
(...)

If you only want the new intermediate versions, add -l 1. If you only want the new minor (bugfix) versions, add -l 2 instead. If you ever have some packages with 4 version digits, you can even use -l 3:

$ checkversions -v -l 2
# Checking your installed distributions
twisted-words=10.0.0
pida=0.5.1 # was: 0.5.0
foolscap=0.5.1
distribute=0.6.14
twisted-names=10.0.0
bicyclerepair=0.9
python-dateutil=1.5
genshi=0.6
buildbot=0.8.1
pyparsing=1.5.3
(...)

Now you can uninstall it:

$ sudo pip uninstall z3c.checkversions

Working with a virtualenv

Do the same, but install it in a virtualenv:

$ virtualenv --no-site-packages --distribute sandbox
$ sandbox/bin/pip install z3c.checkversions

Then the script is available only in the virtualenv:

$ sandbox/bin/checkversions -v
# Checking your installed distributions
pip=0.8 # was: 0.7.1
python=2.6
distribute=0.6.14 # was: 0.6.10
z3c.checkversions=0.4
wsgiref=0.1.2
(...)

Working with a buildout

If the [versions] section of your buildout is huge, finding new versions one by one can be painful, particularly if you want to find only new minor versions. In that case just install z3c.checkversions in your buildout. Don't forget to enable the [buildout] extra:

[some_part]
recipe = zc.recipe.egg
eggs = z3c.checkversions [buildout]

Then run your buildout again, and run the checkversions script by passing the buildout.cfg (or versions.cfg) file as an argument:

$ bin/checkversions -v -l 2  versions.cfg
# Checking buildout file versions.cfg
zope.app.error=3.5.2
distribute=0.6.14 # was: 0.6.10
zope.dottedname=3.4.6
Twisted=10.0.0
zope.hookable=3.4.1
z3c.viewtemplate=0.3.2
zope.app.pagetemplate=3.4.1
zope.decorator=3.4.0
jquery.javascript=1.0.0
zope.app.container=3.5.6 # was: 3.5.4
hachoir-parser=1.2.1
z3c.template=1.1.0
(...)

Blacklist and incremental options

While setting up the AFPY buildbots for the Zope Toolkit, I've been experimenting with a special buildbot that would be able to create a new Zope Toolkit version list automatically, by testing arbitrary new versions. For this purpose I've added two options to z3c.checkversions:

  • -1 or --incremental
  • -b or --blacklist

The first option allows to suggest only one new version:

$ checkversions -v -l 2 --incremental versions.cfg
# Checking buildout file versions.cfg
zope.app.error=3.5.2
distribute=0.6.14 # was: 0.6.10
zope.dottedname=3.4.6
Twisted=10.0.0
zope.hookable=3.4.1
z3c.viewtemplate=0.3.2
zope.app.pagetemplate=3.4.1
zope.decorator=3.4.0
jquery.javascript=1.0.0
zope.app.container=3.5.4
hachoir-parser=1.2.1
z3c.template=1.1.0
(...)

The second option allows to not suggest a version which is in a blacklist version file. Say we have the following blacklist.cfg file:

zope.app.container=3.5.6

Then the script will suggest all the highest new versions, except the one in the blacklist:

$ checkversions -v -l 2 -b blacklist.cfg versions.cfg
# Checking buildout file versions.cfg
zope.app.error=3.5.2
distribute=0.6.14 # was: 0.6.10
zope.dottedname=3.4.6
Twisted=10.0.0
zope.hookable=3.4.1
z3c.viewtemplate=0.3.2
zope.app.pagetemplate=3.4.1
zope.decorator=3.4.0
jquery.javascript=1.0.0
zope.app.container=3.5.5 # was: 3.5.4
hachoir-parser=1.2.1
z3c.template=1.1.0
(...)

Since zope.app.container=3.5.6 is part of the blacklist, the script suggests the version just below it: zope.app.container=3.5.5.

Automatic discovery of the Zope Toolkit version list

I'm using these two options in this special Zope Toolkit buildbot: http://buildbot.afpy.org:8018/waterfall

This buildbot automatically upgrades one package version (builder at the left), then run the tests. If tests fail, the package is added in the blacklist (builder at the right). In the next run, the buildbot will choose the version just below. If tests fail, it will downgrade again. If tests pass, it will remember the current versions and try to upgrade another package. When the buildbot finally reach a stable state, we automatically get all the latest working versions.

During the first cycles, the buildbot has given the following behaviour :

  • it started with ZTK 1.0a2
  • it upgraded (arbitrary) zope.dublincore 3.6.0 -> 3.6.3
  • tests failed
  • it added zope.dublincore 3.6.3 in the blacklist
  • it upgraded zope.dublincore 3.6.0 -> 3.6.2
  • tests failed
  • it added zope.dublincore 3.6.2 in the blacklist
  • it upgraded zope.dublincore 3.6.0 -> 3.6.1
  • tests failed
  • it added zope.dublincore 3.6.1 in the blacklist
  • so it keeps zope.dublincore 3.6.0 (until 3.6.4 is released)
  • it upgraded lxml 2.2.6 -> 2.2.7
  • tests passed
  • lxml 2.2.7 is kept for future builds
  • etc....

The cycle is not optimal, because zope.dublincore 3.6.3 maybe works well when upgraded with another package. So maybe I should try the opposite: upgrading packages bottom up, one by one, until the highest one is reached.

Zope 3 s'appelle dorénavant BlueBream !

written by ccomb, on Jan 27, 2010 8:12:00 PM.

BlueBream, the Zope Framework.

Un renommage qui aurait dû avoir lieu depuis très lontemps ! Pour ceux qui ont du mal à suivre (et ça se comprend), une petite explication de texte : la réécriture de Zope 2, démarrée il y a 8 ans, et qui a longtemps été appelée « Zope 3 », a consisté à créer une architecture modulaire et innovante, la « Zope Component Architecture » (ZCA), puis à découper proprement Zope et une multitude de paquets utilisant cette architecture. Cet ensemble de paquets, cohérents et compatibles entre eux a été nommé tout d'abord « KGS » (Known Good Set), puis renommé courant 2009 en « Zope Toolkit ». Le Zope Toolkit (ZTK) est l'ensemble des bibliothèques Zope, utilisées maintenant par tout l'écosystème Zope : Zope 2, Plone, Grok, etc... Plus de 900 paquets sont taggés « Zope 3 » dans PyPI !

Nous avons donc l'architecture (la ZCA) et l'ensemble des bibliothèques (le ZTK). Mais où est le serveur d'application dans tout ça ? Rappelons que l'idée originale était de réécrire Zope 2, donc il manque quelque chose. Est-ce Zope 3 ? Oui, mais Zope 3 ça ne veut plus rien dire : le concept Zope 3 a été éclaté en morceaux, et même le nom Zope 3 a fini par se noyer au milieu du reste. On avait presque oublié qu'on pouvait créer une application en pur Zope 3. Un coup de zopeproject et c'était parti !

C'était sans compter sur l'initiative de Baiju M., qui a pris le risque de renommer Zope 3 (le serveur d'application) en BlueBream, et de relancer la machine buzz et documentation ! La vidéo fait sourire, mais on ne peut rien lui reprocher, vu l'énergie qu'il déploie actuellement. Globalement son effort a été extrêmement bien accueilli et encouragé par la communauté. BlueBream, en soi, ne contient pas grand chose, c'est un simple template de projet du même genre que zopeproject, grokproject, django-admin.py startproject ou autres zf.sh create project. C'est donc une nouvelle identité, un nouveau logo et une nouvelle dynamique de contribution. Dans BlueBream, il n'y a absolument rien d'autre que les paquets du Zope Toolkit, c'est donc bien du Zope 3 pur. Il n'y a même pas de namespace bluebream et ce n'est pas à l'ordre du jour.

Voici quelques ressources utiles pour s'informer et suivre l'actualité BlueBream :

Petit tutoriel de démarrage

La documentation officielle explique ça très bien en anglais, mais je vous en fais une en français.

Création d'une application

Avant tout, assurez-vous d'avoir Python 2.5 ou 2.6 et les bons paquets de développement, sur Debian/Ubuntu ça ressemble à ça:

$ sudo aptitude install python-dev build-essential libxml2-dev libxslt1-dev

On commence par installer la dernière version de Distribute:

$ wget http://python-distribute.org/distribute_setup.py
$ sudo python distribute_setup.py

Maintenant on installe le paquet bluebream (0.1.9 à la date de cet article), qui est minuscule et n'a pour dépendances que Sphinx-PyPI-upload, PasteScript, PasteDeploy et Paste.:

$ sudo easy_install bluebream

C'est tout, maintenant on peut démarrer un nouveau projet BlueBream. Remarquez que la méthode est la même que pour un projet Pylons, BFG, Plone ou n'importe quoi pris en charge par un template Paste. Vous devez répondre au moins à la première question en donnant le nom de votre projet, ce qui aura pour effet de créer un dosser du même nom. Pour tout le reste, vous pouvez appuyer sur Entrée.

$ paster create -t bluebream

Maintenant on rentre dans le dossier, et on construit l'application grâce à Buildout (Je suppose que votre projet s'appelle monprojet)

$ cd monprojet
$ python bootstrap.py
$ ./bin/buildout

Avant de lancer buildout, un bon conseil est de configurer le dossier partagé pour les paquets Python, qui évitera de les re-télécharger dans chaque buildout ou projet : vous devriez avoir un fichier ~/.buildout/default.cfg contenant ça :

[buildout]
eggs-directory = /home/ccomb/buildout-eggs

Si tout s'est déroulé correctement, vous devriez avoir un dossier bin contenant : breampy, buildout, paster, test. (Installez la dernière version de Virtualenv, créez un environnement isolé avec virtualenv --no-site-packages --distribute monprojet, activez le avec source bin/activate et recommencez sans sudo à partir de l'installaton de bluebream.)

Vous pouvez maintenant démarrer votre application:

$ bin/paster serve deploy.ini

Puis accéder à la page par défaut sur http://127.0.0.1:8080/

Page d'accueil BlueBream

Vous pouvez aussi démarrer en utilisant debug.ini, ce qui active divers outils de debug, dont un middleware WSGI très utile, pour afficher le traceback dans le navigateur et même inspecter les variables de manière interactive.

Quelque chose de nouveau par rapport à Zope 3.4, il y a une commande shell qui permet de se retrouver dans l'environnement de l'application, et d'accéder directement à la racine de base de données pour l'inspecter (objet root). Cette commande shell est l'équivalent du debugzope ou zopectl debug des versions précédentes de Zope 2 ou Zope 3.:

$ bin/paster shell debug.ini
>>> root
<zope.site.folder.Folder object at 0x46319b0>

On voir que l'objet racine de la ZODB est maintenant pris en charge par un nouveau paquet zope.site. On a aussi accès à un objet debugger ou app (c'est le même), provenant de zope.app.debug, et permettant de simuler une requête ou d'avoir accès à l'objet DB. Par exemple si vous voulez vider l'historique de la ZODB (ce qu'on appelle faire un « pack »), il suffit de taper ça dans le shell de debug:

>>> app.db.pack()

Modifier la page d'accueil

Pour comprendre d'où vient la page d'accueil que vous voyez sur http://localhosts:8080 , il suffit de regarder dans le dossier src/monprojet/main/. Dans le fichier configure.zcml, une vue est configurée :

<browser:page
   for="zope.site.interfaces.IRootFolder"
   name="index"
   permission="zope.Public"
   class=".views.RootDefaultView"
   />

Cette déclaration signifie : « J'ai une vue disponible pour l'objet racine (celui fournissant l'interface IRootFolder). Cette vue est gérée par la classe RootDefaultView, la vue a pour nom « index », qui sera le nom visible dans l'URL, et cette vue est publique (permission zope.Public). »

La vue est une simple classe Python visible dans le fichier views.py, et on peut voir que la vue renvoie elle-même la page HTML, sans même utiliser de langage de templating :

class RootDefaultView(BrowserView):

    def __call__(self):
        return """\
<html><head><title>Welcome to BlueBream!</title></head><body>
<h1>Welcome to BlueBream!</h1>
<ul>
(...)

Dans cette page d'accueil, on peut déjà s'authentifier en cliquant sur login, avec le mot de passe admin/admin. On peut ensuite cliquer sur Add a sample application pour ajouter une Sample Application. Cette SampleApplication n'est rien d'autre qu'un conteneur qui sera ajouté à la racine de la ZODB. Elle est définie dans le fichier app.py:

class SampleApplication(BTreeContainer):

  implements(ISampleApplication)
  name = u""
  description = u""

Tout ceci fait penser un peu à l'interface d'accueil de Grok qui permet d'« ajouter une application ». Ça ne sert pas à grand chose, à part montrer un exemple simple de formulaire, et d'ajout de contenu hiérarchique dans la ZODB. Si vous créez votre propre application, vous pouvez supprimer ces classes d'exemples, redéfinir la vue pour l'objet racine, de préférence en utilisant le templating par défaut de Zope : le ZPT.

Pour remplacer cette page d'accueil, commencez par supprimer la méthode __call__ de la vue RootDefaultView, car cette méthode surcharge celle de la classe parente (BrowserView). De cette façon on bénéficie à nouveau de la méthode de publication par défaut de BrowserView, qui peut faire appel à un template configuré en ZCML.

Dans view.py :

class RootDefaultView(BrowserView):
    pass

Et dans configure.zcml :

<browser:page
   for="zope.site.interfaces.IRootFolder"
   name="index"
   permission="zope.Public"
   class=".views.RootDefaultView"
   template="accueil.pt"
   />

Ensuite évidemment il faut créer le template pour l'accueil (fichier accueil.pt) :

<html><body>

<h1>Accueil</h1>

<p>Bonjour, la classe de l'objet racine (le contexte de cette vue) est :
  <span tal:content="python: context.__class__.__name__" style="color: blue">
  nom de la classe
  </span>
</p>

<p>
  Le user-agent de mon navigateur est :<br/>
  <span tal:content="python: request['HTTP_USER_AGENT']" style="color: blue">
  contenu de la requête
  </span>
</p>

</body></html>
Accueil modifié

La vue étant un double adaptateur sur le contexte (qui dans ce cas est l'objet racine) et sur la requête. Ces deux objet sont donc disponibles dans la vue en Python via self.context et self.request. Ces deux objet sont même transmis par défaut au template via les variables context et request. De cette façon, on peut accéder à l'objet racine et connaître le nom de sa classe (voir la capture d'écran), et à l'objet requête ce qui permet de récupérer entre autres le User-Agent, ou d'autres informations liées à la requête, comme l'utilisateur authentifié.

C'est tout pour aujourd'hui.