Author: tziade Date: Sun Mar 19 00:30:11 2006 New Revision: 2657 Modified: cookbook/trunk/recipe57.fr.tex Log: french version
Modified: cookbook/trunk/recipe57.fr.tex ============================================================================== --- cookbook/trunk/recipe57.fr.tex (original) +++ cookbook/trunk/recipe57.fr.tex Sun Mar 19 00:30:11 2006 @@ -9,11 +9,235 @@ \chapter*{Organiser le code dans un paquet} \begin{problem} -Pas encore traduit de l'anglais. +Un paquet est compos� de fichiers Python et ZCML, parfois de Page Templates +et de resources, que ce soit des fichiers CSS, Javascript, ou des images. + +Cette recette explique comment organiser tout ces �l�ments, pour rendre +le paquet facile � maintenir. \end{problem} \begin{solution} -Pas encore traduit de l'anglais. + +\section*{Comprendre ce qu'est un paquet} + +La d�finition d'un paquet en Python est: un r�pertoire contenant des modules +et des sous-r�pertoire, le tout composant un espace de nom ajout� au chemin +de l'interpr�teur. Chaque r�pertoire composant le paquet doit contenir un +fichier \code{\_\_init\_\_.py} pour �tre pris en compte. + +Zope utilise les paquets pour d�finir son code d'extension. Ces paquets +s'appelaient des \textit{Produits} sous Zope 2, puis ont repris le nom plus +pythonique de \textit{paquet} sous Zope 3. Comme l'initialisation d'une +extension se fait par la lecture des directives ZCML, Zope agit comme Python +mais en recherchant pour sa part le fichier \code{configure.zcml} du paquet. + +Aux yeux de Zope, le code peut donc �tre organis� de n'importe quelle mani�re +dans le paquet, du moment qu'il est li� dans le fichier ZCML. Mais pour +faciliter la maintenance et l'�volution, un minimum de structuration est +n�cessaire, bas� sur quelques conventions. + +\section*{D�finir une structure minimum} + +Le plus petit paquet possible est compos� d'un fichier \code{\_\_init\_\_.py} +vide, et d'un fichier \code{configure.zcml} contenant au minimum une directive +\code{configure} vide. + +\codetitle{Le plus petit fichier configure.zcml possible:} +\begin{verbatim} +<configure\> +\end{verbatim} + +Ces deux fichiers sont r�unis dans un dossier, qui est d�clar� dans un fichier +de configuration plac� dans le dossier \textit{INSTANCE/etc/package-includes}. +Zope parcourt au d�marrage \textit{package-includes} pour conna�tre la liste +des paquets � initialiser. Les fichiers de ce dossier doivent avoir un nom +avec un suffixe \textit{-configure.zcml}, et utilisent en g�n�ral le nom +du paquet. Le paquet \textit{dummypackage} aura donc comme fichier de +d�claration \textit{dummypackage-configure.zcml}. + +\codetitle{Le fichier dummypackage-configure.zcml:} +\begin{verbatim} +<include package="dummypackage"/> +\end{verbatim} + +Au d�marrage, Zope int�grera le premier paquet nomm� \code{dummypackage} +trouv� dans son chemin. La meilleure place pour conserver les paquets est +\code{INSTANCE/lib/python}. + +\section*{D�finir une structure plus avanc�e} + +Le paquet \code{dummypackage} va maintenant impl�menter une fonctionnalit� +simple, qui se base sur une structure typique: un nouveau type d'objet +qui conserve en interne le nombre de fois qu'il a �t� appel� par une vue. +Le paquet a donc besoin de d�finir: + +\begin{itemize} +\item Une d�claration d'interface; +\item une classe de contenu. +\item une classe de vue; +\end{itemize} + +\subsection*{D�claration d'interface} + +Toutes les d�clarations d'interface d'un paquet sont r�unies dans un fichier +unique nomm� {interfaces.py}. Cette convention offre: + +\begin{itemize} +\item Une mani�re unique de faire r�f�rence � des interfaces. Par exemple, +l'attribut \code{for} d'une directive \code{browser:view} est toujours de la +forme : \textit{package.interfaces.IMyInterface}. +\item Des facilit�s pour organiser l'h�ritage entre les interfaces. +\end{itemize} + +L'interface de l'exemple se nomme \code{IDummyCounter} et est ajout�e au +fichier \code{interfaces.py}. + +\codetitle{interfaces.py:} +\begin{verbatim} +from zope.interface import Interface + +class IDummyCounter(Interface): + + def count(): + """ returns the counter value + after it has been inc'ed """ + +\end{verbatim} + +\subsection*{Classe de contenu} + +La classe de contenu g�re le compteur, et d�rive d'une classe persistante de +base, qui permet son stockage dans la ZODB. Cette classe est sauvegard�e dans +un fichier portant le m�me nom. + +\codetitle{dummycounter.py:} +\begin{verbatim} +import persistent +from zope.interface import implements +from interfaces import IDummyCounter + +class DummyCounter(persistent.Persistent): + + implements(IDummyCounter) + + def __init__(self, initial=0): + self._count = initial + + def count(self): + self._count += 1 + return self._count + +\end{verbatim} + +\code{DummyCounter} est d�j� fonctionnel. + +\codetitle{Tests de DummyCounter dans un prompt:} +\begin{verbatim} +>>> from dummypackage.dummycounter import DummyCounter +>>> my_counter = DummyCounter() +>>> my_counter.count() +1 +>>> my_counter.count() +2 +>>> my_counter.count() +3 +\end{verbatim} + +\subsection*{Classe de vue} + +Le code en charge de l'affichage des instances de \code{DummyCounter} est une +simple classe d�riv�e de \code{BrowserView}, et appel�e +\code{DummyCounterView}. Comme les vues sont d�clar�es par le biais de +directives \code{browser}, elles sont r�unies dans un fichier \code{browser.py} + +\codetitle{browser.py:} +\begin{verbatim} +from zope.app.publisher.browser import BrowserView + +class DummyCounterView(BrowserView): + + def getCount(self): + return 'I have been seen %d times' % self.context.count() +\end{verbatim} + +\code{getCount} fourni le code sp�cifique aux besoins d'affichage. + +\codetitle{Tests de DummyCounterView dans le prompt:} +\begin{verbatim} +>>> from dummypackage.dummycounter import DummyCounter +>>> my_counter = DummyCounter() +>>> from dummypackage.browser import DummyCounterView +>>> my_counter_view = DummyCounterView(my_counter, None) +>>> my_counter_view.getCount() +'I have been seen 1 times' +>>> my_counter_view.getCount() +'I have been seen 2 times' +>>> my_counter_view.getCount() +'I have been seen 3 times' +\end{verbatim} + +L'ensemble est ficel� dans le fichier ZCML par le biais de quelques +directives \code{browser}. + +\codetitle{configure.zcml final:} +\begin{verbatim} +<configure + xmlns="http://namespaces.zope.org/zope" + xmlns:browser="http://namespaces.zope.org/browser" + i18n_domain="zope" + > + + <content class=".dummycounter.DummyCounter"> + <require permission="zope.View" + interface=".interfaces.IDummyCounter" /> + </content> + + <browser:page + for=".interfaces.IDummyCounter" + name="counter.html" + permission="zope.View" + class=".browser.DummyCounterView" + attribute="getCount" + /> + + <browser:addform + schema=".interfaces.IDummyCounter" + label="Add dummy counter" + content_factory=".dummycounter.DummyCounter" + name="AddDummy.html" + permission="zope.ManageContent" + /> + + <browser:addMenuItem + class=".dummycounter.DummyCounter" + title="Dummy Counter" + permission="zope.ManageContent" + view="AddDummy.html" + /> + +</configure> +\end{verbatim} + +\subsection*{Choisir entre structure par modules et dossiers} + +Pour l'instant, notre paquet est compos� de cinq fichiers: + +\begin{itemize} +\item \_\_init\_\_.py: d�clare le dossier comme paquet Python +\item configure.zcml: d�clare � Zope les directives ZCML +\item interfaces.py: groupe les interfaces +\item dummycounter.py: impl�mente la classe de contenu +\item browser.py: impl�mente la classe de vue +\end{itemize} + +Cette structure est bas�e sur des modules, et convient bien � l'exemple +pr�sent�. Quand le paquet grossit, il est conseill� d'utiliser des +sous-dossiers pour simplifier le contenu des fichiers. Ainsi \code{interfaces} +et \code{browser} deviennent des dossiers. Dans ce cas, le dossier +\code{browser} contient des modules pour les vues et d�finit son propre fichier +\code{configure.zcml}, inclus dans le fichier ZCML principal. Le dossier +\code{interfaces} d�fini des modules pour les interfaces. + \end{solution} \end{document} -- http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins