How to get log files rotate in Zope with buildout


– Update : this tip requires Zope 2.11 or Plone 4 –

Zope server includes natively some undocumented option since Zope 2.10 2.11 that allows to rotate log files. They started from the Gilles Lenfant work for iw.rotatezlogs.

The only documenation I found was in ZConfig module test by searching about ‘max-size’ : http://svn.zope.org/ZConfig/trunk/ZConfig/components/logger/tests/test_logger.py?view=markup

To use it in your buildout you should add following code in each intance part :

event-log-custom =
    <logfile>
        path ${buildout:directory}/var/log/instance.log
        #max-size = 5mb
        when D
        old-files 366
    </logfile>

access-log-custom =
    <logfile>
        path ${buildout:directory}/var/log/instance-Z2.log
        #max-size = 5mb
        when D
        old-files 366
    </logfile>

That’s all folks !

2010 : les liens de la semaine 4


Cette  rubrique va sans doute devenir mensuel suite à la fusion de la partie Python avec la rubrique de l’AFPY. Au programme de cette semaine : Les grammaires en  Python, quelques liens utiles et beaucoup de lien autour des frameworks Web :

Python WAW 2010 : Semaine 4

Une question qui revient souvent : mais où allons-nous héberger notre projet ?

Une page wikipedia a été créé dans le but de recenser les plateformes d’hébergement de projets qu’elles soient gratuites ou payantes :

Comparison of open source software hosting facilities

Enfin un article qui montre qu’il est possible d’écrire un sélectionneur de thème en 200 secondes en jQuery :

Quick Tip: How to Create a Theme-Switcher in 200 Seconds

Week 53 web logs


Python

Tarek Ziadé a écrit le plus utile des tutoriels : How to version your Python projects. Il décrit en quelques pages les bonnes pratiques pratiquées dans la communauté pour géré la numéroration des distributions et comment mettre en place rapidement  le versionnage depuis un environnement de développement mercurial. Ce dernier point jette un pavé de plus pour l’utilisation de ce DRCS qui devrait devenir le standard de la communauté ces prochaines années.

Paul Wilson et Chris McDonough ont cherché un moyen d’implémenter les fonctions génériques chères à Guido Van Rossum. Le résultat de leur recherches a été publié dans la liste de diffusion Zope-dev : Zope3 and Generic Functions

Dans un cycle la fin et le début se confondent

Cette année se termine et ce blog va se franciser de plus en plus pour améliorer la visibilité des communautés françaises des utilisateurs de Python, Zope et Plone.

Week 50 web logs


Python

Zope

Plone

On move for Lyon and Plone


I leave Alterway two monthes ago for Quadra Informatique. It is a  more generic service company that choose Plone 4 years ago, and more recently Magento. They not seemed to be very active in the  community for now because they mainly proposed patches and features inside existing products more than creating their own products. They have some good products in their boxes and we prepare some official releases for September and others for the end of the year. These projects will be released under Cecil-B license (http://www.cecill.info/licences.en.html) a BSD-like license.

I will not only developping with Plone for them… and I’m leaving Paris this week to go in Lyon. The goal is  to develop Zope/Plone as a local company in this city that choosed Zope/CPS to develop their website some years ago. For some problems that only french telecom legislation can create I will not have a regular network connexion until the end of August.

Have a good vacation and see you in September.

Le libre en question


Aujourd’hui un client nous met le couteau sous la gorge d’une manière assez peu banale. Il y a quelques années il a choisi de prendre une plateforme libre pour développer ses outils internes et une partie des services qu’il propose à ses clients.

Son choix a été de prendre Plone pour les raisons suivantes :

  • pas de coût de licence
  • un développement via l’interface web de Zope quasiment sans avoir à écrire de code
  • une documentation abondante et une communauté réactive
  • présence en France d’acteurs majeurs du développement international de la plateforme
  • une licence libre (la GPL) qui lui permet de penser que la plateforme ne deviendra jamais propriétaire

Le projet a eu des hauts et des bas. Il y a eu des formations externes, de la maintenance externe, du développement interne et externe. Globalement le projet a dépassé les espérances et est passé en mode industriel il y a un an. Le client possède toutes les sources et la connaissance de son applicatif. Il est maître de son destin. Avec le recul il est satisfait de cette plateforme et de son coût.

Ayant acquis une maitrise certaine de la gestion de contenu dans son corps de métier, ce client aimerai développer un module métier qu’il utilisera pour lui dans un premier temps, mais qu’il compte aussi revendre à ses concurrents à moyen terme. Pour cela ce module sera vedu comme une technologie propriétaire. Cela soulève une série de questions politiques et juridiques en interne (attention, certains de ces arguments sont partiellement erronés ) :

  1. si un site web utilise du code GPL pour fournir un service à des clients, un client peut demander à avoir accès au code source de l’application puisqu’il paie pour ce service
  2. si nous fournissons des sources sous GPL notre code source ne peut être commercialisé à des tiers sans qu’ils soient obligés de reverser ce code dans le domaine public
  3. si nous utilisons une extension sous GPL tout le code source devient GPL

Sur le fond je comprends la démarche de la vente d’un savoir faire que l’on veut protéger. Chez ce client tout ces constats ont amené a une réponse : pour faire du propriétaire il faut se baser sur une technologie propriétaire qui permet de faire ce que l’on veut une fois achetée.

Que faire ? Faut-il abandonner tous les développements en Plone  ? Il est tout à fait possible de réaliser un tel module propriétaire avec Zope et de l’intégrer avec d’autres systèmes sans que cela pose de problèmes de licence. Par contre, le Core de Plone 2 et de Plone 3 sont sous licence GPLv2 ce qui provoque un certain malaise. En anticipant de tels questionnements, la fondation Plone a décidé que le Core de Plone 4 serait sous licence BSD et  qu’elle accepterait que les modules d’extensions soient sous licence compatibles LPGL et GPL. Elle accepte aussi que des plateformes sous licence propriétaire soit développé à partir de Plone.

Dans notre cas précis ce questionnement est orienté : il faut vendre notre savoir faire pour générer des royalties et améliorer la rentabilité. Pour cela le choix d’une technologie libre est risquée et il faut adopter en masse une technologie propriétaire quitte à remettre en cause les développements en cours. Les coûts à justifier sont tels qu’il n’est pas possible de tolérer qu’un autre technologie puisse damer le pion à la technologie propriétaire à court terme car le choix de la technologie propriétaire est celui fait à moyen terme.

Il nous est proposé de fournir un canva pour fabriquer ce module dans la technologie propriétaire qui soit intégrable à Plone. Et dans tous les cas Plone va être abandoné. Autant nous mettre la corde au cou nous-même et attendre le bourreau.

Write a toolbox for a Plone 2.5 product


For years we have had the need to embed a utility in Plone products that allows us to execute private methods in restricted Python mode. You need such a utility when using a ZMI Python script in a Page Template or in an Expression. The last one is a CMFCore class that is used in workflow transition condition or in Archetypes field condition for example. To be able to do this utility you need to create a ‘portal tool’ for your site with some public methods. Here I will show you how to build a very basic utility that I can use in the next blog entry.

What is a tool

In pure Zope 2/CMF, a tool is a unique item with a forced id that inherits from the SimpleItem class. An instance of a tool is always created on the root of your Plone site to be acquirable from everywhere in the site.

The CMFCore product provides a function that allows us to call a tool in an unique way: ‘getToolByName’.
In python modules, external methods, or python scripts, you can use following code:

from Products.CMFCore.utils import getToolByName
mytool = getToolByName(obj or context, 'tool id', default value is not found - None if not specified)

You can use it in Page Template too, using the ‘module’ call:

python:modules['Products.CMFCore.utils'].getToolByName(here, 'tool id')

Implementation

What should a tool module contain

Now back to our implementation.

First you need to have a product to write in. To create a new product please read this howto , or download someone else’s to play with.
In your product create a file called ‘tool.py,’ if there will be only one tool in your product, or ‘myfunctiontool.py’ if there will be more than one. As a best practice, I recommend to always choose the second way.

A simple tool code could be:

from OFS.SimpleItem import SimpleItemfrom Products.CMFCore.utils import UniqueObject

from AccessControl import ClassSecurityInfo

from Globals import InitializeClass

class ProductNameTool(SimpleItem, UniqueObject):

    """ Description of what your tool handle
    """

    id = 'portal_productname'

    meta_type = 'Product Name Tool'

    manage_options = SimpleItem.manage_options
    security = ClassSecurityInfo()

InitializeClass(ProductNameTool)

Description of imported items:

  • SimpleItem is a class coming from Zope that ensures us that we have persistence and base views available in ZMI.
  • UniqueObject is a utility class coming from CMF that ensures us that nobody can rename an instance of it. It’s important for us because our tool must never be renamed by error.
  • ClassSecurityInfo is the class to use in every Zope persistent class in order to define the security of each method.
  • InitializeClass is the helper function that registers our class in the Zope context.

Description of class attributes:

  • The id must be unique on your site root and should start with ‘portal_’ or end with ‘_tool’. If your tool unherit from ZCatolog the id must be suffixed by ‘_catalog’.
  • All classes must have a meta type. You can just extend your class name with spaces.
  • manage_options contains the tabs displayed in the ZMI.
  • security defines the security in your class. All classes must contain such a declaration.

Initialize our tool at Zope startup

Now that Zope knows that you have a tool, what about Plone? Plone requires an extra step in order to register our tool (full details in: "Write your first Zope 2 product".
We have to edit the __init__.py file of our product and add following lines:
 

from Products.CMFCore.utils import ToolInit

from myfunctiontool import ProductNameTool

tools = (ProductNameTool,)


def initialize( context ):

    ToolInit( 'My Product Tools'
                , tools=tools
                , product_name='ProductName'
                , icon='tool.gif'
                ).initialize( context )

ToolInit is a class that handles tool registration for us. We can register all tools defined in our product in only one pass.
ProductNameTool is our tool class. Here we need to import all tool classes we want to register.

At last, we call the ToolInit constructor and run its ‘initialize‘ method to build our tool factories:

  • the first parameter is the name viewed in the Add dropdown menu in the ZMI
  • tools is a tuple of classes
  • product_name should contain the name of your product
  • icon is the name of the icon displayed in the ZMI (16×16) that must be on the root of your product

We can restart Zope then add the tool in the ZMI. After that, we can add methods to this tool. Most often these methods are public or protected by ‘View’ or ‘Manage portal’ permissions.

Future of Zope 2 tools

In Zope 3 tools are becoming utilities. In Plone 3 we are in limbo, with all old Zope 2 tools registered both as tools and as utilities. In the near future, however, only the utilities will be used. Use Tool for Plone 2.5 development only.

You can read more about utilities in Zope 3 and Plone 3 documentation.

How to hide a column in CPS with CPSSkins


Since few weeks I went back in CPS to make maintenance on it. I was a CPS core developper, three years ago…
I’m customing a CPS theme with CPSSkins. It could be a very cool product if a documentation exists.
It was so in advanced on web2.0 that only few people really used it outside its main developper and Nuxeo team.

It’s the first article on CPS and not the last one.

a quick recipe to explain how to hide a skin in a part of your site

The goal is to hide the right column when the ‘projects_results’ template is used

  1. login with site Manager rights
  2. in the portal box cloick on ‘Edit themes’
  3. duplicate ‘Fille’ page and named it ‘SansColonne’
  4. switch to layout mode
  5. set column number to 1 in the main block
  6. go in the ZMI on the site root and edit the .cpsskins_theme script with the following code
theme_id = 'mysitetheme'

if REQUEST is None:
    REQUEST = context.REQUEST

if not context.portal_membership.isAnonymousUser():
    return '%s+Authenticated' % theme_id
elif REQUEST.get('PUBLISHED').getId() == 'index_html':
    return '%s+HomePage' % theme_id
elif REQUEST.get('URL').endswith('projects_results'):
    return '%s+SansColonne' % theme_id
else:
    return '%s+Fille' % theme_id

Write functionnal doctests with files in forms


A short bill about testing forms with files.

First you need to setup you environment using your site policy product then your
product to test. The function setUpDefaultMembersAndFolder create the
structure with access rights positioned. After that you can focus yourself on
Formula module test.

Test Formule creation process
=============================

For the test you need to create three Nomenclatures and two Validation Process.

First, some set-up:

    >>> from Products.Five import zcml
    >>> import Products
    >>> import iw
    >>> zcml.load_config('configure.zcml', package=iw.sitepolicy)
    >>> zcml.load_config('configure.zcml', package=Products.Formula)

    >>> from iw.sitepolicy.tests import utils
    >>> utils.setUpDefaultMembersAndFolder(self)

    >>> from Products.Five.testbrowser import Browser
    >>> browser = Browser()
    >>> browser.handleErrors = False

Let us log all exceptions, which is useful for debugging. Also, clear portlet
slots, to make the test browser less confused by things like the recent portlet
and the navtree.

    >>> self.portal.error_log._ignored_exceptions = ()
    >>> self.portal.left_slots = self.portal.right_slots = []

Import needed for testing file in forms

    >>> import cStringIO
    >>> portal_url = self.portal.absolute_url()

We will need of cStringIO to create fake files.

Now we will logon with an user and jump directly into working folder.

    >>> browser.open('%s/logout' % portal_url)
    >>> browser.open(portal_url + '/login_form')
    >>> browser.getControl('Login Name').value = 'jdoe'
    >>> browser.getControl('Password').value = 'secret'
    >>> browser.getControl('Log in').click()
    >>> 'John Doe' in browser.contents
    True
    >>> browser.open(self.formula_folder.absolute_url())
    >>> browser.url
    '.../formula...'

Verify that an author keeps modification and creation rights

    >>> self.formula_folder.absolute_url()+'/edit' in browser.contents
    True

    >>> self.formula_folder.absolute_url()+'/createObject?type_name=BaseFormula' in browser.contents
    True

self.formula_folder is set in setUpDefaultMembersAndFolder.

Now we can fill the form and test the result. Document’s id is the filename
prefixed by ‘formula_‘ and document’s title is the first file line.

Create a new Formula for with special pink flavor

    >>> browser.getLink('Add Base Formula').click()
    >>> 'portal_factory' in browser.url
    True
    >>> browser.getControl(name='special').value = u"pink flavor"
    >>> browser.getControl(name='formula_file').add_file(cStringIO.StringIO('Pink flavor\n   etc'), 'text/plain', "32048432.txt")
    >>> browser.getControl('Save').click()
    >>> 'Changes%20saved' in browser.url
    True
    >>> browser.getLink('View').click()
    >>> '<h1>Pink flavor</h1>' in browser.contents
    True
    >>> print browser.url

http://nohost/plone/folder1/formula_folder/formula_32048432

If you want to do the same with Plone 2.5 – Zope 2.9 – you will have an error
because the ‘add_file‘ is not implemented on FileControl. You need to use
following code:

getControl(name='formula_file').mech_control.add_file

ArchGenXML et le futur de la génération de code sous Zope/Plone


Cela faisait un bon moment que je n’avais pas écrit un billet ici… et pour cause: on temps libre est principalement occupé par le développement et les tests de la version 2.0 de ArchGenXML. Contrairement à la version 1.5 qui ciblait Plone 2.1avec une compatibilité Plone 2.5 cette version est construite autour du support de Plone 3.0 avec une compatibilité vers Plone 2.5.

Les buts atteints de cette version sont le passage en egg de ce module, le support des profils Generic Setup , la génération des interfaces Zope3, la généaration des tests unitaires et des tests fonctionnels en python et au format doctest. Des gros changement en perspective, et une incompatibilité avec la génération précédente. Nous restons bloqués en phase d’évaluation béta par manque testeurs. Nous cherhcons en particulier des testeurs pour la partie génération de workflows.

L’autre nouveauté, plus contraignante celle-ci, est l’utilisation de nouveaux connecteurs dans les schémas UML pour symboliser les ‘adapter’. Les versions précédentes d’ArchGenXML se satisfaisaient d’éditeurs utilisant UML 1.4 et il faut à présent des éditeurs utilisant UML 2.0 au minimum pour cette nouvelle fonctionnalité. Exit donc les éditeurs tel que ArgoUML qui était le seul éditeur UML libre supporté. J’ai passé beaucoup de temps à tester d’autres éditeurs libre comme gaphor, umbrello et papyrus (une extension d’eclipse). Pour l’instant aucun ne permet d’être utilisé avec ArchGenXML. Du coté des éditeurs propriétaires Poseidon UML est toujours supporté avec son nouveau système de rente pour la version communautaire. Par contre le greffon Apollo pour eclipse du même éditeur n’est pas du tout utilisable. Si vous connaissez un bon éditeur UML 2.0 faites-le moi savoir.

Le test du plugin Apollo m’a montré une vue intéressante de la génération de code : la vue du développeur. Avec un projet Java et ce greffon dans eclipse il est possible d’attacher un schéma UML à chaque package Java puis de faire évoluer le diagramme de classe en même temps que le code et réciproquement. Ce greffon prend en charge l’ingénieurie inverse des fichiers Java comme la génération de code puis la synchronisation entre les deux. C’est particulièrement bluffant. Il existe déjà des outils pour faire ces opérations en Python, mais ceux-ci ne peuvent pas être réunis en un seul pour faciliter la vie des développeurs Python. Pour atteindre ce niveau de fonctionnalité il faut un IDE (Pype, WingIDE, Eric, …) et éditeur UML (gaphor, umbrello) et un composant d’ingénieurie inverse (python… epydoc et happydoc montrent comment faire).

Du coté du futur de la génération de code, ArchGenXML génère déjà du code Zope 3 (pour son utilisaton dans Plone) et d’autres projets de CMS en python commencent à s’intéresser à cette possibilité (voir la branche Django). Cet été il y a eu un projet « Google Summer of Code » autour de Genesis qui se présente comme le succésseur de ArchGenXML, mais faute de communication ce projet semble être retombé dans les limbes des vaporwares.

Suivre

Recevez les nouvelles publications par mail.

Rejoignez 310 autres abonnés