Merge lp:~ccomb/zcadoc/book-fr into lp:~baijum/zcadoc/book

Proposed by Christophe Combelles
Status: Merged
Merged at revision: not available
Proposed branch: lp:~ccomb/zcadoc/book-fr
Merge into: lp:~baijum/zcadoc/book
Diff against target: 5672 lines (+2429/-1926)
3 files modified
TODO-fr-generator.py (+0/-178)
TODO-fr.txt (+0/-124)
izca-fr.txt (+2429/-1624)
To merge this branch: bzr merge lp:~ccomb/zcadoc/book-fr
To post a comment you must log in.
lp:~ccomb/zcadoc/book-fr updated
106. By Christophe Combelles

some fixes on the french translation

107. By Christophe Combelles

small fixes

108. By Christophe Combelles

fixes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'TODO-fr-generator.py'
2--- TODO-fr-generator.py 2007-12-03 18:27:59 +0000
3+++ TODO-fr-generator.py 1970-01-01 00:00:00 +0000
4@@ -1,178 +0,0 @@
5-from text_table import TextTable
6-from enum import Enum
7-
8-TRANSLATED_STATUS = Enum("WIP", "Y", "N")
9-REREADED_STATUS = Enum("WIP", "Y", "N")
10-DONE_STATUS = Enum("Y", "N")
11-NOTE_LEVEL = Enum("-", "1", "2", "3", "4", "5")
12-
13-
14-heading_content = ("Chapter or section name", "TRANSLATED", "REREADED", "DONE", "NOTE")
15-
16-table_content = (
17- (" * Getting started", TRANSLATED_STATUS.WIP, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
18- (" o Introduction", TRANSLATED_STATUS.Y, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
19- (" o A brief history", TRANSLATED_STATUS.Y, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
20- (" o Installation", TRANSLATED_STATUS.Y, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
21- (" o Experimenting with code", TRANSLATED_STATUS.Y, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
22- (" * An example", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
23- (" o Introduction", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
24- (" o Procedural approach", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
25- (" o Object oriented approach", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
26- (" o The adapter pattern", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
27- (" * Interfaces", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
28- (" o Introduction", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
29- (" o Declaring interfaces", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
30- (" o Implementing interfaces", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
31- (" o Example revisited", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
32- (" o Marker interfaces", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
33- (" o Invariants", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
34- (" * Adapters", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
35- (" o Implementation", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
36- (" o Registration", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
37- (" o Querying adapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
38- (" o Retrieving adapter using interface", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
39- (" o Adapter pattern", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
40- (" * Utility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
41- (" o Introduction", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
42- (" o Simple utility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
43- (" o Named utility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
44- (" o Factory", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
45- (" * Advanced adapters", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
46- (" o Multi adapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
47- (" o Subscription adapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
48- (" o Handler", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
49- (" * ZCA usage in Zope", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
50- (" o ZCML", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
51- (" o Overrides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
52- (" o NameChooser", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
53- (" o LocationPhysicallyLocatable", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
54- (" o DefaultSized", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
55- (" o ZopeVersionUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
56- (" * Reference", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
57- (" o Attribute", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
58- (" o Declaration", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
59- (" o Interface", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
60- (" o adapts", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
61- (" o alsoProvides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
62- (" o classImplements", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
63- (" o classImplementsOnly", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
64- (" o classProvides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
65- (" o ComponentLookupError", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
66- (" o createObject", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
67- (" o directlyProvidedBy", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
68- (" o directlyProvides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
69- (" o getAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
70- (" o getAdapterInContext", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
71- (" o getAdapters", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
72- (" o getAllUtilitiesRegisteredFor", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
73- (" o getFactoriesFor", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
74- (" o getFactoryInterfaces", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
75- (" o getGlobalSiteManager", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
76- (" o getMultiAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
77- (" o getSiteManager", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
78- (" o getUtilitiesFor", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
79- (" o getUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
80- (" o handle", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
81- (" o implementedBy", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
82- (" o implementer", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
83- (" o implements", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
84- (" o implementsOnly", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
85- (" o moduleProvides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
86- (" o noLongerProvides", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
87- (" o provideAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
88- (" o provideHandler", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
89- (" o provideSubscriptionAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
90- (" o provideUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
91- (" o providedBy", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
92- (" o queryAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
93- (" o queryAdapterInContext", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
94- (" o queryMultiAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
95- (" o queryUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
96- (" o registerAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
97- (" o registeredAdapters", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
98- (" o registeredHandlers", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
99- (" o registeredSubscriptionAdapters", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
100- (" o registeredUtilities", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
101- (" o registerHandler", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
102- (" o registerSubscriptionAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
103- (" o registerUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
104- (" o subscribers", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
105- (" o unregisterAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
106- (" o unregisterHandler", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
107- (" o unregisterSubscriptionAdapter", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0]),
108- (" o unregisterUtility", TRANSLATED_STATUS.N, REREADED_STATUS.N, DONE_STATUS.N, NOTE_LEVEL[0])
109-)
110-
111-column_greater_size_content = [0, 0, 0, 0, 0]
112-
113-#summary_value = {
114-# "TRANSLATED" : { "YES" : 0, "WIP": 0 },
115-# "REREADED" : { "YES" : 0 },
116-# "DONE" : { "YES" : 0 }
117-#}
118-
119-summary_value = {
120- TRANSLATED_STATUS.Y : 0,
121- TRANSLATED_STATUS.WIP : 0,
122- REREADED_STATUS.Y : 0,
123- REREADED_STATUS.WIP : 0,
124- DONE_STATUS.Y: 0
125-}
126-
127-for row in (heading_content,) + table_content:
128- for col_index in range(0, len(row)):
129- if (len(str(row[col_index])) > column_greater_size_content[col_index]):
130- column_greater_size_content[col_index] = len(str(row[col_index]))
131-
132- if (summary_value.has_key(row[col_index])):
133- summary_value[row[col_index]] = summary_value[row[col_index]] + 1
134-
135-ascii_table_content = TextTable(
136- *tuple([(column_greater_size_content[i], heading_content[i]) for i in range(0, 5)])
137-)
138-
139-for row in table_content:
140- ascii_table_content.row(*(((row[0]),) + tuple([str(row[col_index]).center(column_greater_size_content[col_index]) for col_index in range(1, len(row))])))
141-
142-
143-summary_content = (
144- ("Translated", str(str(summary_value[TRANSLATED_STATUS.Y]) + " / " + str(len(table_content)) + " (" + str((summary_value[TRANSLATED_STATUS.Y] * 100) / len(table_content)) + " %) , " + str(summary_value[TRANSLATED_STATUS.WIP]) + " in WIP")),
145- ("Rereaded", str(str(summary_value[REREADED_STATUS.Y]) + " / " + str(len(table_content)) + " (" + str((summary_value[REREADED_STATUS.Y] * 100) / len(table_content)) + " %) , " + str(summary_value[REREADED_STATUS.WIP]) + " in WIP")),
146- ("Done", str(str(summary_value[DONE_STATUS.Y]) + " / " + str(len(table_content)) + " (" + str((summary_value[DONE_STATUS.Y] * 100) / len(table_content)) + " %)"))
147-)
148-
149-ascii_summary_content = TextTable((12), (28))
150-for row in summary_content:
151- ascii_summary_content.row(*row)
152-
153-print(
154-"""
155-This file contain some informations about the growth of french
156-translation.
157-
158-This file is generate by TODO-fr-generator.py script file.
159-
160-Summary
161-=======
162-""")
163-
164-
165-print(ascii_summary_content.draw())
166-
167-print("""
168-Detail table
169-============
170-
171-Fields values :
172-
173- * Translated column can be Yes, No, WIP (Work In Progress)
174- * Rereaded column can be Yes, No, WIP (Work In Progress)
175- * Done column can be Yes, No
176- * Note column can be "-" or 1 to 5, it's quality note
177-
178-""")
179-
180-print ascii_table_content.draw()
181-
182-
183
184=== removed file 'TODO-fr.txt'
185--- TODO-fr.txt 2007-12-03 18:27:59 +0000
186+++ TODO-fr.txt 1970-01-01 00:00:00 +0000
187@@ -1,124 +0,0 @@
188-
189-This file contain some informations about the growth of french
190-translation.
191-
192-This file is generate by TODO-fr-generator.py script file.
193-
194-Summary
195-=======
196-
197-.--------------+------------------------------.
198-| Translated | 4 / 92 (4 %) , 1 in WIP |
199-| Rereaded | 0 / 92 (0 %) , 0 in WIP |
200-| Done | 0 / 92 (0 %) |
201-'--------------+------------------------------'
202-
203-
204-Detail table
205-============
206-
207-Fields values :
208-
209- * Translated column can be Yes, No, WIP (Work In Progress)
210- * Rereaded column can be Yes, No, WIP (Work In Progress)
211- * Done column can be Yes, No
212- * Note column can be "-" or 1 to 5, it's quality note
213-
214-
215-.---------------------------------------------+------------+----------+------+------.
216-| Chapter or section name | TRANSLATED | REREADED | DONE | NOTE |
217-+---------------------------------------------+------------+----------+------+------+
218-| * Getting started | WIP | N | N | - |
219-| o Introduction | Y | N | N | - |
220-| o A brief history | Y | N | N | - |
221-| o Installation | Y | N | N | - |
222-| o Experimenting with code | Y | N | N | - |
223-| * An example | N | N | N | - |
224-| o Introduction | N | N | N | - |
225-| o Procedural approach | N | N | N | - |
226-| o Object oriented approach | N | N | N | - |
227-| o The adapter pattern | N | N | N | - |
228-| * Interfaces | N | N | N | - |
229-| o Introduction | N | N | N | - |
230-| o Declaring interfaces | N | N | N | - |
231-| o Implementing interfaces | N | N | N | - |
232-| o Example revisited | N | N | N | - |
233-| o Marker interfaces | N | N | N | - |
234-| o Invariants | N | N | N | - |
235-| * Adapters | N | N | N | - |
236-| o Implementation | N | N | N | - |
237-| o Registration | N | N | N | - |
238-| o Querying adapter | N | N | N | - |
239-| o Retrieving adapter using interface | N | N | N | - |
240-| o Adapter pattern | N | N | N | - |
241-| * Utility | N | N | N | - |
242-| o Introduction | N | N | N | - |
243-| o Simple utility | N | N | N | - |
244-| o Named utility | N | N | N | - |
245-| o Factory | N | N | N | - |
246-| * Advanced adapters | N | N | N | - |
247-| o Multi adapter | N | N | N | - |
248-| o Subscription adapter | N | N | N | - |
249-| o Handler | N | N | N | - |
250-| * ZCA usage in Zope | N | N | N | - |
251-| o ZCML | N | N | N | - |
252-| o Overrides | N | N | N | - |
253-| o NameChooser | N | N | N | - |
254-| o LocationPhysicallyLocatable | N | N | N | - |
255-| o DefaultSized | N | N | N | - |
256-| o ZopeVersionUtility | N | N | N | - |
257-| * Reference | N | N | N | - |
258-| o Attribute | N | N | N | - |
259-| o Declaration | N | N | N | - |
260-| o Interface | N | N | N | - |
261-| o adapts | N | N | N | - |
262-| o alsoProvides | N | N | N | - |
263-| o classImplements | N | N | N | - |
264-| o classImplementsOnly | N | N | N | - |
265-| o classProvides | N | N | N | - |
266-| o ComponentLookupError | N | N | N | - |
267-| o createObject | N | N | N | - |
268-| o directlyProvidedBy | N | N | N | - |
269-| o directlyProvides | N | N | N | - |
270-| o getAdapter | N | N | N | - |
271-| o getAdapterInContext | N | N | N | - |
272-| o getAdapters | N | N | N | - |
273-| o getAllUtilitiesRegisteredFor | N | N | N | - |
274-| o getFactoriesFor | N | N | N | - |
275-| o getFactoryInterfaces | N | N | N | - |
276-| o getGlobalSiteManager | N | N | N | - |
277-| o getMultiAdapter | N | N | N | - |
278-| o getSiteManager | N | N | N | - |
279-| o getUtilitiesFor | N | N | N | - |
280-| o getUtility | N | N | N | - |
281-| o handle | N | N | N | - |
282-| o implementedBy | N | N | N | - |
283-| o implementer | N | N | N | - |
284-| o implements | N | N | N | - |
285-| o implementsOnly | N | N | N | - |
286-| o moduleProvides | N | N | N | - |
287-| o noLongerProvides | N | N | N | - |
288-| o provideAdapter | N | N | N | - |
289-| o provideHandler | N | N | N | - |
290-| o provideSubscriptionAdapter | N | N | N | - |
291-| o provideUtility | N | N | N | - |
292-| o providedBy | N | N | N | - |
293-| o queryAdapter | N | N | N | - |
294-| o queryAdapterInContext | N | N | N | - |
295-| o queryMultiAdapter | N | N | N | - |
296-| o queryUtility | N | N | N | - |
297-| o registerAdapter | N | N | N | - |
298-| o registeredAdapters | N | N | N | - |
299-| o registeredHandlers | N | N | N | - |
300-| o registeredSubscriptionAdapters | N | N | N | - |
301-| o registeredUtilities | N | N | N | - |
302-| o registerHandler | N | N | N | - |
303-| o registerSubscriptionAdapter | N | N | N | - |
304-| o registerUtility | N | N | N | - |
305-| o subscribers | N | N | N | - |
306-| o unregisterAdapter | N | N | N | - |
307-| o unregisterHandler | N | N | N | - |
308-| o unregisterSubscriptionAdapter | N | N | N | - |
309-| o unregisterUtility | N | N | N | - |
310-'---------------------------------------------+------------+----------+------+------'
311-
312
313=== modified file 'izca-fr.txt'
314--- izca-fr.txt 2007-12-03 18:27:59 +0000
315+++ izca-fr.txt 2009-12-11 23:53:09 +0000
316@@ -1,246 +1,270 @@
317-===========================
318-Zope Component Architecture
319-===========================
320-
321-
322-:Auteur: Baiju M
323-:Version: 0.4.1
324-:URL: `http://www.muthukadan.net/docs/zca.pdf
325- <http://www.muthukadan.net/docs/zca.pdf>`_
326-:Traducteur: Stéphane Klein <stephane@harobed.org>
327-
328-Copyright (C) 2007 Baiju M <baiju.m.mail AT gmail.com>.
329+========================================================
330+Le guide complet de l'Architecture de Composants de Zope
331+========================================================
332+
333+:Author: Baiju M
334+:Version: 0.5.8
335+:Printed Book: `http://www.lulu.com/content/1561045
336+ <http://www.lulu.com/content/1561045>`_
337+:Online PDF: `http://www.muthukadan.net/docs/zca.pdf
338+ <http://www.muthukadan.net/docs/zca.pdf>`_
339+:Traducteur: Christophe Combelles <ccomb@free.fr>, Stéphane Klein <stephane@harobed.org>
340+
341+Copyright (C) 2007,2008,2009 Baiju M <baiju.m.mail AT gmail.com>.
342
343 Chacun est autorisé à copier, distribuer et/ou modifier ce document
344-suivant les termes de la "GNU Free Documentation License", version 1.2
345-ou (à votre gré) toute version ultérieur publiée par la Free Software
346+suivant les termes de la « GNU Free Documentation License », version 1.3
347+ou toute version ultérieure publiée par la Free Software
348 Foundation.
349
350 Le code source présent dans ce document est soumis aux conditions de
351-la licence Zope Public License, Version 2.1 (ZPL).
352-
353-LE CODE SOURCE DE CE DOCUMENT EST FOURNI "EN L'ETAT" SANS AUCUNE
354-GARANTIE.
355-
356-.. note::
357-
358- Merci à Kent Tenney (Wisconsin, USA) et Brad Allen (Dallas, USA)
359- pour leurs suggestions.
360-
361+la « Zope Public License », Version 2.1 (ZPL).
362+
363+THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED
364+"AS IS" AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED,
365+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE,
366+MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR
367+PURPOSE.
368+
369+.. sidebar:: Remerciements
370+
371+ De nombreuses personnes m'ont aidé à écrire ce livre. Le brouillon initial a été
372+ relu par mon collègue Brad Allen. Quand j'ai annoncé ce livre sur mon blog, j'ai
373+ reçu de nombreux encouragements pour poursuivre ce travail. Kent Tenney a
374+ modifié de nombreuses parties du livre et a également réécrit l'application
375+ servant d'exemple. De nombreuses autres personnes m'ont envoyé des corrections
376+ et des commentaires, dont Lorenzo Gil Sanchez, Michael Haubenwallner, Nando
377+ Quintana, Stephane Klein, Tim Cook, Kamal Gill et Thomas Herve. Lorenzo a
378+ traduit ce travail en espagnol et Stephane initié la traduction en français. Merci à
379+ toutes ces personnes !
380
381 .. contents::
382 .. .. sectnum::
383
384
385-Premiers pas
386-------------
387+Mise en route
388+-------------
389
390
391 Introduction
392 ~~~~~~~~~~~~
393
394-Le développement de logiciels de grandes tailles (grande quantité de
395-lignes de code...) est toujours une tâche très complexe. L'expérience
396-montre que l'utilisation d'une approche orienté objet simplifie
397-l'analyse, la modélisation et l'implémentation de programmes
398-complexes. Les logiciels informatiques basés sur une architecture et
399-une programmation oriénté composant sont de nos jours de plus en plus
400-populaire. Une grande partie des langages de programmations disposent
401-de framework qui permettent ou simplifient la programmation orienté
402-composant. Certain de ces frameworks sont même compatibles avec
403-plusieurs langages. Parmi ces frameworks orientés composants on trouve
404-par exemple la technologie COM de Microsoft ou alors la technologie
405+Le développement de grands systèmes logiciels est toujours une tâche ardue
406+L'expérience montre que l'approche orientée objet est bien appropriée à
407+l'analyse, à la modélisation et à la programmation des systèmes complexes. La
408+conception orientée composants et la programmation basée sur des composants
409+deviennent actuellement très populaires. L'approche basée composants est d'une
410+grande aide pour l'écriture et la maintenance de systèmes logiciels et
411+de leurs tests unitaires. Il existe de nombreux frameworks permettant la
412+conception basée sur des composants dans différents langages, certains étant
413+même indépendants du langage. On peut citer comme exemple : COM de Microsoft, ou
414 XPCOM de Mozilla.
415
416-L'architecture composant de Zope (nommé ZCA : Zope Component
417-Architecture) est un framework qui permet d'écrire des programmes
418-orientés composants en langage Python. ZCA est très bien adapté pour
419-écrire des programmes Python complexes. Ce framework n'est pas limité
420-au serveur web d'application Zope, il peut être utilisé pour
421-l'écriture de tout type d'application Python, peut être même qu'il
422-devrait être nommé `Python Component Architecture` plutôt que Zope
423-Component Architecture.
424-
425-ZCA dépend principalement de deux paquets:
426-
427- - ``zope.interface`` utilisé pour définir l'interface des
428+La **Zope Component Architecture (ZCA)** est un framework en Python qui autorise
429+la conception et la programmation basée sur des composants. Elle est très bien
430+adaptée au développement de grands systèmes logiciels. La ZCA n'est
431+pas liée au serveur d'application Zope : elle peut être utilisée pour développer
432+n'importe quelle application en Python. Peut-être devrait-elle s'appeler la «
433+Python Component Architecture ».
434+
435+Le but de la ZCA est d'utiliser des objets Python de manière efficace. Les
436+composants sont des objets réutilisables fournissant une interface que l'on peut
437+introspecter. Une interface est un objet qui décrit comment on peut travailler
438+avec un composant particulier. Autrement dit, un composant fournit une interface
439+implémentée dans une classe ou tout autre objet appelable (*callable*). La façon
440+dont le composant est implémenté n'a pas d'importance : ce qui compte est que
441+celui-ci soit en accord avec l'interface. Grâce à la ZCA, vous pouvez éclater la
442+complexité d'un système dans plusieurs composants travaillant ensemble. Elle
443+vous aide à créer notamment deux types de composants : les « adaptateurs » et les «
444+utilitaires ».
445+
446+Trois paquets composent la ZCA :
447+
448+ - ``zope.interface`` est utilisé pour la définition d'une interface.
449+
450+ - ``zope.event`` fournit un système simple d'événements.
451+
452+ - ``zope.component`` sert à la création, l'inscription et la récupération des
453 composants.
454
455- - ``zope.component`` pour réaliser les opérations d'enregistrements
456- et de recherches de composants.
457-
458-ZCA dispose de tout ce qu'il faut pour utiliser efficacement des
459-objets Python. Les composants sont des objets réutilisables disposant
460-d'interface est introspectable. Un composant est un objet disposant
461-d'une interface implémenté par une classe ou tout autre objet
462-exécutable. L'implémentation d'un composant n'est pas l'élément le
463-plus important, ce qui compte avant tout c'est sa conformité avec le
464-"contrat" défini par son interface. L'utilisation d'une architecture
465-orienté composant vous permet de diviser la compléxité d'un système à
466-travers de multiples composants coopératifs. L'architecture composant
467-de Zope vous aide à créer deux types de composants de base : des
468-`adapter` et des `utility`.
469-
470-Notez bien que l'architecture composant de Zope ne vous aide pas à
471-écrire les composants eux-mêmes mais elle vous permet la création,
472-l'enregistrement et la recherche de composants.Notez aussi qu'un
473-composant `adapter` est une classe Python tout à fait normal (ou en
474-général une fabrique d'objet (factory)) et qu'un composant `utility`
475-est un objet Python exécutable standard.
476-
477-L'architecture composant Zope est développé comme une partie distincte
478-du projet Zope 3. ZCA, comme indiqué plus tôt, est un framework
479-purement Python, il peut être utilisé pour développer n'importe quel
480-type d'application. Actuellement à la fois Zope 3 et Zope 2 utilisent
481-très fortement ce framework mais il existe de nombreux autres projets
482-et même des applications non orientés Internet qui utilisent
483-l'architecture composant de Zope [#projects]_.
484+Souvenez-vous que la ZCA ne fournit pas de composants par elle-même. Elle n'a
485+pour but que de créer, inscrire et récupérer des composants. Gardez également à
486+l'esprit qu'un adaptateur est une classe Python tout à fait normale (en général
487+une fabrique) et qu'un utilitaire est un simple objet Python appelable.
488+
489+Le framework ZCA est développé comme une partie du projet Zope 3. Comme
490+mentionné plus haut, c'est un framework purement Python et il peut être utilisé
491+dans n'importe quelle application Python. Actuellement, Zope 3, Zope 2 et Grok
492+l'utilisent abondamment. De nombreux autres projets l'utilisent, y compris des
493+applications non liées au web [#projects]_.
494+
495+.. [#projects] http://wiki.zope.org/zope3/ComponentArchitecture
496
497
498 Petit historique
499 ~~~~~~~~~~~~~~~~
500
501-Le développement de la ZCA a débuté en 2001 dans le cadre du projet
502-Zope 3. Ce framework est le fruit de l'expérience aquise durant le
503-développement d'application d'envergure en Zope 2. Jim Fulton est le
504-père de ce projet. De nombreuses personnes ont participé à la
505-conception de ce framework, parmit eux on peut citer : Stephan
506-Richter, Philipp von Weitershausen, Guido van Rossum (créateur du
507-langage Python), Tres Seaver, Phillip J Eby et Martijn Faassen.
508-
509-Par rapport à la version actuel, les premières versions de ZCA
510-disposaient de quelques composants supplémentaires : les composants
511-`services` et les composants `views`. Ils ont été supprimé car les
512-développeurs ont réalisé que le composant `utility` pouvait remplacer
513-le composant `service` et le composant `multi-adapter` pouvait
514-remplacer le composant `view`. La ZCA comporte actuellement un nombre
515-réduit de type de type de composant :les `utility`, les `adapter`, les
516-`subscribers` et les `handler`. En fait, les composants `subscriber`
517-et `handler` sont tous deux des adaptateurs spécialisés.
518-
519-Pendant le cycle de développement de Zope 3.2, Jim Fulton a proposé
520-une importante simplification de l'achitecture composant de Zope
521-[#proposal]_. Parmit ces simplications, on trouve la possibilité en
522-passant par une interface unique de déclarer à la fois des composants
523-globaux et locaux.
524-
525-Le paquet ``zope.component`` a une longue liste de dépendances, parmit
526-elles beaucoup ne sont pas nécessaire aux applications non Zope 3.
527-Pendant le PyCon 2007, Jim Fulton a ajouté à setuptools une nouvelle
528-fonctionnalité nommée `extras_require`. Elle permet de séparer les
529-fonctionnalités constituant le coeur de ZCA des fonctionnalités
530+Le développement de la ZCA a débuté en 2001 dans le cadre du projet Zope 3. Ce
531+framework est le fruit de l'expérience acquise pendant le développement
532+d'applications d'envergure avec Zope 2. Jim Fulton est le père de ce projet. De
533+nombreuses personnes ont participé à sa conception et à son implémentation,
534+notamment Stephan Richter, Philipp von Weitershausen, Guido van Rossum (*aka.
535+Python BDFL*), Tres Seaver, Phillip J Eby et Martijn Faassen.
536+
537+À ses débuts, la ZCA définissait des types de composants supplémentaires : les
538+*services* et les *vues*, mais les développeurs ont fini par réaliser qu'un
539+*utilitaire* peut remplacer un *service* et qu'un *multi-adaptateur* peut
540+remplacer une *vue*. Aujourd'hui, la ZCA comporte un nombre très réduit de types
541+de composants de base : les *utilitaires* (en anglais *utilities*), les *adaptateurs*
542+(*adapters*), les *abonnés* (*subscribers*) et les *gestionnaires* (*handlers*).
543+Et encore, les *abonnés* et les *gestionnaires* sont des cas particuliers de
544+l'*adaptateur*.
545+
546+Pendant le cycle de développement de Zope 3.2, Jim Fulton a proposé une
547+importante simplification de la ZCA [#proposal]_. Grâce à cette simplification,
548+une nouvelle interface unique (`IComponentRegistry`) a été créée pour
549+l'inscription des composants globaux et locaux.
550+
551+.. [#proposal] http://wiki.zope.org/zope3/LocalComponentManagementSimplification
552+
553+Le paquet ``zope.component`` avait une longue liste de dépendances, dont une
554+grande partie n'était pas nécessaire pour une application non liée à Zope 3.
555+Pendant PyCon 2007, Jim Fulton a ajouté la fonctionnalité `extras_require` à
556+setuptools pour permettre d'extraire le cœur de la ZCA des fonctionnalités
557 annexes [#extras]_.
558
559-Maintenant, le projet Zope Component Architecture est un projet
560-indépendant avec son propre cycle de version et son propre dépôt
561-Subversion. Toutefois, les bugs et problèmes sont encore traités à
562-l'intérieur du projet Zope 3 [#bugs]_, et la liste de diffusion
563-zope-dev est utilisé pour les discussions liées aux développements
564-[#discussions]_.
565+.. [#extras] http://peak.telecommunity.com/DevCenter/setuptools#declaring-dependencies
566+
567+En mars 2009, Tres Seaver a supprimé les dépendances à ``zope.deferredimport`` et
568+``zope.proxy``.
569+
570+Aujourd'hui, le projet ZCA est indépendant et possède son propre cycle de
571+publications et son propre dépôt Subversion. Il est fourni avec le framework
572+Zope. [#framework]_. Cependant, les anomalies et les bogues sont toujours pris
573+en charge au travers du projet Zope 3 [#bugs]_ et la liste de diffusion
574+zope-dev est utilisée pour débattre du développement [#discussions]_. Il existe
575+également une liste pour les utilisateurs de Zope 3 (`zope3-users`) qui peut
576+être utilisée pour toute demande au sujet de la ZCA [#z3users]_.
577+
578+.. [#framework] http://docs.zope.org/zopeframework/
579+.. [#bugs] https://bugs.launchpad.net/zope3
580+.. [#discussions] http://mail.zope.org/mailman/listinfo/zope-dev
581+.. [#z3users] http://mail.zope.org/mailman/listinfo/zope3-users
582
583
584 Installation
585 ~~~~~~~~~~~~
586
587-Les paquets ``zope.component`` et ``zope.interface`` forment
588-ensemble le coeur de l'architecture composant de Zope. Ils fournissent
589-les fonctionnalités permettant de définir, déclarer et retrouver des
590-composants. Le paquet ``zope.component`` et ses dépendances sont
591-disponibles sous forme de PythonEggs dans le dépôt PyPI (Python Package
592-Index) [#pypi]_.
593-
594-Vous pouvez utiliser `easy_install` [#easyinstall]_ pour installer
595-``zope.component`` et ses dépendances :
596+Les paquets ``zope.component``, ``zope.interface`` et ``zope.event`` constituent
597+le cœur de la *Zope Component Architecture*. Ils fournissent des outils
598+permettant de définir, inscrire et rechercher des composants. Le paquet
599+``zope.component`` et ses dépendances sont disponibles sous forme d'*egg* dans
600+l'index des paquets Python (PyPI) [#pypi]_.
601+
602+.. [#pypi] Dépôt des paquets Python : http://pypi.python.org/pypi
603+
604+Vous pouvez installer ``zope.component`` et ses dépendances avec `easy_install`
605+[#easyinstall]_ ::
606
607 $ easy_install zope.component
608
609-Cette commande télécharge ``zope.component`` et ses depandances depuis
610-le dépôt PyPI et les installe sur votre système.
611-
612-D'une manière alternative, vous pouvez télécharger manuellement le
613-paquet ``zope.component`` et ses dépendances depuis PyPi puis les
614-installer manuellement. L'ordre d'installation des paquets vous est
615-donné ci-dessous. Sous Windows, vous aurais besoin du paquet binaire
616-de ``zope.interface`` et ``zope.proxy``.
617+.. [#easyinstall] http://peak.telecommunity.com/DevCenter/EasyInstall
618+
619+Cette commande télécharge ``zope.component`` et ses dépendances depuis PyPI et
620+l'installe dans votre *Python path*.
621+
622+Une autre manière de procéder est de télécharger ``zope.component`` et ses
623+dépendances depuis PyPI et de les installer. Il faut installer les paquets dans
624+l'ordre donné ci-dessous. Sous Windows, vous aurez probablement besoin du paquet
625+binaire de ``zope.interface``.
626
627 1. ``zope.interface``
628- 2. ``zope.proxy``
629- 3. ``zope.deferredimport``
630- 4. ``zope.event``
631- 5. ``zope.deprecation``
632- 6. ``zope.component``
633-
634-Pour installer ces paquets après les avoir téléchagré, vous pouvez
635-utiliser la commande ``easy_install`` avec le nom des paquets comme
636-argument (vous pouvez aussi donner la totalité des noms des paquets
637-en argument sur la même ligne)::
638-
639- $ easy_install /path/to/zope.interface-3.4.x.tar.gz
640- $ easy_install /path/to/zope.proxy-3.4.x.tar.gz
641- ...
642-
643-Cette méthode install le framework ZCA dans votre `system Python`, dans
644-le répertoire ``site-packages``... ce qui peut poser certain soucis.
645-Dans un poste présent dans la liste de diffusion Zope 3, Jim Fulton
646-est défavorable à l'utilisation du `system Python` [#systempython]_
647-(c'est à dire à l'installation dans ``site-packages``).
648-
649-
650-Environement d'expérimentation
651-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
652-
653-``virtualenv`` et ``zc.buildout`` sont des outils qui permettent
654-l'installation de la ZCA dans un environement isolé. L'utilisation de
655-ces outils est conseillé lors l'expérimentation de code. De plus, il
656-est bénéfique de se familiariser avec eux car ils sont très pratiques autant
657-lors de la phase de développement que lors du déploiement d'applications.
658-
659-Vous pouvez installer``virtualenv`` via ``easy_install``::
660+ 2. ``zope.event``
661+ 3. ``zope.component``
662+
663+Pour installer ces paquet, après téléchargement, vous pouvez utiliser la
664+commande ``easy_install`` avec les eggs comme argument (éventuellement en
665+fournissant tous les eggs sur la même ligne de commande) ::
666+
667+ $ easy_install /path/to/zope.interface-3.x.x.tar.gz
668+ $ easy_install /path/to/zope.event-3.x.x.tar.gz
669+ $ easy_install /path/to/zope.component-3.x.x.tar.gz
670+
671+Vous pouvez aussi installer ces paquets en les décompressant séparément. Par
672+exemple ::
673+
674+ $ tar zxvf /path/to/zope.interface-3.x.x.tar.gz
675+ $ cd zope.interface-3.x.x
676+ $ python setup.py build
677+ $ python setup.py install
678+
679+Ces méthodes installeront la ZCA dans votre *Python système*, dans le dossier
680+``site-packages``, ce qui peut être problématique. Dans un message sur la liste
681+de diffusion Zope 3, Jim Fulton déconseille d'utiliser le Python système
682+[#systempython]_. Vous pouvez utiliser ``virtualenv`` ou ``zc.buildout`` pour
683+jouer avec n'importe quel paquet Python, et également pour les déploiements.
684+
685+.. [#systempython] http://article.gmane.org/gmane.comp.web.zope.zope3/21045
686+
687+
688+Méthode pour expérimenter
689+~~~~~~~~~~~~~~~~~~~~~~~~~
690+
691+Il existe deux approches populaires en Python pour construire un environnement
692+de travail isolé. La première est ``virtualenv`` créé par Ian Biking, la
693+deuxième est ``zc.buildout`` créé par Jim Fulton. Il est même possible
694+d'utiliser ces paquets ensemble. Ils vous aideront à installer
695+``zope.component`` et d'autres dépendances dans un environnement de
696+développement isolé. Passer un peu de temps à se familiariser avec ces outils
697+vous sera bénéfique lors des développements et des déploiements.
698+
699+**virtualenv**
700+
701+Vous pouvez installer ``virtualenv`` grâce à ``easy_install`` ::
702
703 $ easy_install virtualenv
704
705-Vous pouvez créez ensuite un nouvel environement comme ceci::
706-
707- $ virtualenv myve
708-
709-Cette command a pour effet de créer un nouvel environement virtuel dans le
710-dossier ``myve``. Maintenant, à partir du dossier ``myve``, vous
711-pouvez installer ``zope.component`` et ses dépendances en utilisant
712-l'exécutable ``easy_install`` qui se trouve dans le dossier
713-``myve/bin``::
714+Puis vous pouvez créer un nouvel environnement de cette façon ::
715+
716+ $ virtualenv --no-site-packages myve
717+
718+Ceci crée un nouvel environnement virtuel dans le dossier ``myve``.
719+Maintenant, depuis ce dossier, vous pouvez installer ``zope.component`` et ses
720+dépendances avec le script ``easy_install`` situé dans ``myve/bin`` ::
721
722 $ cd myve
723 $ ./bin/easy_install zope.component
724
725-Vous pouvez maintenant importer les modules ``zope.interface`` et
726-``zope.component`` a partir de votre nouvel interpréteur ``python``
727-qui se trouve dans le dossier ``myve/bin||::
728+Ensuite vous pouvez importer ``zope.interface`` et ``zope.component`` depuis
729+le nouvel interprète ``python`` situé dans ``myve/bin`` ::
730
731 $ ./bin/python
732
733-Cette commande vous donnera une invite de commande Python que vous
734-pouvez utiliser pour exécuter les codes sources de ce livre.
735-
736-L'utilisation de la recette ``zc.recipe.egg`` du paquet
737-``zc.buildout`` vous permet de créer un interpréteur python avec des
738-PythonEggs spécifique. Premièrement, installez ``zc.buildout`` en
739-utilisant la commande ``easy_install`` (Vous pouvez aussi faire cela à
740-l'intérieur d'un environement virtuel). Pour créer un nouveau buildout
741-pour expériement des PythonEggs, commencez par créer un nouveau
742-dossier et initialisez le en utilisant la command ``buildout init``::
743+Cette commande démarre un interprète Python que vous pourrez utiliser pour
744+lancer le code de ce livre.
745+
746+
747+**zc.buildout**
748+
749+En combinant ``zc.buildout`` et la recette ``zc.recipe.egg``, vous pouvez créer
750+un interprète Python ayant accès aux eggs Python spécifiés. Tout d'abord,
751+installez ``zc.buildout`` grâce à la commande ``easy_install`` (vous pouvez le
752+faire à l'intérieur de l'environnement virtuel). Pour créer un nouveau
753+*buildout* servant à expérimenter des eggs Python, commencez par créer un
754+dossier, puis initialisez-le grâce à la commande ``buildout init`` ::
755
756 $ mkdir mybuildout
757 $ cd mybuildout
758 $ buildout init
759
760-Maintenant, le nouveau dossier ``mybuildout`` est un buildout. Le
761-fichier de configuration par défaut du buildout est `buildout.cfg`.
762-Après l'initilisation, il a pour contenu::
763+De cette façon, le dossier ``mybuildout`` devient un « buildout ». Le fichier de
764+configuration de buildout est par défaut `buildout.cfg`. Après initialisation,
765+il doit contenir les lignes suivantes ::
766
767 [buildout]
768 parts =
769
770-Vous pouvez le modifier comme ceci::
771+Vous pouvez le modifier pour qu'il corresponde à ceci ::
772
773 [buildout]
774 parts = py
775@@ -250,319 +274,314 @@
776 interpreter = python
777 eggs = zope.component
778
779-Maintenant exécutez la commande ``buildout`` disponible dans le
780-dossier ``mybuildout/bin`` sans aucun argument. Cela a pour effet de
781-créer un nouvel interpréteur à l'intérieur du dossier
782-``mybuildout/bin``::
783+Si maintenant vous lancez la commande ``buildout`` disponible à l'intérieur du
784+dossier ``mybuildout/bin``, vous obtiendrez un nouvel interprète Python dans le
785+dossier ``mybuildout/bin`` ::
786
787 $ ./bin/buildout
788 $ ./bin/python
789
790-Cette commande vous donnera un invite de commande Python que vous
791-pourrez utiliser pour tester le code source de ce livre.
792-
793-.. [#projects] http://wiki.zope.org/zope3/ComponentArchitecture
794-.. [#proposal] http://wiki.zope.org/zope3/LocalComponentManagementSimplification
795-.. [#extras] http://peak.telecommunity.com/DevCenter/setuptools#declaring-dependencies
796-.. [#bugs] https://bugs.launchpad.net/zope3
797-.. [#discussions] http://mail.zope.org/mailman/listinfo/zope-dev
798-.. [#pypi] Repository of Python packages: http://pypi.python.org/pypi
799-.. [#easyinstall] http://peak.telecommunity.com/DevCenter/EasyInstall
800-.. [#systempython] http://article.gmane.org/gmane.comp.web.zope.zope3/21045
801-
802-
803-An example
804+Cette commande démarre un interprète Python que vous pourrez utiliser pour
805+lancer le code de ce livre.
806+
807+
808+Un exemple
809 ----------
810
811
812 Introduction
813 ~~~~~~~~~~~~
814
815-Consider a business application for registering guests staying in a
816-hotel. Python can implement this in a number of ways. We will start
817-with a brief look at a procedural implementation, and then move to a
818-basic object oriented approach. As we examine the object oriented
819-approach, we will see how we can benefit from the classic design
820-patterns, `adapter` and `interface`. This will bring us into the
821-world of the Zope Component Architecture.
822-
823-
824-Procedural approach
825-~~~~~~~~~~~~~~~~~~~
826-
827-In any business application, data storage is very critical. For
828-simplicity, this example use a Python dictionary as the storage. Key
829-of the dictionary will be the unique Id for a particular guest. And
830-value will be another dictionary with key as the property name::
831-
832- >>> guests_db = {} #key: unique Id, value: details in a dictionary
833-
834-In a simplistic method, a function which accepts details as arguments
835-is enough to do the registration. You also required a supporting
836-function to get the next Id for your data storage.
837-
838-The supporting function, for getting the next Id can be implemented
839-like this::
840+Imaginez une application servant à enregistrer les clients d'un hôtel. En
841+Python, il est possible de faire ceci de différentes manières. Nous allons
842+commencer par étudier rapidement la méthode procédurale, puis nous diriger vers
843+une approche basique orientée objet. En examinant l'approche orientée objet,
844+nous verrons comment nous pouvons bénéficier des motifs de conception
845+`adaptateur` et `interface`. Cela nous fera entrer dans le monde de la Zope
846+Component Architecture.
847+
848+
849+Approche procédurale
850+~~~~~~~~~~~~~~~~~~~~
851+
852+Dans toute application professionnelle, le stockage des données est un point
853+critique. Pour une question de simplicité, cet exemple utilise un simple
854+dictionnaire Python comme méthode de stockage. Nous allons générer des
855+identifiants uniques pour le dictionnaire, la valeur associée sera elle-même un
856+dictionnaire contenant les détails de l'enregistrement.
857+
858+ >>> bookings_db = {} #key: unique ID, value: details in a dictionary
859+
860+Une implémentation minimaliste nécessite une fonction à laquelle on transmet les
861+détails de l'enregistrement et une fonction annexe qui fournit les
862+identifiants uniques utilisés comme clés du dictionnaire de stockage.
863+
864+Nous pouvons obtenir un identifiant unique de cette façon ::
865
866 >>> def get_next_id():
867- ... db_keys = guests_db.keys()
868+ ... db_keys = bookings_db.keys()
869 ... if db_keys == []:
870 ... next_id = 1
871 ... else:
872 ... next_id = max(db_keys) + 1
873 ... return next_id
874
875-As you can see, the `get_next_id` function implementation is very
876-simple. Well, this is not the ideal way, but it is sufficient to
877-explain concepts. The function first get all keys of storage as list
878-and check whether it is empty or not. If the list is empty, so no
879-item is stored, it return `1` as the next Id. And if the list is not
880-empty, the next Id is calculated by adding `1` to the maximum value of
881-list.
882-
883-The function to register guest can get next unique Id using
884-`get_next_id` function, then assign the details of guest using a
885-dictionary. Here is the function to get details and store in the
886-database::
887-
888- >>> def register_guest(name, place):
889+Comme vous pouvez voir, l'implémentation de la fonction `get_next_id` est très
890+simple. La fonction récupère une liste de clés et vérifie si la liste est vide.
891+Si c'est le cas, nous savons que nous en sommes au premier enregistrement et
892+nous renvoyons `1`. Sinon, nous ajoutons `1` à la valeur maximale de la liste et
893+nous renvoyons la nouvelle valeur en résultant.
894+
895+Ensuite, pour créer des enregistrements dans le dictionnaire bookings_db, nous
896+utilisons la fonction suivante ::
897+
898+ >>> def book_room(name, place):
899 ... next_id = get_next_id()
900- ... guests_db[next_id] = {
901+ ... bookings_db[next_id] = {
902 ... 'name': name,
903- ... 'place': place
904+ ... 'room': place
905 ... }
906
907-We will end our discussion of the procedural approach here.
908-It will be much easier to add required features such as data
909-persistence, design flexibility, and code testability using objects.
910-
911-
912-Object oriented approach
913-~~~~~~~~~~~~~~~~~~~~~~~~
914-
915-.. ??? should this paragraph talk about "creating an object for
916- handling registration" or "creating a class to handle registration"?
917-
918-In object oriented methodology, you can think of a registrar object
919-handling the registration. There are many advantages for creating an
920-object for handling registration. Most importantly, the abstraction
921-provided by the registrar object makes the code easier to understand.
922-It offers a way to group related functionality, and can be extended
923-via inheritance. As features are added, such as canceling and updating
924-registration, the registrar object can grow to provide them, or
925-delegate them to another object.
926-
927-Lets look at the implementation details of a registrar object
928-implemented as a class::
929-
930- >>> class guestRegistrar(object):
931+Une application de gestion des enregistrements d'hôtel a besoin de données
932+supplémentaires :
933+
934+ - les numéros de téléphone
935+ - les options des chambres
936+ - les méthodes de paiement
937+ - ...
938+
939+Et de code pour gérer les données :
940+
941+ - annuler une réservation
942+ - Modifier une réservation
943+ - payer une chambre
944+ - stocker les données
945+ - assurer la sécurité des données
946+ - ...
947+
948+Si nous devions continuer l'exemple procédural, il faudrait créer plusieurs
949+fonctions, en renvoyant les données de l'une à l'autre. Au fur à mesure que les
950+fonctionnalités seraient ajoutées, le code deviendrait de plus en plus difficile
951+à maintenir et les bogues deviendraient difficiles à trouver et à corriger.
952+
953+Nous n'irons pas plus loin dans l'approche procédurale. Il sera beaucoup plus
954+facile d'assurer la persistance des données, la flexibilité de la conception et
955+l'écriture de tests unitaires en utilisant des objets.
956+
957+
958+Approche orientée objet
959+~~~~~~~~~~~~~~~~~~~~~~~
960+
961+Notre discussion sur la conception orientée objet nous amène à la notion de
962+« classe » qui sert à encapsuler les données et le code qui les gère.
963+
964+Notre classe principale sera « FrontDesk ». Le FrontDesk et d'autres classes
965+auxquelles il délèguera du traitement, sauront comment gérer les données de
966+l'hôtel. Nous allons créer des instances de FrontDesk pour appliquer cette
967+connaissance au métier de la gestion d'hôtel.
968+
969+L'expérience a montré qu'en consolidant le code et les contraintes sur les
970+données via des objets, on aboutit à un code qui est plus facile à comprendre, à
971+tester et à modifier.
972+
973+Observons les détails d'implémentation de la classe FrontDesk ::
974+
975+ >>> class FrontDesk(object):
976 ...
977- ... def register(self, name, place):
978+ ... def book_room(self, name, place):
979 ... next_id = get_next_id()
980- ... guests_db[next_id] = {
981+ ... bookings_db[next_id] = {
982 ... 'name': name,
983 ... 'place': place
984 ... }
985
986-In this implementation, the registrar object (an instance of
987-`GuestRegistrar` class) is handling the registration. With this
988-design, a particular registrar object can perform multiple
989-registrations.
990-
991-This is how you can use the current registrar implementation::
992-
993- >>> registrar = GuestRegistrar()
994- >>> registrar.register("Jack", "Bangalore")
995-
996-Requirement changes are unavoidable in any real world project.
997-Consider this case, after some time, a new requirement is arising: the
998-guests also required to provide phone number to admit them. You will
999-be required to change the implementation of registrar object to
1000-support it.
1001-
1002-You can achieve this requirement by adding one argument to `registrar`
1003-method and use that argument in the dictionary of values. Here is the
1004-new implementation for this requirement::
1005-
1006- >>> class GuestRegistrar(object):
1007+Dans cette implémentation, l'objet `frontdesk` (une instance de la classe
1008+FrontDesk) est capable de prendre en charge les réservations. Nous pouvons
1009+l'utiliser de la façon suivante ::
1010+
1011+ >>> frontdesk = FrontDesk()
1012+ >>> frontdesk.book_room("Jack", "Bangalore")
1013+
1014+Dans tout projet, on est confronté à des changements de besoins. Dans notre cas,
1015+la direction a décidé que chaque client devait fournit un numéro de téléphone,
1016+donc nous devons changer le code.
1017+
1018+Nous pouvons satisfaire ce nouveau besoin en ajoutant un argument à la méthode
1019+`book_room` qui sera ajouté au dictionnaire des valeurs ::
1020+
1021+ >>> class FrontDesk(object):
1022 ...
1023- ... def register(self, name, place, phone):
1024+ ... def book_room(self, name, place, phone):
1025 ... next_id = get_next_id()
1026- ... guests_db[next_id] = {
1027+ ... bookings_db[next_id] = {
1028 ... 'name': name,
1029 ... 'place': place,
1030 ... 'phone': phone
1031 ... }
1032
1033-Other than migrating the data to new schema, now you have to change
1034-the usage of `GuestRegistrar` in all places. If you can abstract the
1035-details of guest into an object and use it for registration, the code
1036-changes can be minimized. If you follow this design, you have to pass
1037-that guest object instead of more arguments to the function. The new
1038-implementation with guest object will look like this::
1039-
1040- >>> class GuestRegistrar(object):
1041+En plus de devoir migrer les données vers le nouveau schéma, nous devons changer
1042+tous les appels à la classe ``FrontDesk``. Si nous incorporons les coordonnées
1043+de chaque client dans un objet et que nous utilisons cet objet pour les
1044+réservations, les modifications de code pourront être minimisées. Nous pouvons
1045+maintenant changer les détails de l'objet client sans avoir à changer les appels
1046+à FrontDesk.
1047+
1048+Nous avons donc ::
1049+
1050+ >>> class FrontDesk(object):
1051 ...
1052- ... def register(self, guest):
1053+ ... def book_room(self, guest):
1054 ... next_id = get_next_id()
1055- ... guests_db[next_id] = {
1056+ ... bookings_db[next_id] = {
1057 ... 'name': guest.name,
1058 ... 'place': guest.place,
1059 ... 'phone': guest.phone
1060 ... }
1061
1062-Well, even in this implementation you have to change code. Code
1063-change for requirement is unavoidable, your goal should be to minimize
1064-changes and make it maintainable.
1065+Nous devons toujours modifier le code pour répondre aux nouvelles demandes.
1066+C'est inévitable, cependant notre but est de minimiser ces changements et donc
1067+d'améliorer la maintenabilité.
1068
1069 .. note::
1070
1071- You should have the courage to make any change, major or minor, at
1072- any time. Immediate feedback is the only way you can get the
1073- courage. Using automated testing, you can get the immediate
1074- feedback and so the courage to make changes. For more details about
1075- this subject, you can read the book called `Extreme Programming
1076- Explained` by Kent Beck.
1077-
1078-By introducing the guest object, you saved some typing. More than
1079-that, the abstraction of guest object made the system much simpler and
1080-easy to understand. The better understanding leads to better
1081-restructuring and hence maintainable code.
1082-
1083-
1084-The adapter pattern
1085-~~~~~~~~~~~~~~~~~~~
1086-
1087-In a real application, as you noted earlier, the registrar object may
1088-have cancellation and/or updation functionalities. Suppose there are
1089-two more methods like, `cancel_registration` and
1090-`update_registration`. In the new design you will be required to pass
1091-the guest object for each methods. You can solve this problem by
1092-setting guest object as an attribute of registrar object.
1093-
1094-Here is the new implementation of registrar object which set guest
1095-object as an attribute::
1096-
1097- >>> class GuestRegistrarNG(object):
1098+ Lors du développement il ne faut jamais hésiter à faire des changements sans
1099+ craindre de casser l'application. L'avertissement nécessaire doit être
1100+ immédiatement obtenu grâce à des tests automatisés. Avec des tests bien écrits
1101+ (et un bon contrôle de versions), vous pouvez faire impunément des changements
1102+ aussi importants que vous souhaitez. Une bonne source d'informations à propos de
1103+ cette philosophie de programmation est l'ouvrage `Extreme Programming Explained`
1104+ par Kent Beck.
1105+
1106+En introduisant l'objet guest, vous avez économisé un peu de temps. Mais plus
1107+important, l'abstraction apportée par l'objet guest a rendu le système plus
1108+simple et mieux compréhensible. Par conséquent, le code est plus facile à
1109+restructurer et à maintenir.
1110+
1111+
1112+Le motif `adaptateur`
1113+~~~~~~~~~~~~~~~~~~~~~
1114+
1115+Dans une vraie application, l'objet frontdesk devra gérer des fonctionnalités
1116+comme les annulations et les modifications. Avec la conception actuelle, nous
1117+devons transmettre l'objet `guest` au frontdesk à chaque fois que nous appelons
1118+les méthodes `cancel_booking` et `update_booking`.
1119+
1120+Nous pouvons éviter ceci si nous transmettons l'objet `guest` à
1121+FrontDesk.__init__() et si nous le stockons en attribut de l'instance.
1122+
1123+ >>> class FrontDeskNG(object):
1124 ...
1125 ... def __init__(self, guest):
1126 ... self.guest = guest
1127 ...
1128- ... def register(self):
1129+ ... def book_room(self):
1130 ... guest = self.guest
1131 ... next_id = get_next_id()
1132- ... guests_db[next_id] = {
1133+ ... bookings_db[next_id] = {
1134 ... 'name': guest.name,
1135 ... 'place': guest.place,
1136 ... 'phone': guest.phone
1137 ... }
1138-
1139-The solution you reached is a common design pattern called, `Adapter`.
1140-With this design, now you can add more methods, so more functionality,
1141-if required.
1142-
1143-In this implementation, while creating the instance you have to pass
1144-the guest object which has the values as attributes. Now you also
1145-required to create separate instances of `GuestRegistrarNG` for each
1146-guest object.
1147-
1148-Now just step back and think differently. Suppose you are the creator
1149-of this software and selling it to many hotel customers. Consider a
1150-case where your different clients requires different storages. For
1151-example, one registrar might store the details in a relational
1152-database and another one might store them in Zope Object Database
1153-(ZODB). It would be better if you can replace the registrar object
1154-with another one which store guest details in a different way. So, a
1155-mechanism to change implementation based on some configuration would
1156-be useful.
1157-
1158-Zope component architecture provides a mechanism to replace components
1159-based on configuration. Using Zope component architecture you can
1160-register components in a registry called component registry. Later,
1161-retrieve component based on the configuration.
1162-
1163-The `GuestRegistrarNG` class follows, as you noted, a pattern called
1164-`Adapter`. The `GuestRegistrarNG` is the adapter which adapts the
1165-guest object (adaptee). As you can see, the adapter should contain
1166-the component it adapts (adaptee). This is a typical implementation
1167-of adapter::
1168+ ...
1169+ ... def cancel_booking(self):
1170+ ... guest = self.guest
1171+ ... #code for cancellations goes here ...
1172+ ...
1173+ ... def update_booking(self):
1174+ ... guest = self.guest
1175+ ... #code for updatiion goes here ...
1176+
1177+
1178+ La solution que nous avons obtenue est un motif de conception courant appelé
1179+ `adaptateur`. Le `Gang of Four` [#patternbook]_ résume ainsi l'*esprit* de
1180+ l'adaptateur ::
1181+
1182+ « Convertir l'interface d'une classe en une autre interface
1183+ à laquelle le client s'attend. L'adaptateur permet à des
1184+ classes de fonctionner ensemble même si elles ont des
1185+ interfaces incompatibles. »
1186+
1187+En général, un objet adaptateur *contient* un objet adapté ::
1188
1189 >>> class Adapter(object):
1190 ...
1191 ... def __init__(self, adaptee):
1192 ... self.adaptee = adaptee
1193
1194-Now the adapter can make use adaptee (call its methods or access
1195-attributes). An adapter may adapt more than one component. Zope
1196-component architecture provides a mechanism to effectively use these
1197-kind of objects. So, which component should be used will become a
1198-matter of configuration.
1199-
1200-This is a common scenario where you want to use different objects
1201-doing same things, but the details may change. There are many
1202-situations in programming where you want to use different
1203-implementations for same type of objects. Here is a small list of
1204-other common scenarios:
1205-
1206- - A wiki engine with support for multiple markups (STX, reST, Plain
1207- text, etc.)
1208-
1209- - An object browser which shows size of different types of objects.
1210-
1211- - Different types of output formats for text data (PDF, HTML etc.)
1212-
1213- - When developing an application for multiple clients, their
1214- requirements may change. Maintaining separate code bases of the
1215- same application for different clients is difficult. A better
1216- approach would be to create reusable components and configure them
1217- based on client-specific requirements.
1218-
1219-All these examples points to situations where you want to make
1220-applications extensible or pluggable. Do not use `adapter`
1221-components where you do not want extensibility or pluggability.
1222-
1223-Zope component architecture provides `adapter` components to solve
1224-these kinds of problems. In fact, `GuestRegistrarNG` is an adapter
1225-without explicit interface declaration. This tutorial will discuss
1226-adapters after introducing the concept of interfaces. Interfaces are
1227-one of the foundations of Zope components, so understanding the
1228-concept and usage of interfaces is very important.
1229+Ce motif sera utile lorsqu'on sera confronté à des détails d'implémentation qui
1230+dépendent de considérations telles que:
1231+
1232+- modification des besoins client
1233+- modification des méthodes de stockage (ZODB, RDBM, XML)
1234+- modification des méthodes de sortie (HTML, PDF, texte pur)
1235+- modification de la source utilisée (ReST, Markdown, Textile)
1236+
1237+La ZCA utilise des adaptateurs et un *registre de composants* pour fournir la
1238+capacité de changer les détails d'implémentation du code via de la
1239+*configuration*.
1240+
1241+Comme nous pouvons le constater dans la section sur les adaptateurs de la ZCA,
1242+la capacité de configurer les détails d'implémentation fournit des avantages
1243+intéressants :
1244+
1245+- on peut interchanger les implémentations
1246+- on peut ajouter de nouvelles implémentations si besoin
1247+- on améliore les possibilités de réutilisation, aussi bien d'un code existant que
1248+ du code utilisant la ZCA.
1249+
1250+Ces possibilités mènent à du code qui est flexible, évolutif et réutilisable. Il
1251+y a un cependant un coût : maintenir le registre de composants ajoute un niveau
1252+de complexité à l'application. Si une application n'a pas besoin de ces
1253+avantages, la ZCA n'est pas pas nécessaire.
1254+
1255+Nous sommes maintenant prêts à étudier la Zope Component Architecture, en
1256+commençant avec les interfaces.
1257
1258
1259 Interfaces
1260 ----------
1261
1262-
1263 Introduction
1264 ~~~~~~~~~~~~
1265
1266-`Design Patterns` is a classic book in software engineering by the
1267-`Gang of Four` [#patternbook]_. In this book they recommend: "Program
1268-to an interface, not an implementation". Defining formal interfaces
1269-helps you better understand system. Moreover interface brings you all
1270-the benefits of ZCA.
1271-
1272-Interface define the behavior and state of objects. An interface
1273-describes how you work with the object. If you like metaphor, think
1274-of interface as a `contract for object`. Another metaphor which may
1275-help is `blueprint for objects`. In the code, methods and attributes
1276-are forming the object's interface.
1277-
1278-The notion of interface is very explicit in modern languages like
1279-Java, C#, VB.NET etc. Also these languages provide some syntax for
1280-defining interfaces. Python has the notion interfaces, but it is not
1281-very explicit. To simulate a formal definition of interfaces in C++,
1282-`Gang of Four` used classes with virtual functions in `Design
1283-Patterns` book. In a similar fashion, Zope component architecture use
1284-``zope.interface.Interface`` inherited meta-class for defining an
1285-interface.
1286-
1287-The base of object-orientation is the communication between objects.
1288-Messages are used for the communication between objects. In Python,
1289-functions, methods or any other callable can be used to handle
1290-messages.
1291-
1292-For example, consider this class::
1293+Le fichier README.txt [#readmes]_ dans chemin/vers/zope/interface définit les
1294+interfaces de cette manière ::
1295+
1296+ Les interfaces sont des objets qui spécifient (documentent) le
1297+ comportement externe des objets qui les « fournissent ».
1298+ Une interface spécifie un comportement au travers :
1299+
1300+ - de documentation informelle dans une docstring
1301+
1302+ - de définitions d'attributs
1303+
1304+ - d'invariants qui sont des conditions posées sur les objets
1305+ fournissant l'interface.
1306+
1307+L'ouvrage de référence `Design Patterns` [#patternbook]_ par le `Gang of Four`
1308+recommande que vous devez « programmer pour une interface, pas pour une
1309+implémentation ». Définir une interface formelle est utile dans la compréhension
1310+d'un système. De plus, les interfaces vous apportent tous les bénéfices de la
1311+ZCA.
1312+
1313+.. [#readmes] L'arborescence du code de Zope contient de nombreux fichiers README.txt
1314+ qui offrent une très bonne documentation.
1315+.. [#patternbook] http://en.wikipedia.org/wiki/Design_Patterns
1316+
1317+Une interface spécifie les caractéristiques d'un objet, son comportement et ses
1318+capacités. Elle décrit le « quoi » d'un objet. Pour apprendre le « comment »,
1319+vous devez regarder l'implémentation.
1320+
1321+Les métaphores couramment utilisées pour les interfaces sont `contrat` ou
1322+`plan`, des termes légaux et architecturaux pour représenter un jeu de
1323+spécifications.
1324+
1325+Dans certains langages de programmation comme Java, C# ou VB.NET, les
1326+interfaces sont un aspect explicite du langage. Étant donné que Python ne
1327+possède pas nativement d'interfaces, la ZCA les implémente comme des
1328+meta-classes desquelles on hérite.
1329+
1330+Voici un exemple classique de Hello World ::
1331
1332 >>> class Host(object):
1333 ...
1334@@ -571,24 +590,23 @@
1335 ...
1336 ... return "Good morning, %s!" % name
1337
1338-In the above class, you defined a `goodmorning` method. If you call
1339-the `goodmorning` method from an object created using this class, it
1340-will return `Good morning, ...!` ::
1341+Dans la classe ci-dessus, on a défini une méthode `goodmorning`. Si vous appelez
1342+cette méthode depuis un objet créé en utilisant cette classe, vous obtiendrez un
1343+`Good morning, ...!` ::
1344
1345 >>> host = Host()
1346 >>> host.goodmorning('Jack')
1347 'Good morning, Jack!'
1348
1349-Here ``host`` is the actual object. The implementation details of
1350-this object is the class ``Host``. Now, how to find how the object
1351-looks like, that is, what are the methods and attributes of the
1352-object. For this, either you have go through the implementation
1353-details (``Host`` class) of the object or a separate API documentation
1354-[#api]_ will be required.
1355-
1356-You can use the ``zope.interface`` package to define the interface of
1357-objects. For the class given above you can specify the interface like
1358-this::
1359+Ici, ``host`` est l'objet réel que votre code utilise. Si vous voulez
1360+examiner les détails d'implémentation, vous devez accéder à la classe ``Host``,
1361+soit via le code source, soit au travers d'un outil de documentation d'API
1362+[#api]_.
1363+
1364+.. [#api] http://en.wikipedia.org/wiki/Application_programming_interface
1365+
1366+Maintenant nous allons commencer à utiliser les interfaces de la ZCA. Pour la
1367+classe ci-dessus, vous pouvez définir l'interface comme suit ::
1368
1369 >>> from zope.interface import Interface
1370
1371@@ -597,21 +615,18 @@
1372 ... def goodmorning(guest):
1373 ... """Say good morning to guest"""
1374
1375-As you can see, the interface is defined using Python class statement.
1376-We use (abuse?) Python's class statement to define interfaces. To
1377-make a class an interface, it must be inherited from
1378-``zope.interface.Interface`` . The ``I`` prefix for interface name is
1379-a convention.
1380-
1381-
1382-Declaring interfaces
1383-~~~~~~~~~~~~~~~~~~~~
1384-
1385-You have already seen how to declare an interface using
1386-``zope.interface`` in previous section. This section will explain the
1387-concepts in detail.
1388-
1389-Consider this example interface::
1390+Vous pouvez constater que l'interface hérite de zope.interface.Interface. C'est
1391+de cette façon (abusive ?) que la ZCA définit des interfaces. Le préfixe « I »
1392+pour le nom de la classe est une convention utile.
1393+
1394+
1395+Déclarer des interfaces
1396+~~~~~~~~~~~~~~~~~~~~~~~
1397+
1398+Vous avez déjà vu comment déclarer une interface en utilisant ``zope.interface``
1399+dans la section précédente. Cette section va expliquer les concepts en détail.
1400+
1401+Prenez cette exemple d'interface ::
1402
1403 >>> from zope.interface import Interface
1404 >>> from zope.interface import Attribute
1405@@ -624,60 +639,58 @@
1406 ... def goodmorning(guest):
1407 ... """Say good morning to guest"""
1408
1409-The interface, ``IHost`` has two attributes, ``name`` and
1410-``goodmorning``. Recall that, at least in Python, methods are also
1411-attributes of classes. The ``name`` attribute is defined using
1412-``zope.interface.Attribute`` class. When you add the attribute
1413-``name`` to the ``IHost`` interface, you don't set an initial value.
1414-The purpose of defining the attribute ``name`` here is merely to
1415-indicate that any implementation of this interface will feature an
1416-attribute named ``name``. In this case, you don't even say what type
1417-of attribute it has to be!. You can pass a documentation string as a
1418-first argument to ``Attribute``.
1419-
1420-The other attribute, ``goodmorning`` is a method defined using a
1421-function definition. Note that `self` is not required in interfaces,
1422-because `self` is an implementation detail of class. For example, a
1423-module can implement this interface. If a module implement this
1424-interface, there will be a ``name`` attribute and ``goodmorning``
1425-function defined. And the ``goodmorning`` function will accept one
1426-argument.
1427-
1428-Now you will see how to connect `interface-class-object`. So object
1429-is the real living thing, objects are instances of classes. And
1430-interface is the actual definition of the object, so classes are just
1431-the implementation details. This is why you should program to an
1432-interface and not to an implementation.
1433-
1434-Now you should familiarize two more terms to understand other
1435-concepts. First one is `provide` and the other one is `implement`.
1436-Object provides interfaces and classes implement interfaces. In other
1437-words, objects provide interfaces that their classes implement. In
1438-the above example ``host`` (object) provides ``IHost`` (interface) and
1439-``Host`` (class) implement ``IHost`` (interface). One object can
1440-provide more than one interface also one class can implement more than
1441-one interface. Objects can also provide interfaces directly, in
1442-addition to what their classes implement.
1443+L'interface ``IHost`` possède deux attributs, ``name`` et ``goodmorning``.
1444+Rappelez-vous qu'en Python les méthodes des classes sont aussi des attributs.
1445+L'attribut ``name`` est défini en utilisant la classe
1446+``zope.interface.Attribute``. Quand vous ajoutez l'attribut ``name`` à
1447+l'interface ``IHost``, vous ne définissez pas de valeur initiale. La raison de
1448+définir l'attribut ``name`` ici est simplement d'indiquer que toute
1449+implémentation de cette interface doit fournir un attribut nommé ``name``. Dans
1450+ce cas, vous n'indiquez même pas de quel type doit être l'attribut ! Vous pouvez
1451+juste fournir une chaîne de documentation comme premier argument à
1452+``Attribute``.
1453+
1454+L'autre attribut, ``goodmorning`` est une méthode définie en utilisant une
1455+fonction. Notez bien que ``self`` n'est pas nécessaire dans les interfaces, car
1456+``self`` est un détail d'implémentation de la classe. Il est possible pour un
1457+module d'implémenter cette interface. Si un module implémente cette interface,
1458+cela signifiera qu'un attribut ``name`` et une fonction ``goodmorning`` seront
1459+définis. Et la fonction ``goodmorning`` devra accepter un argument.
1460+
1461+Nous allons maintenant voir comment effectuer le lien entre les objets, les
1462+classes et les interfaces. Seuls les objets sont vivants : ce sont des instances
1463+de classes. Et les interfaces représentent la définition des objets, donc les
1464+classes ne sont qu'un détail d'implémentation. C'est pour cette raison que vous
1465+devez programmer pour une interface, pas pour une implémentation.
1466+
1467+Nous devons nous familiariser avec deux termes supplémentaires pour comprendre
1468+les autres concepts. Le premier est `fournir`, le deuxième est `implémenter`.
1469+Les objets fournissent des interfaces, tandis que les classes implémentent des
1470+interfaces. Autrement dit, les objets fournissent les interfaces que les classes
1471+implémentent. Dans l'exemple ci-dessus, l'objet ``host`` fournit l'interface
1472+``IHost`` et la classe ``Host`` implémente l'interface ``IHost``. Un objet peut
1473+fournir plusieurs interfaces. Les objets peuvent également fournir directement
1474+des interfaces, en plus de celles implémentées par leur classe.
1475
1476 .. note::
1477
1478- Classes are the implementation details of objects. In Python,
1479- classes are callable objects, so why other callable objects can't
1480- implement an interface. Yes, it is possible. For any `callable
1481- object` you can declare that it produces objects that provide some
1482- interfaces by saying that the `callable object` implements the
1483- interfaces. The `callable objects` are generally called as
1484- `factories`. Since functions are callable objects, a function can
1485- be an `implementer` of an interface.
1486-
1487-
1488-Implementing interfaces
1489-~~~~~~~~~~~~~~~~~~~~~~~
1490-
1491-To declare a class implements a particular interface, use the function
1492-``zope.interface.implements`` in the class statement.
1493-
1494-Consider this example, here ``Host`` implements ``IHost``::
1495+ Les classes sont les détails d'implémentation des objets. En Python, les
1496+ classes sont des objets appelables (`callable`). Pourquoi un autre objet
1497+ appelable ne pourrait-il pas implémenter une interface ? En fait c'est possible.
1498+ Pour n'importe quel objet appelable, vous pouvez déclarer qu'il produit des
1499+ objets qui fournissent une interface donnée, en disant simplement que cet objet
1500+ appelable implémente l'interface. Ces objets appelables sont généralement
1501+ nommés des « fabriques ». Étant donné que les fonctions sont des objets
1502+ appelables, une fonction peut implémenter une interface.
1503+
1504+
1505+Implémentation des interfaces
1506+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1507+
1508+Pour déclarer qu'une classe implémente une interface donnée, utilisez la
1509+fonction ``zope.interface.implements`` dans la déclaration de classe.
1510+
1511+Considérons cet exemple. Ici, ``Host`` implémente ``IHost`` ::
1512
1513 >>> from zope.interface import implements
1514
1515@@ -694,55 +707,54 @@
1516
1517 .. note::
1518
1519- If you wonder how ``implements`` function works, refer the blog post
1520- by James Henstridge
1521+ Si vous vous demandez comment ``implements`` fonctionne, faites un tour sur
1522+ l'article de blog de James Henstridge
1523 (http://blogs.gnome.org/jamesh/2005/09/08/python-class-advisors/) .
1524- In the adapter section, you will see an ``adapts`` function, it is
1525- also working similarly.
1526+ Dans la section sur les adaptateurs, vous allez voir une fonction ``adapts``,
1527+ celle-ci fonctionne de manière similaire.
1528
1529-Since ``Host`` implements ``IHost``, instances of ``Host`` provides
1530-``IHost``. There are some utility methods to introspect the
1531-declarations. The declaration can write outside the class also. If
1532-you don't write ``interface.implements(IHost)`` in the above example,
1533-then after defining the class statement, you can write like this::
1534+Comme ``Host`` implémente ``IHost``, les instances de ``Host`` fournissent
1535+``IHost``. Il existe des méthodes permettant d'introspecter les déclarations. La
1536+déclaration peut également s'écrire en dehors de la classe. Au lieu d'écrire
1537+``interface.implements(IHost)`` comme dans l'exemple ci-dessus, vous pouvez
1538+écrire la chose suivante après la déclaration de classe ::
1539
1540 >>> from zope.interface import classImplements
1541 >>> classImplements(Host, IHost)
1542
1543
1544-Example revisited
1545-~~~~~~~~~~~~~~~~~
1546+L'exemple revisité
1547+~~~~~~~~~~~~~~~~~~
1548
1549-Now, return to the example application. Here you will see how to
1550-define the interface of the registrar object::
1551+Maintenant retournons à notre application exemple. Voici comment définir
1552+l'interface de l'objet frontdesk ::
1553
1554 >>> from zope.interface import Interface
1555
1556- >>> class IRegistrar(Interface):
1557- ... """A registrar will register object's details"""
1558+ >>> class IDesk(Interface):
1559+ ... """A frontdesk will register object's details"""
1560 ...
1561 ... def register():
1562 ... """Register object's details"""
1563 ...
1564
1565-Here, first you imported ``Interface`` class from ``zope.interface``
1566-module. If you define a subclass of this ``Interface`` class, it will
1567-be an interface from Zope component architecture point of view. An
1568-interface can be implemented, as you already noted, in a class or any
1569-other callable object.
1570-
1571-The registrar interface defined here is ``IRegistrar``. The
1572-documentation string for interface gives an idea about the object. By
1573-defining a method in the interface, you made a contract for the
1574-component, that there will be a method with same name available. For
1575-the method definition interface, the first argument should not be
1576-`self`, because an interface will never be instantiated nor will its
1577-methods ever be called. Instead, the interface class merely documents
1578-what methods and attributes should appear in any normal class that
1579-claims to implement it, and the `self` parameter is an implementation
1580-detail which doesn't need to be documented.
1581-
1582-As you know, an interface can also specify normal attributes::
1583+Nous avons d'abord importé la classe ``Interface`` depuis le module
1584+``zope.interface``. Si vous définissez une sous-classe de cette classe
1585+``Interface``, ce sera considéré comme une interface, du point de vue de
1586+l'Architecture de Composants. Une interface peut être implémentée, comme nous
1587+l'avons vu, dans une classe ou tout autre objet appelable.
1588+
1589+L'interface de frontdesk ici définie est ``IDesk``. La chaîne de documentation
1590+de l'interface donne une idée sur la nature de l'objet. En définissant une
1591+méthode dans l'interface, vous avez passé un contrat avec le composant, imposant
1592+la présence d'une méthode du même nom. Dans la déclaration de la méthode côté
1593+interface, le premier argument ne doit pas être `self`, car une interface ne
1594+sera jamais instanciée et ses méthodes ne seront jamais appelées. Le rôle d'une
1595+interface est simplement de documenter quels arguments et quelles méthodes
1596+doivent apparaître dans une classe qui l'implémente, et le paramètre `self`
1597+n'est qu'un détail d'implémentation qui n'a pas besoin d'être documenté.
1598+
1599+Comme vous le savez, une interface peut aussi spécifier des attributs normaux ::
1600
1601 >>> from zope.interface import Interface
1602 >>> from zope.interface import Attribute
1603@@ -752,26 +764,25 @@
1604 ... name = Attribute("Name of guest")
1605 ... place = Attribute("Place of guest")
1606
1607-In this interface, guest object has two attributes specified with
1608-documentation. An interface can also specify both attributes and
1609-methods together. An interface can be implemented in a class, module
1610-or any other objects. For example a function can dynamically create
1611-the component and return, in this case the function is an implementer
1612-for the interface.
1613-
1614-Now you know what is an interface and how to define and use it. In
1615-the next chapter you can see how an interface is used to define an
1616-adapter component.
1617-
1618-
1619-Marker interfaces
1620-~~~~~~~~~~~~~~~~~
1621-
1622-An interface can be used to declare that a particular object belongs
1623-to a special type. An interface without any attribute or method is
1624-called `marker interface`.
1625-
1626-Here is a `marker interface`::
1627+Dans cette interface, l'objet guest a deux attributs contenant de la
1628+documentation. Une interface peut spécifier à la fois des méthodes et des
1629+attributs. Une interface peut être implémentée dans une classe, un module ou
1630+tout autre objet. Par exemple une fonction peut créer dynamiquement le composant
1631+et le renvoyer, auquel cas on dit que la fonction implémente l'interface.
1632+
1633+Vous savez maintenant ce qu'est une interface, comment la créer et l'utiliser.
1634+Dans le chapitre suivant nous allons voir comment une interface peut être
1635+utilisée pour définir un composant adaptateur.
1636+
1637+
1638+Interfaces marqueurs
1639+~~~~~~~~~~~~~~~~~~~~
1640+
1641+Une interface peut être utilisée pour déclarer qu'un objet appartient à un
1642+type donné. Une interface sans aucun attribut ni aucune méthode est appelée une
1643+« interface marqueur ».
1644+
1645+Voici une `interface marqueur` ::
1646
1647 >>> from zope.interface import Interface
1648
1649@@ -779,24 +790,25 @@
1650 ... """A special guest"""
1651
1652
1653-This interface can be used to declare an object is a special guest.
1654+Cette interface peut être utilisée pour déclarer qu'un objet est un client
1655+spécial.
1656
1657
1658 Invariants
1659 ~~~~~~~~~~
1660
1661-Sometimes you will be required to use some rule for your component
1662-which involve one or more normal attributes. These kind of rule is
1663-called `invariants`. You can use ``zope.interface.invariant`` for
1664-setting `invariants` for your objects in their interface.
1665-
1666-Consider a simple example, there is a `person` object. A person
1667-object has `name`, `email` and `phone` attributes. How do you
1668-implement a validation rule that says either email or phone have to
1669-exist, but not necessarily both.
1670-
1671-First you have to make a callable object, either a simple function or
1672-callable instance of a class like this::
1673+Parfois vous aurez besoin de définir des règles ou des contraintes sur les
1674+attributs de vos composants. Ces types de règles sont appelés des `invariants`.
1675+Vous pouvez utiliser ``zope.interface.invariant`` pour définir des
1676+``invariants`` sur vos objets dans leur interface.
1677+
1678+Considérons un exemple simple, avec un objet `person`. Une objet `person` a un
1679+attribut `nom`, un attribut `email` et un attribut `phone`. Comment peut-on
1680+implémenter une règle de validation qui oblige à définir au choix le `phone` ou
1681+l'`email` mais pas forcément les deux ?
1682+
1683+Créez tout d'abord un objet appelable, soit une simple fonction soit une
1684+instance appelable d'une classe de la façon suivante ::
1685
1686 >>> def contacts_invariant(obj):
1687 ...
1688@@ -804,8 +816,8 @@
1689 ... raise Exception(
1690 ... "At least one contact info is required")
1691
1692-Then define the `person` object's interface like this. Use the
1693-``zope.interface.invariant`` function to set the invariant::
1694+Ensuite définissez l'interface de l'objet `person` en utilisant la fonction
1695+``zope.interface.invariant`` pour définir l'invariant ::
1696
1697 >>> from zope.interface import Interface
1698 >>> from zope.interface import Attribute
1699@@ -819,7 +831,8 @@
1700 ...
1701 ... invariant(contacts_invariant)
1702
1703-Now use `validateInvariants` method of the interface to validate::
1704+Maintenant, utilisez la méthode `validateInvariants` de l'interface pour
1705+effectuer la validation ::
1706
1707 >>> from zope.interface import implements
1708
1709@@ -839,37 +852,34 @@
1710 ...
1711 Exception: At least one contact info is required
1712
1713-As you can see `jack` object validated without raising any
1714-exception. But `jill` object didn't validated the invariant
1715-constraint, so it raised exception.
1716-
1717-.. [#patternbook] http://en.wikipedia.org/wiki/Design_Patterns
1718-.. [#api] http://en.wikipedia.org/wiki/Application_programming_interface
1719-
1720-
1721-Adapters
1722---------
1723-
1724-
1725-Implementation
1726+Vous constatez que l'ojet `jack` est validé sans erreur. Mais l'objet `jill` n'a
1727+pas pu valider la contrainte de l'invariant, il a donc levé une exception.
1728+
1729+
1730+Adaptateurs
1731+-----------
1732+
1733+
1734+Implémentation
1735 ~~~~~~~~~~~~~~
1736
1737-This section will describe adapters in detail. Zope component
1738-architecture, as you noted, helps to effectively use Python objects.
1739-Adapter components are one of the basic components used by Zope
1740-component architecture for effectively using Python objects. Adapter
1741-components are Python objects, but with well defined interface.
1742+Cette section décrit les adaptateurs en détail. L'Architecture de Composants,
1743+comme vous l'avez remarqué, fournit une aide dans l'utilisation efficace des objets
1744+Python. Les composants adaptateurs sont l'un des composants basiques utilisés
1745+par l'Architecture de Composants de Zope pour utiliser efficacement des objets
1746+Python. Les adaptateurs sont aussi des objets Python, mais avec une interface bien
1747+définie.
1748
1749-To declare a class is an adapter use `adapts` function defined in
1750-``zope.component`` package. Here is a new `GuestRegistrarNG` adapter
1751-with explicit interface declaration::
1752+Pour déclarer qu'une classe est un adaptateur, utilisez la fonction `adapts`
1753+définie dans le paquet ``zope.component``. Voici un nouvel adaptateur
1754+`FrontDeskNG` avec une déclaration explicite d'interface ::
1755
1756 >>> from zope.interface import implements
1757 >>> from zope.component import adapts
1758
1759- >>> class GuestRegistrarNG(object):
1760+ >>> class FrontDeskNG(object):
1761 ...
1762- ... implements(IRegistrar)
1763+ ... implements(IDesk)
1764 ... adapts(IGuest)
1765 ...
1766 ... def __init__(self, guest):
1767@@ -878,17 +888,16 @@
1768 ... def register(self):
1769 ... guest = self.guest
1770 ... next_id = get_next_id()
1771- ... guests_db[next_id] = {
1772+ ... bookings_db[next_id] = {
1773 ... 'name': guest.name,
1774 ... 'place': guest.place,
1775 ... 'phone': guest.phone
1776 ... }
1777
1778
1779-What you defined here is an `adapter` for `IRegistrar`, which adapts
1780-`IGuest` object. The `IRegistrar` interface is implemented by
1781-`GuestRegistrarNG` class. So, an instance of this class will provide
1782-`IRegistrar` interface.
1783+Ce que nous avons défini ici est un `adaptateur` pour `IDesk`, qui s'adapte à
1784+l'objet `IGuest`. L'interface `IDesk` est implémentée par la classe
1785+`FrontDeskNG`. Donc une instance de cette classe fournira l'interface `IDesk`.
1786
1787 ::
1788
1789@@ -901,252 +910,254 @@
1790 ... self.place = place
1791
1792 >>> jack = Guest("Jack", "Bangalore")
1793- >>> jack_registrar = GuestRegistrarNG(jack)
1794+ >>> jack_frontdesk = FrontDeskNG(jack)
1795
1796- >>> IRegistrar.providedBy(jack_registrar)
1797+ >>> IDesk.providedBy(jack_frontdesk)
1798 True
1799
1800-The `GuestRegistrarNG` is just one adapter you created, you can also
1801-create other adapters which handles guest registration differently.
1802-
1803-
1804-Registration
1805-~~~~~~~~~~~~
1806-
1807-To use this adapter component, you have to register this in a
1808-component registry also known as site manager. A site manager
1809-normally resides in a site. A site and site manager will be more
1810-important when developing a Zope 3 application. For now you only
1811-required to bother about global site and global site manager ( or
1812-component registry). A global site manager will be in memory, but a
1813-local site manager is persistent.
1814-
1815-To register your component, first get the global site manager::
1816+`FrontDeskNG` est juste un adaptateur que nous avons créé. Vous pouvez créer
1817+d'autres adaptateurs qui prendront en charge le bureau d'enregistrement différemment.
1818+
1819+
1820+Inscription
1821+~~~~~~~~~~~
1822+
1823+Pour utiliser ce composant adaptateur, vous devez l'inscrire dans un registre de
1824+composants (appelé également « gestionnaire de site »). Un gestionnaire de site
1825+réside normalement à l'intérieur d'un site. Le site et le gestionnaire de site
1826+prendront leur importance lors du développement d'une application Zope 3. Pour
1827+l'instant vous avez juste besoin de connaître les notions de site global et de
1828+gestionnaire global de site (ou registre de composant). Un gestionnaire global
1829+de site est situé en mémoire, alors qu'un gestionnaire de site local est
1830+persistant.
1831+
1832+Pour inscrire votre composant, commencez par récupérer le gestionnaire global de
1833+site ::
1834
1835 >>> from zope.component import getGlobalSiteManager
1836 >>> gsm = getGlobalSiteManager()
1837- >>> gsm.registerAdapter(GuestRegistrarNG,
1838- ... (IGuest,), IRegistrar, 'ng')
1839-
1840-To get the global site manager, you have to call
1841-``getGlobalSiteManager`` function available in ``zope.component``
1842-package. In fact, the global site manager is available as an
1843-attribute (``globalSiteManager``) of ``zope.component`` package. So,
1844-you can directly use ``zope.component.globalSiteManager`` attribute.
1845-To register the adapter in component, as you can see above, use
1846-``registerAdapter`` method of component registry. The first argument
1847-should be your adapter class/factory. The second argument is a tuple
1848-of `adaptee` objects, i.e, the object which you are adapting. In this
1849-example, you are adapting only `IGuest` object. The third argument is
1850-the interface provided by the adapter component. The fourth argument
1851-is optional, that is the name of the particular adapter. Since you
1852-gave a name for this adapter, this is a `named adapter`. If name is
1853-not given, it will default to an empty string ('').
1854-
1855-In the above registration, you have given the adaptee interface and
1856-interface to be provided by the adapter. Since you have already given
1857-these details in adapter implementation, it is not required to specify
1858-again. In fact, you could have done the registration like this::
1859-
1860- >>> gsm.registerAdapter(GuestRegistrarNG, name='ng')
1861-
1862-There are some old API to do the registration, which you should avoid.
1863-The old API functions starts with `provide`, eg: ``provideAdapter``,
1864-``provideUtility`` etc. While developing a Zope 3 application you can
1865-use Zope configuration markup language (ZCML) for registration of
1866-components. In Zope 3, local components (persistent components) can
1867-be registered from Zope Management Interface (ZMI) or you can do it
1868-programmatically also.
1869-
1870-You registered `GuestRegistrarNG` with a name `ng`. Similarly you can
1871-register other adapters with different names. If a component is
1872-registered without name, it will default to an empty string.
1873+ >>> gsm.registerAdapter(FrontDeskNG,
1874+ ... (IGuest,), IDesk, 'ng')
1875+
1876+Pour récupérer le gestionnaire global de site, vous devez appeler la fonction
1877+``getGlobalSiteManager` disponible dans le paquet ``zope.component``.
1878+En fait, le gestionnaire global de site est disponible dans un attribut
1879+(``globalSiteManager``) du paquet ``zope.component``. Vous pouvez donc utiliser
1880+directement l'attribut ``zope.component.globalSiteManager``.
1881+Pour inscrire l'adaptateur comme un composant, utilisez la méthode
1882+``registerAdapter`` du registre de composants. Le premier argument doit être
1883+votre classe ou fabrique d'adaptateur. Le deuxième argument est un tuple d'objets
1884+adaptés, c'est à dire les objets sur lesquels vous vous adaptez. Dans cet
1885+exemple, vous vous adaptez seulement à l'objet `IGuest`. Le troisième argument
1886+est l'interface implémentée par le composant adaptateur. Le quatrième argument
1887+est optionnel, il s'agit du nom de cet adaptateur particulier. Si vous donnez un
1888+nom à l'adaptateur, celui devient un `adaptateur nommé`. Si aucun nom n'est
1889+donné, la valeur transmise par défaut est une chaîne vide ('').
1890+
1891+Dans l'inscription ci-dessus, vous avez donné l'interface de l'objet adapté et
1892+l'interface fournie par l'adaptateur. Comme vous avez déjà donné ces
1893+informations dans l'implémentation de l'adaptateur, il est inutile de les
1894+spécifier à nouveau. En réalité, vous pouvez effectuer l'inscription de la
1895+manière suivante ::
1896+
1897+ >>> gsm.registerAdapter(FrontDeskNG, name='ng')
1898+
1899+Pour effectuer l'inscription, il existe d'anciennes API que vous devriez
1900+éviter. Les fonctions de l'ancienne API commencent par `provide`, par exemple :
1901+``provideAdapter``, ``provideUtility``, etc. Si vous développez une application
1902+Zope 3, vous pouvez utiliser le langage ZCML (Zope Configuration Markup
1903+Language) pour effectuer les inscriptions des composants. Avec Zope 3, les
1904+composants locaux (persistants) peut être inscrits depuis la ZMI (Zope
1905+Management Interface), ou bien par programmation.
1906+
1907+Vous avez inscrit `FrontDeskNG` avec le nom `ng`. De la même manière, vous
1908+pouvez inscrire d'autre adaptateurs avec différents noms. Si un composant est
1909+inscrit sans nom, son nom sera la chaîne vide par défaut.
1910
1911 .. note::
1912
1913- Local components are persistent components but global components are
1914- in memory. Global components will be registered based on the
1915- configuration of application. Local components are taken to memory
1916- from database while starting the application.
1917-
1918-
1919-Querying adapter
1920-~~~~~~~~~~~~~~~~
1921-
1922-Retrieving registered components from component registry is achieved
1923-through two functions available in ``zope.component`` package. One of
1924-them is ``getAdapter`` and the other is ``queryAdapter`` . Both
1925-functions accepts same arguments. The ``getAdapter`` will raise
1926-``ComponentLookupError`` if component lookup fails on the other hand
1927-``queryAdapter`` will return `None`.
1928-
1929-You can import the methods like this::
1930+ Les composants locaux sont persistants mais les composants globaux sont en
1931+ mémoire. Les composants globaux sont inscrits en fonction de la configuration de
1932+ l'application. Les composants locaux sont récupérés dans la base de données au
1933+ démarrage de l'application.
1934+
1935+
1936+récupération d'un adaptateur
1937+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1938+
1939+La récupération des composants inscrits dans le registre est effectuée grâce à
1940+deux fonctions disponibles dans le paquet ``zope.component``. La première est
1941+``getAdapter``, la deuxième ``queryAdapter``. Les deux fonctions prennent les
1942+mêmes arguments. ``getAdapter`` lève une exception ``ComponentLookupError`` si
1943+la recherche de composant échoue, tandis que ``queryAdapter`` renvoie `None`.
1944+
1945+Vous pouvez importer ces fonctions comme ceci ::
1946
1947 >>> from zope.component import getAdapter
1948 >>> from zope.component import queryAdapter
1949
1950-In the previous section you have registered a component for guest
1951-object (adaptee) which provides `IRegistrar` interface with name as
1952-'ng'. In the first section of this chapter, you have created a guest
1953-object named `jack` .
1954-
1955-This is how you can retrieve a component which adapts the interface of
1956-`jack` object (`IGuest`) and provides `IRegistrar` interface also with
1957-name as 'ng'. Here both ``getAdapter`` and ``queryAdapter`` works
1958-similarly::
1959-
1960- >>> getAdapter(jack, IRegistrar, 'ng') #doctest: +ELLIPSIS
1961- <GuestRegistrarNG object at ...>
1962- >>> queryAdapter(jack, IRegistrar, 'ng') #doctest: +ELLIPSIS
1963- <GuestRegistrarNG object at ...>
1964-
1965-As you can see, the first argument should be adaptee then, the
1966-interface which should be provided by component and last the name of
1967-adapter component.
1968-
1969-If you try to lookup the component with an name not used for
1970-registration but for same adaptee and interface, the lookup will fail.
1971-Here is how the two methods works in such a case::
1972-
1973- >>> getAdapter(jack, IRegistrar, 'not-exists') #doctest: +ELLIPSIS
1974+Dans la section précédente, nous avons inscrit un composant qui fournit
1975+l'interface `IDesk` avec un nom `ng`, et qui s'adapte à l'objet guest.
1976+Dans la première section nous avons créé un objet nommé `jack`.
1977+
1978+Voici maintenant comment récupérer un composant qui s'adapte à l'interface de l'objet
1979+`jack` (`IGuest`) et qui fournit l'interface `IDesk` également avec le nom `ng`.
1980+Ici, ``getAdapter`` et ``queryAdapter`` fonctionnent de la même manière ::
1981+
1982+ >>> getAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
1983+ <FrontDeskNG object at ...>
1984+ >>> queryAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
1985+ <FrontDeskNG object at ...>
1986+
1987+Vous pouvez constater que le premier argument doit être l'objet adapté, puis
1988+l'interface qui doit être fournie par le composant et finalement le nom du
1989+composant adaptateur.
1990+
1991+Si vous essayez de récupérer le composant grâce à un nom inutilisé pour
1992+l'inscription mais pour le même objet adapté et la même interface, la recherche
1993+échouera. Voici dans ce cas comment fonctionnent les deux méthodes ::
1994+
1995+ >>> getAdapter(jack, IDesk, 'not-exists') #doctest: +ELLIPSIS
1996 Traceback (most recent call last):
1997 ...
1998 ComponentLookupError: ...
1999 >>> reg = queryAdapter(jack,
2000- ... IRegistrar, 'not-exists') #doctest: +ELLIPSIS
2001+ ... IDesk, 'not-exists') #doctest: +ELLIPSIS
2002 >>> reg is None
2003 True
2004
2005-As you can see above, ``getAdapter`` raised a ``ComponentLookupError``
2006-exception, but ``queryAdapter`` returned `None` when lookup failed.
2007-
2008-The third argument, the name of registration, is optional. If the
2009-third argument is not given it will default to empty string ('').
2010-Since there is no component registered with an empty string,
2011-``getAdapter`` will raise ``ComponentLookupError`` . Similarly
2012-``queryAdapter`` will return `None`, see yourself how it works::
2013-
2014- >>> getAdapter(jack, IRegistrar) #doctest: +ELLIPSIS
2015+``getAdapter`` a levé une exception ``ComponentLookupError`` mais
2016+``queryAdapter`` a renvoyé `None`.
2017+
2018+Le troisième argument, le nom d'inscription, est optionnel. Si le troisième
2019+argument n'est pas fourni, sa valeur par défaut est la chaîne vide (''). Comme
2020+il n'y a aucun composant inscrit avec la chaîne vide comme nom, ``getAdapter``
2021+lève l'exception ``ComponentLookupError``. De la même manière, ``queryAdapter``
2022+renvoie `None`. Voyez vous-même comment cela fonctionne ::
2023+
2024+ >>> getAdapter(jack, IDesk) #doctest: +ELLIPSIS
2025 Traceback (most recent call last):
2026 ...
2027 ComponentLookupError: ...
2028- >>> reg = queryAdapter(jack, IRegistrar) #doctest: +ELLIPSIS
2029+ >>> reg = queryAdapter(jack, IDesk) #doctest: +ELLIPSIS
2030 >>> reg is None
2031 True
2032
2033-In this section you have learned how to register a simple adapter and
2034-how to retrieve it from component registry. These kind of adapters is
2035-called single adapter, because it adapts only one adaptee. If an
2036-adapter adapts more that one adaptee, then it is called multi
2037-adapter.
2038-
2039-
2040-Retrieving adapter using interface
2041-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2042-
2043-Adapters can be directly retrieved using interfaces, but it will only
2044-work for non-named single adapters. The first argument is the adaptee
2045-and the second argument is a keyword argument. If adapter lookup
2046-fails, second argument will be returned.
2047-
2048- >>> IRegistrar(jack, alternate='default-output')
2049- 'default-output'
2050-
2051- Keyword name can be omitted:
2052-
2053- >>> IRegistrar(jack, 'default-output')
2054- 'default-output'
2055-
2056- If second argument is not given, it will raise `TypeError`:
2057-
2058- >>> IRegistrar(jack) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
2059+Dans cette section, vous avez appris à inscrire un simple adaptateur et à le
2060+récupérer depuis le registre de composants. Ce type d'adaptateurs est appelé un
2061+adaptateur simple, car il ne s'adapte qu'à un seul objet. Si un adaptateur
2062+s'adapte à plusieurs objets, on l'appelle un multi-adaptateur.
2063+
2064+
2065+Récupérer un adaptateur en utilisant l'interface
2066+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2067+
2068+Les adaptateurs peuvent être récupérés directement en utilisant les interfaces,
2069+mais cela ne fonctionne qu'avec les adaptateurs simples. Le premier argument est
2070+l'objet adapté, le deuxième argument est un argument mot-clé. Si la recheche
2071+d'adaptateur échoue, le deuxième argument est renvoyé.
2072+
2073+ >>> IDesk(jack, alternate='default-output')
2074+ 'default-output'
2075+
2076+ Le mot-clé peut être omis :
2077+
2078+ >>> IDesk(jack, 'default-output')
2079+ 'default-output'
2080+
2081+ Si le deuxième argument n'est pas fourni, une erreur `TypeError` est levée :
2082+
2083+ >>> IDesk(jack) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
2084 Traceback (most recent call last):
2085 ...
2086 TypeError: ('Could not adapt',
2087 <Guest object at ...>,
2088- <InterfaceClass __builtin__.IRegistrar>)
2089-
2090- Here `GuestRegistrarNG` is registered without name:
2091-
2092- >>> gsm.registerAdapter(GuestRegistrarNG)
2093-
2094- Now the adapter lookup should succeed:
2095-
2096- >>> IRegistrar(jack, 'default-output') #doctest: +ELLIPSIS
2097- <GuestRegistrarNG object at ...>
2098-
2099-For simple cases, you may use interface to get adapter components.
2100-
2101-
2102-Adapter pattern
2103-~~~~~~~~~~~~~~~
2104-
2105-The adapter concept in Zope Component Architecture and the classic
2106-`adapter pattern` as described in Design Patterns book are very
2107-similar. But the intent of ZCA adapter usage is more wider than the
2108-`adapter pattern` itself. The intent of `adapter pattern` is to
2109-convert the interface of a class into another interface clients
2110-expect. This allows classes work together that couldn't otherwise
2111-because of incompatible interfaces. But in the `motivation` section
2112-of Degisgn Patterns book, GoF says: "Often the adapter is responsible
2113-for functionality the adapted class doesn't provide". ZCA adapter has
2114-more focus on adding functionalities than creating a new interface for
2115-an adapted object (adaptee). ZCA adapter lets adapter classes extend
2116-functionality by adding methods. (It would be interesting to note
2117-that `Adapter` was known as `Feature` in earlier stage of ZCA
2118-design. ) [#feature]_
2119-
2120-The above paragraph has a quote from Gang of Four book, it ends like
2121-this: " ...adapted class doesn't provide". But in the next sentence I
2122-used "adapted object" instead of "adapted class", because GoF
2123-describes about two variants of adapters based on implementations.
2124-The first one is called `class adapter` and the other one is called
2125-`object adapter`. A class adapter uses multiple inheritance to adapt
2126-one interface to another, on the other hand an object adapter relies
2127-on object composition. ZCA adapter is following object adapter
2128-pattern, which use delegation as a mechanism for composition. GoF's
2129-second principle of object-oriented design goes like this: "Favor
2130-object composition over class inheritance". For more details about
2131-this subject please read Design Patterns book.
2132-
2133-The major attraction of ZCA adapter are the explicit interface for
2134-components and the component registry. ZCA adapter components are
2135-registered in component registry and looked up by client objects using
2136-interface and name when required.
2137+ <InterfaceClass __builtin__.IDesk>)
2138+
2139+ Ici, `FrontDeskNG` est inscrit sans nom :
2140+
2141+ >>> gsm.registerAdapter(FrontDeskNG)
2142+
2143+ Maintenant la récupération de l'adaptateur doit réussir :
2144+
2145+ >>> IDesk(jack, 'default-output') #doctest: +ELLIPSIS
2146+ <FrontDeskNG object at ...>
2147+
2148+Pour les cas simples, vous pouvez utiliser l'interface pour récupérer des
2149+adaptateurs.
2150+
2151+
2152+Motif adaptateur
2153+~~~~~~~~~~~~~~~~
2154+
2155+Le principe de l'adaptateur dans l'Architecture de Composants de Zope est très
2156+similaire au `motif adaptateur` classique, tel que décrit dans le livre « Design
2157+Patterns ». Mais l'objectif visé par l'utilisation des adaptateurs dans la ZCA
2158+est plus large que le principe de l'adaptateur lui-même. Le but de l'adaptateur
2159+est de convertir l'interface d'une classe en une autre interface attendue par le
2160+client. Ceci permet de faire fonctionner des classes ensemble même si elles ont
2161+des interfaces incompatibles entre elles. Mais dans la section `motivations` du
2162+livre « Design Patterns », le GoF dit : « souvent, l'adaptateur est responsable
2163+d'une fonctionnalité que la classe adaptée ne fournit pas ». Un adaptateur de la
2164+ZCA se concentre effectivement plus sur l'ajout de fonctionnalités que sur la
2165+création d'une nouvelle interface pour un objet adapté. L'adaptateur de la ZCA
2166+permet aux classes adaptateurs d'étendre des fonctionnalités par ajout de
2167+méthodes. (Il peut être intéressant de remarquer que l'adaptateur était appelé
2168+`Fonctionnalité` (`feature`) dans les premières étapes de conception de la ZCA.) [#feature]_
2169
2170 .. [#feature] Thread discussing renaming of `Feature` to `Adapter`:
2171 http://mail.zope.org/pipermail/zope3-dev/2001-December/000008.html
2172
2173-
2174-Utility
2175--------
2176+La citation du Gang of Four dans le paragraphe ci-dessus se termine de la façon
2177+suivante : « ... que la classe adaptée ne fournit pas ». Mais dans la phrase
2178+suivante nous avons utilisé « objet adapté » plutôt que « classe adaptée », car
2179+le GoF décrit deux variantes d'adaptateurs selon les implémentations.
2180+Le premier est appelé `adaptateur de classe`, le deuxième `adaptateur d'objet`.
2181+Un adaptateur de classe utilise l'héritage multiple pour adapter une interface à
2182+une autre, alors que l'adaptateur d'objet se base sur la composition d'objet.
2183+L'adaptateur de la ZCA utilise le principe de l'adaptateur d'objet, qui utilise
2184+la délégation comme mécanisme de composition. Le second principe du GoF à propos
2185+de la conception orientée objets est la suivante : « favorisez la composition
2186+d'objets plutôt que l'héritage de classes ». Pour approfondir le sujet,
2187+reportez-vous au livre « Design Patterns ».
2188+
2189+Les principaux atouts des adaptateurs de la ZCA sont les interfaces explicites
2190+et les registres de composants. Les composants adaptateurs de la ZCA sont inscrits
2191+dans le registre de composants et sont récupérés par les objets clients via leur
2192+interface et leur nom si besoin.
2193+
2194+
2195+Utilitaires
2196+-----------
2197
2198
2199 Introduction
2200 ~~~~~~~~~~~~
2201
2202-Now you know the concept of interface, adapter and component registry.
2203-Sometimes it would be useful to register an object which is not
2204-adapting anything. Database connection, XML parser, object returning
2205-unique Ids etc. are examples of these kinds of objects. These kind of
2206-components provided by Zope component architecture are called
2207-``utility`` components.
2208-
2209-Utilities are just objects that provide an interface and that are
2210-looked up by an interface and a name. This approach creates a global
2211-registry by which instances can be registered and accessed by
2212-different parts of your application, with no need to pass the
2213-instances around as parameters.
2214-
2215-You need not to register all component instances like this. Only
2216-register components which you want to make replaceable.
2217-
2218-
2219-Simple utility
2220-~~~~~~~~~~~~~~
2221-
2222-Before implementing the utility, as usual, define its interface. Here
2223-is a `greeter` interface::
2224+Vous connaissez maintenant le principe des interfaces, des adaptateurs et du
2225+registre de composants. Parfois, il peut être utile d'inscrire un objet qui ne
2226+s'adapte à rien du tout, par exemple une connexion à une base de données, un analyseur XML
2227+ou un objet retournant des identifiants uniques. Ce type de composant
2228+fourni par la ZCA est appelé un « utilitaire » (*utility*).
2229+
2230+Les utilitaires sont simplement des objets qui fournissent une interface et qui sont
2231+récupérés à partir de cette interface et d'un nom. Cette approche permet de créer
2232+un registre global dans lequel des instances peuvent être inscrites et
2233+récupérées à différents endroits de votre application, sans avoir besoin de
2234+transmettre les instances comme paramètres.
2235+
2236+Vous n'avez pas besoin d'inscrire toutes les instances de composants de cette
2237+façon. Inscrivez seulement les composants que vous voulez rendre
2238+interchangeables.
2239+
2240+
2241+Utilitaire simple
2242+~~~~~~~~~~~~~~~~~
2243+
2244+Un utilitaire peut être inscrit avec ou sans nom. Un utilitaire inscrit avec un nom
2245+est appelé un `utilitaire nommé`. Vous le verrez dans la prochaine section.
2246+Avant d'implémenter l'utilitaire, comme d'habitude, définissez son interface.
2247+Voici une interface qui dit bonjour ::
2248
2249 >>> from zope.interface import Interface
2250 >>> from zope.interface import implements
2251@@ -1154,9 +1165,10 @@
2252 >>> class IGreeter(Interface):
2253 ...
2254 ... def greet(name):
2255- ... "say hello"
2256+ ... """Say hello"""
2257
2258-Here is a possible implementation of the above interface::
2259+Comme un adaptateur, un utilitaire peut avoir plusieurs implémentations. Voici
2260+une implémentation possible de l'interface ci-dessus ::
2261
2262 >>> class Greeter(object):
2263 ...
2264@@ -1165,7 +1177,10 @@
2265 ... def greet(self, name):
2266 ... return "Hello " + name
2267
2268-You can register an instance of this class using ``registerUtility``::
2269+L'utilitaire réel sera une instance de cette classe. Pour utiliser cet
2270+utilitaire, vous devez l'inscrire, puis vous pourrez la récupérer en
2271+utilisant l'API de la ZCA. Vous pouvez inscrire une instance de cette classe
2272+(`utilitaire`) grâce à ``registerUtility`` ::
2273
2274 >>> from zope.component import getGlobalSiteManager
2275 >>> gsm = getGlobalSiteManager()
2276@@ -1173,9 +1188,9 @@
2277 >>> greet = Greeter()
2278 >>> gsm.registerUtility(greet, IGreeter)
2279
2280-In this example you registered the utility as providing the `IGreeter`
2281-interface. You can look the interface up with either `queryUtility`
2282-or `getUtility`::
2283+Dans cet exemple, vous avez inscrit l'utilitaire en fournissant l'interface
2284+`IGreeter`. Vous pouvez récupérer l'utilitaire avec `queryUtility` ou
2285+`getUtility` ::
2286
2287 >>> from zope.component import queryUtility
2288 >>> from zope.component import getUtility
2289@@ -1186,24 +1201,27 @@
2290 >>> getUtility(IGreeter).greet('Jack')
2291 'Hello Jack'
2292
2293-As you can see, adapters are normally classes, but utilities are
2294-normally instances of classes.
2295-
2296-
2297-Named utility
2298-~~~~~~~~~~~~~
2299-
2300-When registering a utility component, like adapter, you can use a
2301-name.
2302-
2303-For example consider this:
2304+Comme vous pouvez le constater, alors que les adaptateurs sont habituellement
2305+des classes, les utilitaires sont habituellement des instances de classes. vous
2306+ne créez une instance d'utilitaire qu'une fois, alors que les instances
2307+d'adaptateurs sont créées à chaque fois que vous les récupérez.
2308+
2309+
2310+Utilitaire nommé
2311+~~~~~~~~~~~~~~~~
2312+
2313+Lorsque vous inscrivez un composant utilitaire, de la même manière que pour les
2314+adaptateurs, vous pouvez utiliser un nom. Comme mentionné dans la section
2315+précédente, un utilitaire inscrit avec un nom est appelé un `utilitaire nommé`.
2316+
2317+Voici comment inscrire l'utilitaire `greeter` avec un nom ::
2318
2319 >>> greet = Greeter()
2320 >>> gsm.registerUtility(greet, IGreeter, 'new')
2321
2322-In this example you registered the utility with a name as providing
2323-the `IGreeter` interface. You can look the interface up with either
2324-`queryUtility` or `getUtility`::
2325+Dans cet exemple, nous avons inscrit l'utilitaire avec un nom en fournissant
2326+l'interface `IGreeter`. Vous pouvez récupérer l'utilitaire avec `queryUtility`
2327+ou `getUtility` ::
2328
2329 >>> from zope.component import queryUtility
2330 >>> from zope.component import getUtility
2331@@ -1214,28 +1232,25 @@
2332 >>> getUtility(IGreeter, 'new').greet('Jill')
2333 'Hello Jill'
2334
2335-As you can see here, while querying you have to use the `name` as
2336-second argument.
2337-
2338-.. note::
2339-
2340- Calling `getUtility` function without a name (second argument) is
2341- equivalent to calling with an empty string ('') as the name.
2342- Because, the default value for second (keyword) argument is an empty
2343- string. Then, component lookup mechanism will try to find the
2344- component with name as empty string (''), and it will fail. When
2345- component lookup fails it will raise `ComponentLookupError`
2346- exception. Remember, it will not return some random component
2347- registered with some other name.
2348-
2349-
2350-Factory
2351-~~~~~~~
2352-
2353-A ``Factory`` is a utility component which provides ``IFactory``
2354-interface.
2355-
2356-To create a factory, first define the interface of the object::
2357+Remarquez que vous devez utiliser le nom de l'utilitaire comme second argument
2358+pour que la récupération fonctionne.
2359+
2360+Appeler `getUtility` sans nom (comme second argument) est équivalent à l'appeler
2361+avec un nom vide (''), car la valeur par défaut pour ce second argument est
2362+justement la chaîne vide. Donc le mécanisme de recherche de composant essaiera
2363+de trouver le composant ayant une chaîne vide comme nom et il échouera.
2364+Lorsqu'une recherche de composant échoue, le résultat est une exception
2365+``ComponentLookupError``. Souvenez-vous qu'aucun composant aléatoire avec un
2366+autre nom ne sera renvoyé. Les fonctions de récupération d'adaptateurs,
2367+`getAdapter` et `queryUtility` fonctionnent de manière similaire.
2368+
2369+
2370+Fabrique
2371+~~~~~~~~
2372+
2373+Une ``fabrique`` est un composant utilitaire qui fournit l'interface ``IFactory``.
2374+
2375+Pour créer une fabrique, commencez par définir l'interface de l'objet ::
2376
2377 >>> from zope.interface import Attribute
2378 >>> from zope.interface import Interface
2379@@ -1246,7 +1261,7 @@
2380 ... def getConnection():
2381 ... """Return connection object"""
2382
2383-Here is fake implementation of `IDatabase` interface::
2384+Voici une implémentation factice de l'interface `IDatabase` ::
2385
2386 >>> class FakeDb(object):
2387 ...
2388@@ -1255,13 +1270,13 @@
2389 ... def getConnection(self):
2390 ... return "connection"
2391
2392-You can create a factory using ``zope.component.factory.Factory``::
2393+Vous pouvez créer une fabrique en utilisant ``zope.component.factory.Factory`` ::
2394
2395 >>> from zope.component.factory import Factory
2396
2397 >>> factory = Factory(FakeDb, 'FakeDb')
2398
2399-Now you can register it like this::
2400+Maintenant vous pouvez l'inscrire de cette façon ::
2401
2402 >>> from zope.component import getGlobalSiteManager
2403 >>> gsm = getGlobalSiteManager()
2404@@ -1269,29 +1284,32 @@
2405 >>> from zope.component.interfaces import IFactory
2406 >>> gsm.registerUtility(factory, IFactory, 'fakedb')
2407
2408-To use the factory, you may do it like this::
2409+Pour utiliser la fabrique, vous pouvez faire comme ceci ::
2410
2411 >>> from zope.component import queryUtility
2412 >>> queryUtility(IFactory, 'fakedb')() #doctest: +ELLIPSIS
2413 <FakeDb object at ...>
2414
2415-There is a shortcut to use factory::
2416+Voici l'écriture simplifiée pour utiliser une fabrique ::
2417
2418 >>> from zope.component import createObject
2419 >>> createObject('fakedb') #doctest: +ELLIPSIS
2420 <FakeDb object at ...>
2421
2422
2423-Advanced adapters
2424------------------
2425-
2426-
2427-Multi adapter
2428-~~~~~~~~~~~~~
2429-
2430-A simple adapter normally adapts only one object, but an adapter can
2431-adapt more than one object. If an adapter adapts more than one
2432-objects, it is called as multi-adapter.
2433+Adaptateurs avancés
2434+-------------------
2435+
2436+Ce chapître traite de concepts avancés comme les multi-adaptateurs, les
2437+abonnés (subscribers) et les gestionnaires (handles).
2438+
2439+
2440+Multi-adaptateur
2441+~~~~~~~~~~~~~~~~
2442+
2443+Un adaptateur simple s'adapte normalement à un seul objet, mais un adaptateur
2444+peut s'adapter à plusieurs objets. Si un adaptateur s'adapte à plus d'un objet,
2445+il s'appelle un multi-adaptateur.
2446
2447 ::
2448
2449@@ -1342,16 +1360,16 @@
2450 <Two object at ...>
2451
2452
2453-Subscription adapter
2454-~~~~~~~~~~~~~~~~~~~~
2455-
2456-Unlike regular adapters, subscription adapters are used when we want
2457-all of the adapters that adapt an object to a particular adapter.
2458-Subscription adapter is also known as `subscriber` .
2459-
2460-Consider a validation problem. We have objects and we want to assess
2461-whether they meet some sort of standards. We define a validation
2462-interface::
2463+Adaptateur d'abonnement
2464+~~~~~~~~~~~~~~~~~~~~~~~
2465+
2466+À la différence des adaptateurs habituels, les adaptateurs d'abonnement sont
2467+utilisés quand on veut récupérer tous les adaptateurs qui adaptent un objet à
2468+une interface donnée. Un adaptateur d'abonnement est également appelé `abonné`.
2469+
2470+Considérons un problème de validation. Nous avons des objets et nous voulons
2471+vérifier s'ils satisfont à un certain critère. Nous définissons une interface
2472+de validation ::
2473
2474 >>> from zope.interface import Interface
2475 >>> from zope.interface import Attribute
2476@@ -1367,7 +1385,7 @@
2477 ... object is valid.
2478 ... """
2479
2480-Perhaps we have documents::
2481+Nous avons également des documents ::
2482
2483 >>> class IDocument(Interface):
2484 ...
2485@@ -1381,9 +1399,9 @@
2486 ... def __init__(self, summary, body):
2487 ... self.summary, self.body = summary, body
2488
2489-Now, we may want to specify various validation rules for
2490-documents. For example, we might require that the summary be a single
2491-line:
2492+Maintenant, nous pouvons avoir besoin de préciser différentes règles de
2493+validation pour les documents. Par exemple, nous voulons que le résumé tienne
2494+sur une seule ligne ::
2495
2496 >>> from zope.component import adapts
2497
2498@@ -1401,7 +1419,7 @@
2499 ... else:
2500 ... return ''
2501
2502-Or we might require the body to be at least 1000 characters in length:
2503+Ou bien nous voulons que le corps du document fasse au moins 1000 caractères ::
2504
2505 >>> class AdequateLength(object):
2506 ...
2507@@ -1417,7 +1435,7 @@
2508 ... else:
2509 ... return ''
2510
2511-We can register these as subscription adapters:
2512+Nous pouvons inscrire ces deux composants comme des adaptateurs d'abonnement ::
2513
2514 >>> from zope.component import getGlobalSiteManager
2515 >>> gsm = getGlobalSiteManager()
2516@@ -1425,7 +1443,7 @@
2517 >>> gsm.registerSubscriptionAdapter(SingleLineSummary)
2518 >>> gsm.registerSubscriptionAdapter(AdequateLength)
2519
2520-We can then use the subscribers to validate objects:
2521+Nous pouvons ensuite utiliser ces abonnés pour valider les objets ::
2522
2523 >>> from zope.component import subscribers
2524
2525@@ -1448,36 +1466,37 @@
2526 ['too short']
2527
2528
2529-Handler
2530-~~~~~~~
2531-
2532-Handlers are subscription adapter factories that don't produce
2533-anything. They do all of their work when called. Handlers are
2534-typically used to handle events. Handlers are also known as event
2535-subscribers or event subscription adapters.
2536-
2537-Event subscribers are different from other subscription adapters in
2538-that the caller of event subscribers doesn't expect to interact with
2539-them in any direct way. For example, an event publisher doesn't
2540-expect to get any return value. Because subscribers don't need to
2541-provide an API to their callers, it is more natural to define them
2542-with functions, rather than classes. For example, in a
2543-document-management system, we might want to record creation times for
2544-documents::
2545+Gestionnaire
2546+~~~~~~~~~~~~
2547+
2548+Les gestionnaires sont des fabriques d'abonnés qui ne
2549+produisent rien du tout. Ils font la totalité de leur travail lorsqu'ils sont
2550+appelés. Les gestionnaires sont typiquement utilisés pour gérer des événements.
2551+Les gestionnaires sont aussi connus sous le nom d'``abonnés
2552+à des événements`` ou ``adaptateurs d'abonnement à des événements``.
2553+
2554+Les abonnés à des événements sont différents des autres abonnés car l'objet qui
2555+appelle les abonnés ne s'attend pas à interagir avec eux d'une quelconque façon.
2556+Par exemple, un publicateur d'événements ne s'attend pas à récupérer une valeur
2557+de retour. Comme les abonnés n'ont pas besoin de fournir une API aux objets qui
2558+les appellent, il est plus naturel de les définir avec des fonctions, plutôt
2559+qu'avec des classes. Par exemple, dans un système de gestion de documents, nous
2560+pouvons avoir besoin de gérer les heures de création des documents ::
2561
2562 >>> import datetime
2563
2564 >>> def documentCreated(event):
2565 ... event.doc.created = datetime.datetime.utcnow()
2566
2567-In this example, we have a function that takes an event and performs
2568-some processing. It doesn't actually return anything. This is a
2569-special case of a subscription adapter that adapts an event to
2570-nothing. All of the work is done when the adapter "factory" is
2571-called. We call subscribers that don't actually create anything
2572-"handlers". There are special APIs for registering and calling them.
2573+Dans cet exemple, nous avons une fonction qui prend un événement et effectue un
2574+traitement. La fonction ne retourne en fait rien du tout. C'est un cas
2575+particulier de l'adaptateur d'abonnement qui s'adapte à un événement et ne
2576+fournit rien. Tout le travail est effectué lorsque la fabrique de l'adaptateur
2577+est appelée. Nous appelons les abonnés qui ne fabriquent rien des « gestionnaires ».
2578+Il existe des APIs spécialisées dans leur inscription et leur récupération.
2579
2580-To register the subscriber above, we define a document-created event::
2581+Pour inscrire l'abonné ci-dessus, nous définissons un événement « document créé
2582+» ::
2583
2584 >>> from zope.interface import Interface
2585 >>> from zope.interface import Attribute
2586@@ -1494,7 +1513,7 @@
2587 ... def __init__(self, doc):
2588 ... self.doc = doc
2589
2590-We'll also change our handler definition to:
2591+Nous modifions également notre définition du gestionnaire ::
2592
2593 >>> def documentCreated(event):
2594 ... event.doc.created = datetime.datetime.utcnow()
2595@@ -1505,17 +1524,18 @@
2596 ... def documentCreated(event):
2597 ... event.doc.created = datetime.datetime.utcnow()
2598
2599-This marks the handler as an adapter of `IDocumentCreated` events.
2600+Ceci marque le gestionnaire comme étant un adaptateur des événements
2601+`IDocumentCreated`.
2602
2603-Now we'll register the handler::
2604+Nous inscrivons le gestionnaire ::
2605
2606 >>> from zope.component import getGlobalSiteManager
2607 >>> gsm = getGlobalSiteManager()
2608
2609 >>> gsm.registerHandler(documentCreated)
2610
2611-Now, if we can create an event and use the `handle` function to call
2612-handlers registered for the event::
2613+Il est maintenant possible de créer un événement et d'utiliser la fonction
2614+`handle` pour appeler les gestionnaires inscrits à l'événement ::
2615
2616 >>> from zope.component import handle
2617
2618@@ -1524,29 +1544,34 @@
2619 'datetime'
2620
2621
2622-ZCA usage in Zope
2623------------------
2624+Usage de la ZCA dans Zope
2625+-------------------------
2626
2627-Zope Component Architecture is used in both Zope 3 and Zope 2. This
2628-chapter go through ZCA usage in Zope.
2629+L'Architecture de Composants de Zope est utilisée dans Zope 2 et dans Zope 3. Ce
2630+chapitre traite de l'usage de la ZCA dans Zope.
2631
2632
2633 ZCML
2634 ~~~~
2635
2636-The Zope Configuration Markup Language (ZCML) is an XML based
2637-configuration system for registration of components. So, instead of
2638-using Python API for registration, you can use ZCML. But to use ZCML,
2639-unfortunately, you will be required to install more dependency
2640-packages.
2641+Le **Zope Configuration Markup Language (ZCML)** est un système de configuration
2642+pour l'inscription des composants. Au lieu d'utiliser l'API Python pour les
2643+inscriptions, vous pouvez utiliser le ZCML. Pour pouvoir utiliser le ZCML,
2644+vous devez installer des paquets supplémentaires.
2645
2646-To install these packages::
2647+Vous pouvez installer ``zope.component`` avec la prise en charge du ZCML en
2648+utilisant easy_install comme ceci ::
2649
2650 $ easy_install "zope.component [zcml]"
2651
2652-To register an adapter::
2653+Un fichier ZCML doit commencer par une directive ``configure`` avec la
2654+déclaration d'espace de nom appropriée ::
2655
2656 <configure xmlns="http://namespaces.zope.org/zope">
2657+ ...
2658+ </configure>
2659+
2660+La directive `adapter` peut être utilisée pour inscrire des adaptateurs ::
2661
2662 <adapter
2663 factory=".company.EmployeeSalary"
2664@@ -1554,73 +1579,59 @@
2665 for=".interfaces.IEmployee"
2666 />
2667
2668-The `provides` and `for` attributes are optional, provided you have
2669-declared it in the implementation::
2670-
2671- <configure xmlns="http://namespaces.zope.org/zope">
2672+Les attributs `provides` et `for` sont optionnels, à condition que vous ayez
2673+fait les déclaration correspondantes dans l'implémentation ::
2674
2675 <adapter
2676 factory=".company.EmployeeSalary"
2677 />
2678
2679-If you want to register the component as named adapter, you can give a
2680-`name` attribute::
2681-
2682-
2683- <configure xmlns="http://namespaces.zope.org/zope">
2684+Si vous voulez inscrire le composant comme un adaptateur nommé, vous pouvez
2685+utiliser l'attribut `name` ::
2686
2687 <adapter
2688 factory=".company.EmployeeSalary"
2689 name="salary"
2690 />
2691
2692-Utilities are also registered similarly.
2693-
2694-To register an utility::
2695-
2696- <configure xmlns="http://namespaces.zope.org/zope">
2697+Un utilitaire peut être inscrit avec la directive `utility` ::
2698
2699 <utility
2700 component=".database.connection"
2701 provides=".interfaces.IConnection"
2702 />
2703
2704-The `provides` attribute is optional, provided you have declared it in
2705-the implementation::
2706-
2707- <configure xmlns="http://namespaces.zope.org/zope">
2708-
2709- <utility
2710- component=".database.connection"
2711- />
2712-
2713-If you want to register the component as named adapter, you can give a
2714-`name` attribute::
2715-
2716-
2717- <configure xmlns="http://namespaces.zope.org/zope">
2718-
2719- <utility
2720- component=".database.connection"
2721- name="Database Connection"
2722- />
2723-
2724-Instead of directly using the component, you can also give a factory::
2725-
2726- <configure xmlns="http://namespaces.zope.org/zope">
2727+L'attribut `provides` est optionnel, à condition que vous ayez fait la
2728+déclaration correspondante dans l'implémentation ::
2729+
2730+ <configure xmlns="http://namespaces.zope.org/zope">
2731+
2732+ <utility
2733+ component=".database.connection"
2734+ />
2735+
2736+Si vous voulez inscrire le composant comme un utilitaire nommé, vous pouvez
2737+utiliser l'attribut `name` ::
2738+
2739+ <utility
2740+ component=".database.connection"
2741+ name="db_connection"
2742+ />
2743+
2744+Plutôt que d'utiliser directement le composant, vous pouvez aussi fournir une
2745+fabrique ::
2746
2747 <utility
2748 factory=".database.Connection"
2749 />
2750
2751
2752-Overrides
2753-~~~~~~~~~
2754+Surchargements
2755+~~~~~~~~~~~~~~
2756
2757-When you register components using Python API (``register*`` methods),
2758-the last registered component will replace previously registered
2759-component, if both are registered with same type of arguments. For
2760-example, consider this example::
2761+Lorsque vous inscrivez des composants avec l'API Python (méthodes
2762+``register*``), le dernier composant inscrit remplace le précédent, si les deux
2763+sont inscrits avec les mêmes arguments. Considérons l'exemple suivant ::
2764
2765 >>> from zope.interface import Attribute
2766 >>> from zope.interface import Interface
2767@@ -1665,22 +1676,21 @@
2768 >>> getAdapter(a, IP) #doctest: +ELLIPSIS
2769 <AP object at ...>
2770
2771- If you register another adapter, the existing one will be replaced:
2772+Si vous inscrivez un autre adaptateur, celui existant sera surchargé ::
2773
2774 >>> gsm.registerAdapter(AP2)
2775
2776 >>> getAdapter(a, IP) #doctest: +ELLIPSIS
2777 <AP2 object at ...>
2778
2779-But when registering components using ZCML, the second registration
2780-will raise a conflict error. This is a hint for you, otherwise there
2781-is a chance for overriding registration by mistake. This may lead to
2782-hard to track bugs in your system. So, using ZCML is a win for the
2783-application.
2784+Mais lorsque vous inscrivez des composants en ZCML, la deuxième inscription
2785+provoquera un conflit. Ceci est fait pour éviter les surchargements accidentels
2786+d'inscriptions, qui sont difficiles à retrouver et corriger.
2787+L'utilisation de ZCML est donc un avantage pour votre application.
2788
2789-Sometimes you will be required to override existing registration.
2790-ZCML provides ``includeOverrides`` directive for this. Using this,
2791-you can write your overrides in a separate file::
2792+Parfois vous aurez besoin de surcharger une inscription existante. ZCML fournit
2793+une directive ``includeOverrides`` à cet effet. Avec la directive ci-dessous,
2794+vous pouvez écrire vos surcharges dans un fichier séparé ::
2795
2796 <includeOverrides file="overrides.zcml" />
2797
2798@@ -1688,12 +1698,11 @@
2799 NameChooser
2800 ~~~~~~~~~~~
2801
2802-Location: `zope.app.container.contained.NameChooser`
2803-
2804-This is an adapter for choosing a unique name for an object inside a
2805-container.
2806-
2807-The registration of adapter is like this::
2808+Emplacement : `zope.app.container.contained.NameChooser`
2809+
2810+C'est un adaptateur qui choisit un nom unique pour un objet dans un conteneur.
2811+
2812+L'inscription de l'adaptateur ressemble à ceci ::
2813
2814 <adapter
2815 provides=".interfaces.INameChooser"
2816@@ -1701,40 +1710,37 @@
2817 factory=".contained.NameChooser"
2818 />
2819
2820-From the registration, you can see that the adaptee is a
2821-``IWriteContainer`` and the adapter provides ``INameChooser``.
2822+Dans cette inscription, vous pouvez observer qu'on s'adapte à un
2823+``IWriteContainer`` et que l'adaptateur fournit ``INameChooser``.
2824
2825-This adapter provides a very convenient functionality for Zope
2826-programmers. The main implementations of ``IWriteContainer`` in
2827-Zope 3 are ``zope.app.container.BTreeContainer`` and
2828-``zope.app.folder.Folder``. Normally you will be inheriting from
2829-these implementations for creating your own container classes.
2830-Suppose there is no interface called ``INameChooser`` and
2831-adapter, then you will be required to implement this functionality
2832-for every implementations separately.
2833+Cet adaptateur fournit une fonctionnalité très pratique pour les développeurs
2834+Zope. Les implémentations principales de ``IWriteContainer`` dans Zope 3 sont
2835+`zope.app.container.BTreeContainer`` et ``zope.app.folder.Folder``. Normalement
2836+vous hériterez de ces implémentations pour créer vos propres classes de
2837+conteneurs. Supposez qu'il n'y ait pas d'interface ``INameChooser`` ni
2838+d'adaptateur : vous seriez obligé de recréer cette fonctionnalité séparément
2839+pour chaque implémentation.
2840
2841
2842 LocationPhysicallyLocatable
2843 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
2844
2845-Location:
2846+Emplacement :
2847 ``zope.location.traversing.LocationPhysicallyLocatable``
2848
2849-This adapter is frequently used in Zope 3 applications, but
2850-normally it is called through an API in ``zope.traversing.api``.
2851-(Some old code even use ``zope.app.zapi`` functions, which is
2852-again one more indirection)
2853+Cet adaptateur est fréquemment utilisé dans les applications Zope 3, mais
2854+habituellement il est appelé au travers d'une API dans ``zope.traversing.api``.
2855+(Certains vieux codes utilisent même les fonctions ``zope.app.zapi`` qui ne sont
2856+qu'une indirection supplémentaire).
2857
2858-The registration of adapter is like this::
2859+L'inscription de l'adaptateur ressemble à ceci ::
2860
2861 <adapter
2862 factory="zope.location.traversing.LocationPhysicallyLocatable"
2863 />
2864
2865-The interface provided and adaptee interface is given in the
2866-implementation.
2867-
2868-Here is the beginning of implementation::
2869+L'interface fournie et l'interface adaptée sont données dans l'implémentation,
2870+dont voici le début ::
2871
2872 class LocationPhysicallyLocatable(object):
2873 """Provide location information for location objects
2874@@ -1743,43 +1749,41 @@
2875 zope.interface.implements(IPhysicallyLocatable)
2876 ...
2877
2878-Normally, almost all persistent objects in Zope 3 application
2879-will be providing the ``ILocation`` interface. This interface
2880-has only two attribute, ``__parent__`` and ``__name__``. The
2881-``__parent__`` is the parent in the location hierarchy. And
2882-``__name__`` is the name within the parent.
2883-
2884-The ``IPhysicallyLocatable`` interface has four methods:
2885-``getRoot``, ``getPath``, ``getName``, and ``getNearestSite``.
2886-
2887- - ``getRoot`` function will return the physical root object.
2888-
2889- - ``getPath`` return the physical path to the object as a
2890- string.
2891-
2892- - ``getName`` return the last segment of the physical path.
2893-
2894- - ``getNearestSite`` return the site the object is contained
2895- in. If the object is a site, the object itself is returned.
2896-
2897-If you learn Zope 3, you can see that these are the important
2898-things which you required very often. To understand the beauty
2899-of this system, you must see how Zope 2 actually get the physical
2900-root object and how it is implemented. There is a method called
2901-``getPhysicalRoot`` virtually for all container objects.
2902+Normalement, presque tous les objets persistants d'une application Zope 3
2903+fournissent l'interface ``ILocation``. Cette interface n'a que deux attributs,
2904+``__parent__`` et ``__name__``. ``__parent__`` est le parent dans la hiérarchie
2905+des objets et ``__name__`` est le nom, vu depuis le parent.
2906+
2907+L'interface ``IPhysicallyLocatable`` a quatre méthodes:
2908+``getRoot``, ``getPath``, ``getName``, et ``getNearestSite``.
2909+
2910+ - ``getRoot`` renvoie l'objet racine physique.
2911+
2912+ - ``getPath`` renvoie une chaîne donnant le chemin physique vers l'objet.
2913+
2914+ - ``getName`` renvoie le dernier segment du chemin physique.
2915+
2916+ - ``getNearestSite`` renvoie le site dans lequel l'objet est contenu. Si
2917+ l'objet est lui-même un site, il est renvoyé.
2918+
2919+Si vous apprenez Zope 3, ce sont des choses importantes dont vous aurez besoin
2920+très souvent. Pour comprendre la beauté de ce système, vous devriez regarder
2921+comment Zope 2 récupère l'objet racine physique et comment ceci est implémenté.
2922+Il existe une méthode ``getPhysicalRoot`` virtuellement pour tous les objets
2923+conteneurs.
2924
2925
2926 DefaultSized
2927 ~~~~~~~~~~~~
2928
2929-Location: ``zope.size.DefaultSized``
2930-
2931-This adapter is just a default implementation of ``ISized`` interface.
2932-This adapter is registered for all kind of objects. If you want to
2933-register this adapter for a particular interface, then you have to
2934-override this registration for your implementation.
2935-
2936-The registration of adapter is like this::
2937+Emplacement : ``zope.size.DefaultSized``
2938+
2939+Cet adaptateur n'est qu'une implémentation par défaut de l'interface ``ISized``.
2940+Il est inscrit pour tous les types d'objets. Si vous voulez inscrire cet
2941+adaptateur pour une interface particulière, vous devez surcharger cette
2942+inscription avec votre implémentation.
2943+
2944+L'inscription de l'adaptateur ressemble à ceci ::
2945
2946 <adapter
2947 for="*"
2948@@ -1788,10 +1792,10 @@
2949 permission="zope.View"
2950 />
2951
2952-As you can see, the adaptee interface is `*`, so it can adapt any kind
2953-of objects.
2954+Comme vous pouvez voir, l'interface adaptée est « * », pour pouvoir s'adapter à
2955+tous les types d'objets.
2956
2957-The ``ISized`` is a simple interface with two method contracts::
2958+``ISized`` est une interface simple possédant deux méthodes ::
2959
2960 class ISized(Interface):
2961
2962@@ -1806,112 +1810,793 @@
2963 """Returns a string giving the size.
2964 """
2965
2966-You can see another ``ISized`` adapter registered for ``IZPTPage`` in
2967-``zope.app.zptpage`` package.
2968+Vous pouvez trouver un autre adaptateur ``ISized`` pour ``IZPTPage`` dans le
2969+paquet ``zope.app.zptpage``.
2970
2971
2972 ZopeVersionUtility
2973 ~~~~~~~~~~~~~~~~~~
2974
2975-Location: ``zope.app.applicationcontrol.ZopeVersionUtility``
2976-
2977-This utility gives version of the running Zope.
2978-
2979-The registration goes like this::
2980+Emplacement : ``zope.app.applicationcontrol.ZopeVersionUtility``
2981+
2982+Cet utilitaire donne la version de Zope en fonctionnement.
2983+
2984+L'inscription est la suivante ::
2985
2986 <utility
2987 component=".zopeversion.ZopeVersionUtility"
2988 provides=".interfaces.IZopeVersion" />
2989
2990-The interface provided, ``IZopeVersion``, has only one method named
2991-``getZopeVersion``. This method return a string containing the Zope
2992-version (possibly including SVN information).
2993-
2994-The default implementation, ``ZopeVersionUtility``, get version info
2995-from a file ``version.txt`` in `zope/app` directory. If Zope is
2996-running from subversion checkout, it will show the latest revision
2997-number. If none of the above works it will set it to:
2998-`Development/Unknown`.
2999-
3000+L'interface fournie, ``IZopeVersion``, n'a qu'une méthode nommée
3001+``getZopeVersion``. Cette méthode renvoie une chaîne contenant la version de
3002+Zope (avec éventuellement un changeset SVN).
3003+
3004+L'implémentation par défaut, ``ZopeVersionUtility``, récupère le numéro de
3005+version dans un fichier ``version.txt`` du répertoire `zope/app`. Si Zope
3006+fonctionne depuis un espace de travail Subversion, il montre le dernier numéro
3007+de révision. Si aucun des deux ne fonctionne il renvoie `DevCenter/Unknown`.
3008+
3009+
3010+Étude de cas
3011+------------
3012+
3013+.. note::
3014+
3015+ Ce chapitre n'est pas terminé. Merci d'envoyer vos suggestions !
3016+
3017+Introduction
3018+~~~~~~~~~~~~
3019+
3020+Ce chapitre est un exemple de création d'une application lourde avec la
3021+bibliothèque d'interface graphique PyGTK et la ZCA. Cette application utilise
3022+également deux types différents de mécanismes de persistance des données : le
3023+premier est une base de données objet (ZODB), l'autre est une base de données
3024+relationnelle (SQLite). Cependant, en pratique, un seul des deux mécanismes peut
3025+être utilisé dans une installation donnée. L'utilisation de deux types de
3026+persistance est là pour démontrer comment utiliser la ZCA pour brancher des
3027+composants entre eux. La majorité de code de cette application est lié à PyGTK.
3028+
3029+Lorsque l'application grossit, vous pouvez utiliser les composants de la ZCA aux
3030+endroits où vous souhaitez fournir de la modularité ou de l'extensibilité.
3031+Utilisez des objets Python classiques quand vous n'avez pas besoin de ces
3032+propriétés.
3033+
3034+Il n'y a pas de différence entre l'utilisation de la ZCA pour une application
3035+web, pour une application graphique lourde, ou pour toute autre application ou
3036+framework. Il est préférable de suivre une convention pour l'emplacement où vous
3037+allez inscrire les composants. Cette application utilise une convention qui peut
3038+être étendue en plaçant des inscriptions ou des composants similaires dans des
3039+modules séparés et en les important plus tard depuis le module principal
3040+d'inscription. Dans cette application, le module principal pour l'inscription
3041+est `register.py`.
3042+
3043+Le code source de cette application peut être téléchargé sur :
3044+http://www.muthukadan.net/downloads/zcalib.tar.bz2
3045+
3046+
3047+Cas d'utilisation
3048+~~~~~~~~~~~~~~~~~
3049+
3050+L'application que nous allons créer ici est un système de gestion de
3051+bibliothèque avec des fonctionnalités minimales. Les besoins peuvent être
3052+résumés comme ceci:
3053+
3054+- Ajouter des membres avec un numéro et un nom uniques.
3055+
3056+- Ajouter des livres avec un code barre, un auteur et un titre.
3057+
3058+- Prêter des livres
3059+
3060+- Récupérer des livres
3061+
3062+
3063+L'application peut être conçue de telle façon que les grandes fonctionnalités
3064+seront utilisées dans une fenêtre unique. La fenêtre principale peut être conçue
3065+de cette façon :
3066+
3067+.. image:: mainwindow.png
3068+ :align: center
3069+
3070+Depuis la fenêtre des membres, l'utilisateur devrait être capable de gérer des
3071+membres. Donc il devrait être possible d'*ajouter*, *modifier* et *effacer* des
3072+membres comme dans l'image ci-dessous :
3073+
3074+.. image:: memberwindow.png
3075+ :align: center
3076+
3077+Similaire à la fenêtre des membres, la fenêtre du catalogue permet aux
3078+utilisateurs d'*ajouter*, *modifier* et *effacer* des livres :
3079+
3080+.. image:: catalogwindow.png
3081+ :align: center
3082+
3083+La fenêtre de circulation doit avoir ce qu'il faut pour prêter et récupérer des
3084+livres :
3085+
3086+.. image:: circulationwindow.png
3087+ :align: center
3088+
3089+
3090+Survol du code PyGTK
3091+~~~~~~~~~~~~~~~~~~~~
3092+
3093+Vous pouvez constater que la majorité du code est en rapport avec PyGTK.
3094+Sa structure est très similaire pour les différentes fenêtres. Les écrans
3095+de cette application sont conçus avec le créateur d'interface graphiques Glade.
3096+Vous devriez donner des noms appropriés aux widgets que vous allez utiliser dans
3097+votre code. Dans la fenêtre principale, tous les éléments de menu ont des noms
3098+du type : circulation, catalog, member, quit et about.
3099+
3100+La classe ``gtk.glade.XML`` est utilisée pour analyser le fichier Glade, et donc
3101+pour créer les objets widgets de l'interface graphique. Voici comment faire ::
3102+
3103+ import gtk.glade
3104+ xmlobj = gtk.glade.XML('/path/to/file.glade')
3105+ widget = xmlobj.get_widget('widget_name')
3106+
3107+Dans mainwindow.py, vous pouvez voir le code suivant ::
3108+
3109+ curdir = os.path.abspath(os.path.dirname(__file__))
3110+ xml = os.path.join(curdir, 'glade', 'mainwindow.glade')
3111+ xmlobj = gtk.glade.XML(xml)
3112+
3113+ self.mainwindow = xmlobj.get_widget('mainwindow')
3114+
3115+Le nom du widget fenêtre principal est `mainwindow`. Les autres widgets sont
3116+créés de la même manière ::
3117+
3118+ circulation = xmlobj.get_widget('circulation')
3119+ member = xmlobj.get_widget('member')
3120+ quit = xmlobj.get_widget('quit')
3121+ catalog = xmlobj.get_widget('catalog')
3122+ about = xmlobj.get_widget('about')
3123+
3124+Ensuite ces widgets sont connectés à certains événements ::
3125+
3126+ self.mainwindow.connect('delete_event', self.delete_event)
3127+ quit.connect('activate', self.delete_event)
3128+ circulation.connect('activate', self.on_circulation_activate)
3129+ member.connect('activate', self.on_member_activate)
3130+ catalog.connect('activate', self.on_catalog_activate)
3131+ about.connect('activate', self.on_about_activate)
3132+
3133+L'événement `delete_event` est celui correspondant à la fermeture de la fenêtre lors
3134+de l'appui sur le bouton de fermeture. L'événement `activate` est émis lorsque
3135+le menu est sélectionné. Les widgets sont connectés à des fonctions de rappel
3136+pour certains événements.
3137+
3138+Vous pouvez voir dans le code ci-dessus que la fenêtre principale est connectée
3139+à la méthode `on_delete_event` pour l'événement `delete_event`. Le widget `quit`
3140+est aussi connecté aux mêmes méthodes pour l'événement `activate` ::
3141+
3142+ def on_delete_event(self, *args):
3143+ gtk.main_quit()
3144+
3145+La fonction de rappel lance juste la fonction `main_quit`.
3146+
3147+
3148+Le code
3149+~~~~~~~
3150+
3151+Voici `zcalib.py` ::
3152+
3153+ import registry
3154+ import mainwindow
3155+
3156+ if __name__ == '__main__':
3157+ registry.initialize()
3158+ try:
3159+ mainwindow.main()
3160+ except KeyboardInterrupt:
3161+ import sys
3162+ sys.exit(1)
3163+
3164+Ici, deux modules sont importés : `registry` et `mainwindow`.
3165+Ensuite le registre est initialisé et la fonction `main` de la fenêtre
3166+principale est appelée. Si l'utilisateur essaye de fermer l'application en
3167+appuyant sur `Ctrl-C`, celle-ci s'arrête normalement car nous avons intercepté
3168+l'exception `KeyboardInterrupt`.
3169+
3170+Voici `registry.py` ::
3171+
3172+ import sys
3173+ from zope.component import getGlobalSiteManager
3174+
3175+ from interfaces import IMember
3176+ from interfaces import IBook
3177+ from interfaces import ICirculation
3178+ from interfaces import IDbOperation
3179+
3180+
3181+ def initialize_rdb():
3182+ from interfaces import IRelationalDatabase
3183+ from relationaldatabase import RelationalDatabase
3184+ from member import MemberRDbOperation
3185+ from catalog import BookRDbOperation
3186+ from circulation import CirculationRDbOperation
3187+
3188+ gsm = getGlobalSiteManager()
3189+ db = RelationalDatabase()
3190+ gsm.registerUtility(db, IRelationalDatabase)
3191+
3192+ gsm.registerAdapter(MemberRDbOperation,
3193+ (IMember,),
3194+ IDbOperation)
3195+
3196+ gsm.registerAdapter(BookRDbOperation,
3197+ (IBook,),
3198+ IDbOperation)
3199+
3200+ gsm.registerAdapter(CirculationRDbOperation,
3201+ (ICirculation,),
3202+ IDbOperation)
3203+
3204+ def initialize_odb():
3205+ from interfaces import IObjectDatabase
3206+ from objectdatabase import ObjectDatabase
3207+ from member import MemberODbOperation
3208+ from catalog import BookODbOperation
3209+ from circulation import CirculationODbOperation
3210+
3211+ gsm = getGlobalSiteManager()
3212+ db = ObjectDatabase()
3213+ gsm.registerUtility(db, IObjectDatabase)
3214+
3215+ gsm.registerAdapter(MemberODbOperation,
3216+ (IMember,),
3217+ IDbOperation)
3218+
3219+ gsm.registerAdapter(BookODbOperation,
3220+ (IBook,),
3221+ IDbOperation)
3222+
3223+ gsm.registerAdapter(CirculationODbOperation,
3224+ (ICirculation,),
3225+ IDbOperation)
3226+
3227+ def check_use_relational_db():
3228+ use_rdb = False
3229+ try:
3230+ arg = sys.argv[1]
3231+ if arg == '-r':
3232+ return True
3233+ except IndexError:
3234+ pass
3235+ return use_rdb
3236+
3237+ def initialize():
3238+ use_rdb = check_use_relational_db()
3239+ if use_rdb:
3240+ initialize_rdb()
3241+ else:
3242+ initialize_odb()
3243+
3244+Observez la fonction `initialize` que nous appelons depuis le module principal
3245+`zcalib.py`. Cette fonction commence par vérifier quelle base de données
3246+utiliser : une base relationnelle (RDB) ou une base objet (ODB). Cette
3247+vérification est effectuée dans la fonction `check_use_relational_db`. Si
3248+l'option `-r` est passé dans la ligne de commandes, elle appelera la fonction
3249+`initialize_rdb`, sinon `initialize_odb`. Si la fonction RDB est appelée, elle
3250+configure tous les composants liés à la base relationnelle. Si la fonction ODB est appelée,
3251+elle configure tous les composants liés à la base objet.
3252+
3253+Voici `mainwindow.py` ::
3254+
3255+ import os
3256+ import gtk
3257+ import gtk.glade
3258+
3259+ from circulationwindow import circulationwindow
3260+ from catalogwindow import catalogwindow
3261+ from memberwindow import memberwindow
3262+
3263+ class MainWindow(object):
3264+
3265+ def __init__(self):
3266+ curdir = os.path.abspath(os.path.dirname(__file__))
3267+ xml = os.path.join(curdir, 'glade', 'mainwindow.glade')
3268+ xmlobj = gtk.glade.XML(xml)
3269+
3270+ self.mainwindow = xmlobj.get_widget('mainwindow')
3271+ circulation = xmlobj.get_widget('circulation')
3272+ member = xmlobj.get_widget('member')
3273+ quit = xmlobj.get_widget('quit')
3274+ catalog = xmlobj.get_widget('catalog')
3275+ about = xmlobj.get_widget('about')
3276+
3277+ self.mainwindow.connect('delete_event', self.delete_event)
3278+ quit.connect('activate', self.delete_event)
3279+
3280+ circulation.connect('activate', self.on_circulation_activate)
3281+ member.connect('activate', self.on_member_activate)
3282+ catalog.connect('activate', self.on_catalog_activate)
3283+ about.connect('activate', self.on_about_activate)
3284+
3285+ def delete_event(self, *args):
3286+ gtk.main_quit()
3287+
3288+ def on_circulation_activate(self, *args):
3289+ circulationwindow.show_all()
3290+
3291+ def on_member_activate(self, *args):
3292+ memberwindow.show_all()
3293+
3294+ def on_catalog_activate(self, *args):
3295+ catalogwindow.show_all()
3296+
3297+ def on_about_activate(self, *args):
3298+ pass
3299+
3300+ def run(self):
3301+ self.mainwindow.show_all()
3302+
3303+ def main():
3304+ mainwindow = MainWindow()
3305+ mainwindow.run()
3306+ gtk.main()
3307+
3308+
3309+La fonction `main` crée une instance de la classe `MainWindow` qui initialise
3310+tous les widgets.
3311+
3312+Voici `memberwindow.py` ::
3313+
3314+ import os
3315+ import gtk
3316+ import gtk.glade
3317+
3318+ from zope.component import getAdapter
3319+
3320+ from components import Member
3321+ from interfaces import IDbOperation
3322+
3323+
3324+ class MemberWindow(object):
3325+
3326+ def __init__(self):
3327+ curdir = os.path.abspath(os.path.dirname(__file__))
3328+ xml = os.path.join(curdir, 'glade', 'memberwindow.glade')
3329+ xmlobj = gtk.glade.XML(xml)
3330+
3331+ self.memberwindow = xmlobj.get_widget('memberwindow')
3332+ self.number = xmlobj.get_widget('number')
3333+ self.name = xmlobj.get_widget('name')
3334+ add = xmlobj.get_widget('add')
3335+ update = xmlobj.get_widget('update')
3336+ delete = xmlobj.get_widget('delete')
3337+ close = xmlobj.get_widget('close')
3338+ self.treeview = xmlobj.get_widget('treeview')
3339+
3340+ self.memberwindow.connect('delete_event', self.on_delete_event)
3341+ add.connect('clicked', self.on_add_clicked)
3342+ update.connect('clicked', self.on_update_clicked)
3343+ delete.connect('clicked', self.on_delete_clicked)
3344+ close.connect('clicked', self.on_delete_event)
3345+
3346+ self.initialize_list()
3347+
3348+ def show_all(self):
3349+ self.populate_list_store()
3350+ self.memberwindow.show_all()
3351+
3352+ def populate_list_store(self):
3353+ self.list_store.clear()
3354+ member = Member()
3355+ memberdboperation = getAdapter(member, IDbOperation)
3356+ members = memberdboperation.get()
3357+ for member in members:
3358+ number = member.number
3359+ name = member.name
3360+ self.list_store.append((member, number, name,))
3361+
3362+ def on_delete_event(self, *args):
3363+ self.memberwindow.hide()
3364+ return True
3365+
3366+ def initialize_list(self):
3367+ self.list_store = gtk.ListStore(object, str, str)
3368+ self.treeview.set_model(self.list_store)
3369+ tvcolumn = gtk.TreeViewColumn('Member Number')
3370+ self.treeview.append_column(tvcolumn)
3371+
3372+ cell = gtk.CellRendererText()
3373+ tvcolumn.pack_start(cell, True)
3374+ tvcolumn.add_attribute(cell, 'text', 1)
3375+
3376+ tvcolumn = gtk.TreeViewColumn('Member Name')
3377+ self.treeview.append_column(tvcolumn)
3378+
3379+ cell = gtk.CellRendererText()
3380+ tvcolumn.pack_start(cell, True)
3381+ tvcolumn.add_attribute(cell, 'text', 2)
3382+
3383+ def on_add_clicked(self, *args):
3384+ number = self.number.get_text()
3385+ name = self.name.get_text()
3386+ member = Member()
3387+ member.number = number
3388+ member.name = name
3389+ self.add(member)
3390+ self.list_store.append((member, number, name,))
3391+
3392+ def add(self, member):
3393+ memberdboperation = getAdapter(member, IDbOperation)
3394+ memberdboperation.add()
3395+
3396+ def on_update_clicked(self, *args):
3397+ number = self.number.get_text()
3398+ name = self.name.get_text()
3399+ treeselection = self.treeview.get_selection()
3400+ model, iter = treeselection.get_selected()
3401+ if not iter:
3402+ return
3403+ member = self.list_store.get_value(iter, 0)
3404+ member.number = number
3405+ member.name = name
3406+ self.update(member)
3407+ self.list_store.set(iter, 1, number, 2, name)
3408+
3409+ def update(self, member):
3410+ memberdboperation = getAdapter(member, IDbOperation)
3411+ memberdboperation.update()
3412+
3413+ def on_delete_clicked(self, *args):
3414+ treeselection = self.treeview.get_selection()
3415+ model, iter = treeselection.get_selected()
3416+ if not iter:
3417+ return
3418+ member = self.list_store.get_value(iter, 0)
3419+ self.delete(member)
3420+ self.list_store.remove(iter)
3421+
3422+ def delete(self, member):
3423+ memberdboperation = getAdapter(member, IDbOperation)
3424+ memberdboperation.delete()
3425+
3426+ memberwindow = MemberWindow()
3427+
3428+Voici `components.py` ::
3429+
3430+ from zope.interface import implements
3431+
3432+ from interfaces import IBook
3433+ from interfaces import IMember
3434+ from interfaces import ICirculation
3435+
3436+ class Book(object):
3437+
3438+ implements(IBook)
3439+
3440+ barcode = ""
3441+ title = ""
3442+ author = ""
3443+
3444+ class Member(object):
3445+
3446+ implements(IMember)
3447+
3448+ number = ""
3449+ name = ""
3450+
3451+ class Circulation(object):
3452+
3453+ implements(ICirculation)
3454+
3455+ book = Book()
3456+ member = Member()
3457+
3458+Voici `interfaces.py` ::
3459+
3460+ from zope.interface import Interface
3461+ from zope.interface import Attribute
3462+
3463+
3464+ class IBook(Interface):
3465+
3466+ barcode = Attribute("Barcode")
3467+ author = Attribute("Author of book")
3468+ title = Attribute("Title of book")
3469+
3470+
3471+ class IMember(Interface):
3472+
3473+ number = Attribute("ID number")
3474+ name = Attribute("Name of member")
3475+
3476+
3477+ class ICirculation(Interface):
3478+
3479+ book = Attribute("A book")
3480+ member = Attribute("A member")
3481+
3482+
3483+ class IRelationalDatabase(Interface):
3484+
3485+ def commit():
3486+ pass
3487+
3488+ def rollback():
3489+ pass
3490+
3491+ def cursor():
3492+ pass
3493+
3494+ def get_next_id():
3495+ pass
3496+
3497+
3498+ class IObjectDatabase(Interface):
3499+
3500+ def commit():
3501+ pass
3502+
3503+ def rollback():
3504+ pass
3505+
3506+ def container():
3507+ pass
3508+
3509+ def get_next_id():
3510+ pass
3511+
3512+
3513+ class IDbOperation(Interface):
3514+
3515+ def get():
3516+ pass
3517+
3518+ def add():
3519+ pass
3520+
3521+ def update():
3522+ pass
3523+
3524+ def delete():
3525+ pass
3526+
3527+Here is the `member.py` ::
3528+
3529+ from zope.interface import implements
3530+ from zope.component import getUtility
3531+ from zope.component import adapts
3532+
3533+ from components import Member
3534+
3535+ from interfaces import IRelationalDatabase
3536+ from interfaces import IObjectDatabase
3537+ from interfaces import IMember
3538+ from interfaces import IDbOperation
3539+
3540+
3541+ class MemberRDbOperation(object):
3542+
3543+ implements(IDbOperation)
3544+ adapts(IMember)
3545+
3546+ def __init__(self, member):
3547+ self.member = member
3548+
3549+ def get(self):
3550+ db = getUtility(IRelationalDatabase)
3551+ cr = db.cursor()
3552+ number = self.member.number
3553+ if number:
3554+ cr.execute("""SELECT
3555+ id,
3556+ number,
3557+ name
3558+ FROM members
3559+ WHERE number = ?""",
3560+ (number,))
3561+ else:
3562+ cr.execute("""SELECT
3563+ id,
3564+ number,
3565+ name
3566+ FROM members""")
3567+ rst = cr.fetchall()
3568+ cr.close()
3569+ members = []
3570+ for record in rst:
3571+ id = record['id']
3572+ number = record['number']
3573+ name = record['name']
3574+ member = Member()
3575+ member.id = id
3576+ member.number = number
3577+ member.name = name
3578+ members.append(member)
3579+ return members
3580+
3581+ def add(self):
3582+ db = getUtility(IRelationalDatabase)
3583+ cr = db.cursor()
3584+ next_id = db.get_next_id("members")
3585+ number = self.member.number
3586+ name = self.member.name
3587+ cr.execute("""INSERT INTO members
3588+ (id, number, name)
3589+ VALUES (?, ?, ?)""",
3590+ (next_id, number, name))
3591+ cr.close()
3592+ db.commit()
3593+ self.member.id = next_id
3594+
3595+ def update(self):
3596+ db = getUtility(IRelationalDatabase)
3597+ cr = db.cursor()
3598+ number = self.member.number
3599+ name = self.member.name
3600+ id = self.member.id
3601+ cr.execute("""UPDATE members
3602+ SET
3603+ number = ?,
3604+ name = ?
3605+ WHERE id = ?""",
3606+ (number, name, id))
3607+ cr.close()
3608+ db.commit()
3609+
3610+ def delete(self):
3611+ db = getUtility(IRelationalDatabase)
3612+ cr = db.cursor()
3613+ id = self.member.id
3614+ cr.execute("""DELETE FROM members
3615+ WHERE id = ?""",
3616+ (id,))
3617+ cr.close()
3618+ db.commit()
3619+
3620+
3621+ class MemberODbOperation(object):
3622+
3623+ implements(IDbOperation)
3624+ adapts(IMember)
3625+
3626+ def __init__(self, member):
3627+ self.member = member
3628+
3629+ def get(self):
3630+ db = getUtility(IObjectDatabase)
3631+ zcalibdb = db.container()
3632+ members = zcalibdb['members']
3633+ return members.values()
3634+
3635+ def add(self):
3636+ db = getUtility(IObjectDatabase)
3637+ zcalibdb = db.container()
3638+ members = zcalibdb['members']
3639+ number = self.member.number
3640+ if number in [x.number for x in members.values()]:
3641+ db.rollback()
3642+ raise Exception("Duplicate key")
3643+ next_id = db.get_next_id('members')
3644+ self.member.id = next_id
3645+ members[next_id] = self.member
3646+ db.commit()
3647+
3648+ def update(self):
3649+ db = getUtility(IObjectDatabase)
3650+ zcalibdb = db.container()
3651+ members = zcalibdb['members']
3652+ id = self.member.id
3653+ members[id] = self.member
3654+ db.commit()
3655+
3656+ def delete(self):
3657+ db = getUtility(IObjectDatabase)
3658+ zcalibdb = db.container()
3659+ members = zcalibdb['members']
3660+ id = self.member.id
3661+ del members[id]
3662+ db.commit()
3663+
3664+
3665+PySQLite
3666+~~~~~~~~
3667+
3668+ZODB
3669+~~~~
3670+
3671+Conclusions
3672+~~~~~~~~~~~
3673
3674 Reference
3675 ---------
3676
3677
3678-Attribute
3679-~~~~~~~~~
3680-
3681-Using this class, you can define normal attribute in an interface.
3682-
3683- - Location: ``zope.interface``
3684-
3685- - Signature: `Attribute(name, doc='')`
3686-
3687-Example::
3688-
3689- >>> from zope.interface import Attribute
3690- >>> from zope.interface import Interface
3691-
3692- >>> class IPerson(Interface):
3693- ...
3694- ... name = Attribute("Name of person")
3695- ... email = Attribute("Email Address")
3696-
3697-
3698-Declaration
3699-~~~~~~~~~~~
3700-
3701-Need not to use directly.
3702-
3703-
3704-Interface
3705-~~~~~~~~~
3706-
3707-Using this class, you can define an interface. To define an
3708-interface, just inherit from ``Interface`` class.
3709-
3710- - Location: ``zope.interface``
3711-
3712- - Signature: `Interface(name, doc='')`
3713-
3714-Example 1::
3715-
3716- >>> from zope.interface import Attribute
3717- >>> from zope.interface import Interface
3718-
3719- >>> class IPerson(Interface):
3720- ...
3721- ... name = Attribute("Name of person")
3722- ... email = Attribute("Email Address")
3723-
3724-
3725-Example 2::
3726-
3727- >>> from zope.interface import Interface
3728-
3729- >>> class IHost(Interface):
3730- ...
3731- ... def goodmorning(guest):
3732- ... """Say good morning to guest"""
3733+adaptedBy
3734+~~~~~~~~~
3735+
3736+Cette fonction permet de trouver les interfaces adaptées.
3737+
3738+ - Emplacement : ``zope.component``
3739+
3740+ - Signature : `adaptedBy(object)`
3741+
3742+Exemple ::
3743+
3744+ >>> from zope.interface import implements
3745+ >>> from zope.component import adapts
3746+ >>> from zope.component import adaptedBy
3747+
3748+ >>> class FrontDeskNG(object):
3749+ ...
3750+ ... implements(IDesk)
3751+ ... adapts(IGuest)
3752+ ...
3753+ ... def __init__(self, guest):
3754+ ... self.guest = guest
3755+
3756+ >>> adaptedBy(FrontDeskNG)
3757+ (<InterfaceClass __builtin__.IGuest>,)
3758+
3759+
3760+adapter
3761+~~~~~~~
3762+
3763+Un adaptateur peut être n'importe quel objet appelable. Vous pouvez
3764+utiliser le décorateur `adapter` pour déclarer qu'un objet appelable s'adapte à
3765+des interfaces (ou des classes).
3766+
3767+ - Emplacement : ``zope.component``
3768+
3769+ - Signature : `adapter(*interfaces)`
3770+
3771+Exemple ::
3772+
3773+ >>> from zope.interface import Attribute
3774+ >>> from zope.interface import Interface
3775+ >>> from zope.interface import implementer
3776+ >>> from zope.component import adapter
3777+ >>> from zope.interface import implements
3778+
3779+ >>> class IJob(Interface):
3780+ ... """A job"""
3781+
3782+ >>> class Job(object):
3783+ ... implements(IJob)
3784+
3785+ >>> class IPerson(Interface):
3786+ ...
3787+ ... name = Attribute("Name")
3788+ ... job = Attribute("Job")
3789+
3790+ >>> class Person(object):
3791+ ... implements(IPerson)
3792+ ...
3793+ ... name = None
3794+ ... job = None
3795+
3796+ >>> @implementer(IJob)
3797+ ... @adapter(IPerson)
3798+ ... def personJob(person):
3799+ ... return person.job
3800+
3801+ >>> jack = Person()
3802+ >>> jack.name = "Jack"
3803+ >>> jack.job = Job()
3804+ >>> personJob(jack) #doctest: +ELLIPSIS
3805+ <Job object at ...>
3806
3807
3808 adapts
3809 ~~~~~~
3810
3811-This function helps to declare adapter classes.
3812-
3813- - Location: ``zope.component``
3814-
3815- - Signature: `adapts(*interfaces)`
3816-
3817-Example::
3818+Cette fonction permet de déclarer les classes adaptateurs.
3819+
3820+ - Emplacement : ``zope.component``
3821+
3822+ - Signature : `adapts(*interfaces)`
3823+
3824+Exemple ::
3825
3826 >>> from zope.interface import implements
3827 >>> from zope.component import adapts
3828
3829- >>> class GuestRegistrarNG(object):
3830+ >>> class FrontDeskNG(object):
3831 ...
3832- ... implements(IRegistrar)
3833+ ... implements(IDesk)
3834 ... adapts(IGuest)
3835 ...
3836 ... def __init__(self, guest):
3837@@ -1919,7 +2604,7 @@
3838 ...
3839 ... def register(self):
3840 ... next_id = get_next_id()
3841- ... guests_db[next_id] = {
3842+ ... bookings_db[next_id] = {
3843 ... 'name': guest.name,
3844 ... 'place': guest.place,
3845 ... 'phone': guest.phone
3846@@ -1929,15 +2614,15 @@
3847 alsoProvides
3848 ~~~~~~~~~~~~
3849
3850-Declare interfaces declared directly for an object. The arguments
3851-after the object are one or more interfaces. The interfaces given are
3852-added to the interfaces previously declared for the object.
3853-
3854- - Location: ``zope.interface``
3855-
3856- - Signature: `alsoProvides(object, *interfaces)`
3857-
3858-Example::
3859+Déclare des interfaces additionnelles fournies par un objet. Les arguments après
3860+l'objet sont une ou plusieurs interfaces. Les interfaces données sont ajoutées
3861+aux interfaces précédemment déclarées pour l'objet.
3862+
3863+ - Emplacement : ``zope.interface``
3864+
3865+ - Signature : `alsoProvides(object, *interfaces)`
3866+
3867+Exemple ::
3868
3869 >>> from zope.interface import Attribute
3870 >>> from zope.interface import Interface
3871@@ -1954,7 +2639,7 @@
3872
3873 >>> class Person(object):
3874 ...
3875- ... implements(IRegistrar)
3876+ ... implements(IDesk)
3877 ... name = u""
3878
3879 >>> jack = Person()
3880@@ -1962,25 +2647,48 @@
3881 >>> jack.college = "New College"
3882 >>> alsoProvides(jack, IStudent)
3883
3884- You can test it like this:
3885+ Vous pouvez tester de cette façon:
3886
3887 >>> from zope.interface import providedBy
3888 >>> IStudent in providedBy(jack)
3889 True
3890
3891
3892+Attribute
3893+~~~~~~~~~
3894+
3895+En utilisant cette classe, vous pouvez définir des attributs dans une interface.
3896+
3897+ - Emplacement : ``zope.interface``
3898+
3899+ - Signature : `Attribute(name, doc='')`
3900+
3901+ - Voir aussi : `Interface`_
3902+
3903+Exemple ::
3904+
3905+ >>> from zope.interface import Attribute
3906+ >>> from zope.interface import Interface
3907+
3908+ >>> class IPerson(Interface):
3909+ ...
3910+ ... name = Attribute("Name of person")
3911+ ... email = Attribute("Email Address")
3912+
3913+
3914 classImplements
3915 ~~~~~~~~~~~~~~~
3916
3917-Declare additional interfaces implemented for instances of a class.
3918-The arguments after the class are one or more interfaces. The
3919-interfaces given are added to any interfaces previously declared.
3920-
3921- - Location: ``zope.interface``
3922-
3923- - Signature: `classImplements(cls, *interfaces)`
3924-
3925-Example::
3926+Déclare des interfaces additionnelles qui doivent être fournies par les
3927+instances d'une classe. Les arguments après la classe sont une ou plusieurs
3928+interfaces. Les interfaces données sont ajoutées aux interfaces précédemment
3929+déclarées.
3930+
3931+ - Emplacement : ``zope.interface``
3932+
3933+ - Signature : `classImplements(cls, *interfaces)`
3934+
3935+Exemple ::
3936
3937 >>> from zope.interface import Attribute
3938 >>> from zope.interface import Interface
3939@@ -1997,7 +2705,7 @@
3940
3941 >>> class Person(object):
3942 ...
3943- ... implements(IRegistrar)
3944+ ... implements(IDesk)
3945 ... name = u""
3946 ... college = u""
3947
3948@@ -2006,7 +2714,7 @@
3949 >>> jack.name = "Jack"
3950 >>> jack.college = "New College"
3951
3952- You can test it like this:
3953+ Vous pouvez tester de cette façon :
3954
3955 >>> from zope.interface import providedBy
3956 >>> IStudent in providedBy(jack)
3957@@ -2016,15 +2724,16 @@
3958 classImplementsOnly
3959 ~~~~~~~~~~~~~~~~~~~
3960
3961-Declare the only interfaces implemented by instances of a class. The
3962-arguments after the class are one or more interfaces. The interfaces
3963-given replace any previous declarations.
3964-
3965- - Location: ``zope.interface``
3966-
3967- - Signature: `classImplementsOnly(cls, *interfaces)`
3968-
3969-Example::
3970+Déclare les seules interfaces qui devront être fournies par les instances d'une
3971+classe. Les arguments après la classe sont une ou plusieurs interfaces. Les
3972+interfaces fournies vont remplacer toutes les interfaces des déclarations
3973+précédentes.
3974+
3975+ - Emplacement : ``zope.interface``
3976+
3977+ - Signature : `classImplementsOnly(cls, *interfaces)`
3978+
3979+Exemple ::
3980
3981 >>> from zope.interface import Attribute
3982 >>> from zope.interface import Interface
3983@@ -2048,7 +2757,7 @@
3984 >>> jack = Person()
3985 >>> jack.college = "New College"
3986
3987- You can test it like this:
3988+ Vous pouvez tester de cette façon :
3989
3990 >>> from zope.interface import providedBy
3991 >>> IPerson in providedBy(jack)
3992@@ -2060,16 +2769,16 @@
3993 classProvides
3994 ~~~~~~~~~~~~~
3995
3996-Normally if a class implements a particular interface, the instance of
3997-that class will provide the interface implemented by that class. But
3998-if you want a class to be provided by an interface, you can declare it
3999-using ``classProvides`` function.
4000-
4001- - Location: ``zope.interface``
4002-
4003- - Signature: `classProvides(*interfaces)`
4004-
4005-Example::
4006+Normalement si une classe implémente une interface particulière, les instances
4007+de cette classe fourniront l'interface implémentée par la classe. Mais si vous
4008+voulez qu'une classe fournisse une interface, vous pouvez le déclarer grâce à la
4009+fonction ``classProvides``.
4010+
4011+ - Emplacement : ``zope.interface``
4012+
4013+ - Signature : `classProvides(*interfaces)`
4014+
4015+Exemple ::
4016
4017 >>> from zope.interface import Attribute
4018 >>> from zope.interface import Interface
4019@@ -2084,7 +2793,7 @@
4020 ... classProvides(IPerson)
4021 ... name = u"Jack"
4022
4023- You can test it like this:
4024+ Vous pouvez tester de cette façon :
4025
4026 >>> from zope.interface import providedBy
4027 >>> IPerson in providedBy(Person)
4028@@ -2094,26 +2803,39 @@
4029 ComponentLookupError
4030 ~~~~~~~~~~~~~~~~~~~~
4031
4032+C'est l'exception levée quand une recherche de composant échoue.
4033+
4034+Exemple ::
4035+
4036+ >>> class IPerson(Interface):
4037+ ...
4038+ ... name = Attribute("Name of person")
4039+
4040+ >>> person = object()
4041+ >>> getAdapter(person, IPerson, 'not-exists') #doctest: +ELLIPSIS
4042+ Traceback (most recent call last):
4043+ ...
4044+ ComponentLookupError: ...
4045+
4046
4047 createObject
4048 ~~~~~~~~~~~~
4049
4050-Create an object using a factory.
4051-
4052-Finds the named factory in the current site and calls it with the
4053-given arguments. If a matching factory cannot be found raises
4054-ComponentLookupError. Returns the created object.
4055-
4056-A context keyword argument can be provided to cause the factory to be
4057-looked up in a location other than the current site. (Of course, this
4058-means that it is impossible to pass a keyword argument named "context"
4059-to the factory.
4060-
4061- - Location: ``zope.component``
4062-
4063- - Signature: `createObject(factory_name, *args, **kwargs)`
4064-
4065-Example::
4066+Crée un objet en utilisant une fabrique.
4067+
4068+Cette fonction trouve une fabrique nommée dans le site courant et l'appelle avec
4069+les arguments donnés. Si la bonne fabrique ne peut pas être trouvée, une erreur
4070+``ComponentLookupError`` est déclenchée. Sinon l'objet créé est renvoyé.
4071+
4072+Un argument mot-clé contextuel peut être fourni pour rechercher une fabrique
4073+dans un emplacement différent du site courant. (Bien sûr, cela signifie qu'il
4074+est impossible de transmettre à la fabrique un argument mot-clé nommé « context ».
4075+
4076+ - Emplacement : ``zope.component``
4077+
4078+ - Signature : `createObject(factory_name, *args, **kwargs)`
4079+
4080+Exemple ::
4081
4082 >>> from zope.interface import Attribute
4083 >>> from zope.interface import Interface
4084@@ -2146,17 +2868,22 @@
4085 <FakeDb object at ...>
4086
4087
4088+Declaration
4089+~~~~~~~~~~~
4090+
4091+N'a pas besoin d'être utilisé directement.
4092+
4093+
4094 directlyProvidedBy
4095 ~~~~~~~~~~~~~~~~~~
4096
4097-This function will return the interfaces directly provided by the
4098-given object.
4099-
4100- - Location: ``zope.interface``
4101-
4102- - Signature: `directlyProvidedBy(object)`
4103-
4104-Example::
4105+Cette fonction renvoie les interfaces fournies directement par un objet donné.
4106+
4107+ - Emplacement : ``zope.interface``
4108+
4109+ - Signature : `directlyProvidedBy(object)`
4110+
4111+Exemple ::
4112
4113 >>> from zope.interface import Attribute
4114 >>> from zope.interface import Interface
4115@@ -2196,15 +2923,15 @@
4116 directlyProvides
4117 ~~~~~~~~~~~~~~~~
4118
4119-Declare interfaces declared directly for an object. The arguments
4120-after the object are one or more interfaces. The interfaces given
4121-replace interfaces previously declared for the object.
4122-
4123- - Location: ``zope.interface``
4124-
4125- - Signature: `directlyProvides(object, *interfaces)`
4126-
4127-Example::
4128+Déclare que des interfaces sont fournies directement par un objet. Les arguments
4129+après l'objet sont une ou plusieurs interfaces. Les interfaces données
4130+remplacent celles précédemment déclarées pour l'objet.
4131+
4132+ - Emplacement : ``zope.interface``
4133+
4134+ - Signature : `directlyProvides(object, *interfaces)`
4135+
4136+Exemple ::
4137
4138 >>> from zope.interface import Attribute
4139 >>> from zope.interface import Interface
4140@@ -2262,21 +2989,22 @@
4141 getAdapter
4142 ~~~~~~~~~~
4143
4144-Get a named adapter to an interface for an object. Returns an adapter
4145-that can adapt object to interface. If a matching adapter cannot be
4146-found, raises ``ComponentLookupError`` .
4147-
4148- - Location: ``zope.interface``
4149-
4150- - Signature: `getAdapter(object, interface=Interface, name=u'', context=None)`
4151-
4152-Example::
4153+Cette fonction récupère un adaptateur (nommé) vers une interface, pour un objet
4154+donné. Elle renvoie un adaptateur qui peut adapter les objets à l'interface
4155+voulue. Si aucun adaptateur ne peut être trouvé, une erreur
4156+``ComponentLookupError`` est émise.
4157+
4158+ - Emplacement : ``zope.interface``
4159+
4160+ - Signature : `getAdapter(object, interface=Interface, name=u'', context=None)`
4161+
4162+Exemple ::
4163
4164 >>> from zope.interface import Attribute
4165 >>> from zope.interface import Interface
4166
4167- >>> class IRegistrar(Interface):
4168- ... """A registrar will register object's details"""
4169+ >>> class IDesk(Interface):
4170+ ... """A frontdesk will register object's details"""
4171 ...
4172 ... def register():
4173 ... """Register object's details"""
4174@@ -2285,9 +3013,9 @@
4175 >>> from zope.interface import implements
4176 >>> from zope.component import adapts
4177
4178- >>> class GuestRegistrarNG(object):
4179+ >>> class FrontDeskNG(object):
4180 ...
4181- ... implements(IRegistrar)
4182+ ... implements(IDesk)
4183 ... adapts(IGuest)
4184 ...
4185 ... def __init__(self, guest):
4186@@ -2295,7 +3023,7 @@
4187 ...
4188 ... def register(self):
4189 ... next_id = get_next_id()
4190- ... guests_db[next_id] = {
4191+ ... bookings_db[next_id] = {
4192 ... 'name': guest.name,
4193 ... 'place': guest.place,
4194 ... 'phone': guest.phone
4195@@ -2310,31 +3038,33 @@
4196 ... self.place = place
4197
4198 >>> jack = Guest("Jack", "Bangalore")
4199- >>> jack_registrar = GuestRegistrarNG(jack)
4200+ >>> jack_frontdesk = FrontDeskNG(jack)
4201
4202- >>> IRegistrar.providedBy(jack_registrar)
4203+ >>> IDesk.providedBy(jack_frontdesk)
4204 True
4205
4206 >>> from zope.component import getGlobalSiteManager
4207 >>> gsm = getGlobalSiteManager()
4208- >>> gsm.registerAdapter(GuestRegistrarNG,
4209- ... (IGuest,), IRegistrar, 'ng')
4210+ >>> gsm.registerAdapter(FrontDeskNG,
4211+ ... (IGuest,), IDesk, 'ng')
4212
4213- >>> getAdapter(jack, IRegistrar, 'ng') #doctest: +ELLIPSIS
4214- <GuestRegistrarNG object at ...>
4215+ >>> getAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
4216+ <FrontDeskNG object at ...>
4217
4218
4219 getAdapterInContext
4220 ~~~~~~~~~~~~~~~~~~~
4221
4222-Instead of this function, use `context` argument of `getAdapter`_
4223-function.
4224-
4225- - Location: ``zope.component``
4226-
4227- - Signature: `getAdapterInContext(object, interface, context)`
4228-
4229-Example::
4230+Au lieu d'utiliser cette fonction, utilisez `getAdapter`_ avec un argument
4231+`context`.
4232+
4233+ - Emplacement : ``zope.component``
4234+
4235+ - Signature : `getAdapterInContext(object, interface, context)`
4236+
4237+ - Voir aussi : `queryAdapterInContext`_
4238+
4239+Exemple ::
4240
4241 >>> from zope.component.globalregistry import BaseGlobalComponents
4242 >>> from zope.component import IComponentLookup
4243@@ -2352,8 +3082,8 @@
4244 >>> from zope.interface import Attribute
4245 >>> from zope.interface import Interface
4246
4247- >>> class IRegistrar(Interface):
4248- ... """A registrar will register object's details"""
4249+ >>> class IDesk(Interface):
4250+ ... """A frontdesk will register object's details"""
4251 ...
4252 ... def register():
4253 ... """Register object's details"""
4254@@ -2362,9 +3092,9 @@
4255 >>> from zope.interface import implements
4256 >>> from zope.component import adapts
4257
4258- >>> class GuestRegistrarNG(object):
4259+ >>> class FrontDeskNG(object):
4260 ...
4261- ... implements(IRegistrar)
4262+ ... implements(IDesk)
4263 ... adapts(IGuest)
4264 ...
4265 ... def __init__(self, guest):
4266@@ -2372,7 +3102,7 @@
4267 ...
4268 ... def register(self):
4269 ... next_id = get_next_id()
4270- ... guests_db[next_id] = {
4271+ ... bookings_db[next_id] = {
4272 ... 'name': guest.name,
4273 ... 'place': guest.place,
4274 ... 'phone': guest.phone
4275@@ -2387,42 +3117,41 @@
4276 ... self.place = place
4277
4278 >>> jack = Guest("Jack", "Bangalore")
4279- >>> jack_registrar = GuestRegistrarNG(jack)
4280+ >>> jack_frontdesk = FrontDeskNG(jack)
4281
4282- >>> IRegistrar.providedBy(jack_registrar)
4283+ >>> IDesk.providedBy(jack_frontdesk)
4284 True
4285
4286 >>> from zope.component import getGlobalSiteManager
4287 >>> gsm = getGlobalSiteManager()
4288- >>> sm.registerAdapter(GuestRegistrarNG,
4289- ... (IGuest,), IRegistrar)
4290+ >>> sm.registerAdapter(FrontDeskNG,
4291+ ... (IGuest,), IDesk)
4292
4293 >>> from zope.component import getAdapterInContext
4294- >>> from zope.component import queryAdapterInContext
4295
4296- >>> getAdapterInContext(jack, IRegistrar, sm) #doctest: +ELLIPSIS
4297- <GuestRegistrarNG object at ...>
4298+ >>> getAdapterInContext(jack, IDesk, sm) #doctest: +ELLIPSIS
4299+ <FrontDeskNG object at ...>
4300
4301
4302 getAdapters
4303 ~~~~~~~~~~~
4304
4305-Look for all matching adapters to a provided interface for objects.
4306-Return a list of adapters that match. If an adapter is named, only the
4307-most specific adapter of a given name is returned.
4308-
4309- - Location: ``zope.component``
4310-
4311- - Signature: `getAdapters(objects, provided, context=None)`
4312-
4313-Example::
4314+Recherche pour des objets tous les adaptateurs fournissant une interface donnée.
4315+Une liste d'adaptateurs est renvoyée. Si un adaptateur est nommé, seul
4316+l'adaptateur le plus spécifique pour un nom donné est renvoyé.
4317+
4318+ - Emplacement : ``zope.component``
4319+
4320+ - Signature : `getAdapters(objects, provided, context=None)`
4321+
4322+Exemple ::
4323
4324 >>> from zope.interface import implements
4325 >>> from zope.component import adapts
4326
4327- >>> class GuestRegistrarNG(object):
4328+ >>> class FrontDeskNG(object):
4329 ...
4330- ... implements(IRegistrar)
4331+ ... implements(IDesk)
4332 ... adapts(IGuest)
4333 ...
4334 ... def __init__(self, guest):
4335@@ -2430,37 +3159,37 @@
4336 ...
4337 ... def register(self):
4338 ... next_id = get_next_id()
4339- ... guests_db[next_id] = {
4340+ ... bookings_db[next_id] = {
4341 ... 'name': guest.name,
4342 ... 'place': guest.place,
4343 ... 'phone': guest.phone
4344 ... }
4345
4346 >>> jack = Guest("Jack", "Bangalore")
4347- >>> jack_registrar = GuestRegistrarNG(jack)
4348+ >>> jack_frontdesk = FrontDeskNG(jack)
4349
4350 >>> from zope.component import getGlobalSiteManager
4351 >>> gsm = getGlobalSiteManager()
4352
4353- >>> gsm.registerAdapter(GuestRegistrarNG, name='ng')
4354+ >>> gsm.registerAdapter(FrontDeskNG, name='ng')
4355
4356 >>> from zope.component import getAdapters
4357- >>> list(getAdapters((jack,), IRegistrar)) #doctest: +ELLIPSIS
4358- [(u'ng', <GuestRegistrarNG object at ...>)]
4359+ >>> list(getAdapters((jack,), IDesk)) #doctest: +ELLIPSIS
4360+ [(u'ng', <FrontDeskNG object at ...>)]
4361
4362
4363 getAllUtilitiesRegisteredFor
4364 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4365
4366-Return all registered utilities for an interface. This includes
4367-overridden utilities. The returned value is an iterable of utility
4368-instances.
4369-
4370- - Location: ``zope.component``
4371-
4372- - Signature: `getAllUtilitiesRegisteredFor(interface)`
4373-
4374-Example::
4375+Renvoie tous les utilitaires inscrits pour une interface. Ceci inclut les
4376+utilitaires surchargés. La valeur renvoyée est un objet iterable listant les
4377+instances d'utilitaires correspondants.
4378+
4379+ - Emplacement : ``zope.component``
4380+
4381+ - Signature : `getAllUtilitiesRegisteredFor(interface)`
4382+
4383+Exemple ::
4384
4385 >>> from zope.interface import Interface
4386 >>> from zope.interface import implements
4387@@ -2491,14 +3220,14 @@
4388 getFactoriesFor
4389 ~~~~~~~~~~~~~~~
4390
4391-Return a tuple (name, factory) of registered factories that create
4392-objects which implement the given interface.
4393-
4394- - Location: ``zope.component``
4395-
4396- - Signature: `getFactoriesFor(interface, context=None)`
4397-
4398-Example::
4399+Renvoie un tuple (nom, fabrique) de fabriques inscrites capables de créer des
4400+objets qui fournissent une interface donnée.
4401+
4402+ - Emplacement : ``zope.component``
4403+
4404+ - Signature : `getFactoriesFor(interface, context=None)`
4405+
4406+Exemple ::
4407
4408 >>> from zope.interface import Attribute
4409 >>> from zope.interface import Interface
4410@@ -2535,16 +3264,16 @@
4411 getFactoryInterfaces
4412 ~~~~~~~~~~~~~~~~~~~~
4413
4414-Get interfaces implemented by a factory. Finds the factory of the
4415-given name that is nearest to the context, and returns the interface
4416-or interface tuple that object instances created by the named factory
4417-will implement.
4418-
4419- - Location: ``zope.component``
4420-
4421- - Signature: `getFactoryInterfaces(name, context=None)`
4422-
4423-Example::
4424+Récupère les interfaces implémentées par une fabrique. Cette fonction trouve la
4425+fabrique possédant le nom donné la plus proche du contexte, puis renvoie
4426+l'interface ou le tuple d'interfaces que les instances créées par la fabrique
4427+vont fournir.
4428+
4429+ - Emplacement : ``zope.component``
4430+
4431+ - Signature : `getFactoryInterfaces(name, context=None)`
4432+
4433+Exemple ::
4434
4435 >>> from zope.interface import Attribute
4436 >>> from zope.interface import Interface
4437@@ -2581,14 +3310,14 @@
4438 getGlobalSiteManager
4439 ~~~~~~~~~~~~~~~~~~~~
4440
4441-Return the global site manager. This function should never fail and
4442-always return an object that provides `IGlobalSiteManager`
4443-
4444- - Location: ``zope.component``
4445-
4446- - Signature: `getGlobalSiteManager()`
4447-
4448-Example::
4449+Renvoie le gestionnaire global de site. Cette fonction ne doit jamais échouer
4450+et doit toujours renvoyer un objet qui fournit `IGlobalSiteManager`.
4451+
4452+ - Emplacement : ``zope.component``
4453+
4454+ - Signature : `getGlobalSiteManager()`
4455+
4456+Exemple ::
4457
4458 >>> from zope.component import getGlobalSiteManager
4459 >>> from zope.component import globalSiteManager
4460@@ -2600,19 +3329,21 @@
4461 getMultiAdapter
4462 ~~~~~~~~~~~~~~~
4463
4464-Look for a multi-adapter to an interface for an objects. Returns a
4465-multi-adapter that can adapt objects to interface. If a matching
4466-adapter cannot be found, raises ComponentLookupError. The name
4467-consisting of an empty string is reserved for unnamed adapters. The
4468-unnamed adapter methods will often call the named adapter methods with
4469-an empty string for a name.
4470-
4471- - Location: ``zope.component``
4472-
4473- - Signature: `getMultiAdapter(objects, interface=Interface, name='',
4474+Cette fonction recherche pour des objets un multi-adaptateur vers une interface
4475+donnée. Elle renvoie un multi-adaptateur qui peut s'adapter aux objets donnés et
4476+fournir l'interface voulue. Si aucun adaptateur ne peut être trouvé, une erreur
4477+`ComponentLookupError` est émise. Le nom constitué de la chaîne vide est réservé
4478+aux adaptateur sans nom. Les méthodes des adaptateurs sans nom appellent souvent
4479+les méthodes des adaptateurs nommés en fournissant un nom vide ('').
4480+
4481+ - Emplacement : ``zope.component``
4482+
4483+ - Signature : `getMultiAdapter(objects, interface=Interface, name='',
4484 context=None)`
4485
4486-Example::
4487+ - Voir aussi : `queryMultiAdapter`_
4488+
4489+Exemple ::
4490
4491 >>> from zope.interface import Interface
4492 >>> from zope.interface import implements
4493@@ -2664,17 +3395,17 @@
4494 getSiteManager
4495 ~~~~~~~~~~~~~~
4496
4497-Get the nearest site manager in the given context. If `context` is
4498-`None`, return the global site manager. If the `context` is not
4499-`None`, it is expected that an adapter from the `context` to
4500-`IComponentLookup` can be found. If no adapter is found, a
4501-`ComponentLookupError` is raised.
4502-
4503- - Location: ``zope.component``
4504-
4505- - Signature: `getSiteManager(context=None)`
4506-
4507-Example 1::
4508+Récupère le gestionnaire de site le plus proche du contexte donné. Si `context`
4509+est `None`, cette fonction renvoie le gestionnaire global de site. Si le
4510+`context` n'est pas `None`, on s'attend à ce qu'un adaptateur sur le contexte
4511+vers `IComponentLookup` soit trouvé. Si aucun adaptateur n'est trouvé, une
4512+erreur `ComponentLookupError` est émise.
4513+
4514+ - Emplacement : ``zope.component``
4515+
4516+ - Signature : `getSiteManager(context=None)`
4517+
4518+Exemple 1 ::
4519
4520 >>> from zope.component.globalregistry import BaseGlobalComponents
4521 >>> from zope.component import IComponentLookup
4522@@ -2695,7 +3426,7 @@
4523 >>> lsm is sm
4524 True
4525
4526-Example 2::
4527+Exemple 2 ::
4528
4529 >>> from zope.component import getGlobalSiteManager
4530 >>> gsm = getGlobalSiteManager()
4531@@ -2708,14 +3439,14 @@
4532 getUtilitiesFor
4533 ~~~~~~~~~~~~~~~
4534
4535-Look up the registered utilities that provide an interface. Returns
4536-an iterable of name-utility pairs.
4537-
4538- - Location: ``zope.component``
4539-
4540- - Signature: `getUtilitiesFor(interface)`
4541-
4542-Example::
4543+Récupère les utilitaires inscrits pour une interface particulière. Renvoie un
4544+objet iterable listant les paires nom/utilitaire.
4545+
4546+ - Emplacement : ``zope.component``
4547+
4548+ - Signature : `getUtilitiesFor(interface)`
4549+
4550+Exemple ::
4551
4552 >>> from zope.interface import Interface
4553 >>> from zope.interface import implements
4554@@ -2746,15 +3477,15 @@
4555 getUtility
4556 ~~~~~~~~~~
4557
4558-Get the utility that provides interface. Returns the nearest utility
4559-to the context that implements the specified interface. If one is not
4560-found, raises ComponentLookupError.
4561-
4562- - Location: ``zope.component``
4563-
4564- - Signature: `getUtility(interface, name='', context=None)`
4565-
4566-Example::
4567+Récupère l'utilitaire qui fournit une interface donnée. Cette fonction renvoie
4568+l'utilitaire le plus proche du contexte et qui fournit l'interface donnée. Si
4569+aucun n'est trouvé, une erreur ``ComponentLookupError`` est levée.
4570+
4571+ - Emplacement : ``zope.component``
4572+
4573+ - Signature : `getUtility(interface, name='', context=None)`
4574+
4575+Exemple ::
4576
4577 >>> from zope.interface import Interface
4578 >>> from zope.interface import implements
4579@@ -2785,16 +3516,15 @@
4580 handle
4581 ~~~~~~
4582
4583-Call all of the handlers for the given objects. Handlers are
4584-subscription adapter factories that don't produce anything. They do
4585-all of their work when called. Handlers are typically used to handle
4586-events.
4587-
4588- - Location: ``zope.component``
4589-
4590- - Signature: `handle(*objects)`
4591-
4592-Example::
4593+Appelle tous les gestionnaires pour un objet donné. Les gestionnaires sont des
4594+fabriques d'abonnés qui ne produisent rien. Ils font tout leur travail lors de
4595+l'appel. Ils sont typiquement utilisés pour gérer des événements.
4596+
4597+ - Emplacement : ``zope.component``
4598+
4599+ - Signature : `handle(*objects)`
4600+
4601+Exemple ::
4602
4603 >>> import datetime
4604
4605@@ -2840,13 +3570,13 @@
4606 implementedBy
4607 ~~~~~~~~~~~~~
4608
4609-Return the interfaces implemented for a class' instances.
4610-
4611- - Location: ``zope.interface``
4612-
4613- - Signature: `implementedBy(class_)`
4614-
4615-Example 1::
4616+Renvoie les interfaces implémentées par une classe.
4617+
4618+ - Emplacement : ``zope.interface``
4619+
4620+ - Signature : `implementedBy(class_)`
4621+
4622+Exemple 1 ::
4623
4624 >>> from zope.interface import Interface
4625 >>> from zope.interface import implements
4626@@ -2866,7 +3596,7 @@
4627 >>> implementedBy(Greeter)
4628 <implementedBy __builtin__.Greeter>
4629
4630-Example 2::
4631+Exemple 2 ::
4632
4633 >>> from zope.interface import Attribute
4634 >>> from zope.interface import Interface
4635@@ -2887,7 +3617,8 @@
4636
4637 >>> from zope.interface import implementedBy
4638
4639- To get a list of all interfaces implemented by that class::
4640+ Pour récupérer une liste de toutes les interfaces implémentées par cette
4641+ classe ::
4642
4643 >>> [x.__name__ for x in implementedBy(Person)]
4644 ['IPerson', 'ISpecial']
4645@@ -2896,15 +3627,15 @@
4646 implementer
4647 ~~~~~~~~~~~
4648
4649-Create a decorator for declaring interfaces implemented by a factory.
4650-A callable is returned that makes an implements declaration on objects
4651-passed to it.
4652-
4653- - Location: ``zope.interface``
4654-
4655- - Signature: `implementer(*interfaces)`
4656-
4657-Example::
4658+Créer un décorateur permettant de déclarer des interfaces implémentées par une
4659+fabrique. Un objet appelable est renvoyé, qui fait une déclaration
4660+d'implémentation sur les objets qui lui sont transmis.
4661+
4662+ - Emplacement : ``zope.interface``
4663+
4664+ - Signature : `implementer(*interfaces)`
4665+
4666+Exemple ::
4667
4668 >>> from zope.interface import implementer
4669 >>> class IFoo(Interface):
4670@@ -2923,17 +3654,17 @@
4671 implements
4672 ~~~~~~~~~~
4673
4674-Declare interfaces implemented by instances of a class This function
4675-is called in a class definition. The arguments are one or more
4676-interfaces. The interfaces given are added to any interfaces
4677-previously declared. Previous declarations include declarations for
4678-base classes unless implementsOnly was used.
4679-
4680- - Location: ``zope.interface``
4681-
4682- - Signature: `implements(*interfaces)`
4683-
4684-Example::
4685+Déclare que des interfaces seront fournies par une classe. Cette fonction est
4686+appelée dans une définition de classe. Les arguments sont une ou plusieurs
4687+interfaces. Les interfaces données sont ajoutées aux interfaces précédemment
4688+déclarées. Les déclarations précédentes incluent les déclarations des classes
4689+debase, à moins que `implementsOnly` ne soit utilisé.
4690+
4691+ - Emplacement : ``zope.interface``
4692+
4693+ - Signature : `implements(*interfaces)`
4694+
4695+Exemple ::
4696
4697 >>> from zope.interface import Attribute
4698 >>> from zope.interface import Interface
4699@@ -2957,19 +3688,20 @@
4700 >>> IPerson in providedBy(jack)
4701 True
4702
4703+
4704 implementsOnly
4705 ~~~~~~~~~~~~~~
4706
4707-Declare the only interfaces implemented by instances of a class. This
4708-function is called in a class definition. The arguments are one or
4709-more interfaces. Previous declarations including declarations for
4710-base classes are overridden.
4711-
4712- - Location: ``zope.interface``
4713-
4714- - Signature: `implementsOnly(*interfaces)`
4715-
4716-Example::
4717+Déclare les seules interfaces qui doivent être implémentées par une classe.
4718+Cette fonction est appelée dans la définition de classe. Les arguments sont une
4719+ou plusieurs interfaces. Les déclarations précédentes, y compris celles des
4720+classes de base, sont remplacées.
4721+
4722+ - Emplacement : ``zope.interface``
4723+
4724+ - Signature : `implementsOnly(*interfaces)`
4725+
4726+Exemple ::
4727
4728 >>> from zope.interface import Attribute
4729 >>> from zope.interface import Interface
4730@@ -3005,35 +3737,78 @@
4731 True
4732
4733
4734+Interface
4735+~~~~~~~~~
4736+
4737+Grâce à cette classe, vous pouvez définir une interface. Pour définir une
4738+interface, contentez-vous d'hériter de cette classe.
4739+
4740+ - Emplacement : ``zope.interface``
4741+
4742+ - Signature : `Interface(name, doc='')`
4743+
4744+Exemple 1 ::
4745+
4746+ >>> from zope.interface import Attribute
4747+ >>> from zope.interface import Interface
4748+
4749+ >>> class IPerson(Interface):
4750+ ...
4751+ ... name = Attribute("Name of person")
4752+ ... email = Attribute("Email Address")
4753+
4754+
4755+Exemple 2 ::
4756+
4757+ >>> from zope.interface import Interface
4758+
4759+ >>> class IHost(Interface):
4760+ ...
4761+ ... def goodmorning(guest):
4762+ ... """Say good morning to guest"""
4763+
4764+
4765 moduleProvides
4766 ~~~~~~~~~~~~~~
4767
4768-Declare interfaces provided by a module. This function is used in a
4769-module definition. The arguments are one or more interfaces. The
4770-given interfaces are used to create the module's direct-object
4771-interface specification. An error will be raised if the module
4772-already has an interface specification. In other words, it is an
4773-error to call this function more than once in a module definition.
4774-
4775-This function is provided for convenience. It provides a more
4776-convenient way to call directlyProvides for a module.
4777-
4778- - Location: ``zope.interface``
4779-
4780- - Signature: `moduleProvides(*interfaces)`
4781+Déclare les interfaces fournies par un module. Cette fonction est utilisée dans
4782+une définition de module. Les arguments sont une ou plusieurs interfaces. Les
4783+interfaces fournies sont utilisées pour créer la spécification d'interface objet
4784+du module. Une erreur est levée si le module a déjà une spécification
4785+d'interface. Autrement dit, c'est une erreur d'appeler cette fonction plus d'une
4786+fois dans une définition de module.
4787+
4788+Cette fonction est fournie pour des raisons pratiques. Elle fournit une manière
4789+plus pratique d'appeler ``directlyProvides`` pour un module.
4790+
4791+ - Emplacement : ``zope.interface``
4792+
4793+ - Signature : `moduleProvides(*interfaces)`
4794+
4795+ - Voir aussi : `directlyProvides`_
4796+
4797+Vous pouvez consulter un exemple d'utilisation dans le code source de
4798+`zope.component` lui-même. Le fichier `__init__.py` possède celle
4799+instruction ::
4800+
4801+ moduleProvides(IComponentArchitecture,
4802+ IComponentRegistrationConvenience)
4803+
4804+Ainsi, le paquet `zope.component` fournit deux interfaces :
4805+`IComponentArchitecture` et `IComponentRegistrationConvenience`.
4806
4807
4808 noLongerProvides
4809 ~~~~~~~~~~~~~~~~
4810
4811-Remove an interface from the list of an object's directly provided
4812-interfaces.
4813-
4814- - Location: ``zope.interface``
4815-
4816- - Signature: `noLongerProvides(object, interface)`
4817-
4818-Example::
4819+Retire une interface de la liste des interfaces directements fournies par un
4820+objet.
4821+
4822+ - Emplacement : ``zope.interface``
4823+
4824+ - Signature : `noLongerProvides(object, interface)`
4825+
4826+Exemple ::
4827
4828 >>> from zope.interface import Attribute
4829 >>> from zope.interface import Interface
4830@@ -3076,39 +3851,38 @@
4831 provideAdapter
4832 ~~~~~~~~~~~~~~
4833
4834-It is recommend to use `registerAdapter`_ .
4835+Il est recommandé d'utilier `registerAdapter`_ .
4836
4837
4838 provideHandler
4839 ~~~~~~~~~~~~~~
4840
4841-It is recommend to use `registerHandler`_ .
4842+Il est recommandé d'utiliser `registerHandler`_ .
4843
4844
4845 provideSubscriptionAdapter
4846 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4847
4848-It is recommend to use `registerSubscriptionAdapter`_ .
4849+Il est recommandé d'utiliser `registerSubscriptionAdapter`_ .
4850
4851
4852 provideUtility
4853 ~~~~~~~~~~~~~~
4854
4855-It is recommend to use `registerUtility`_ .
4856+Il est recommandé d'utiliser `registerUtility`_ .
4857
4858
4859 providedBy
4860 ~~~~~~~~~~
4861
4862-Test whether the interface is implemented by the object. Return true
4863-if the object asserts that it implements the interface, including
4864-asserting that it implements an extended interface.
4865-
4866- - Location: ``zope.interface``
4867-
4868- - Signature: `providedBy(object)`
4869-
4870-Example 1::
4871+Teste si l'interface est implémentée par l'objet. Renvoie True si l'objet
4872+affirme qu'il implémente l'interface, y compris les interfaces étendues.
4873+
4874+ - Emplacement : ``zope.interface``
4875+
4876+ - Signature : `providedBy(object)`
4877+
4878+Exemple 1 ::
4879
4880 >>> from zope.interface import Attribute
4881 >>> from zope.interface import Interface
4882@@ -3132,7 +3906,7 @@
4883 >>> IPerson in providedBy(jack)
4884 True
4885
4886-Example 2::
4887+Exemple 2 ::
4888
4889 >>> from zope.interface import Attribute
4890 >>> from zope.interface import Interface
4891@@ -3154,7 +3928,7 @@
4892 >>> jack = Person()
4893 >>> jack.name = "Jack"
4894
4895- To get a list of all interfaces provided by that object::
4896+ Pour obtenir une liste de toutes les interfaces fournies par cet objet ::
4897
4898 >>> [x.__name__ for x in providedBy(jack)]
4899 ['IPerson', 'ISpecial']
4900@@ -3163,22 +3937,22 @@
4901 queryAdapter
4902 ~~~~~~~~~~~~
4903
4904-Look for a named adapter to an interface for an object. Returns an
4905-adapter that can adapt object to interface. If a matching adapter
4906-cannot be found, returns the default.
4907-
4908- - Location: ``zope.component``
4909-
4910- - Signature: `queryAdapter(object, interface=Interface, name=u'',
4911+Recherche pour un objet un adaptateur nommé vers une interface. Renvoie un
4912+adaptateur qui peut s'adapter à un objet et fournir une interface. Si aucun
4913+adaptateur ne peut être trouvé, la valeur par défaut est renvoyée.
4914+
4915+ - Emplacement : ``zope.component``
4916+
4917+ - Signature : `queryAdapter(object, interface=Interface, name=u'',
4918 default=None, context=None)`
4919
4920-Example::
4921+Exemple ::
4922
4923 >>> from zope.interface import Attribute
4924 >>> from zope.interface import Interface
4925
4926- >>> class IRegistrar(Interface):
4927- ... """A registrar will register object's details"""
4928+ >>> class IDesk(Interface):
4929+ ... """A frontdesk will register object's details"""
4930 ...
4931 ... def register():
4932 ... """Register object's details"""
4933@@ -3187,9 +3961,9 @@
4934 >>> from zope.interface import implements
4935 >>> from zope.component import adapts
4936
4937- >>> class GuestRegistrarNG(object):
4938+ >>> class FrontDeskNG(object):
4939 ...
4940- ... implements(IRegistrar)
4941+ ... implements(IDesk)
4942 ... adapts(IGuest)
4943 ...
4944 ... def __init__(self, guest):
4945@@ -3197,7 +3971,7 @@
4946 ...
4947 ... def register(self):
4948 ... next_id = get_next_id()
4949- ... guests_db[next_id] = {
4950+ ... bookings_db[next_id] = {
4951 ... 'name': guest.name,
4952 ... 'place': guest.place,
4953 ... 'phone': guest.phone
4954@@ -3212,32 +3986,50 @@
4955 ... self.place = place
4956
4957 >>> jack = Guest("Jack", "Bangalore")
4958- >>> jack_registrar = GuestRegistrarNG(jack)
4959+ >>> jack_frontdesk = FrontDeskNG(jack)
4960
4961- >>> IRegistrar.providedBy(jack_registrar)
4962+ >>> IDesk.providedBy(jack_frontdesk)
4963 True
4964
4965 >>> from zope.component import getGlobalSiteManager
4966 >>> gsm = getGlobalSiteManager()
4967- >>> gsm.registerAdapter(GuestRegistrarNG,
4968- ... (IGuest,), IRegistrar, 'ng')
4969+ >>> gsm.registerAdapter(FrontDeskNG,
4970+ ... (IGuest,), IDesk, 'ng')
4971
4972- >>> queryAdapter(jack, IRegistrar, 'ng') #doctest: +ELLIPSIS
4973- <GuestRegistrarNG object at ...>
4974+ >>> queryAdapter(jack, IDesk, 'ng') #doctest: +ELLIPSIS
4975+ <FrontDeskNG object at ...>
4976
4977
4978 queryAdapterInContext
4979 ~~~~~~~~~~~~~~~~~~~~~
4980
4981-Instead of this function, use `context` argument of `queryAdapter`_
4982-function.
4983-
4984- - Location: ``zope.component``
4985-
4986- - Signature: `queryAdapterInContext(object, interface, context,
4987+Recherche pour un objet un adaptateur spécial vers une interface.
4988+
4989+NOTE : cette méthode ne doit être utilisée que si un contexte personnalisé doit
4990+être fourni lors d'une recherche de composant personnalisée. Sinon, appelez
4991+l'interface comme ci-dessous ::
4992+
4993+ interface(object, default)
4994+
4995+Renvoie un adaptateur qui peut s'adapter à l'objet et fournir l'interface. Si
4996+aucun adaptateur n'est fourni, la valeur par défaut est renvoyée.
4997+
4998+Le contexte est adapté à IServiceService, et ce service d'adaptateurs, fourni par
4999+l'adaptateur, est utilisé.
5000+
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: