P. 1
zca

zca

|Views: 10|Likes:
Published by mail2saud

More info:

Published by: mail2saud on Oct 21, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

10/21/2011

pdf

text

original

Sections

  • Getting started
  • 1.1 Introduction
  • 1.2 A brief history
  • 1.3 Installation
  • 1.4. EXPERIMENTING WITH CODE 9
  • 1.4 Experimenting with code
  • An example
  • 2.1 Introduction
  • 2.2 Procedural approach
  • 2.3 Object oriented approach
  • 2.4 The adapter pattern
  • Interfaces
  • 3.1 Introduction
  • 3.2 Declaring interfaces
  • 3.3. IMPLEMENTING INTERFACES 17
  • 3.3 Implementing interfaces
  • 3.4 Example revisited
  • 3.5 Marker interfaces
  • 3.6 Invariants
  • Adapters
  • 4.1 Implementation
  • 4.2 Registration
  • 4.3 Querying adapter
  • 4.4 Retrieving adapter using interface
  • 4.5 Adapter pattern
  • Utility
  • 5.1 Introduction
  • 5.2 Simple utility
  • 5.3 Named utility
  • 5.4 Factory
  • Advanced adapters
  • 6.1 Multi adapter
  • 6.2 Subscription adapter
  • 6.3 Handler
  • ZCA usage in Zope
  • 7.1 ZCML
  • 7.2 Overrides
  • 7.3 NameChooser
  • 7.4 LocationPhysicallyLocatable
  • 7.5 DefaultSized
  • 7.6 ZopeVersionUtility
  • Case study
  • 8.1 Introduction
  • 8.2 Use cases
  • 8.3 Overview of PyGTK code
  • 8.4 The code
  • 8.5 PySQLite
  • 8.6 ZODB
  • 8.7 Conclusions
  • Reference
  • 9.1 adaptedBy
  • 9.2 adapter
  • 9.3 adapts
  • 9.4 alsoProvides
  • 9.5 Attribute
  • 9.6 classImplements
  • 9.7 classImplementsOnly
  • 9.8 classProvides
  • 9.9 ComponentLookupError
  • 9.10 createObject
  • 9.11 Declaration
  • 9.12 directlyProvidedBy
  • 9.13 directlyProvides
  • 9.14 getAdapter
  • 9.15 getAdapterInContext
  • 9.16 getAdapters
  • 9.17 getAllUtilitiesRegisteredFor
  • 9.18 getFactoriesFor
  • 9.19 getFactoryInterfaces
  • 9.20 getGlobalSiteManager
  • 9.21 getMultiAdapter
  • 9.22 getSiteManager
  • 9.23 getUtilitiesFor
  • 9.24 getUtility
  • 9.25 handle
  • 9.26 implementedBy
  • 9.27 implementer
  • 9.28 implements
  • 9.29 implementsOnly
  • 9.30 Interface
  • 9.31 moduleProvides
  • 9.32 noLongerProvides
  • 9.33 provideAdapter
  • 9.34 provideHandler
  • 9.35 provideSubscriptionAdapter
  • 9.36 provideUtility
  • 9.37 providedBy
  • 9.38 queryAdapter
  • 9.39 queryAdapterInContext
  • 9.40 queryMultiAdapter
  • 9.41 queryUtility
  • 9.42 registerAdapter
  • 9.43 registeredAdapters
  • 9.44 registeredHandlers
  • 9.45. REGISTEREDSUBSCRIPTIONADAPTERS 91
  • 9.45 registeredSubscriptionAdapters
  • 9.46 registeredUtilities
  • 9.47 registerHandler
  • 9.48. REGISTERSUBSCRIPTIONADAPTER 93
  • 9.48 registerSubscriptionAdapter
  • 9.49 registerUtility
  • 9.50 subscribers
  • 9.51 unregisterAdapter
  • 9.52 unregisterHandler
  • 9.53. UNREGISTERSUBSCRIPTIONADAPTER 99
  • 9.53 unregisterSubscriptionAdapter
  • 9.54 unregisterUtility

A Comprehensive Guide to Zope Component Architecture

Baiju M

2 Version: Printed Book: Online PDF: 0.5.7 http://www.lulu.com/content/1561045 http://www.muthukadan.net/docs/zca.pdf

Copyright (C) 2007,2008,2009 Baiju M <baiju.m.mail AT gmail.com>. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or (at your option) any later version published by the Free Software Foundation. The source code in this document is subject to the provisions of the Zope Public License, Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgements
Many people have helped me to write this book. The initial draft was reviewed by my colleague Brad Allen. When I announced this book through my blog, I received many encouraging comments to proceed with this work. Kent Tenney edited most parts of the book, he also rewrote the example application. Many others sent me fixes and comments including, Lorenzo Gil Sanchez, Michael Haubenwallner, Nando Quintana, Stephane Klein, Tim Cook, Kamal Gill and Thomas Herve. Lorenzo translated this work to Spanish and Stephane translated it to French. Thanks to all !

Contents
1 Getting started 1.1 1.2 1.3 1.4 2 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A brief history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Experimenting with code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 6 7 9 9 9 10 12 13 13 14 15 16 16 17 19 19 20 21 22 22 25 25 25 26 27

An example 2.1 2.2 2.3 2.4 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Procedural approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object oriented approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The adapter pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3

Interfaces 3.1 3.2 3.3 3.4 3.5 3.6 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Declaring interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementing interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Example revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Marker interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4

Adapters 4.1 4.2 4.3 4.4 4.5 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Registration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Querying adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retrieving adapter using interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adapter pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5

Utility 5.1 5.2 5.3 5.4 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Named utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3

4 6 Advanced adapters 6.1 6.2 6.3 7

CONTENTS 29 29 30 32 35 35 36 38 38 39 39 41 41 41 43 44 53 53 53 55 55 55 56 57 58 58 59 60 60 60 61 61 62 64 65 66

Multi adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Subscription adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

ZCA usage in Zope 7.1 7.2 7.3 7.4 7.5 7.6 ZCML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overrides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NameChooser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . LocationPhysicallyLocatable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DefaultSized . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ZopeVersionUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

Case study 8.1 8.2 8.3 8.4 8.5 8.6 8.7 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Use cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overview of PyGTK code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . PySQLite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ZODB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9

Reference 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 adaptedBy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . adapts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . alsoProvides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . classImplements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . classImplementsOnly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . classProvides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ComponentLookupError . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.10 createObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.11 Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.12 directlyProvidedBy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.13 directlyProvides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.14 getAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15 getAdapterInContext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.16 getAdapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CONTENTS 9.17 getAllUtilitiesRegisteredFor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.18 getFactoriesFor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.19 getFactoryInterfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.20 getGlobalSiteManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.21 getMultiAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.22 getSiteManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.23 getUtilitiesFor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.24 getUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.25 handle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.26 implementedBy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.27 implementer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.28 implements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.29 implementsOnly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.30 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.31 moduleProvides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.32 noLongerProvides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.33 provideAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.34 provideHandler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.35 provideSubscriptionAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.36 provideUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.37 providedBy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.38 queryAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.39 queryAdapterInContext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.40 queryMultiAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.41 queryUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.42 registerAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.43 registeredAdapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.44 registeredHandlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.45 registeredSubscriptionAdapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.46 registeredUtilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.47 registerHandler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.48 registerSubscriptionAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.49 registerUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.50 subscribers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.51 unregisterAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.52 unregisterHandler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.53 unregisterSubscriptionAdapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.54 unregisterUtility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 67 68 69 69 70 71 72 72 73 74 75 75 76 77 77 78 79 79 79 79 79 80 82 83 84 85 86 88 89 90 90 91 92 93 95 96 97 99

6

CONTENTS

rather it is about creating. Components are reusable objects with introspectable interfaces. The ZCA is all about using Python objects effectively.component deals with creation. and retrieving components.zope. The ZCA is not specific to the Zope web application server: it can be used for developing any Python application. registration and retrieval of components. There are many frameworks for supporting component based design in different languages. or any other callable object. 1 http://wiki. Component based approach helps you to write and maintain easily unit-testable software systems. Currently Zope 3. • zope. so it can be used in any kind of Python application. design and programming has been shown to be well suited for dealing with large systems. Zope Component Architecture (ZCA) is a Python framework for supporting component based design and programming.org/zope3/ComponentArchitecture 7 . component provides an interface implemented in a class. the important part is that it comply with its interface contracts. It is very well suited to developing large Python software systems. the ZCA is not the components themselves. Examples of these are Microsoft’s COM and Mozilla’s XPCOM. As noted earlier. it is a pure Python framework. There are three core packages related to the ZCA: • zope. an adapter is a normal Python class (or a factory in general) and utility is a normal Python callable object. Zope 2 and Grok projects use this framework extensively. In other words. Maybe it should be called as Python Component Architecture. registering.1 Introduction Developing a large software system is always very complicated.event provides a simple event system. and programming using components are becoming very popular these days. Component based design. Using ZCA. It helps you to create two basic kinds of components: adapter and utility. An interface is an object that describes how you work with a particular component. Remember. Remember also.interface is used to define the interface of a component. It doesn’t matter how the component is implemented. you can spread the complexity of systems over multiple cooperating components.Chapter 1 Getting started 1. An object oriented approach to analysis. The ZCA framework is developed as part of the Zope 3 project. some are even language neutral. • zope. There are many other projects including non-web applications using it1 .

There is also another general user list for Zope 3 (zope3-users) which can be used for any queries about the ZCA7 .deferredimport and zope.com/DevCenter/setuptools#declaring-dependencies 4 http://docs. Philipp von Weitershausen.component and its dependencies from PyPI and then install them.telecommunity.launchpad. Jim Fulton was the project leader of this project. zope. They provide facilities for defining. Install packages in the order given below. Now. This project is coming as part the bigger the Zope framework project4 .2 A brief history The ZCA framework project began in 2001 as part of Zope 3 project. package together with the zope.interface.event 3.com/DevCenter/EasyInstall . and the main zope-dev list is used for development discussions6 . During PyCon 2007.3 Installation The zope. including but not limited to.zope.interface and zope. 1. With this simplification. It grew out of lessons learned while developing large software systems using Zope 2. Many people contributed to the design and implementation.zope.org/zopeframework/ 5 https://bugs. In fact.component and its dependencies from PyPI and install it in your Python path.org/zope3/LocalComponentManagementSimplification 3 http://peak.python.component package had a long list of dependencies.proxy. services and views. The zope. However.interface 2. Python BDFL). Guido van Rossum (aka. Stephan Richter.component 2 http://wiki.2 release cycle.component This command will download zope. subscribers and handlers are two special types of adapters. On Windows. issues and bugs are still tracked as part of the Zope 3 project5 . many of which were not required for a non Zope 3 application.8 CHAPTER 1. you can download zope. Initially ZCA defined additional components. but the developers came to realize that utility can replace service and multi-adapter can replace view. adapters. The ZCA project is an independent project with it’s own release cycle and Subversion repository.event packages are the core of Zope component architecture. Alternately.zope. Tres Seaver. 1. Now ZCA has a very small number of core component types: utilities. GETTING STARTED 1. In March 2009.org/mailman/listinfo/zope3-users 8 Repository of Python packages: http://pypi. registering and looking up components.component.net/zope3 6 http://mail.org/mailman/listinfo/zope-dev 7 http://mail. subscribers and handlers. Tres Seaver removed dependcencies of zope. a new single interface (IComponentRegistry) for registration of both global and local component was created. Jim Fulton added setuptools’ extras_require feature to allow separating out core ZCA functionality from add-on features3 .zope. Phillip J Eby and Martijn Faassen. Jim Fulton proposed a major simplification of ZCA2 . During the Zope 3. zope.telecommunity.org/pypi 9 http://peak. you may need binary packages of zope. You can install zope. zope.component package and its dependencies are available in egg format from the Python Package Index (PyPI)8 .component and it’s dependencies using easy_install 9 $ easy_install zope. The zope.

tar.recipe. To create new buildout to experiment with Python eggs.tar. You can also use these packages together.zope. Now. virtualenv created by Ian Biking and zc.gz cd zope.x.py build python setup. In a Zope 3 mailing list post.component and dependencies using easy_install inside myve/bin directory: $ cd myve $ . also good for deployments. zc.comp. in the site-packages directory. from inside the myve directory.buildout with zc.gz $ easy_install /path/to/zope.interface-3.4 Experimenting with code There are two approaches in Python for setting up isolated working environments for developing Python applications.x. EXPERIMENTING WITH CODE 9 To install these packages.tar.zope3/21045 .org/gmane.): $ easy_install /path/to/zope. which can cause problems.buildout created by Jim Fulton are these two packages.x.4.x python setup.x. and familiarity with these tools will be beneficial when developing and deploying applications.py install These methods will install the ZCA to the system Python.x.1. after downloading them. you can install zope./bin/python This command will give you a Python prompt which you can use to run the code in this book.tar. you can use easy_install command with argument as the eggs.interface and zope. virtualenv You can install virtualenv using easy_install: $ easy_install virtualenv Then create a new environment like this: $ virtualenv --no-site-packges myve This will create a new virtual environment in the myve directory.x. Using these packages you can install zope.web.interface-3.buildout Using zc. 1.gmane. (You may also give all these eggs in the same line.component Now you can import zope.event-3./bin/easy_install zope.component-3. First.x. (You may also do it inside virtual environment).gz $ easy_install /path/to/zope.gz You can also install these packages after extracting each one separately.egg recipe you can create Python interpreter with specified Python eggs.component from the new python interpreter inside myve/bin directory: $ .x. This is a good practice for experimenting with any Python code.component and other dependencies into an isolated working environment. You can use virtualenv and/or zc. Jim Fulton recommends against using the system Python10 . For example: $ $ $ $ tar zxvf /path/to/zope.interface-3.buildout for playing with any Python packages.buildout using easy_install command.x. install zc. first create a directory and initialize it using buildout init command: 10 http://article.

/bin/python This command will give you a Python prompt which you can use to run the code in this book.egg interpreter = python eggs = zope.recipe.10 $ mkdir mybuildout $ cd mybuildout $ buildout init CHAPTER 1. The default configuration file for buildout is buildout. This will create a new Python interpreter inside mybuildout/bin directory: $ . After initializing.component Now run buildout command available inside mybuildout/bin directory without any argument.cfg . it will be having this content: [buildout] parts = You can change it like this: [buildout] parts = py [py] recipe = zc. . GETTING STARTED Now the new mybuildout directory is a buildout./bin/buildout $ .

next_id = 1 . Now we will use the above function to create entries in the bookings_db dictionary: 11 . We will start with a brief look at a procedural implementation. adapter and interface. and then move to a basic object oriented approach.. this example use a Python dictionary as the storage. We will generate unique id’s for the dictionary.. value: details in a dictionary A minimal implementation requires a function which we pass the details of the booking. >>> bookings_db = {} #key: unique Id...2 Procedural approach In any business application.. we add 1 to the maximum value in the list and return it. As we examine the object oriented approach. we will see how we can benefit from the classic design patterns.1 Introduction Consider a business application for registering guests staying in a hotel. data storage is very critical. next_id = max(db_keys) + 1 .Chapter 2 An example 2. the associated value will be a dictionary of details about the booking.. return next_id As you can see. if db_keys == []: . This will bring us into the world of the Zope Component Architecture. 2. so we return 1. If the list is not empty. db_keys = bookings_db.. the get_next_id function implementation is very simple.keys() . and a supporting function which provides the the unique id for the storage dictionary key. The function gets a list of keys and checks for an empty list...... We can get the unique id like this: >>> def get_next_id(): . else: . If the list is empty this is our first booking. For simplicity. Python can implement this in a number of ways.

. passing data back and forth between them.. It will be much easier to provide data persistence. Lets look at the implementation details of a FrontDesk class: >>> class FrontDesk(object): . the code becomes harder to maintain and bugs become harder to find and fix. As requirements change and are added. Experience has shown that by consolidating the code and data requirements via objects... Were we to continue with the procedural example. design flexibility and code testability using objects. . bookings_db[next_id] = { . place): .. And code to manage the data: • cancel a reservation • update a reservation • pay for a room • persist the data • insure security of the data • . def book_room(self... FrontDesk.. next_id = get_next_id() . test... ’name’: name... bookings_db[next_id] = { ...12 >>> def book_room(name.. name.. . } CHAPTER 2.. ’name’: name. and change. We will create instances of FrontDesk to apply this knowledge to the business of running a hotel. we would create many functions. Our main class will be the FrontDesk. ’place’: place .. and the code to manage it. ’room’: place ..... will know how to manage the data for the hotel.3 Object oriented approach Our discussion of object oriented design will introduce the class which serves to encapsulate the data. 2. place): . we will end up with a design which is easier to understand. } ... We will end our discussion of the procedural approach here. AN EXAMPLE The requirements of a hotel booking management application require considering additional data: • phone numbers • room options • payment methods • ... next_id = get_next_id() . .. or other classes it delegates to..

so we must change the code. you saved some typing..place. phone): . our goal is to minimize those changes... Now we have: >>> class FrontDesk(object): . the frontdesk object (an instance of FrontDesk class) is able to handle the bookings... the code changes can be minimized. place. the code is easier to restructure and maintain. . bookings_db[next_id] = { . it is important to feel free to make changes without fear of breaking the application.... however.. . "Bangalore") Any real project will involve changing requirements. we now have to change all calls to FrontDesk. next_id = get_next_id() ... If we abstract the details of guest into an object and use it for registration. } In addition to migrating the data to new schema... the abstraction provided by the guest object made the system simpler and more understandable.. .3.. ’phone’: guest. bookings_db[next_id] = { ... More importantly.. thereby increasing maintainability.. A good source of information about this programming philosophy is the book Extreme Programming Explained by Kent Beck. ’name’: name.. name. As a result.name. . The way to get the immediate feedback required is via automated testing.... ’place’: guest.... With well written tests (and good version control) you can make changes large or small with impunity. next_id = get_next_id() .2. We can achieve this requirement by adding one argument to the book_room method which will be added to the dictionary of values: >>> class FrontDesk(object): . . By introducing the guest object. This is unavoidable. ’place’: place.phone .. OBJECT ORIENTED APPROACH 13 In this implementation.. .. In this case management has decided that each guest must provide a phone number. def book_room(self.. } We still will have to change code to respond to changing requirements. guest): .book_room("Jack". ’name’: guest. We now can make changes to the details of the guest object and the calls to FrontDesk won’t need to change... def book_room(self. ’phone’: phone . . Note When coding. We can use it like this: >>> frontdesk = FrontDesk() >>> frontdesk.

. bookings_db[next_id] = { . ... the ability to configure implementation details provides useful capability: • the ability to switch between implementations • the ability to add implementations as needed • increased re-use of both legacy and ZCA code These capabilities lead to code that is flexible.phone .) • markup rendering (ReST...) ZCA uses adapters and a component registry to provide the capability to change implementation details of code via configuration. . guest = self. we will need to pass the guest object to frontdesk every time we call methods such as cancel_booking and update_booking. ’phone’: guest. plain text . guest): . def book_room(self): . Textile . RDBM.place.. self. self.__init__(). As we will see in the section on ZCA adapters. making it an attribute of the instance. We can avoid this requirement if we pass the guest object to FrontDesk. ... XML .. def __init__(self. an adapter contains an adaptee: >>> class Adapter(object): ... In the current design. Markdown.. next_id = get_next_id() . maintaining the component registry adds a level of complexity to the application.. There is a cost however.... PDF... scalable and re-usable. the frontdesk object will need to handle chores such as cancellations and updates.. def __init__(self. .. } The solution we have reached is a well known pattern. ZCA is unnecessary. In general.....name...14 CHAPTER 2.4 The adapter pattern In a real application.. If an application will never require these features.guest . adaptee): ... beginning with interfaces.guest = guest .... ’name’: guest.adaptee = adaptee This pattern will be useful in dealing with implementation details which depend on considerations such as: • changing customer requirements • storage requirements (ZODB.) • output requirements (HTML. . We are now ready to begin our study of the Zope Component Architecture. ’place’: guest. AN EXAMPLE 2. the adapter. >>> class FrontDeskNG(object): . .....

Defining a formal interface is helpful in understanding a system... not an implementation”.txt files which offer wonderful documentation. C#..wikipedia. Since Python lacks interfaces.. %s!" % name 11 The Zope code tree is full of README. which are conditions that must hold for objects that provide the interface The classic software engineering book Design Patterns 12 by the Gang of Four recommends that you “Program to an interface. An interface specifies behavior through: .. to learn how.Attribute definitions . In some modern programming languages: Java.Informal documentation in a doc string . def goodmorning(self.txt11 in path/to/zope/interface defines interfaces like this: Interfaces are objects that specify (document) the external behavior of objects that "provide" them.org/wiki/Design_Patterns 15 . .. Commonly used metaphors for interfaces are contract or blueprint. interfaces bring to you all the benefits of ZCA. interfaces are an explicit aspect of the language. name): . Moreover.1 Introduction The README. VB. An interface specifies the characteristics of an object. you must look at the implementation.. it’s behaviour. it’s capabilities. """Say good morning to guests""" .. . return "Good morning.Invariants. the legal and architectural terms for a set of specifications...NET etc. 12 http://en.Chapter 3 Interfaces 3. Here is a classic hello world style example: >>> class Host(object): . The interface describes what an object can do. ZCA implements them as a meta-class to inherit from.

. name and goodmorning.. For the class given above you can specify the interface like this: >>> from zope.interface in previous section.. you don’t even say what type of attribute it has to be!.2 Declaring interfaces You have already seen how to declare an interface using zope.interface. INTERFACES In the above class. . methods are also attributes of classes. The other attribute. Note that self is not required in interfaces.Attribute class. For example. In this case. at least in Python..wikipedia.. If a module implement this interface. Jack!’ Here host is the actual object your code uses.... You can pass a documentation string as a first argument to Attribute.interface.! >>> host = Host() >>> host. name = Attribute("""Name of host""") . The name attribute is defined using zope. 3. you don’t set an initial value. If you want to examine implementation details you need to access the class Host. 13 http://en. Now we will begin to use the ZCA interfaces. either via the source code or an API13 documentation tool.interface import Attribute >>> class IHost(Interface): .interface import Interface >>> from zope. IHost has two attributes.. you defined a goodmorning method. And the goodmorning function will accept one argument... because self is an implementation detail of class. .org/wiki/Application_programming_interface .16 CHAPTER 3.... def goodmorning(guest): .. the interface inherits from zope. The I prefix for the interface name is a useful convention. This section will explain the concepts in detail... goodmorning is a method defined using a function definition.. a module can implement this interface. The purpose of defining the attribute name here is merely to indicate that any implementation of this interface will feature an attribute named name.. When you add the attribute name to the IHost interface. If you call the goodmorning method from an object created using this class.interface import Interface >>> class IHost(Interface): . def goodmorning(guest): . """A host object""" . it will return Good morning. Consider this example interface: >>> from zope.Interface.goodmorning(’Jack’) ’Good morning.. """Say good morning to guest""" The interface. Recall that.. This use (abuse?) of Python’s class statement is how ZCA defines an interface. . """Say good morning to guest""" As you can see. there will be a name attribute and goodmorning function defined.

First one is provide and the other one is implement.3 Implementing interfaces To declare a class implements a particular interface.. IHost) . so why other callable objects can’t implement an interface. name = u’’ .gnome. use the function zope.. . In the adapter section. it is also working similarly. %s!" % guest Note If you wonder how implements function works. 3. a function can be an implementer of an interface.. return "Good morning. Yes. in addition to what their classes implement. you will see an adapts function. implements(IHost) .3.implements in the class statement. so classes are just the implementation details. refer the blog post by James Henstridge (http://blogs. For any callable object you can declare that it produces objects that provide some interfaces by saying that the callable object implements the interfaces.interface import classImplements >>> classImplements(Host.. Consider this example. classes are callable objects. you can write like this: >>> from zope. One object can provide more than one interface also one class can implement more than one interface.. it is possible. There are some utility methods to introspect the declarations. In other words... . then after defining the class statement. IMPLEMENTING INTERFACES 17 Now you will see how to connect interface-class-object. This is why you should program to an interface and not to an implementation.. Since functions are callable objects. So object is the real living thing. """Say good morning to guest""" .... If you don’t write interface. Object provides interfaces and classes implement interfaces. The callable objects are generally called as factories.... Note Classes are the implementation details of objects. The declaration can write outside the class also.org/jamesh/2005/09/08/python-class-advisors/) . Now you should familiarize two more terms to understand other concepts.. objects are instances of classes. Since Host implements IHost.interface import implements >>> class Host(object): .. In the above example host (object) provides IHost (interface) and Host (class) implement IHost (interface). . Objects can also provide interfaces directly. In Python. instances of Host provides IHost. objects provide interfaces that their classes implement.. def goodmorning(self. And interface is the actual definition of the object..interface. guest): .3.implements(IHost) in the above example. . here Host implements IHost: >>> from zope.

An interface can also specify both attributes and methods together. module or any other objects. An interface can be implemented. as you already noted. return to the example application. The documentation string for interface gives an idea about the object. Instead. it will be an interface from Zope component architecture point of view. By defining a method in the interface. and the self parameter is an implementation detail which doesn’t need to be documented. 3. the first argument should not be self.... An interface without any attribute or method is called marker interface. """A frontdesk will register object’s details""" ... because an interface will never be instantiated nor will its methods ever be called.. If you define a subclass of this Interface class. In the next chapter you can see how an interface is used to define an adapter component. an interface can also specify normal attributes: >>> from zope. .interface import Interface >>> class IDesk(Interface): . Here is a marker interface: >>> from zope. Now you know what is an interface and how to define and use it.. you made a contract for the component. As you know. The frontdesk interface defined here is IDesk. """A special guest""" This interface can be used to declare an object is a special guest...interface import Attribute >>> class IGuest(Interface): . that there will be a method with same name available. in this case the function is an implementer for the interface. INTERFACES 3.5 Marker interfaces An interface can be used to declare that a particular object belongs to a special type. place = Attribute("Place of guest") In this interface.interface import Interface >>> from zope.. For example a function can dynamically create the component and return...4 Example revisited Now. .. the interface class merely documents what methods and attributes should appear in any normal class that claims to implement it.18 CHAPTER 3..interface module. first you imported Interface class from zope... Here. An interface can be implemented in a class. def register(): . name = Attribute("Name of guest") . For the method definition interface. """Register object’s details""" . in a class or any other callable object.interface import Interface >>> class ISpecialGuest(Interface): .. . guest object has two attributes specified with documentation.. Here you will see how to define the interface of the frontdesk object: >>> from zope.

phone): . Exception: At least one contact info is required As you can see jack object validated without raising any exception.. phone = None >>> jack = Person() >>> jack...interface.. First you have to make a callable object.validateInvariants(jack) >>> jill = Person() >>> IPerson. there is a person object.6 Invariants Sometimes you will be required to use some rule for your component which involve one or more normal attributes. invariant(contacts_invariant) Now use validateInvariants method of the interface to validate: >>> from zope.. . if not (obj. but not necessarily both. .com" >>> IPerson.6.. INVARIANTS 19 3. But jill object didn’t validated the invariant constraint.interface import Interface >>> from zope. . either a simple function or callable instance of a class like this: >>> def contacts_invariant(obj): ... raise Exception( .invariant function to set the invariant: >>> from zope. These kind of rule is called invariants..interface import implements >>> class Person(object): .interface import invariant >>> class IPerson(Interface): . email = None .. Consider a simple example. . You can use zope.address... name = None ...interface.... How do you implement a validation rule that says either email or phone have to exist. A person object has name...email = u"jack@some. so it raised exception.. "At least one contact info is required") Then define the person object’s interface like this.. .validateInvariants(jill) Traceback (most recent call last): .email or obj.... email = Attribute("Email Address") .3. phone = Attribute("Phone Number") ..invariant for setting invariants for your objects in their interface... implements(IPerson) .interface import Attribute >>> from zope. name = Attribute("Name") . Use the zope...... email and phone attributes.

INTERFACES .20 CHAPTER 3.

name..place. implements(IDesk) ... To declare a class is an adapter use adapts function defined in zope.guest = guest .. place): 21 ... ....phone . self. ..Chapter 4 Adapters 4. . Adapter components are one of the basic components used by Zope component architecture for effectively using Python objects. as you noted.. implements(IGuest) . guest = self. but with well defined interface.. name. guest): ..interface import implements >>> from zope. Zope component architecture.... def __init__(self.guest . Here is a new FrontDeskNG adapter with explicit interface declaration: >>> from zope... adapts(IGuest) .. def register(self): ..component package..... def __init__(self.. ’phone’: guest. next_id = get_next_id() ..... Adapter components are Python objects.. helps to effectively use Python objects. .. an instance of this class will provide IDesk interface.. >>> class Guest(object): . The IDesk interface is implemented by FrontDeskNG class.. which adapts IGuest object.. ’place’: guest.... } What you defined here is an adapter for IDesk. . So.1 Implementation This section will describe adapters in detail.. ’name’: guest. .component import adapts >>> class FrontDeskNG(object): . . bookings_db[next_id] = { .

4. but a local site manager is persistent. If name is not given. you are adapting only IGuest object. While developing a Zope 3 application you can use Zope configuration markup language (ZCML) for registration of components.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. i. In this example. this is a named adapter. The second argument is a tuple of adaptee objects.e. it will default to an empty string.registerAdapter(FrontDeskNG. A site manager normally resides in a site. that is the name of the particular adapter. you can also create other adapters which handles guest registration differently.22 .. you could have done the registration like this: >>> gsm.component package. Since you gave a name for this adapter. you have to register this in a component registry also known as site manager. To register your component. So.. In Zope 3. . use registerAdapter method of component registry.component. ’ng’) To get the global site manager. the global site manager is available as an attribute (globalSiteManager) of zope. The fourth argument is optional. To register the adapter in component.place = place CHAPTER 4. If a component is registered without name. . it will default to an empty string (”). IDesk. (IGuest.2 Registration To use this adapter component. it is not required to specify again. "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.component package.globalSiteManager attribute. A global site manager will be in memory. Note Local components are persistent components but global components are in memory.). self. Since you have already given these details in adapter implementation. name=’ng’) There are some old API to do the registration. The third argument is the interface implemented by the adapter component. you have to call getGlobalSiteManager function available in zope. as you can see above. eg: provideAdapter. In fact. In fact. The first argument should be your adapter class/factory. Local components are taken to memory from database while starting the application. provideUtility etc. first get the global site manager: >>> from zope.providedBy(jack_frontdesk) True The FrontDeskNG is just one adapter you created. which you should avoid. Similarly you can register other adapters with different names.. you can directly use zope.. the object which you are adapting. In the above registration.. ADAPTERS >>> jack = Guest("Jack".registerAdapter(FrontDeskNG. .name = name self. For now you only required to bother about global site and global site manager ( or component registry). local components (persistent components) can be registered from Zope Management Interface (ZMI) or you can do it programmatically also. A site and site manager will be more important when developing a Zope 3 application. Global components will be registered based on the configuration of application. The old API functions starts with provide. you have given the adaptee interface and interface to be provided by the adapter. You registered FrontDeskNG with a name ng..

the interface which should be provided by component and last the name of adapter component. >>> reg = queryAdapter(jack.4. IDesk) #doctest: +ELLIPSIS Traceback (most recent call last): . but queryAdapter returned None when lookup failed. The getAdapter will raise ComponentLookupError if component lookup fails on the other hand queryAdapter will return None.. . You can import the methods like this: >>> from zope. >>> reg = queryAdapter(jack. IDesk. IDesk... ComponentLookupError: . Here is how the two methods works in such a case: >>> getAdapter(jack. see yourself how it works: >>> getAdapter(jack. If the third argument is not given it will default to empty string (”). One of them is getAdapter and the other is queryAdapter . These kind of adapters is called single adapter.. ’not-exists’) #doctest: +ELLIPSIS Traceback (most recent call last): .> As you can see. In the first section of this chapter. IDesk) #doctest: +ELLIPSIS >>> reg is None True In this section you have learned how to register a simple adapter and how to retrieve it from component registry. Here both getAdapter and queryAdapter works similarly: >>> getAdapter(jack. the lookup will fail. This is how you can retrieve a component which adapts the interface of jack object (IGuest) and provides IDesk interface also with name as ’ng’. ’ng’) #doctest: +ELLIPSIS <FrontDeskNG object at . because it adapts only one adaptee. ’ng’) #doctest: +ELLIPSIS <FrontDeskNG object at . ’not-exists’) #doctest: +ELLIPSIS >>> reg is None True As you can see above.. If you try to lookup the component with an name not used for registration but for same adaptee and interface..component import getAdapter >>> from zope.... Similarly queryAdapter will return None. QUERYING ADAPTER 23 4..3.. IDesk.> >>> queryAdapter(jack. .component import queryAdapter In the previous section you have registered a component for guest object (adaptee) which provides IDesk interface with name as ’ng’. getAdapter raised a ComponentLookupError exception. you have created a guest object named jack . Both functions accepts same arguments.component package. then it is called multi adapter. If an adapter adapts more that one adaptee. IDesk. Since there is no component registered with an empty string. the first argument should be adaptee then.. The third argument.. ComponentLookupError: .3 Querying adapter Retrieving registered components from component registry is achieved through two functions available in zope. the name of registration. is optional. getAdapter will raise ComponentLookupError ..

5 Adapter pattern The adapter concept in Zope Component Architecture and the classic adapter pattern as described in Design Patterns book are very similar. The intent of adapter pattern is to convert the interface of a class into another interface clients expect. But the intent of ZCA adapter usage is more wider than the adapter pattern itself... TypeError: (’Could not adapt’.zope.24 CHAPTER 4. on the other hand an object adapter relies on object composition. ZCA adapter is following object adapter pattern. (It would be interesting to note that Adapter was known as Feature in earlier stage of ZCA design.4 Retrieving adapter using interface Adapters can be directly retrieved using interfaces. The first one is called class adapter and the other one is called object adapter. <Guest object at . you may use interface to get adapter components. it will raise TypeError: >>> IDesk(jack) #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS Traceback (most recent call last): . GoF says: “Often the adapter is responsible for functionality the adapted class doesn’t provide”. ZCA adapter lets adapter classes extend functionality by adding methods. )14 The above paragraph has a quote from Gang of Four book. ’default-output’) #doctest: +ELLIPSIS <FrontDeskNG object at . ’default-output’) ’default-output’ If second argument is not given.html .. A class adapter uses multiple inheritance to adapt one interface to another. GoF’s second principle of object-oriented design goes like this: 14 Thread discussing renaming of Feature to Adapter: http://mail.. >>> IDesk(jack.. If adapter lookup fails.org/pipermail/zope3-dev/2001-December/000008. it ends like this: “ .. because GoF describes about two variants of adapters based on implementations.>. which use delegation as a mechanism for composition. 4.registerAdapter(FrontDeskNG) Now the adapter lookup should succeed: >>> IDesk(jack. This allows classes work together that couldn’t otherwise because of incompatible interfaces. second argument will be returned. but it will only work for non-named single adapters. But in the motivation section of Design Patterns book.adapted class doesn’t provide”..IDesk>) Here FrontDeskNG is registered without name: >>> gsm. The first argument is the adaptee and the second argument is a keyword argument. But in the next sentence I used “adapted object” instead of “adapted class”. ADAPTERS 4. ZCA adapter has more focus on adding functionality than creating a new interface for an adapted object (adaptee). alternate=’default-output’) ’default-output’ Keyword name can be omitted: >>> IDesk(jack..> For simple cases. <InterfaceClass __builtin__.

ZCA adapter components are registered in component registry and looked up by client objects using interface and name when required.5. . The major attraction of ZCA adapter are the explicit interface for components and the component registry. For more details about this subject please read Design Patterns book.4. ADAPTER PATTERN 25 “Favor object composition over class inheritance”.

ADAPTERS .26 CHAPTER 4.

. 5. This approach creates a global registry by which instances can be registered and accessed by different parts of your application.2 Simple utility A utility can be registered with a name or without a name. which you will see in the next section.. Before implementing the utility. Utilities are just objects that provide an interface and that are looked up by an interface and a name. Only register components which you want to make replaceable. adapter and component registry. . define its interface... Sometimes it would be useful to register an object which is not adapting anything. name): .. ... are examples of these kinds of objects. You need not to register all component instances like this.. A utility registered with a name is called named utility. Here is a possible implementation of the above interface: >>> class Greeter(object): .. def greet(name): .. """Say hello""" Like an adapter a utility may have more than one implementation. XML parser.... implements(IGreeter) .. . as usual.. return "Hello " + name 27 .interface import implements >>> class IGreeter(Interface): .1 Introduction Now you know the concept of interface. with no need to pass the instances around as parameters. object returning unique Ids etc.interface import Interface >>> from zope.Chapter 5 Utility 5.. Database connection. These kind of components provided by the ZCA are called utility components. def greet(self. Here is a greeter interface: >>> from zope.

You can look up the interface with either queryUtility or getUtility: >>> from zope. like adapter. but utilities are normally instances of classes. IGreeter) In this example you registered the utility as providing the IGreeter interface. This is how you can register the greeter utility with a name: >>> greet = Greeter() >>> gsm.greet(’Jill’) ’Hello Jill’ As you can see here. Calling getUtility function without a name (second argument) is equivalent to calling with an empty string as the name. while querying you have to use the name as second argument.registerUtility(greet.component import queryUtility >>> from zope. Only once you are creating the instance of a utility class. ’new’) In this example you registered the utility with a name as providing the IGreeter interface. Remember. Then. .component import getUtility >>> queryUtility(IGreeter.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm. you can use a name. getAdapter and queryAdapter also works similarly. You can register an instance of this class (utility) using registerUtility: >>> from zope. adapters are normally classes. When component lookup fails it will raise ComponentLookupError exception.28 CHAPTER 5. a utility registered with a particular name is called named utility.3 Named utility When registering a utility component. The adapter look up functions. but adapter instances are dynamically created whenever you query for it. Because. you have to register it.greet(’Jill’) ’Hello Jill’ >>> getUtility(IGreeter. To use this utility. 5. IGreeter.greet(’Jack’) ’Hello Jack’ >>> getUtility(IGreeter). later you can query it using the ZCA API. You can look the interface up with either queryUtility or getUtility: >>> from zope. component lookup mechanism will try to find the component with name as empty string. the default value for second (keyword) argument is an empty string. ’new’). ’new’).greet(’Jack’) ’Hello Jack’ As you can see.component import getUtility >>> queryUtility(IGreeter). As mentioned in the previous section. it will not return some random component registered with some other name.registerUtility(greet. and it will fail. UTILITY The actual utility will be an instance of this class.component import queryUtility >>> from zope.

factory import Factory >>> factory = Factory(FakeDb.interface import Interface >>> from zope.. IFactory.> There is a shortcut to use factory: >>> from zope.interface import implements >>> class IDatabase(Interface): .registerUtility(factory.component.. FACTORY 29 5.interfaces import IFactory >>> gsm.. .component import createObject >>> createObject(’fakedb’) #doctest: +ELLIPSIS <FakeDb object at .Factory: >>> from zope.component.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> from zope....... ....4.factory. . ’fakedb’) To use the factory..4 Factory A Factory is a utility component which provides IFactory interface. return "connection" You can create a factory using zope... def getConnection(self): . implements(IDatabase) . To create a factory. def getConnection(): .component import queryUtility >>> queryUtility(IFactory. """Return connection object""" Here is fake implementation of IDatabase interface: >>> class FakeDb(object): .> ..component.interface import Attribute >>> from zope.. you may do it like this: >>> from zope. first define the interface of the object: >>> from zope..5.. ’fakedb’)() #doctest: +ELLIPSIS <FakeDb object at . ’FakeDb’) Now you can register it like this: >>> from zope..

UTILITY .30 CHAPTER 5.

Chapter 6 Advanced adapters This chapter discuss some advanced adapters like multi adapter. one.. self.. implements(IFunctionality) .interface import implements >>> from zope.. two): .. subscription adapter and handler... IAdapteeTwo) . pass >>> class MyFunctionality(object): ... .component import adapts >>> class IAdapteeOne(Interface): . >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm..two = two >>> from zope.. implements(IAdapteeOne) 31 . pass >>> class IFunctionality(Interface): . def __init__(self. pass >>> class IAdapteeTwo(Interface): . it is called multi-adapter. adapts(IAdapteeOne.. self.. but an adapter may adapt more than one object... If an adapter adapts more than one objects. 6.one = one .1 Multi adapter A simple adapter normally adapts only one object.interface import Interface >>> from zope.......registerAdapter(MyFunctionality) >>> class One(object): .

implements(IDocument) ..... self. ..... Return a string describing a validation problem..interface import Attribute >>> from zope.....> >>> myfunctionality = getMultiAdapter((one...... . . object is valid. We have objects and we want to assess whether they meet some sort of standards. ..one #doctest: +ELLIPSIS <One object at . .summary... We define a validation interface: >>> from zope. def validate(ob): .> >>> myfunctionality..2 Subscription adapter Unlike regular adapters. summary = Attribute("Document summary") .. Subscription adapter is also known as subscriber.component import getMultiAdapter >>> getMultiAdapter((one... Consider a validation problem.. """ Perhaps we have documents: >>> class IDocument(Interface): .. """Determine whether the object is valid . def __init__(self. summary... .body = summary. body .interface import Interface >>> from zope. ADVANCED ADAPTERS >>> class Two(object): .two)..two)..> 6. body = Attribute("Document text") >>> class Document(object): .32 CHAPTER 6.interface import implements >>> class IValidate(Interface): . subscription adapters are used when we want all of the adapters that adapt an object to a particular interface...two #doctest: +ELLIPSIS <Two object at . An empty string is returned to indicate that the . body): . IFunctionality) #doctest: +ELLIPSIS <MyFunctionality object at .... IFunctionality) >>> myfunctionality. self. implements(IAdapteeTwo) >>> one = One() >>> two = Two() >>> from zope.. ....

SUBSCRIPTION ADAPTER 33 Now. for adapter in subscribers([doc]. adapts(IDocument) .. return ’’ Or we might require the body to be at least 1000 characters in length: >>> class AdequateLength(object): . implements(IValidate) . we may want to specify various validation rules for documents.component import adapts >>> class SingleLineSummary: ...2. . else: . adapts(IDocument) . if len(self.doc = doc . return ’’ We can register these as subscription adapters: >>> from zope. .........doc.... we might require that the summary be a single line: >>> from zope. return ’too short’ . .body) < 1000: . self... "blah") >>> [adapter. if adapter.. ’too short’] .. For example... doc): ..registerSubscriptionAdapter(SingleLineSummary) >>> gsm.validate() ... ... def __init__(self.validate()] [’Summary should only have one line’. def validate(self): .registerSubscriptionAdapter(AdequateLength) We can then use the subscribers to validate objects: >>> from zope..... ... ... def __init__(self. else: .. def validate(self): ... doc): .....doc = doc . if ’\n’ in self.doc..6..component import subscribers >>> doc = Document("A\nDocument". IValidate) . implements(IValidate) . return ’Summary should only have one line’ ..summary: ........component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm... self.

. rather than classes. self. IValidate) .. IValidate) . it is more natural to define them with functions..34 CHAPTER 6... for adapter in subscribers([doc]. implements(IDocumentCreated) .validate()] [’too short’] 6. "blah") >>> [adapter. Because subscribers don’t need to provide an API to their callers. This is a special case of a subscription adapter that adapts an event to nothing.validate()] [’Summary should only have one line’] >>> doc = Document("A Document". There are special APIs for registering and calling them. we define a document-created event: >>> from zope. To register the subscriber above. doc): ...validate() . we might want to record creation times for documents: >>> import datetime >>> def documentCreated(event): .. For example. .datetime. They do all of their work when called. an event publisher doesn’t expect to get any return value.3 Handler Handlers are subscription adapter factories that don’t produce anything... in a document-management system... ADVANCED ADAPTERS >>> doc = Document("A\nDocument".. We call subscribers that don’t actually create anything “handlers”.doc = doc We’ll also change our handler definition to: .created = datetime. if adapter.interface import implements >>> class IDocumentCreated(Interface): . . for adapter in subscribers([doc]..doc.interface import Attribute >>> from zope.interface import Interface >>> from zope. doc = Attribute("The document that was created") >>> class DocumentCreated(object): .. Handlers are also known as event subscribers or event subscription adapters. . For example. Event subscribers are different from other subscription adapters in that the caller of event subscribers doesn’t expect to interact with them in any direct way... def __init__(self. All of the work is done when the adapter “factory” is called. "blah" * 1000) >>> [adapter.utcnow() In this example. It doesn’t actually return anything. if adapter.validate() .... we have a function that takes an event and performs some processing.... Handlers are typically used to handle events. event..

def documentCreated(event): .6...utcnow() >>> from zope.datetime.created = datetime.doc.created.doc.registerHandler(documentCreated) Now. event..__name__ ’datetime’ 35 ..component import handle >>> handle(DocumentCreated(doc)) >>> doc. we can create an event and use the handle function to call handlers registered for the event: >>> from zope.utcnow() This marks the handler as an adapter of IDocumentCreated events.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. event.component import adapter >>> @adapter(IDocumentCreated) . HANDLER >>> def documentCreated(event): ..3. Now we’ll register the handler: >>> from zope.datetime.created = datetime.__class__..

ADVANCED ADAPTERS .36 CHAPTER 6.

company.interfaces.interfaces.zope. instead of using Python API for registration.zope. But to use ZCML. This chapter will go through usage of the ZCA in Zope. you can use ZCML.1 ZCML The Zope Configuration Markup Language (ZCML) is an XML based configuration system for registration of components.component [zcml]" To register an adapter: <configure xmlns="http://namespaces. you will be required to install more dependency packages.IEmployee" /> The provides and for attributes are optional. 7.Chapter 7 ZCA usage in Zope Zope Component Architecture is used in both Zope 3 and Zope 2.org/zope"> <adapter factory=".ISalary" for=".org/zope"> <adapter factory=". you can give a name attribute: <configure xmlns="http://namespaces.EmployeeSalary" /> If you want to register the component as named adapter. So.zope. unfortunately. provided you have declared it in the implementation: <configure xmlns="http://namespaces.company. To install these packages: $ easy_install "zope.EmployeeSalary" provides=".org/zope"> <adapter 37 .

database.database. the last registered component will replace previously registered component. consider this example: >>> from zope.IConnection" /> The provides attribute is optional.company.org/zope"> <utility component=".zope.database.interface import Attribute >>> from zope.zope..EmployeeSalary" name="salary" /> Utilities are also registered similarly.database.zope.org/zope"> <utility component=". you can give a name attribute: <configure xmlns="http://namespaces.org/zope"> <utility component=".connection" provides=".Connection" /> 7. pass .org/zope"> <utility factory=".2 Overrides When you register components using Python API (register* methods).interface import Interface >>> class IA(Interface): . To register an utility: CHAPTER 7.zope. you can also give a factory: <configure xmlns="http://namespaces..connection" name="Database Connection" /> Instead of directly using the component. For example. if both are registered with same type of arguments.connection" /> If you want to register the component as named utility. ZCA USAGE IN ZOPE <configure xmlns="http://namespaces.38 factory=".interfaces. provided you have declared it in the implementation: <configure xmlns="http://namespaces.

otherwise there is a chance for overriding registration by mistake. adapts(IA) . implements(IA) >>> a = A() >>> ap = AP(a) >>> gsm.interface import implements >>> from zope. implements(IP) .. So... OVERRIDES >>> class IP(Interface): ... self. This may lead to hard to track bugs in your system.. the second registration will raise a conflict error.. ZCML provides includeOverrides directive for this. def __init__(self..registerAdapter(AP) >>> getAdapter(a...... implements(IP) ..2.7.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> class AP(object): .context = context >>> class AP2(object): . IP) #doctest: +ELLIPSIS <AP2 object at .registerAdapter(AP2) >>> getAdapter(a. self.. . Sometimes you will be required to override existing registration.. IP) #doctest: +ELLIPSIS <AP object at ... you can write your overrides in a separate file: <includeOverrides file="overrides..zcml" /> . . adapts(IA) . context): .> If you register another adapter.. the existing one will be replaced: >>> gsm. context): .... . def __init__(self. using ZCML is a win for the application... ...... This is a hint for you..> 39 But when registering components using ZCML.. pass >>> from zope. Using this. ..component import adapts >>> from zope.context = context >>> class A(object): ..

__parent__ and __name__. getRoot.Folder.traversing. getName. 7.app.component. almost all persistent objects in Zope 3 application will be providing the ILocation interface. The __parent__ is the parent in the location hierarchy. which is again one more indirection) The registration of adapter is like this: <adapter factory="zope. Here is the beginning of implementation: class LocationPhysicallyLocatable(object): """Provide location information for location objects """ zope. (Some old code even use zope.folder. you can see that the adaptee is a IWriteContainer and the adapter provides INameChooser.40 CHAPTER 7.contained.container. And __name__ is the name within the parent.app.BTreeContainer and zope.LocationPhysicallyLocatable" /> The interface provided and adaptee interface is given in the implementation.interface.NameChooser This is an adapter for choosing a unique name for an object inside a container.INameChooser" for="zope. This adapter provides a very convenient functionality for Zope programmers.location.interfaces.location.IWriteContainer" factory="..api. Normally.zapi functions.NameChooser" /> From the registration. and .app. The registration of adapter is like this: <adapter provides=". The main implementations of IWriteContainer in Zope 3 are zope.adapts(ILocation) zope. but normally it is called through an API in zope. Suppose there is no interface called INameChooser and adapter.. The IPhysicallyLocatable interface has four methods: getNearestSite.app.interfaces.4 LocationPhysicallyLocatable Location: zope.implements(IPhysicallyLocatable) .traversing.contained. ZCA USAGE IN ZOPE 7. Normally you will be inheriting from these implementations for creating your own container classes. This interface has only two attribute. getPath. then you will be required to implement this functionality for every implementations separately.LocationPhysicallyLocatable This adapter is frequently used in Zope 3 applications.app.traversing.container.3 NameChooser Location: zope.container.

the adaptee interface is *. then you have to override this registration for your implementation. the object itself is returned. DEFAULTSIZED • getRoot function will return the physical root object.ZopeVersionUtility This utility gives version of the running Zope.5. This adapter is registered for all kind of objects. • getNearestSite return the site the object is contained in. • getName return the last segment of the physical path. The ISized is a simple interface with two method contracts: class ISized(Interface): def sizeForSorting(): """Returns a tuple (basic_unit.7. """ You can see another ISized adapter registered for IZPTPage in zope.app.6 ZopeVersionUtility Location: zope. amount) Used for sorting among different kinds of sized objects. you can see that these are the important things which you required very often. 7.app.size.size. To understand the beauty of this system. so it can adapt any kind of objects.View" /> As you can see. 41 If you learn Zope 3.ISized" permission="zope.5 DefaultSized Location: zope. There is a method called getPhysicalRoot virtually for all container objects.DefaultSized This adapter is just a default implementation of ISized interface.zptpage package. ’amount’ need only be sortable among things that share the same basic unit. The registration of adapter is like this: <adapter for="*" factory="zope. you must see how Zope 2 actually get the physical root object and how it is implemented. • getPath return the physical path to the object as a string. If you want to register this adapter for a particular interface.interfaces. 7.""" def sizeForDisplay(): """Returns a string giving the size.applicationcontrol. If the object is a site.size. The registration goes like this: .DefaultSized" provides="zope.

This method return a string containing the Zope version (possibly including SVN information).zopeversion.interfaces. ZCA USAGE IN ZOPE <utility component=". The default implementation.IZopeVersion" /> The interface provided. has only one method named getZopeVersion.ZopeVersionUtility" provides=". it will show the latest revision number.txt in zope/app directory. If none of the above works it will set it to: Development/Unknown.42 CHAPTER 7. ZopeVersionUtility. get version info from a file version. If Zope is running from subversion checkout. IZopeVersion. .

This application use a convention. one object database (ZODB) & and another relational database (SQLite). However. The main window for accessing all these features can be designed like this: 43 . Use plain Python objects directly where you do not required pluggability or extensibility.net/downloads/zcalib.2 Use cases The application we are going to discuss here is a library management system with minimal features. The reason for using two different persistence mechanisms is to demonstrate how to use the ZCA to glue components. Source code of this application can be downloaded from: http://www.muthukadan. As the application grows you may use the ZCA components wherever you want pluggability or extensibility. only one storage can be used for a particular installation. practically. The requirements can be summarized like this: • Add members with a unique number and name.bz2 8. which can be extended by putting registration of similar components in separate modules and later import them from main registration module.Chapter 8 Case study Note This chapter is not yet completed.tar. There is no difference in using ZCA for web or desktop or any other kind of application or framework. • Add books with barcode. This application also use two different kinds of data persistence mechanisms.1 Introduction This chapter demonstrates creating a desktop application using PyGTK GUI library and the ZCA. Majority of the code in this application is related to PyGTK. It is better to follow a convention for the location from where you are going to register components. In this application the main component registration module is register.py. Please send your suggestions ! 8. author & title • Issue books • Return books The application can be designed in such a way that major features can be accessed from a single window.

update and delete members as shown in the below picture: Similar to member window. edit and delete books: The circulation window should have the facility for issuing and returning books: .44 CHAPTER 8. user should be able to manage members. it should be possible to add. So. the catalog window allows user to add. CASE STUDY From member window.

Similarly.on_circulation_activate) member.3.connect(’activate’.glade. member.py. The activate event is emitted when the menu is selected.get_widget(’quit’) catalog = xmlobj. The gtk.connect(’delete_event’.get_widget(’mainwindow’) The name of main window widget is mainwindow. *args): gtk.get_widget(’widget_name’) In the mainwindow. The quit widget is also connected to same method for activate event: def on_delete_event(self. OVERVIEW OF PYGTK CODE 45 8.mainwindow = xmlobj. The windows of this application are designed using Glade GUI builder.path. self. these widgets are connected for some events: self. ’mainwindow. main window is connected to on_delete_event method for delete_event.mainwindow.get_widget(’member’) quit = xmlobj. You can see from the above code that. This is how to parse and access objects: import gtk. all menu entries has names like: circulation.path.glade’) xmlobj = gtk.XML(’/path/to/file.abspath(os.on_about_activate) The delete_event is the event when the window is closing using the window close button. other widgets are retrieved like this: circulation = xmlobj.glade’) widget = xmlobj. ’glade’. this will create GUI widget objects. you can see code like this: curdir = os.3 Overview of PyGTK code As you can see in the code. You should give proper names for widgets you are going to use from code. The code structure is very similar for different windows. self. self. In the main window. most of the code are related to PyGTK.main_quit() The callback function just call main_quit function .dirname(__file__)) xml = os.join(curdir.glade.glade.delete_event) quit.get_widget(’catalog’) about = xmlobj. catalog.8.get_widget(’circulation’) member = xmlobj. quit & about.XML class is used to parse glade file.XML(xml) self.on_member_activate) catalog. self.on_catalog_activate) about.path.delete_event) circulation. The widgets are connected to some callback functions for some events.connect(’activate’.connect(’activate’.glade xmlobj = gtk.get_widget(’about’) Then.connect(’activate’. self.connect(’activate’. self.

If user is trying to exit application using Ctrl+C.).4 The code This is the zcalib. CASE STUDY 8.). IDbOperation) gsm.registerAdapter(MemberRDbOperation. that’s why we catched KeyboardInterrupt exception. (IMember. This is the registry.registerUtility(db. Then.main() except KeyboardInterrupt: import sys sys.py: import sys from zope. (IBook. two modules are imported registry and mainwindow. IDbOperation) .initialize() try: mainwindow.registerAdapter(BookRDbOperation.component import getGlobalSiteManager from from from from interfaces interfaces interfaces interfaces import import import import IMember IBook ICirculation IDbOperation def initialize_rdb(): from interfaces import IRelationalDatabase from relationaldatabase import RelationalDatabase from member import MemberRDbOperation from catalog import BookRDbOperation from circulation import CirculationRDbOperation gsm = getGlobalSiteManager() db = RelationalDatabase() gsm.exit(1) Here. IDbOperation) gsm.). system will exit normally. IRelationalDatabase) gsm.registerAdapter(CirculationRDbOperation. registry is initialized and mainwindow’s main function is called. (ICirculation.py: import registry import mainwindow if __name__ == ’__main__’: registry.46 CHAPTER 8.

). If the RDB function is called. zcalib.registerAdapter(CirculationODbOperation.).registerUtility(db. THE CODE def initialize_odb(): from interfaces import IObjectDatabase from objectdatabase import ObjectDatabase from member import MemberODbOperation from catalog import BookODbOperation from circulation import CirculationODbOperation gsm = getGlobalSiteManager() db = ObjectDatabase() gsm. (IMember. If -r option is given at command line. Here is the mainwindow.py. (IBook. if the ODB function is called. IObjectDatabase) gsm. IDbOperation) gsm.8.registerAdapter(BookODbOperation. On the other hand. IDbOperation) def check_use_relational_db(): use_rdb = False try: arg = sys. it will setup all components related to ODB. The initialize function first check which db to use. (ICirculation. initialize_odb. relational database (RDB) or object database (ODB) and this checking is done at check_use_relational_db function.). it will call initialize_rdb otherwise.glade from circulationwindow import circulationwindow . it will setup all components related to RDB.registerAdapter(MemberODbOperation. IDbOperation) gsm.4.argv[1] if arg == ’-r’: return True except IndexError: pass return use_rdb def initialize(): use_rdb = check_use_relational_db() if use_rdb: initialize_rdb() else: initialize_odb() 47 Look at the initialize function which we are calling from the main module.py: import os import gtk import gtk.

connect(’activate’. CASE STUDY def __init__(self): curdir = os.48 from catalogwindow import catalogwindow from memberwindow import memberwindow class MainWindow(object): CHAPTER 8.dirname(__file__)) xml = os.on_catalog_activate) about.get_widget(’about’) self. *args): memberwindow.connect(’activate’. Here is the memberwindow.on_circulation_activate) member.get_widget(’catalog’) about = xmlobj. which will initialize all widgets.connect(’activate’.delete_event) circulation.show_all() def on_member_activate(self.glade. ’glade’.get_widget(’circulation’) member = xmlobj. self. self.delete_event) quit.on_member_activate) catalog. self.path.mainwindow.mainwindow = xmlobj.path. *args): pass def run(self): self.on_about_activate) def delete_event(self.XML(xml) self.mainwindow.connect(’activate’.connect(’activate’.path.show_all() def on_catalog_activate(self.get_widget(’quit’) catalog = xmlobj. *args): circulationwindow. *args): gtk.get_widget(’mainwindow’) circulation = xmlobj. *args): catalogwindow. self.show_all() def on_about_activate(self.get_widget(’member’) quit = xmlobj.main() The main function here creates an instance of MainWindow class.show_all() def main(): mainwindow = MainWindow() mainwindow.py: import os .connect(’delete_event’. self.run() gtk.join(curdir.glade’) xmlobj = gtk. self.abspath(os.main_quit() def on_circulation_activate(self. ’mainwindow.

get_widget(’memberwindow’) self.memberwindow.clear() member = Member() memberdboperation = getAdapter(member.on_update_clicked) delete.hide() return True def initialize_list(self): self. self.get_widget(’update’) delete = xmlobj.path.get_widget(’name’) add = xmlobj. self. ’glade’.memberwindow = xmlobj. self.on_delete_event) self.glade’) xmlobj = gtk. IDbOperation) members = memberdboperation.list_store.get() for member in members: number = member. ’memberwindow.)) def on_delete_event(self.get_widget(’treeview’) self.connect(’clicked’.abspath(os.list_store = gtk.show_all() def populate_list_store(self): self. THE CODE import gtk import gtk.XML(xml) self.memberwindow.populate_list_store() self.4.glade.connect(’clicked’.name self.get_widget(’delete’) close = xmlobj.connect(’delete_event’.treeview = xmlobj. self.append((member.list_store. name.on_delete_event) add.component import getAdapter from components import Member from interfaces import IDbOperation 49 class MemberWindow(object): def __init__(self): curdir = os. number.path.ListStore(object.glade from zope.connect(’clicked’. *args): self.dirname(__file__)) xml = os.join(curdir.number = xmlobj. str) .8.initialize_list() def show_all(self): self.name = xmlobj.path.on_delete_clicked) close. str.get_widget(’close’) self.connect(’clicked’. self.on_add_clicked) update.get_widget(’add’) update = xmlobj.memberwindow.number name = member.get_widget(’number’) self.

delete(member) self.get_selection() model.treeview. ’text’.get_value(iter. 1) tvcolumn = gtk.treeview.list_store.remove(iter) .TreeViewColumn(’Member Number’) self. 0) member. IDbOperation) memberdboperation.update(member) self.CellRendererText() tvcolumn.get_text() member = Member() member. *args): treeselection = self.add() def on_update_clicked(self.CellRendererText() tvcolumn. number.get_selected() if not iter: return member = self.50 CHAPTER 8.list_store.append_column(tvcolumn) cell = gtk. name) def update(self. True) tvcolumn.)) def add(self.treeview.get_text() name = self.add_attribute(cell.list_store.add_attribute(cell.name. 1. *args): number = self. *args): number = self. member): memberdboperation = getAdapter(member. iter = treeselection.name = name self.name. CASE STUDY self.append_column(tvcolumn) cell = gtk.number = number member.number = number member. 2.treeview. iter = treeselection.TreeViewColumn(’Member Name’) self. 0) self. name.pack_start(cell.set_model(self. ’text’. True) tvcolumn.treeview.number.number.update() def on_delete_clicked(self.name = name self.get_text() name = self.pack_start(cell.set(iter.list_store) tvcolumn = gtk.get_selection() model.list_store.append((member.get_value(iter.add(member) self. number. member): memberdboperation = getAdapter(member. IDbOperation) memberdboperation.list_store.get_selected() if not iter: return member = self. 2) def on_add_clicked(self.get_text() treeselection = self.

py: from zope. member): memberdboperation = getAdapter(member.8. THE CODE 51 def delete(self.4.py: from zope.interface import Interface from zope. IDbOperation) memberdboperation.interface import Attribute class IBook(Interface): barcode = Attribute("Barcode") author = Attribute("Author of book") title = Attribute("Title of book") class IMember(Interface): number = Attribute("ID number") .delete() memberwindow = MemberWindow() Here is the components.interface import implements from interfaces import IBook from interfaces import IMember from interfaces import ICirculation class Book(object): implements(IBook) barcode = "" title = "" author = "" class Member(object): implements(IMember) number = "" name = "" class Circulation(object): implements(ICirculation) book = Book() member = Member() Here is the interfaces.

CASE STUDY class ICirculation(Interface): book = Attribute("A book") member = Attribute("A member") class IRelationalDatabase(Interface): def commit(): pass def rollback(): pass def cursor(): pass def get_next_id(): pass class IObjectDatabase(Interface): def commit(): pass def rollback(): pass def container(): pass def get_next_id(): pass class IDbOperation(Interface): def get(): pass def add(): pass def update(): pass def delete(): pass .52 name = Attribute("Name of member") CHAPTER 8.

name = name members. member): self. THE CODE Here is the member.py: from zope.member.component import getUtility from zope.number = number member.number if number: cr. name FROM members WHERE number = ?""".fetchall() cr.close() members = [] for record in rst: id = record[’id’] number = record[’number’] name = record[’name’] member = Member() member.)) else: cr.id = id member. (number.append(member) return members .cursor() number = self.component import adapts from components import Member from from from from interfaces interfaces interfaces interfaces import import import import IRelationalDatabase IObjectDatabase IMember IDbOperation 53 class MemberRDbOperation(object): implements(IDbOperation) adapts(IMember) def __init__(self.member = member def get(self): db = getUtility(IRelationalDatabase) cr = db.execute("""SELECT id. number.8.execute("""SELECT id.interface import implements from zope.4. name FROM members""") rst = cr. number.

commit() def delete(self): db = getUtility(IRelationalDatabase) cr = db.commit() self.member.member.number name = self.id cr.member. CASE STUDY def add(self): db = getUtility(IRelationalDatabase) cr = db. number.execute("""UPDATE members SET number = ?.close() db.)) cr.name cr.member. (next_id. name)) cr.get_next_id("members") number = self.name id = self.member.id = next_id def update(self): db = getUtility(IRelationalDatabase) cr = db.execute("""DELETE FROM members WHERE id = ?""".member. (number.cursor() next_id = db. name) VALUES (?.cursor() id = self.number name = self. number.member = member def get(self): db = getUtility(IObjectDatabase) zcalibdb = db. id)) cr. member): self.container() members = zcalibdb[’members’] .54 CHAPTER 8.cursor() number = self.close() db. name = ? WHERE id = ?""". (id.close() db. ?)""".execute("""INSERT INTO members (id.commit() class MemberODbOperation(object): implements(IDbOperation) adapts(IMember) def __init__(self. ?.member.id cr. name.

8.commit() 55 8.7 PySQLite ZODB Conclusions .id del members[id] db.number for x in members.member db.number if number in [x. PYSQLITE return members.member db.member.container() members = zcalibdb[’members’] id = self.member.5.member.values() def add(self): db = getUtility(IObjectDatabase) zcalibdb = db.commit() def update(self): db = getUtility(IObjectDatabase) zcalibdb = db.get_next_id(’members’) self.container() members = zcalibdb[’members’] number = self.rollback() raise Exception("Duplicate key") next_id = db.member.5 8.commit() def delete(self): db = getUtility(IObjectDatabase) zcalibdb = db.container() members = zcalibdb[’members’] id = self.values()]: db.id = next_id members[next_id] = self.6 8.id members[id] = self.

CASE STUDY .56 CHAPTER 8.

guest): . self...component import adaptedBy >>> class FrontDeskNG(object): .. adapts(IGuest) .guest = guest >>> adaptedBy(FrontDeskNG) (<InterfaceClass __builtin__..IGuest>. def __init__(self...) 9.interface import implements >>> from zope. implements(IDesk) .Chapter 9 Reference 9..component • Signature: adapter(*interfaces) Example: 57 .2 adapter Adapters can be any callable object.1 adaptedBy This function helps to find the adapted interfaces... • Location: zope. you can use the adapter decorator to declare that a callable object adapts some interfaces (or classes) • Location: zope..component import adapts >>> from zope. ... .component • Signature: adaptedBy(object) Example: >>> from zope.

. . ... implements(IDesk) ...... """A job""" >>> class Job(object): .interface import implements >>> from zope. job = None >>> @implementer(IJob) . @adapter(IPerson) .. .58 >>> >>> >>> >>> >>> from from from from from zope. def personJob(person): .name = "Jack" >>> jack.. implements(IJob) >>> class IPerson(Interface): .interface zope....3 adapts This function helps to declare adapter classes..interface import import import import import Attribute Interface implementer adapter implements CHAPTER 9..... implements(IPerson) .. • Location: zope.component import adapts >>> class FrontDeskNG(object): .interface zope. REFERENCE >>> class IJob(Interface): ... .interface zope. adapts(IGuest) .. return person.component • Signature: adapts(*interfaces) Example: >>> from zope. job = Attribute("Job") >>> class Person(object): ..component zope....job >>> jack = Person() >>> jack... name = Attribute("Name") .> 9....job = Job() >>> personJob(jack) #doctest: +ELLIPSIS <Job object at . name = None ....

.. ....name = "Jack" jack. ....4. The arguments after the object are one or more interfaces. guest): self. The interfaces given are added to the interfaces previously declared for the object.. name = u"" >>> >>> >>> >>> jack = Person() jack..interface import providedBy >>> IStudent in providedBy(jack) True ..... ’place’: guest. . . *interfaces) Example: >>> >>> >>> >>> from from from from zope..place.. ALSOPROVIDES .interface import import import import Attribute Interface implements alsoProvides >>> class IPerson(Interface): .name.9.. implements(IDesk) . ... . def __init__(self.. • Location: zope... ..interface zope.. ’phone’: guest.. .phone } 59 9.4 alsoProvides Declare interfaces declared directly for an object..college = "New College" alsoProvides(jack. IStudent) You can test it like this: >>> from zope.. ..interface • Signature: alsoProvides(object... college = Attribute("Name of college") >>> class Person(object): .guest = guest def register(self): next_id = get_next_id() bookings_db[next_id] = { ’name’: guest.interface zope. ..... .interface zope. . name = Attribute("Name of person") >>> class IStudent(Interface): .

. REFERENCE 9. name = u"" ....5 Attribute Using this class...name = "Jack" .. you can define normal attributes in an interface. name = Attribute("Name of person") .. • Location: zope. .. college = u"" >>> classImplements(Person... The interfaces given are added to any interfaces previously declared. doc=”) • See also: Interface Example: >>> from zope.interface • Signature: Attribute(name. *interfaces) Example: >>> >>> >>> >>> from from from from zope. . name = Attribute("Name of person") >>> class IStudent(Interface): . email = Attribute("Email Address") 9.. implements(IDesk) ..interface import Interface >>> class IPerson(Interface): .6 classImplements Declare additional interfaces implemented for instances of a class..interface zope.interface import Attribute >>> from zope....interface zope..interface import import import import Attribute Interface implements classImplements >>> class IPerson(Interface): .. IStudent) >>> jack = Person() >>> jack.60 CHAPTER 9. . The arguments after the class are one or more interfaces. college = Attribute("Name of college") >>> class Person(object): ...interface zope. .interface • Signature: classImplements(cls.. • Location: zope.

The arguments after the class are one or more interfaces.. college = u"" >>> classImplementsOnly(Person.college = "New College" You can test it like this: >>> from zope.. .9.. *interfaces) Example: >>> >>> >>> >>> from from from from zope. • Location: zope. The interfaces given replace any previous declarations.interface import providedBy >>> IPerson in providedBy(jack) False >>> IStudent in providedBy(jack) True .interface import providedBy >>> IStudent in providedBy(jack) True 61 9.. college = Attribute("Name of college") >>> class Person(object): .interface import import import import Attribute Interface implements classImplementsOnly >>> class IPerson(Interface): . name = Attribute("Name of person") >>> class IStudent(Interface): .interface zope. CLASSIMPLEMENTSONLY >>> jack. .7..7 classImplementsOnly Declare the only interfaces implemented by instances of a class.....interface zope. .interface • Signature: classImplementsOnly(cls.interface zope.college = "New College" You can test it like this: >>> from zope..... IStudent) >>> jack = Person() >>> jack.. implements(IPerson) .

REFERENCE 9.interface import providedBy >>> IPerson in providedBy(Person) True 9. . name = u"Jack" You can test it like this: >>> from zope.62 CHAPTER 9.. name = Attribute("Name of person") >>> class Person(object): ...interface • Signature: classProvides(*interfaces) Example: >>> from zope..interface import Attribute >>> from zope. . the instance of that class will provide the interface implemented by that class.. classProvides(IPerson) .interface import Interface >>> from zope. you can declare it using classProvides function.interface import classProvides >>> class IPerson(Interface): . ComponentLookupError: .9 ComponentLookupError This is the exception raised when a component lookup fails. Example: >>> class IPerson(Interface): . 9.. • Location: zope.. IPerson......8 classProvides Normally if a class implements a particular interface... .. .. But if you want a class to be provided by an interface.10 createObject Create an object using a factory.. name = Attribute("Name of person") >>> person = object() >>> getAdapter(person.. ’not-exists’) #doctest: +ELLIPSIS Traceback (most recent call last): .

interfaces import IFactory >>> gsm.12 directlyProvidedBy This function will return the interfaces directly provided by the given object.> 9..component import createObject >>> createObject(’fakedb’) #doctest: +ELLIPSIS <FakeDb object at .. If a matching factory cannot be found raises ComponentLookupError. implements(IDatabase) .. • Location: zope..component. """Return connection object""" >>> class FakeDb(object): . Returns the created object.9.component. . return "connection" >>> from zope.interface import implements >>> class IDatabase(Interface): . *args..registerUtility(factory.. 9. this means that it is impossible to pass a keyword argument named “context” to the factory.. . DECLARATION 63 Finds the named factory in the current site and calls it with the given arguments..component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> from zope... A context keyword argument can be provided to cause the factory to be looked up in a location other than the current site.11.. **kwargs) Example: >>> from zope.interface import Interface >>> from zope. . . (Of course.... IFactory. def getConnection(): .interface import Attribute >>> from zope.11 Declaration Need not to use directly.. ’fakedb’) >>> from zope... def getConnection(self): ..component • Signature: createObject(factory_name.factory import Factory >>> factory = Factory(FakeDb. ’FakeDb’) >>> from zope.

. . ... The arguments after the object are one or more interfaces. REFERENCE >>> from zope. • Location: zope. The interfaces given replace interfaces previously declared for the object. ISmartPerson..interfaces() True 9. name = u"" >>> >>> >>> >>> jack = Person() jack...college = "New College" alsoProvides(jack. name = Attribute("Name of person") >>> class IStudent(Interface): .interface • Signature: directlyProvides(object.interface import Attribute >>> from zope.. *interfaces) Example: >>> from zope. college = Attribute("Name of college") >>> class ISmartPerson(Interface): .interface import Interface >>> class IPerson(Interface): .interfaces() False >>> IStudent in jack_dp...13 directlyProvides Declare interfaces declared directly for an object..interfaces() True >>> ISmartPerson in jack_dp..interface import Attribute ..64 • Location: zope. .interface • Signature: directlyProvidedBy(object) Example: >>> from zope..name = u"Jack" jack..interface import directlyProvidedBy >>> jack_dp = directlyProvidedBy(jack) >>> IPerson in jack_dp. IStudent) CHAPTER 9. implements(IPerson) ... pass >>> class Person(object): .

. DIRECTLYPROVIDES >>> from zope.interfaces() True >>> IPerson in jack_dp..interfaces() False >>> IPerson in jack_dp.interface import providedBy >>> ISmartPerson in providedBy(jack) True >>> from zope.interface import Interface >>> class IPerson(Interface): .... name = Attribute("Name of person") >>> class IStudent(Interface): ..interface import directlyProvides >>> directlyProvides(jack. implements(IPerson) . .9. college = Attribute("Name of college") >>> class ISmartPerson(Interface): .. pass >>> class Person(object): .interface import directlyProvidedBy >>> jack_dp = directlyProvidedBy(jack) >>> ISmartPerson in jack_dp..13...interfaces() True >>> ISmartPerson in providedBy(jack) False .college = "New College" alsoProvides(jack..name = u"Jack" jack..interfaces() False >>> IStudent in jack_dp. IStudent) 65 >>> from zope.interfaces() False >>> IStudent in jack_dp..interfaces() True >>> from zope.. IStudent) >>> jack_dp = directlyProvidedBy(jack) >>> ISmartPerson in jack_dp. . . ISmartPerson.. name = u"" >>> >>> >>> >>> jack = Person() jack..

14 getAdapter Get a named adapter to an interface for an object..... """Register object’s details""" . .place. .... def __init__(self. ’place’: guest. raises ComponentLookupError .interface import Attribute >>> from zope.providedBy(jack_frontdesk) True .... self. adapts(IGuest) .. implements(IDesk) . . next_id = get_next_id() .. """A frontdesk will register object’s details""" .66 CHAPTER 9. ’name’: guest..interface import implements >>> from zope. . def register(): .. } >>> class Guest(object): .. • Location: zope... self.interface • Signature: getAdapter(object. Returns an adapter that can adapt object to interface. implements(IGuest) .. def register(self): . ’phone’: guest..interface import Interface >>> class IDesk(Interface): .. If a matching adapter cannot be found. def __init__(self. .....name = name . guest): ..phone . ...guest = guest ....... .place = place >>> jack = Guest("Jack". "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk. context=None) Example: >>> from zope......component import adapts >>> class FrontDeskNG(object): ... place): . interface=Interface... name.... name=u”. bookings_db[next_id] = { . >>> from zope. ... self.name... REFERENCE 9..

component....sm >>> context = Context(sm) >>> from zope.... def __init__(self. ’ng’) >>> getAdapter(jack. def __conform__(self. guest): ..15.. ...).. use context argument of getAdapter function.... implements(IDesk) .sm = sm . • Location: zope.....9. .interface import Attribute >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.. return self. >>> from zope. IDesk. context) • See also: queryAdapterInContext Example: >>> from zope. ’ng’) #doctest: +ELLIPSIS <FrontDeskNG object at .... if interface. """A frontdesk will register object’s details""" . def __init__(self. (IGuest. IDesk..globalregistry import BaseGlobalComponents >>> from zope..15 getAdapterInContext Instead of this function. self. sm): . .component import IComponentLookup >>> sm = BaseGlobalComponents() >>> class Context(object): . adapts(IGuest) .component • Signature: getAdapterInContext(object. interface. ... interface): ... """Register object’s details""" ...component import adapts >>> class FrontDeskNG(object): ...interface import implements >>> from zope.> 9. GETADAPTERINCONTEXT 67 >>> from zope. def register(): ..registerAdapter(FrontDeskNG.interface import Interface >>> class IDesk(Interface): .isOrExtends(IComponentLookup): ..

. . .component import adapts >>> class FrontDeskNG(object): ..component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> sm.... def __init__(self.. "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.. ’place’: guest.. implements(IGuest) . implements(IDesk) .providedBy(jack_frontdesk) True >>> from zope...registerAdapter(FrontDeskNG.. ... self. .. IDesk. . • Location: zope.. sm) #doctest: +ELLIPSIS <FrontDeskNG object at ..16 getAdapters Look for all matching adapters to a provided interface for objects.component • Signature: getAdapters(objects. (IGuest. .name.. adapts(IGuest) ... . .component import getAdapterInContext >>> getAdapterInContext(jack.. self.. ..phone } CHAPTER 9..interface import implements >>> from zope. ..68 . If an adapter is named.... self. context=None) Example: >>> from zope...).. .place. name. REFERENCE >>> class Guest(object): . provided.guest = guest def register(self): next_id = get_next_id() bookings_db[next_id] = { ’name’: guest...... IDesk) >>> from zope. ’phone’: guest.> 9. place): .. Return a list of adapters that match. only the most specific adapter of a given name is returned. ...place = place >>> jack = Guest("Jack"..name = name ..

interface import Interface >>> from zope.. .. "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> from zope.. . <FrontDeskNG object at . .... . implements(IGreeter) . • Location: zope...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. This includes overridden utilities.. guest): self. name=’ng’) >>> from zope..name.registerAdapter(FrontDeskNG. .. 69 def __init__(self..guest = guest def register(self): next_id = get_next_id() bookings_db[next_id] = { ’name’: guest.. name >>> from zope...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() . name): .. def greet(self.>)] 9... IDesk)) #doctest: +ELLIPSIS [(u’ng’.17. "say hello" >>> class Greeter(object): ... . .. The returned value is an iterable of utility instances. GETALLUTILITIESREGISTEREDFOR ...component import getAdapters >>> list(getAdapters((jack.... .. ..).. ’place’: guest.component • Signature: getAllUtilitiesRegisteredFor(interface) Example: >>> from zope.... .. ’phone’: guest.9.17 getAllUtilitiesRegisteredFor Return all registered utilities for an interface.. ..phone } >>> jack = Guest("Jack"... . def greet(name): . print "Hello".place..interface import implements >>> class IGreeter(Interface): .

component import getAllUtilitiesRegisteredFor >>> getAllUtilitiesRegisteredFor(IGreeter) #doctest: +ELLIPSIS [<Greeter object at ... REFERENCE >>> from zope. context=None) Example: >>> from zope. • Location: zope..interfaces import IFactory >>> gsm.component import getFactoriesFor >>> list(getFactoriesFor(IDatabase)) [(u’fakedb’...>] 9.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> from zope.. .. . IFactory.18 getFactoriesFor Return a tuple (name.component • Signature: getFactoriesFor(interface..component. implements(IDatabase) . ..registerUtility(greet.interface import implements >>> class IDatabase(Interface): . ’FakeDb’) >>> from zope. <Factory for <class ’FakeDb’>>)] .registerUtility(factory.... def getConnection(): . IGreeter) CHAPTER 9... def getConnection(self): .component. """Return connection object""" >>> class FakeDb(object): . return "connection" >>> from zope.70 >>> greet = Greeter() >>> gsm.. ’fakedb’) >>> from zope. factory) of registered factories that create objects which implement the given interface.factory import Factory >>> factory = Factory(FakeDb.interface import Interface >>> from zope..interface import Attribute >>> from zope...

interface import implements >>> class IDatabase(Interface): .component. .component • Signature: getFactoryInterfaces(name.FakeDb> 9.component.9..component import getFactoryInterfaces >>> getFactoryInterfaces(’fakedb’) <implementedBy __builtin__.factory import Factory >>> factory = Factory(FakeDb. def getConnection(): .component • Signature: getGlobalSiteManager() Example: . """Return connection object""" >>> class FakeDb(object): . ... ’FakeDb’) >>> from zope. implements(IDatabase) ..19 getFactoryInterfaces Get interfaces implemented by a factory. return "connection" >>> from zope. GETFACTORYINTERFACES 71 9...20 getGlobalSiteManager Return the global site manager. . and returns the interface or interface tuple that object instances created by the named factory will implement. IFactory.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> from zope.. def getConnection(self): .19. This function should never fail and always return an object that provides IGlobalSiteManager • Location: zope..interfaces import IFactory >>> gsm.. Finds the factory of the given name that is nearest to the context. context=None) Example: >>> from zope.... ’fakedb’) >>> from zope. • Location: zope...interface import Interface >>> from zope...interface import Attribute >>> from zope.registerUtility(factory.

def __init__(self.component import getGlobalSiteManager >>> from zope. implements(IAdapteeOne) >>> class Two(object): .. two): . The name consisting of an empty string is reserved for unnamed adapters. The unnamed adapter methods will often call the named adapter methods with an empty string for a name..interface import Interface >>> from zope. pass >>> class MyFunctionality(object): . pass >>> class IAdapteeTwo(Interface): . interface=Interface.. IAdapteeTwo) ..component • Signature: getMultiAdapter(objects.. one.component import globalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm is globalSiteManager True 9. pass >>> class IFunctionality(Interface): ...component import adapts >>> class IAdapteeOne(Interface): . REFERENCE >>> from zope.two = two >>> from zope.72 CHAPTER 9. raises ComponentLookupError. context=None) • See also: queryMultiAdapter Example: >>> from zope.one = one ...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. • Location: zope. adapts(IAdapteeOne.. . If a matching adapter cannot be found..21 getMultiAdapter Look for a multi-adapter to an interface for an objects..interface import implements >>> from zope. self....registerAdapter(MyFunctionality) >>> class One(object): . implements(IFunctionality) .. name=”.... Returns a multi-adapter that can adapt objects to interface. self.... implements(IAdapteeTwo) .

. if interface..sm >>> context = Context(sm) >>> from zope.22 getSiteManager Get the nearest site manager in the given context..two #doctest: +ELLIPSIS <Two object at .. If the context is not None.two).> >>> myfunctionality.component • Signature: getSiteManager(context=None) Example 1: >>> from zope. • Location: zope.two).component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> sm = getSiteManager() >>> gsm is sm True . def __init__(self. it is expected that an adapter from the context to IComponentLookup can be found....> 73 9..component import getSiteManager >>> lsm = getSiteManager(context) >>> lsm is sm True Example 2: >>> from zope... If no adapter is found.9.. IFunctionality) #doctest: +ELLIPSIS <MyFunctionality object at .component import getMultiAdapter >>> getMultiAdapter((one.. return self.sm = sm . a ComponentLookupError is raised.one #doctest: +ELLIPSIS <One object at . self. GETSITEMANAGER >>> one = One() >>> two = Two() >>> from zope.component.22.component import IComponentLookup >>> sm = BaseGlobalComponents() >>> class Context(object): .globalregistry import BaseGlobalComponents >>> from zope.> >>> myfunctionality = getMultiAdapter((one. return the global site manager... def __conform__(self. sm): .. interface): . If context is None.isOrExtends(IComponentLookup): . IFunctionality) >>> myfunctionality..

component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm... name >>> from zope.24 getUtility Get the utility that provides interface. def greet(name): . "say hello" ...74 CHAPTER 9. • Location: zope. def greet(name): .interface import implements >>> class IGreeter(Interface): .. <Greeter object at . "say hello" >>> class Greeter(object): . IGreeter) >>> from zope. Returns the nearest utility to the context that implements the specified interface. raises ComponentLookupError.>)] 9.. def greet(self. • Location: zope.component • Signature: getUtilitiesFor(interface) Example: >>> from zope..registerUtility(greet... Returns an iterable of name-utility pairs..component • Signature: getUtility(interface.. print "Hello". .. If one is not found..interface import Interface >>> from zope. implements(IGreeter) . name): ....interface import Interface >>> from zope..23 getUtilitiesFor Look up the registered utilities that provide an interface.interface import implements >>> class IGreeter(Interface): . REFERENCE 9..component import getUtilitiesFor >>> list(getUtilitiesFor(IGreeter)) #doctest: +ELLIPSIS [(u’’.. context=None) Example: >>> from zope. name=”. ..

. ..... IGreeter) >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm.. implements(IGreeter) .component • Signature: handle(*objects) Example: >>> import datetime >>> def documentCreated(event): .greet(’Jack’) ’Hello Jack’ 9.interface import implements >>> class IDocumentCreated(Interface): .registerUtility(greet.. Handlers are typically used to handle events. implements(IDocumentCreated) .created = datetime. name): . • Location: zope.. .interface import Attribute >>> from zope. self.. return "Hello " + name >>> from zope. HANDLE 75 >>> class Greeter(object): .utcnow() >>> from zope. doc): . Handlers are subscription adapter factories that don’t produce anything... They do all of their work when called..interface import Interface >>> from zope.doc = doc >>> def documentCreated(event): .... def greet(self.25 handle Call all of the handlers for the given objects...25... doc = Attribute("The document that was created") >>> class DocumentCreated(object): .datetime.9. event.component import getUtility >>> getUtility(IGreeter).datetime...utcnow() . ... def __init__(self.created = datetime.doc..doc. event.

def documentCreated(event): .interface import implementedBy >>> implementedBy(Greeter) <implementedBy __builtin__. ....__name__ ’datetime’ 9..interface import Attribute >>> from zope.registerHandler(documentCreated) >>> from zope. print "Hello".. def greet(self.... def greet(name): . .Greeter> Example 2: >>> from zope.datetime...created.created = datetime.76 >>> from zope.26 implementedBy Return the interfaces implemented for a class’ instances. name >>> from zope. name): ... implements(IGreeter) .component import handle >>> handle(DocumentCreated(doc)) >>> doc.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.. REFERENCE >>> @adapter(IDocumentCreated) ..interface • Signature: implementedBy(class_) Example 1: >>> from zope.interface import Interface >>> from zope.interface import implements >>> class IGreeter(Interface): . "say hello" >>> class Greeter(object): .interface import Interface >>> from zope. • Location: zope.__class__.component import adapter CHAPTER 9...interface import implements .utcnow() >>> from zope.doc. event...

name = u"" >>> from zope. name = Attribute("Name of person") >>> class ISpecial(Interface): ..__name__ for x in implementedBy(Person)] [’IPerson’.interface import implementer >>> class IFoo(Interface): .. The arguments are one or more interfaces. Previous declarations include declarations for base classes unless implementsOnly was used..27..interface ... pass >>> class Person(object): .interface import classImplements >>> classImplements(Person.27 implementer Create a decorator for declaring interfaces implemented by a factory... • Location: zope...IFoo>] 9.28 implements Declare interfaces implemented by instances of a class This function is called in a class definition. implements(IPerson) .. return foo >>> list(implementedBy(foocreator)) [<InterfaceClass __builtin__.. A callable is returned that makes an implements declaration on objects passed to it... pass >>> class Foo(object): .. IMPLEMENTER >>> class IPerson(Interface): . ’ISpecial’] 77 9.. implements(IFoo) >>> @implementer(IFoo) .9. ISpecial) >>> from zope. def foocreator(): . The interfaces given are added to any interfaces previously declared. • Location: zope..interface import implementedBy To get a list of all interfaces implemented by that class:: >>> [x..interface • Signature: implementer(*interfaces) Example: >>> from zope. foo = Foo() .

. Previous declarations including declarations for base classes are overridden.. name = Attribute("Name of person") >>> class Person(object): .interface import providedBy >>> IPerson in providedBy(jack) True CHAPTER 9.interface zope.. This function is called in a class definition........ . name = Attribute("Name of person") >>> class IStudent(Interface): . The arguments are one or more interfaces. .name = "Jack" You can test it like this: >>> from zope. REFERENCE 9...interface import import import import Attribute Interface implements implementsOnly >>> class IPerson(Interface): ... name = u"" >>> jack = Person() >>> jack. college = Attribute("Name of college") >>> class Person(object): .29 implementsOnly Declare the only interfaces implemented by instances of a class. • Location: zope..interface zope.. .interface import Interface >>> from zope.interface • Signature: implementsOnly(*interfaces) Example: >>> >>> >>> >>> from from from from zope.. implements(IPerson) .78 • Signature: implements(*interfaces) Example: >>> from zope..interface zope.interface import implements >>> class IPerson(Interface): .interface import Attribute >>> from zope. .

.. .interface import Interface >>> class IHost(Interface): . def goodmorning(guest): . email = Attribute("Email Address") Example 2: >>> from zope.... . name = Attribute("Name of person") ....30.. The given interfaces are used to create the module’s direct-object interface specification.30 Interface Using this class. .. An .. """Say good morning to guest""" 9.. you can define an interface. just inherit from Interface class...college = "New College" You can test it like this: >>> from zope..interface • Signature: Interface(name.interface import providedBy >>> IPerson in providedBy(jack) False >>> IStudent in providedBy(jack) True 9..... implementsOnly(IStudent) . This function is used in a module definition. .. doc=”) Example 1: >>> from zope.interface import Interface >>> class IPerson(Interface): . INTERFACE .9. The arguments are one or more interfaces. To define an interface. 79 implements(IPerson) name = u"" >>> class NewPerson(Person): ...31 moduleProvides Declare interfaces provided by a module.interface import Attribute >>> from zope. college = u"" >>> jack = NewPerson() >>> jack. • Location: zope.

.80 CHAPTER 9.interface zope. interface) Example: >>> >>> >>> >>> from from from from zope. it is an error to call this function more than once in a module definition.... 9. . • Location: zope. It provides a more convenient way to call directlyProvides for a module.interface zope.interface import import import import Attribute Interface implements classImplements >>> class IPerson(Interface): .. • Location: zope.. implements(IPerson) ..interface • Signature: noLongerProvides(object.name = "Jack" jack. IComponentRegistrationConvenience) So. ... .32 noLongerProvides Remove an interface from the list of an object’s directly provided interfaces.interface • Signature: moduleProvides(*interfaces) • See also: directlyProvides You can see an example usage in zope. The __init__....component provides two interfaces: IComponentArchitecture and IComponentRegistrationConvenience.interface zope.college = "New College" directlyProvides(jack. the zope. REFERENCE error will be raised if the module already has an interface specification. name = Attribute("Name of person") >>> class IStudent(Interface): .component source itself.. college = Attribute("Name of college") >>> class Person(object): .py file has a statement like this: moduleProvides(IComponentArchitecture. This function is provided for convenience.. name = u"" >>> >>> >>> >>> jack = Person() jack. In other words. IStudent) You can test it like this: .

IStudent) >>> IPerson in providedBy(jack) True >>> IStudent in providedBy(jack) False 9. 9.33. 9..33 provideAdapter It is recommended to use registerAdapter ..36 provideUtility It is recommended to use registerUtility . • Location: zope.35 provideSubscriptionAdapter It is recommended to use registerSubscriptionAdapter .interface import Interface >>> from zope. 9.interface import providedBy >>> IPerson in providedBy(jack) True >>> IStudent in providedBy(jack) True >>> from zope. PROVIDEADAPTER 81 >>> from zope.interface import Attribute >>> from zope. including asserting that it implements an extended interface.37 providedBy Test whether the interface is implemented by the object.9. Return true if the object asserts that it implements the interface. 9.interface import noLongerProvides >>> noLongerProvides(jack.interface • Signature: providedBy(object) Example 1: >>> from zope.34 provideHandler It is recommended to use registerHandler .interface import implements >>> class IPerson(Interface): . .

82 ... name = Attribute("Name of person")

CHAPTER 9. REFERENCE

>>> class Person(object): ... ... implements(IPerson) ... name = u"" >>> jack = Person() >>> jack.name = "Jack" You can test it like this: >>> from zope.interface import providedBy >>> IPerson in providedBy(jack) True Example 2: >>> from zope.interface import Attribute >>> from zope.interface import Interface >>> from zope.interface import implements >>> class IPerson(Interface): ... name = Attribute("Name of person") >>> class ISpecial(Interface): ... pass >>> class Person(object): ... implements(IPerson) ... name = u"" >>> >>> >>> >>> >>> from zope.interface import classImplements classImplements(Person, ISpecial) from zope.interface import providedBy jack = Person() jack.name = "Jack"

To get a list of all interfaces provided by that object:: >>> [x.__name__ for x in providedBy(jack)] [’IPerson’, ’ISpecial’]

9.38

queryAdapter

Look for a named adapter to an interface for an object. Returns an adapter that can adapt object to interface. If a matching adapter cannot be found, returns the default. • Location: zope.component • Signature: queryAdapter(object, interface=Interface, name=u”, default=None, context=None)

9.38. QUERYADAPTER Example: >>> from zope.interface import Attribute >>> from zope.interface import Interface >>> class IDesk(Interface): ... """A frontdesk will register object’s details""" ... ... def register(): ... """Register object’s details""" ... >>> from zope.interface import implements >>> from zope.component import adapts >>> class FrontDeskNG(object): ... ... implements(IDesk) ... adapts(IGuest) ... ... def __init__(self, guest): ... self.guest = guest ... ... def register(self): ... next_id = get_next_id() ... bookings_db[next_id] = { ... ’name’: guest.name, ... ’place’: guest.place, ... ’phone’: guest.phone ... } >>> class Guest(object): ... ... implements(IGuest) ... ... def __init__(self, name, place): ... self.name = name ... self.place = place >>> jack = Guest("Jack", "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.providedBy(jack_frontdesk) True >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.registerAdapter(FrontDeskNG, ... (IGuest,), IDesk, ’ng’) >>> queryAdapter(jack, IDesk, ’ng’) #doctest: +ELLIPSIS <FrontDeskNG object at ...>

83

84

CHAPTER 9. REFERENCE

9.39

queryAdapterInContext

Look for a special adapter to an interface for an object. NOTE: This method should only be used if a custom context needs to be provided to provide custom component lookup. Otherwise, call the interface, as in: interface(object, default) Returns an adapter that can adapt object to interface. If a matching adapter cannot be found, returns the default. Context is adapted to IServiceService, and this adapter’s ’Adapters’ service is used. If the object has a __conform__ method, this method will be called with the requested interface. If the method returns a non-None value, that value will be returned. Otherwise, if the object already implements the interface, the object will be returned. • Location: zope.component • Signature: queryAdapterInContext(object, interface, context, default=None) • See also: getAdapterInContext Example: >>> from zope.component.globalregistry import BaseGlobalComponents >>> from zope.component import IComponentLookup >>> sm = BaseGlobalComponents() >>> class Context(object): ... def __init__(self, sm): ... self.sm = sm ... def __conform__(self, interface): ... if interface.isOrExtends(IComponentLookup): ... return self.sm >>> context = Context(sm) >>> from zope.interface import Attribute >>> from zope.interface import Interface >>> class IDesk(Interface): ... """A frontdesk will register object’s details""" ... ... def register(): ... """Register object’s details""" ... >>> from zope.interface import implements >>> from zope.component import adapts >>> class FrontDeskNG(object): ... ... implements(IDesk) ... adapts(IGuest)

’place’: guest.9. .. IDesk) >>> from zope. ’phone’: guest.. ... QUERYMULTIADAPTER . . guest): self... name=u”. If a matching adapter cannot be found. .. . 85 def __init__(self.. name. (IGuest.. ...name = name . default=None... "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.place. . Returns a multi-adapter that can adapt objects to interface. returns the default. self. The unnamed adapter methods will often call the named adapter methods with an empty string for a name.providedBy(jack_frontdesk) True >>> from zope.. . . context=None) • See also: getMultiAdapter Example: >>> from zope.. def __init__(self.40..guest = guest def register(self): next_id = get_next_id() bookings_db[next_id] = { ’name’: guest. sm) #doctest: +ELLIPSIS <FrontDeskNG object at . interface=Interface. IDesk.. self. The name consisting of an empty string is reserved for unnamed adapters. place): .registerAdapter(FrontDeskNG..component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> sm. ....component import queryAdapterInContext >>> queryAdapterInContext(jack..> 9. ...name...interface import Interface ..phone } >>> class Guest(object): .... • Location: zope...). .40 queryMultiAdapter Look for a multi-adapter to an interface for objects.. implements(IGuest) ..place = place >>> jack = Guest("Jack".... .component • Signature: queryMultiAdapter(objects..

one.. ..two = two CHAPTER 9. IFunctionality) #doctest: +ELLIPSIS <MyFunctionality object at .. default=None) . name=”.two).> 9. IAdapteeTwo) .one #doctest: +ELLIPSIS <One object at .86 >>> from zope....component import queryMultiAdapter >>> getMultiAdapter((one.. implements(IAdapteeTwo) >>> one = One() >>> two = Two() >>> from zope. self..interface import implements >>> from zope.component import adapts >>> class IAdapteeOne(Interface): ..... self...two #doctest: +ELLIPSIS <Two object at .. returns default.component • Signature: queryUtility(interface..registerAdapter(MyFunctionality) >>> class One(object): .. pass >>> class IAdapteeTwo(Interface): .. two): ..> >>> myfunctionality = queryMultiAdapter((one.... adapts(IAdapteeOne. If one is not found.two). pass >>> class IFunctionality(Interface): . def __init__(self.. IFunctionality) >>> myfunctionality..41 queryUtility This function is used to look up a utility that provides an interface. REFERENCE >>> from zope...> >>> myfunctionality. pass >>> class MyFunctionality(object): .one = one .component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. • Location: zope.. implements(IFunctionality) . implements(IAdapteeOne) >>> class Two(object): ..

42. implements(IGreeter) ..component . ..component import adapts >>> class FrontDeskNG(object): .. required=None..interface import implements >>> from zope.interface import Attribute >>> from zope.greet(’Jack’) ’Hello Jack’ 87 9.. def register(): . ..42 registerAdapter This function is used to register an adapter factory. info=u”) • See also: unregisterAdapter Example: >>> from zope... return "Hello " + name >>> from zope.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm..interface import Interface >>> class IDesk(Interface): ... .... """Register object’s details""" ..component import queryUtility >>> queryUtility(IGreeter).. "say hello" >>> class Greeter(object): . name=u”.. provided=None.IComponentRegistry • Signature: registerAdapter(factory. IGreeter) >>> from zope..registerUtility(greet. >>> from zope.. def greet(self. name): . def greet(name): .interface import implements >>> class IGreeter(Interface): ... """A frontdesk will register object’s details""" . REGISTERADAPTER Example: >>> from zope.. • Location: zope.9...interface import Interface >>> from zope.

.... . place): ...component . CHAPTER 9.name. implements(IGuest) ..registerAdapter(FrontDeskNG.name = name .. ... ’ng’) You can test it like this: >>> queryAdapter(jack... . • Location: zope...).place = place >>> jack = Guest("Jack". .. ’ng’) #doctest: +ELLIPSIS <FrontDeskNG object at . ...interface import Interface .> 9.. . .guest = guest def register(self): next_id = get_next_id() bookings_db[next_id] = { ’name’: guest.. ’place’: guest.. self.... IDesk. .. IDesk. . . REFERENCE implements(IDesk) adapts(IGuest) def __init__(self.IComponentRegistry • Signature: registeredAdapters() Example: >>> from zope.... "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.. ..phone } >>> class Guest(object): ...place.... ’phone’: guest. ...88 . guest): self. ..43 registeredAdapters Return an iterable of IAdapterRegistrations.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. (IGuest...interface import Attribute >>> from zope.. def __init__(self... .. ..providedBy(jack_frontdesk) True >>> from zope. name. . These registrations describe the current adapter registrations in the object. self.

. >>> from zope.. . implements(IGuest) ... self. implements(IDesk) ... IDesk.. .. ..9...43.. (IGuest.registeredAdapters()) >>> ’ng2’ in [x..). next_id = get_next_id() . . name..name = name ...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. """Register object’s details""" .. """A frontdesk will register object’s details""" .. guest): .. .. "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk.. adapts(IGuest) ... def __init__(self. REGISTEREDADAPTERS 89 >>> class IDesk(Interface): . ’ng2’) >>> reg_adapter = list(gsm....phone ... . } >>> class Guest(object): . bookings_db[next_id] = { .. self..component import adapts >>> class FrontDeskNG(object): . ’name’: guest. ’phone’: guest..interface import implements >>> from zope..registerAdapter(FrontDeskNG.... . def register(self): . def register(): ... self.. def __init__(self. ..name..name for x in reg_adapter] True .. ’place’: guest..place.... .guest = guest .place = place >>> jack = Guest("Jack"...providedBy(jack_frontdesk) True >>> from zope.. place): .....

.. info=’ng3’) >>> reg_adapter = list(gsm.doc.doc.utcnow() >>> from zope. def __init__(self.. TypeError: Named handlers are not yet supported . implements(IDocumentCreated) .. event. • Location: zope. self...datetime.info for x in reg_adapter] True >>> gsm..utcnow() >>> from zope...doc = doc >>> def documentCreated(event): .registeredHandlers()) >>> ’ng3’ in [x. event...registerHandler(documentCreated..interface import Attribute >>> from zope.created = datetime.IComponentRegistry • Signature: registeredHandlers() Example: >>> import datetime >>> def documentCreated(event): .created = datetime. doc): .component import adapter >>> @adapter(IDocumentCreated) .component . event...interface import Interface >>> from zope.interface import implements >>> class IDocumentCreated(Interface): . def documentCreated(event): . REFERENCE 9..datetime. name=’ng4’) Traceback (most recent call last): .component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.doc.. doc = Attribute("The document that was created") >>> class DocumentCreated(object): .registerHandler(documentCreated...datetime. These registrations describe the current handler registrations in the object.90 CHAPTER 9..44 registeredHandlers Return an iterable of IHandlerRegistrations.utcnow() >>> from zope.created = datetime.. .

... def __init__(self. .. else: ... object is valid.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm... .. • Location: zope..interface import Attribute >>> from zope. implements(IValidate) ... REGISTEREDSUBSCRIPTIONADAPTERS 91 9...body = summary.. These registrations describe the current subscription adapter registrations in the object.. return ’’ >>> from zope..component import adapts >>> class AdequateLength(object): .. info=’ng4’) .9..registerSubscriptionAdapter(AdequateLength... .doc. def validate(ob): .. doc): ..IComponentRegistry • Signature: registeredSubscriptionAdapters() Example: >>> from zope.body) < 1000: . """Determine whether the object is valid .. def __init__(self.. Return a string describing a validation problem. summary = Attribute("Document summary") . ...interface import Interface >>> from zope.45.. """ >>> class IDocument(Interface): . body = Attribute("Document text") >>> class Document(object): ....summary. return ’too short’ . .... def validate(self): . body >>> from zope. self...... implements(IDocument) .. adapts(IDocument) . summary.. self.interface import implements >>> class IValidate(Interface): . .. self.....45 registeredSubscriptionAdapters Return an iterable of ISubscriptionAdapterRegistrations. if len(self..doc = doc .. body): .component . An empty string is returned to indicate that the .

.. "say hello" >>> class Greeter(object): .registerUtility(greet.registeredSubscriptionAdapters()) >>> ’ng4’ in [x. info=”) • See also: unregisterHandler .IComponentRegistry • Signature: registerHandler(handler... name >>> from zope. • Location: zope...component .IComponentRegistry • Signature: registeredUtilities() Example: >>> from zope. name): .. . print "Hello".registeredUtilities()) >>> ’ng5’ in [x..47 registerHandler This function is used to register a handler.92 CHAPTER 9. info=’ng5’) >>> reg_adapter = list(gsm. REFERENCE >>> reg_adapter = list(gsm..component ..component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm.interface import Interface >>> from zope. def greet(self.info for x in reg_adapter] True 9. def greet(name): . implements(IGreeter) . name=u”. required=None. A handler is a subscriber that doesn’t compute an adapter but performs some function when called.46 registeredUtilities This function return an iterable of IUtilityRegistrations.. .. • Location: zope..info for x in reg_adapter] True 9.interface import implements >>> class IGreeter(Interface): . These registrations describe the current utility registrations in the object..

REGISTERSUBSCRIPTIONADAPTER Note: In the current implementation of zope... event. .48 registerSubscriptionAdapter This function is used to register a subscriber factory.datetime...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm... event. provides=None.component import adapter >>> @adapter(IDocumentCreated) .created = datetime.component . doc): .component doesn’t support name attribute..__name__ ’datetime’ 9..registerHandler(documentCreated) >>> from zope.utcnow() >>> from zope.doc.doc.doc. event.. Example: >>> import datetime >>> def documentCreated(event): . def documentCreated(event): .utcnow() >>> from zope.. • Location: zope. def __init__(self.created = datetime..__class__..interface import Attribute >>> from zope. doc = Attribute("The document that was created") >>> class DocumentCreated(object): .created = datetime. info=”) .. name=u”.component import handle >>> handle(DocumentCreated(doc)) >>> doc..48. required=None.created..utcnow() >>> from zope.IComponentRegistry • Signature: registerSubscriptionAdapter(factory.datetime..9. implements(IDocumentCreated) ..datetime.doc = doc 93 >>> def documentCreated(event): .. self.interface import implements >>> class IDocumentCreated(Interface): .interface import Interface >>> from zope.

..summary.49 registerUtility This function is used to register a utility.. def validate(self): . . adapts(IDocument) .... def validate(ob): ....IComponentRegistry .. summary = Attribute("Document summary") .component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm..doc = doc .. body): . • Location: zope. """ >>> class IDocument(Interface): ... REFERENCE >>> class IValidate(Interface): . doc): ....doc.interface import implements CHAPTER 9. ... return ’too short’ . An empty string is returned to indicate that the ....interface import Attribute >>> from zope. Return a string describing a validation problem.. else: . . summary.. .body) < 1000: ..component import adapts >>> class AdequateLength(object): .interface import Interface >>> from zope.. if len(self.. body = Attribute("Document text") >>> class Document(object): .. def __init__(self.. """Determine whether the object is valid .. self.... body >>> from zope... implements(IDocument) .. implements(IValidate) .. self. def __init__(self.body = summary. .... self.94 • See also: unregisterSubscriptionAdapter Example: >>> from zope. .registerSubscriptionAdapter(AdequateLength) 9..component ..... object is valid.... return ’’ >>> from zope.

.50.. .IComponentRegistry • Signature: subscribers(required.. def validate(ob): .interface import Interface >>> from zope...interface import Attribute >>> from zope... . def greet(self.. SUBSCRIBERS • Signature: registerUtility(component.. implements(IGreeter) . . summary = Attribute("Document summary") . Return a string describing a validation problem. .... • Location: zope.9. info=u”) • See also: unregisterUtility Example: >>> from zope. name >>> from zope.. "say hello" >>> class Greeter(object): .. provided. An empty string is returned to indicate that the ..component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm.interface import implements >>> class IGreeter(Interface): . name=u”. """Determine whether the object is valid . print "Hello". name): . ... """ >>> class IDocument(Interface): . context=None) Example: >>> from zope.....interface import implements >>> class IValidate(Interface): .50 subscribers This function is used to get subscribers.. provided=None.... object is valid.component ..interface import Interface >>> from zope.registerUtility(greet) 95 9. def greet(name): .. Subscribers are returned that provide the provided interface and that depend on and are computed from the sequence of required objects....

def __init__(self. implements(IValidate) .. self.body) < 1000: .... body >>> from zope.doc = doc ... def __init__(self. return ’’ >>> class AdequateLength(object): . if adapter.. self. implements(IDocument) .component import subscribers >>> doc = Document("A\nDocument". implements(IValidate) .validate() . . if len(self....validate() .. IValidate) ..96 .. return ’Summary should only have one line’ . def validate(self): ...doc......summary: ..validate()] [’Summary should only have one line’... IValidate) ...component import adapts >>> class SingleLineSummary: ....validate()] ..... ’too short’] >>> doc = Document("A\nDocument". def __init__(self.registerSubscriptionAdapter(AdequateLength) >>> from zope. if ’\n’ in self. return ’too short’ . "blah") >>> [adapter.. for adapter in subscribers([doc].doc. .component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm..body = summary..... . else: .....doc = doc ... summary. . adapts(IDocument) . "blah" * 1000) >>> [adapter. self..summary....... def validate(self): ... for adapter in subscribers([doc]. if adapter. body = Attribute("Document text") CHAPTER 9. return ’’ >>> from zope. REFERENCE >>> class Document(object): .. body): ... doc): . else: . adapts(IDocument) . doc): ..registerSubscriptionAdapter(SingleLineSummary) >>> gsm... self..

... .... ... name=u”) • See also: registerAdapter Example: >>> from zope..guest = guest . .place. ....9.. ’phone’: guest. .... A boolean is returned indicating whether the registry was changed. } >>> class Guest(object): .. def register(self): ..name.phone .IComponentRegistry • Signature: unregisterAdapter(factory=None.validate() . "blah") >>> [adapter..interface import implements >>> from zope.51.. >>> from zope. IValidate) . then the function returns False.. UNREGISTERADAPTER [’Summary should only have one line’] >>> doc = Document("A Document". or if the given component is not None and is not registered.. def __init__(self..component . """Register object’s details""" . if adapter. otherwise it returns True. • Location: zope...validate()] [’too short’] 97 9. . next_id = get_next_id() .interface import Interface >>> class IDesk(Interface): .... self.. for adapter in subscribers([doc]. adapts(IGuest) .. implements(IDesk) .... ..interface import Attribute >>> from zope.. """A frontdesk will register object’s details""" ... provided=None.. ’place’: guest. guest): ... ’name’: guest.component import adapts >>> class FrontDeskNG(object): . bookings_db[next_id] = { .. def register(): .51 unregisterAdapter This function is used to unregister an adapter factory. required=None.... If the given component is None and there is no component registered.

. ..98 . name. "Bangalore") >>> jack_frontdesk = FrontDeskNG(jack) >>> IDesk. A handler is a subscriber that doesn’t compute an adapter but performs some function when called. . IDesk. place): self..)...unregisterAdapter(FrontDeskNG..52 unregisterHandler This function is used for unregistering a handler.providedBy(jack_frontdesk) True >>> from zope.. implements(IGuest) def __init__(self. (IGuest.> Now unregister: >>> gsm.component . summary = Attribute("Document summary") .. name=’ng6’) True After unregistration: >>> print queryAdapter(jack.interface import Interface >>> from zope.. ...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm. body = Attribute("Document text") ... IDesk.registerAdapter(FrontDeskNG.. ’ng6’) None 9..name = name self. ’ng6’) #doctest: +ELLIPSIS <FrontDeskNG object at .. ’ng6’) You can test it like this: >>> queryAdapter(jack. . . . name=u”) • See also: registerHandler Example: >>> from zope.interface import Attribute >>> from zope..IComponentRegistry • Signature: unregisterHandler(handler=None... required=None. • Location: zope. A boolean is returned indicating whether the registry was changed. IDesk. REFERENCE >>> jack = Guest("Jack".interface import implements >>> class IDocument(Interface): ..place = place CHAPTER 9.

...component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm.. def __init__(self. UNREGISTERSUBSCRIPTIONADAPTER 99 >>> class Document(object): .. event...count 1 Now unregister: >>> gsm. implements(IDocument) ..doc = doc .doc..component import adapter >>> @adapter(IDocumentAccessed) .registerHandler(documentAccessed) >>> from zope.. body): . doc = Attribute("The document that was accessed") >>> class DocumentAccessed(object): ..53..doc..summary.. def documentAccessed(event): ....body = summary..count = event. self.. self. body >>> doc = Document("A\nDocument".count = 0 >>> from zope... .count 0 9.doc. self.9.. summary. doc): .unregisterHandler(documentAccessed) True After unregistration: >>> handle(DocumentAccessed(doc)) >>> doc.count + 1 >>> from zope... . A boolean is returned indicating whether the registry was changed. or if the given component is not .53 unregisterSubscriptionAdapter This function is used to unregister a subscriber factory. def __init__(self.component import handle >>> handle(DocumentAccessed(doc)) >>> doc. self. implements(IDocumentAccessed) . If the given component is None and there is no component registered. "blah") >>> class IDocumentAccessed(Interface): .

.doc = doc . """Determine whether the object is valid ... . . REFERENCE None and is not registered. def validate(ob): .component import adapts >>> class AdequateLength(object): ..... doc): .interface import Interface >>> from zope... summary.. def __init__(self.component .IComponentRegistry • Signature: name=u”) unregisterSubscriptionAdapter(factory=None.. def validate(self): . ... implements(IDocument) ...... return ’’ >>> from zope. """ >>> class IDocument(Interface): . if len(self..... implements(IValidate) .. then the function returns False.summary..... def __init__(self.. body = Attribute("Document text") >>> class Document(object): . return ’too short’ . • Location: zope.doc. object is valid...body = summary.. self.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> gsm..interface import implements >>> class IValidate(Interface): . adapts(IDocument) .. Return a string describing a validation problem. self..... self.. .. otherwise it returns True. summary = Attribute("Document summary") . required=None.. • See also: registerSubscriptionAdapter Example: >>> from zope.100 CHAPTER 9.interface import Attribute >>> from zope.... .body) < 1000: .. provides=None. An empty string is returned to indicate that the ... body >>> from zope...registerSubscriptionAdapter(AdequateLength) . body): . . else: .

"say hello" >>> class Greeter(object): .. IValidate) ...component import subscribers >>> doc = Document("A\nDocument".54.validate() . • Location: zope..registerUtility(greet) .9.. for adapter in subscribers([doc]... If the given component is None and there is no component registered. "blah") >>> [adapter..interface import Interface >>> from zope.component ... for adapter in subscribers([doc]. then the function returns False. name): . otherwise it returns True.. def greet(name): ... A boolean is returned indicating whether the registry was changed.54 unregisterUtility This function is used for unregistering a utility. . provided=None.component import getGlobalSiteManager >>> gsm = getGlobalSiteManager() >>> greet = Greeter() >>> gsm..IComponentRegistry • Signature: unregisterUtility(component=None.validate()] [] 101 9..unregisterSubscriptionAdapter(AdequateLength) True After unregistration: >>> [adapter...interface import implements >>> class IGreeter(Interface): .validate()] [’too short’] Now unregister: >>> gsm. UNREGISTERUTILITY >>> from zope. or if the given component is not None and is not registered. if adapter. implements(IGreeter) .validate() . .. return "Hello " + name >>> from zope... def greet(self. IValidate) . if adapter. name=u”) • See also: registerUtility Example: >>> from zope...

REFERENCE >>> queryUtility(IGreeter).102 CHAPTER 9.greet(’Jack’) ’Hello Jack’ Now unregister: >>> gsm.unregisterUtility(greet) True After unregistration: >>> print queryUtility(IGreeter) None .

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->