[Checkins] SVN: zope.kgs/trunk/s Start of script to extract the changes of packages in the KGS.

Stephan Richter srichter at cosmos.phy.tufts.edu
Sat Dec 6 19:07:27 EST 2008


Log message for revision 93734:
  Start of script to extract the changes of packages in the KGS.
  

Changed:
  U   zope.kgs/trunk/setup.py
  U   zope.kgs/trunk/src/zope/kgs/README.txt
  A   zope.kgs/trunk/src/zope/kgs/release_data.dat
  U   zope.kgs/trunk/src/zope/kgs/tests.py

-=-
Modified: zope.kgs/trunk/setup.py
===================================================================
--- zope.kgs/trunk/setup.py	2008-12-07 00:05:53 UTC (rev 93733)
+++ zope.kgs/trunk/setup.py	2008-12-07 00:07:26 UTC (rev 93734)
@@ -62,6 +62,7 @@
           'generate-intro = zope.kgs.intro:main',
           'generate-site = zope.kgs.site:main',
           'list-latest = zope.kgs.latest:main',
+          'list-changes = zope.kgs.change:main',
           ]),
       include_package_data = True,
       zip_safe = False,

Modified: zope.kgs/trunk/src/zope/kgs/README.txt
===================================================================
--- zope.kgs/trunk/src/zope/kgs/README.txt	2008-12-07 00:05:53 UTC (rev 93733)
+++ zope.kgs/trunk/src/zope/kgs/README.txt	2008-12-07 00:07:26 UTC (rev 93734)
@@ -332,6 +332,37 @@
   z3c.formdemo: 1.1.1, 1.1.2
 
 
+Extracting Change Information
+-----------------------------
+
+When releasing a version of the KGS, it is desirable to produce a list of
+changes since the last release. Changes are commonly compared to an older
+version.
+
+  >>> cfgFileRealOrig = tempfile.mktemp('-cp.cfg')
+  >>> open(cfgFileRealOrig, 'w').write('''\
+  ... [DEFAULT]
+  ... tested = true
+  ...
+  ... [KGS]
+  ... name = zope-dev
+  ... version = 3.4.0b1
+  ...
+  ... [PIL]
+  ... versions = 1.1.6
+  ...
+  ... [zope.component]
+  ... versions = 3.4.0
+  ...
+  ... [zope.interface]
+  ... versions = 3.4.0
+  ... ''')
+
+
+  >>> from zope.kgs import change
+  >>> change.main((cfgFileReal, cfgFileRealOrig))
+
+
 Introduction Page
 -----------------
 

Added: zope.kgs/trunk/src/zope/kgs/release_data.dat
===================================================================
--- zope.kgs/trunk/src/zope/kgs/release_data.dat	                        (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/release_data.dat	2008-12-07 00:07:26 UTC (rev 93734)
@@ -0,0 +1,351 @@
+(dp0
+(S'zope.component'
+p1
+S'3.4.0'
+p2
+tp3
+(dp4
+S'maintainer'
+p5
+NsS'maintainer_email'
+p6
+NsS'cheesecake_code_kwalitee_id'
+p7
+NsS'keywords'
+p8
+NsS'author'
+p9
+S'Zope Corporation and Contributors'
+p10
+sS'author_email'
+p11
+S'zope3-dev at zope.org'
+p12
+sS'download_url'
+p13
+S'UNKNOWN'
+p14
+sS'platform'
+p15
+S'UNKNOWN'
+p16
+sS'version'
+p17
+S'3.4.0'
+p18
+sS'obsoletes'
+p19
+(lp20
+sS'provides'
+p21
+(lp22
+sS'cheesecake_documentation_id'
+p23
+NsS'_pypi_hidden'
+p24
+I1
+sS'description'
+p25
+S'*****************************\nzope.component Package Readme\n*****************************\n\nThis package represents the core of the Zope Component Architecture.\nTogether with the \'zope.interface\' package, it provides facilities for\ndefining, registering and looking up components.\n\n.. contents::\n\nReleases\n********\n\n3.4.0 (2007-09-29)\n==================\n\nNo further changes since 3.4.0a1.\n\n3.4.0a1 (2007-04-22)\n====================\n\nCorresponds to zope.component from Zope 3.4.0a1.\n\nIn the Zope 3.3.x series, ``zope.component`` was simplified yet once\nmore.  See http://wiki.zope.org/zope3/LocalComponentManagementSimplification\nfor the proposal describing the changes.\n\n3.2.0.2 (2006/04/15)\n====================\n\nFix packaging bug:  \'package_dir\' must be a *relative* path.\n\nzope.component version 3.2.0.1 (2006/04/14)\n----------------------------------------------\n\nPackaging change:  suppress inclusion of \'setup.cfg\' in \'sdist\' builds.\n\n3.
 2.0 (2006/01/05)\n==================\n\nCorresponds to the verison of the zope.component package shipped as part of\nthe Zope 3.2.0 release.\n\nDeprecated services and related APIs. The adapter and utility registries\nare now available directly via the site manager\'s \'adapters\' and \'utilities\'\nattributes, respectively.  Services are accessible, but deprecated, and\nwill be removed in Zope 3.3.\n\nDeprectaed all presentation-related APIs, including all view-related\nAPI functions. Use the adapter API functions instead.\nSee http://dev.zope.org/Zope3/ImplementViewsAsAdapters`\n\nDeprecated \'contextdependent\' package:  site managers are now looked up\nvia a thread global, set during URL traversal.  The \'context\' argument\nis now always optional, and should no longer be passed.\n\n3.0.0 (2004/11/07)\n==================\n\nCorresponds to the verison of the zope.component package shipped as part of\nthe Zope X3.0.0 release.\n\n\nDetailed Documentation\n******************
 ****\n\nZope Component Architecture\n===========================\n\nThis package, together with `zope.interface`, provides facilities for\ndefining, registering and looking up components.  There are two basic\nkinds of components: adapters and utilities.\n\nUtilities\n---------\n\nUtilities are just components that provide an interface and that are\nlooked up by an interface and a name.  Let\'s look at a trivial utility\ndefinition:\n\n    >>> from zope import interface\n\n    >>> class IGreeter(interface.Interface):\n    ...     def greet():\n    ...         "say hello"\n\n    >>> class Greeter:\n    ...     interface.implements(IGreeter)\n    ...\n    ...     def __init__(self, other="world"):\n    ...         self.other = other\n    ...\n    ...     def greet(self):\n    ...         print "Hello", self.other\n\nWe can register an instance this class using `provideUtility` [1]_:\n\n    >>> from zope import component\n    >>> greet = Greeter(\'bob\')\n    >>> component.prov
 ideUtility(greet, IGreeter, \'robert\')\n\nIn this example we registered the utility as providing the `IGreeter`\ninterface with a name of \'bob\'. We can look the interface up with\neither `queryUtility` or `getUtility`:\n\n    >>> component.queryUtility(IGreeter, \'robert\').greet()\n    Hello bob\n\n    >>> component.getUtility(IGreeter, \'robert\').greet()\n    Hello bob\n\n`queryUtility` and `getUtility` differ in how failed lookups are handled:\n\n    >>> component.queryUtility(IGreeter, \'ted\')\n    >>> component.queryUtility(IGreeter, \'ted\', 42)\n    42\n    >>> component.getUtility(IGreeter, \'ted\')\n    ... # doctest: +ELLIPSIS\n    Traceback (most recent call last):\n    ...\n    ComponentLookupError: (<InterfaceClass ...IGreeter>, \'ted\')\n\nIf a component provides only one interface, as in the example above,\nthen we can omit the provided interface from the call to `provideUtility`:\n\n    >>> ted = Greeter(\'ted\')\n    >>> component.provideUtility(ted, na
 me=\'ted\')\n    >>> component.queryUtility(IGreeter, \'ted\').greet()\n    Hello ted\n\nThe name defaults to an empty string:\n\n    >>> world = Greeter()\n    >>> component.provideUtility(world)\n    >>> component.queryUtility(IGreeter).greet()\n    Hello world\n\nAdapters\n--------\n\nAdapters are components that are computed from other components to\nadapt them to some interface.  Because they are computed from other\nobjects, they are provided as factories, usually classes.  Here, we\'ll\ncreate a greeter for persons, so we can provide personalized greetings\nfor different people:\n\n    >>> class IPerson(interface.Interface):\n    ...     name = interface.Attribute("Name")\n\n    >>> class PersonGreeter:\n    ...\n    ...     component.adapts(IPerson)\n    ...     interface.implements(IGreeter)\n    ...\n    ...     def __init__(self, person):\n    ...         self.person = person\n    ...\n    ...     def greet(self):\n    ...         print "Hello", self.person.name\n
 \nThe class defines a constructor that takes an argument for every\nobject adapted.\n\nWe used `component.adapts` to declare what we adapt.  We can find\nout if an object declares that it adapts anything using adaptedBy:\n\n    >>> list(component.adaptedBy(PersonGreeter)) == [IPerson]\n    True\n\nIf an object makes no declaration, then None is returned:\n\n    >>> component.adaptedBy(Greeter()) is None\n    True\n\n\nIf we declare the interfaces adapted and if we provide only one\ninterface, as in the example above, then we can provide the adapter\nvery simply [1]_:\n\n    >>> component.provideAdapter(PersonGreeter)\n\nFor adapters that adapt a single interface to a single interface\nwithout a name, we can get the adapter by simply calling the\ninterface:\n\n    >>> class Person:\n    ...     interface.implements(IPerson)\n    ...\n    ...     def __init__(self, name):\n    ...         self.name = name\n\n    >>> IGreeter(Person("Sally")).greet()\n    Hello Sally\n\nWe can 
 also provide arguments to be very specific about what\nhow to register the adapter.\n\n    >>> class BobPersonGreeter(PersonGreeter):\n    ...     name = \'Bob\'\n    ...     def greet(self):\n    ...         print "Hello", self.person.name, "my name is", self.name\n\n    >>> component.provideAdapter(\n    ...                        BobPersonGreeter, [IPerson], IGreeter, \'bob\')\n\nThe arguments can also be provided as keyword arguments:\n\n    >>> class TedPersonGreeter(BobPersonGreeter):\n    ...     name = "Ted"\n\n    >>> component.provideAdapter(\n    ...     factory=TedPersonGreeter, adapts=[IPerson],\n    ...     provides=IGreeter, name=\'ted\')\n\nFor named adapters, use `queryAdapter`, or `getAdapter`:\n\n    >>> component.queryAdapter(Person("Sally"), IGreeter, \'bob\').greet()\n    Hello Sally my name is Bob\n\n    >>> component.getAdapter(Person("Sally"), IGreeter, \'ted\').greet()\n    Hello Sally my name is Ted\n\nIf an adapter can\'t be found, `queryAdapter` 
 returns a default value\nand `getAdapter` raises an error:\n\n    >>> component.queryAdapter(Person("Sally"), IGreeter, \'frank\')\n    >>> component.queryAdapter(Person("Sally"), IGreeter, \'frank\', 42)\n    42\n    >>> component.getAdapter(Person("Sally"), IGreeter, \'frank\')\n    ... # doctest: +ELLIPSIS\n    Traceback (most recent call last):\n    ...\n    ComponentLookupError: (...Person...>, <...IGreeter>, \'frank\')\n\nAdapters can adapt multiple objects:\n\n    >>> class TwoPersonGreeter:\n    ...\n    ...     component.adapts(IPerson, IPerson)\n    ...     interface.implements(IGreeter)\n    ...\n    ...     def __init__(self, person, greeter):\n    ...         self.person = person\n    ...         self.greeter = greeter\n    ...\n    ...     def greet(self):\n    ...         print "Hello", self.person.name\n    ...         print "my name is", self.greeter.name\n\n    >>> component.provideAdapter(TwoPersonGreeter)\n\nTo look up a multi-adapter, use either `queryMu
 ltiAdapter` or\n`getMultiAdapter`:\n\n    >>> component.queryMultiAdapter((Person("Sally"), Person("Bob")),\n    ...                                  IGreeter).greet()\n    Hello Sally\n    my name is Bob\n\nAdapters need not be classes.  Any callable will do.  We use the\nadapter decorator (in the Python 2.4 decorator sense) to declare that\na callable object adapts some interfaces (or classes):\n\n    >>> class IJob(interface.Interface):\n    ...     "A job"\n\n    >>> class Job:\n    ...     interface.implements(IJob)\n\n    >>> def personJob(person):\n    ...     return getattr(person, \'job\', None)\n    >>> personJob = interface.implementer(IJob)(personJob)\n    >>> personJob = component.adapter(IPerson)(personJob)\n\nIn Python 2.4, the example can be written:\n\n    >>> @interface.implementer(IJob)\n    ... @component.adapter(IPerson)\n    ... def personJob(person):\n    ...     return getattr(person, \'job\', None)\n\nwhich looks a bit nicer.\n\nIn this example, the 
 personJob function simply returns the person\'s\n`job` attribute if present, or None if it\'s not present.  An adapter\nfactory can return None to indicate that adaptation wasn\'t possible.\nLet\'s register this adapter and try it out:\n\n    >>> component.provideAdapter(personJob)\n    >>> sally = Person("Sally")\n    >>> IJob(sally) # doctest: +ELLIPSIS\n    Traceback (most recent call last):\n    ...\n    TypeError: (\'Could not adapt\', ...\n\nThe adaptation failed because sally didn\'t have a job.  Let\'s give her\none:\n\n    >>> job = Job()\n    >>> sally.job = job\n    >>> IJob(sally) is job\n    True\n\nSubscription Adapters\n*********************\n\nUnlike regular adapters, subscription adapters are used when we want\nall of the adapters that adapt an object to a particular adapter.\n\nConsider a validation problem.  We have objects and we want to assess\nwhether they meet some sort of standards.  We define a validation\ninterface:\n\n    >>> class IValidate(interf
 ace.Interface):\n    ...     def validate(ob):\n    ...         """Determine whether the object is valid\n    ...\n    ...         Return a string describing a validation problem.\n    ...         An empty string is returned to indicate that the\n    ...         object is valid.\n    ...         """\n\nPerhaps we have documents:\n\n    >>> class IDocument(interface.Interface):\n    ...     summary = interface.Attribute("Document summary")\n    ...     body = interface.Attribute("Document text")\n\n    >>> class Document:\n    ...     interface.implements(IDocument)\n    ...     def __init__(self, summary, body):\n    ...         self.summary, self.body = summary, body\n\nNow, we may want to specify various validation rules for\ndocuments. For example, we might require that the summary be a single\nline:\n\n    >>> class SingleLineSummary:\n    ...     component.adapts(IDocument)\n    ...     interface.implements(IValidate)\n    ...\n    ...     def __init__(self, doc):\n    
 ...         self.doc = doc\n    ...\n    ...     def validate(self):\n    ...         if \'\\n\' in self.doc.summary:\n    ...             return \'Summary should only have one line\'\n    ...         else:\n    ...             return \'\'\n\nOr we might require the body to be at least 1000 characters in length:\n\n    >>> class AdequateLength:\n    ...     component.adapts(IDocument)\n    ...     interface.implements(IValidate)\n    ...\n    ...     def __init__(self, doc):\n    ...         self.doc = doc\n    ...\n    ...     def validate(self):\n    ...         if len(self.doc.body) < 1000:\n    ...             return \'too short\'\n    ...         else:\n    ...             return \'\'\n\nWe can register these as subscription adapters [1]_:\n\n    >>> component.provideSubscriptionAdapter(SingleLineSummary)\n    >>> component.provideSubscriptionAdapter(AdequateLength)\n\nWe can then use the subscribers to validate objects:\n\n    >>> doc = Document("A\\nDocument", "blah")
 \n    >>> [adapter.validate()\n    ...  for adapter in component.subscribers([doc], IValidate)\n    ...  if adapter.validate()]\n    [\'Summary should only have one line\', \'too short\']\n\n    >>> doc = Document("A\\nDocument", "blah" * 1000)\n    >>> [adapter.validate()\n    ...  for adapter in component.subscribers([doc], IValidate)\n    ...  if adapter.validate()]\n    [\'Summary should only have one line\']\n\n    >>> doc = Document("A Document", "blah")\n    >>> [adapter.validate()\n    ...  for adapter in component.subscribers([doc], IValidate)\n    ...  if adapter.validate()]\n    [\'too short\']\n\nHandlers\n********\n\nHandlers are subscription adapter factories that don\'t produce\nanything.  They do all of their work when called.  Handlers\nare typically used to handle events.\n\nEvent subscribers are different from other subscription adapters in\nthat the caller of event subscribers doesn\'t expect to interact with\nthem in any direct way.  For example, an even
 t publisher doesn\'t\nexpect to get any return value.  Because subscribers don\'t need to\nprovide an API to their callers, it is more natural to define them\nwith functions, rather than classes.  For example, in a\ndocument-management system, we might want to record creation times for\ndocuments:\n\n    >>> import datetime\n\n    >>> def documentCreated(event):\n    ...     event.doc.created = datetime.datetime.utcnow()\n\nIn this example, we have a function that takes an event and performs\nsome processing.  It doesn\'t actually return anything.  This is a\nspecial case of a subscription adapter that adapts an event to\nnothing.  All of the work is done when the adapter "factory" is\ncalled.  We call subscribers that don\'t actually create anything\n"handlers".  There are special APIs for registering and calling\nthem.\n\nTo register the subscriber above, we define a document-created event:\n\n    >>> class IDocumentCreated(interface.Interface):\n    ...     doc = interfac
 e.Attribute("The document that was created")\n\n    >>> class DocumentCreated:\n    ...     interface.implements(IDocumentCreated)\n    ...\n    ...     def __init__(self, doc):\n    ...         self.doc = doc\n\nWe\'ll also change our handler definition to:\n\n    >>> def documentCreated(event):\n    ...     event.doc.created = datetime.datetime.utcnow()\n\n    >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)\n\nNote that in Python 2.4, this can be written:\n\n    >>> @component.adapter(IDocumentCreated)\n    ... def documentCreated(event):\n    ...     event.doc.created = datetime.datetime.utcnow()\n\nThis marks the handler as an adapter of `IDocumentCreated` events.\n\nNow we\'ll register the handler  [1]_:\n\n    >>> component.provideHandler(documentCreated)\n\nNow, if we can create an event and use the `handle` function to call\nhandlers registered for the event:\n\n    >>> component.handle(DocumentCreated(doc))\n    >>> doc.created.__class__._
 _name__\n    \'datetime\'\n\n\n\n.. [1] CAUTION: This API should only be used from test or\n       application-setup code. This API shouldn\'t be used by regular\n       library modules, as component registration is a configuration\n       activity.\n\nEvents\n======\n\nThe Component Architecture provides a way to dispatch events to event\nhandlers.  Event handlers are registered as *subscribers*\na.k.a. *handlers*.\n\nBefore we can start we need to import ``zope.component.event`` to make\nthe dispatching effective:\n\n  >>> import zope.component.event\n\nConsider two event classes:\n\n  >>> class Event1(object):\n  ...     pass\n\n  >>> class Event2(Event1):\n  ...     pass\n\nNow consider two handlers for these event classes:\n\n  >>> called = []\n\n  >>> import zope.component\n  >>> @zope.component.adapter(Event1)\n  ... def handler1(event):\n  ...     called.append(1)\n\n  >>> @zope.component.adapter(Event2)\n  ... def handler2(event):\n  ...     called.append(2)\n\nWe c
 an register them with the Component Architecture:\n\n  >>> zope.component.provideHandler(handler1)\n  >>> zope.component.provideHandler(handler2)\n\nNow let\'s go through the events.  We\'ll see that the handlers have been\ncalled accordingly:\n\n  >>> from zope.event import notify\n  >>> notify(Event1())\n  >>> called\n  [1]\n\n  >>> del called[:]\n  >>> notify(Event2())\n  >>> called.sort()\n  >>> called\n  [1, 2]\n\n\n\nObject events\n-------------\n\n\nThe ``objectEventNotify`` function is a subscriber to dispatch\nObjectEvents to interested adapters.\n\nFirst create an object class:\n\n  >>> class IUseless(zope.interface.Interface):\n  ...     """Useless object"""\n\n  >>> class UselessObject(object):\n  ...     """Useless object"""\n  ...     zope.interface.implements(IUseless)\n\nThen create an event class:\n\n  >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent):\n  ...     """An object has been thrown away"""\n\n  >>> class ObjectThrownEvent(zope.co
 mponent.interfaces.ObjectEvent):\n  ...     """An object has been thrown away"""\n  ...     zope.interface.implements(IObjectThrownEvent)\n\nCreate an object and an event:\n\n  >>> hammer = UselessObject()\n  >>> event = ObjectThrownEvent(hammer)\n\nThen notify the event to the subscribers.\nSince the subscribers list is empty, nothing happens.\n\n  >>> zope.component.event.objectEventNotify(event)\n\nNow create an handler for the event:\n\n  >>> events = []\n  >>> def record(*args):\n  ...     events.append(args)\n\n  >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent])\n\nThe event is notified to the subscriber:\n\n  >>> zope.component.event.objectEventNotify(event)\n  >>> events == [(hammer, event)]\n  True\n\nFollowing test demonstrates how a subscriber can raise an exception\nto prevent an action.\n\n  >>> zope.component.provideHandler(zope.component.event.objectEventNotify)\n\nLet\'s create a container:\n\n  >>> class ToolBox(dict):\n  ...     def 
 __delitem__(self, key):\n  ...         notify(ObjectThrownEvent(self[key]))\n  ...         return super(ToolBox,self).__delitem__(key)\n\n  >>> container = ToolBox()\n\nAnd put the object into the container:\n\n  >>> container[\'Red Hammer\'] = hammer\n\nCreate an handler function that will raise an error when called:\n\n  >>> class Veto(Exception):\n  ...     pass\n\n  >>> def callback(item, event):\n  ...     assert(item == event.object)\n  ...     raise Veto\n\nRegister the handler:\n\n  >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent])\n\nThen if we try to remove the object, an ObjectThrownEvent is fired:\n\n  >>> del container[\'Red Hammer\']\n  ... # doctest: +NORMALIZE_WHITESPACE\n  Traceback (most recent call last):\n  ...\n      raise Veto\n  Veto\n\nComponent-Management objects\n============================\n\nComponent-management objects provide a higher-level\ncomponent-management API over the basic adapter-registration API\nprovided by 
 the zope.interface package.  In particular, it provides:\n\n- utilities\n\n- support for computing adapters, rather than just looking up adapter\n  factories.\n\n- management of registration comments\n\nThe zope.component.registry.Components class provides an\nimplementation of zope.component.interfaces.IComponents that provides\nthese features.\n\n    >>> from zope.component import registry\n    >>> from zope.component import tests\n    >>> components = registry.Components(\'comps\')\n\nAs components are registered, events are generated.  Let\'s register\nan event subscriber, so we can see the events generated:\n\n    >>> import zope.event\n    >>> def logevent(event):\n    ...     print event\n    >>> zope.event.subscribers.append(logevent)\n    \nUtilities\n---------\n\nYou can register Utilities using registerUtility:\n\n    >>> components.registerUtility(tests.U1(1))\n    Registered event:\n    UtilityRegistration(<Components comps>, I1, u\'\', 1, u\'\')\n\nHere we didn
 \'t specify an interface or name.  An unnamed utility was\nregistered for interface I1, since that is only interface implemented\nby the U1 class:\n\n    >>> components.getUtility(tests.I1)\n    U1(1)\n\nIf a component implements other than one interface or no interface,\nthen an error will be raised:\n\n    >>> components.registerUtility(tests.U12(2))\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The utility doesn\'t provide a single interface and\n    no provided interface was specified.\n\n    >>> components.registerUtility(tests.A)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The utility doesn\'t provide a single interface and\n    no provided interface was specified.\n \n    \nWe can provide an interface if desired:\n\n    >>> components.registerUtility(tests.U12(2), tests.I2)\n    Registered event:\n    UtilityRegistration(<Components comps>, I2, u
 \'\', 2, u\'\')\n\nand we can specify a name:\n\n    >>> components.registerUtility(tests.U12(3), tests.I2, u\'three\')\n    Registered event:\n    UtilityRegistration(<Components comps>, I2, u\'three\', 3, u\'\')\n\n    >>> components.getUtility(tests.I2)\n    U12(2)\n\n    >>> components.getUtility(tests.I2, \'three\')\n    U12(3)\n\nIf you try to get a utility that doesn\'t exist, you\'ll get a component\nlookup error:\n\n    >>> components.getUtility(tests.I3)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    ComponentLookupError: \n    (<InterfaceClass zope.component.tests.I3>, u\'\')\n\nUnless you use queryUtility:\n\n    >>> components.queryUtility(tests.I3)\n    >>> components.queryUtility(tests.I3, default=42)\n    42\n\nYou can get information about registered utilities with the\nregisteredUtilities method:\n\n    >>> for registration in sorted(components.registeredUtilities()):\n    ...     print registration.provided,
  registration.name\n    ...     print registration.component, registration.info\n    <InterfaceClass zope.component.tests.I1> \n    U1(1) \n    <InterfaceClass zope.component.tests.I2> \n    U12(2) \n    <InterfaceClass zope.component.tests.I2> three\n    U12(3) \n\nDuplicate registrations replace existing ones:\n\n    >>> components.registerUtility(tests.U1(4), info=u\'use 4 now\')\n    Registered event:\n    UtilityRegistration(<Components comps>, I1, u\'\', 4, u\'use 4 now\')\n    >>> components.getUtility(tests.I1)\n    U1(4)\n\n    >>> for registration in sorted(components.registeredUtilities()):\n    ...     print registration.provided, registration.name\n    ...     print registration.component, registration.info\n    <InterfaceClass zope.component.tests.I1> \n    U1(4) use 4 now\n    <InterfaceClass zope.component.tests.I2> \n    U12(2) \n    <InterfaceClass zope.component.tests.I2> three\n    U12(3) \n\nAs shown in the this example, you can provide an "info" argumem
 nt when\nregistering utilities.  This provides extra documentation about the\nregistration itself that is shown when listing registrations.\n\nYou can also unregister utilities:\n\n    >>> components.unregisterUtility(provided=tests.I1)\n    Unregistered event:\n    UtilityRegistration(<Components comps>, I1, u\'\', 4, u\'use 4 now\')\n    True\n\nA boolean is returned indicating whether anything changed:\n\n    >>> components.queryUtility(tests.I1)\n    >>> for registration in sorted(components.registeredUtilities()):\n    ...     print registration.provided, registration.name\n    ...     print registration.component, registration.info\n    <InterfaceClass zope.component.tests.I2> \n    U12(2) \n    <InterfaceClass zope.component.tests.I2> three\n    U12(3) \n\nWhen you unregister, you can specify a component.  If the component\ndoesn\'t match the one registered, then nothing happens:\n\n    >>> u5 = tests.U1(5)\n    >>> components.registerUtility(u5)\n    Registered event
 :\n    UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n    >>> components.unregisterUtility(tests.U1(6))\n    False\n    >>> components.queryUtility(tests.I1)\n    U1(5)\n    >>> components.unregisterUtility(u5)\n    Unregistered event:\n    UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n    True\n    >>> components.queryUtility(tests.I1)\n\nYou can get the name and utility for all of the utilities that provide\nan interface using getUtilitiesFor:\n\n    >>> sorted(components.getUtilitiesFor(tests.I2))\n    [(u\'\', U12(2)), (u\'three\', U12(3))]\n\ngetAllUtilitiesRegisteredFor is similar to getUtilitiesFor except that\nit includes utilities that are overridden.  For example, we\'ll\nregister a utility that for an extending interface of I2:\n\n    >>> components.registerUtility(tests.U(\'ext\'), tests.I2e)\n    Registered event:\n    UtilityRegistration(<Components comps>, I2e, u\'\', ext, u\'\')\n\nWe don\'t get the new utility for getUtilitiesF
 or:\n\n    >>> sorted(components.getUtilitiesFor(tests.I2))\n    [(u\'\', U12(2)), (u\'three\', U12(3))]\n\nbut we do get it from getAllUtilitiesRegisteredFor:\n\n    >>> sorted(map(str, components.getAllUtilitiesRegisteredFor(tests.I2)))\n    [\'U(ext)\', \'U12(2)\', \'U12(3)\']\n\nAdapters\n--------\n\nYou can register adapters with registerAdapter:\n\n    >>> components.registerAdapter(tests.A12_1)\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\n\nHere, we didn\'t specify required interfaces, a provided interface, or\na name.  The required interfaces were determined from the factory\ns __component_adapts__ attribute and the provided interface was\ndetermined by introspecting what the factory implements.\n\n    >>> components.getMultiAdapter((tests.U1(6), tests.U12(7)), tests.IA1)\n    A12_1(U1(6), U12(7))\n\nIf a factory implements more than one interface, an exception will be\nraised:\n\n    >>> components.register
 Adapter(tests.A1_12)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single\n    interface and no provided interface was specified.\n\nUnless the provided interface is specified:\n\n    >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\'\')\n\nIf a factory doesn\'t declare an implemented interface, an exception will be\nraised:\n\n    >>> components.registerAdapter(tests.A12_)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single\n    interface and no provided interface was specified. \n\nUnless the provided interface is specified:\n\n    >>> components.registerAdapter(tests.A12_, provided=tests.IA2)\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1
 , I2], IA2, u\'\', A12_, u\'\')\n\nThe required interface needs to be specified in the registration if\nthe factory doesn\'t have a __component_adapts__ attribute: \n\n    >>> components.registerAdapter(tests.A_2)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t have a __component_adapts__\n    attribute and no required specifications were specified \n\nUnless the required specifications specified:\n\n    >>> components.registerAdapter(tests.A_2, required=[tests.I3])\n    Registered event:\n    AdapterRegistration(<Components comps>, [I3], IA2, u\'\', A_2, u\'\')\n\nClasses can be specified in place of specifications, in which case the\nimplementedBy specification for the class is used:\n\n    >>> components.registerAdapter(tests.A_3, required=[tests.U],\n    ...                            info="Really class specific")\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    A
 dapterRegistration(<Components comps>, [zope.component.tests.U], IA3, u\'\',\n                        A_3, \'Really class specific\')\n\nWe can see the adapters that have been registered using the\nregisteredAdapters method:\n\n    >>> for registration in sorted(components.registeredAdapters()):\n    ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<InterfaceClass zope.component.tests.I1>, \n     <InterfaceClass zope.component.tests.I2>)\n    <InterfaceClass zope.component.tests.IA1> \n    zope.component.tests.A12_1 \n    (<InterfaceClass zope.component.tests.I1>, \n     <InterfaceClass zope.component.tests.I2>)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A12_ \n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_12 \n    
 (<InterfaceClass zope.component.tests.I3>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A_2 \n    (<implementedBy zope.component.tests.U>,)\n    <InterfaceClass zope.component.tests.IA3> \n    zope.component.tests.A_3 Really class specific\n\nAs with utilities, we can provide registration information when\nregistering adapters.\n\nIf you try to fetch an adapter that isn\'t registered, you\'ll get a\ncomponent-lookup error:\n\n    >>> components.getMultiAdapter((tests.U(8), ), tests.IA1)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    ComponentLookupError: ((U(8),), \n                          <InterfaceClass zope.component.tests.IA1>, u\'\')\n\nunless you use queryAdapter:\n\n    >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1)\n    >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1, default=42)\n    42\n\nWhen looking up an adapter for a single object, you can use the\nslightly 
 simpler getAdapter and queryAdapter calls:\n\n    >>> components.getAdapter(tests.U1(9), tests.IA2)\n    A1_12(U1(9))\n\n    >>> components.queryAdapter(tests.U1(9), tests.IA2)\n    A1_12(U1(9))\n\n    >>> components.getAdapter(tests.U(8), tests.IA1)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    ComponentLookupError: (U(8), \n                           <InterfaceClass zope.component.tests.IA1>, u\'\')\n\n    >>> components.queryAdapter(tests.U(8), tests.IA2)\n    >>> components.queryAdapter(tests.U(8), tests.IA2, default=42)\n    42\n\nYou can unregister an adapter.  If a factory is provided and if the\nrewuired and provided interfaces, can be infered, then they need not\nbe provided:\n\n    >>> components.unregisterAdapter(tests.A12_1)\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\n    True\n\n    >>> for registration in sorted(components.registeredAdapters()):\n   
  ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<InterfaceClass zope.component.tests.I1>, \n     <InterfaceClass zope.component.tests.I2>)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A12_ \n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_12 \n    (<InterfaceClass zope.component.tests.I3>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A_2 \n    (<implementedBy zope.component.tests.U>,)\n    <InterfaceClass zope.component.tests.IA3> \n    zope.component.tests.A_3 Really class specific\n\nA boolean is returned indicating whether a change was made.\n\nIf a factory implements more than one interface, an exception will be\nraised:\n\n    >>> components.unregisterAdapter(tests.A1_12)\n    ... # 
 doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single\n    interface and no provided interface was specified.\n\nUnless the provided interface is specified:\n\n    >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\'\')\n    True\n\nIf a factory doesn\'t declare an implemented interface, an exception will be\nraised:\n\n    >>> components.unregisterAdapter(tests.A12_)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single\n    interface and no provided interface was specified. \n\nUnless the provided interface is specified:\n\n    >>> components.unregisterAdapter(tests.A12_, provided=tests.IA2)\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I1, I2], IA2, 
 u\'\', A12_, u\'\')\n    True\n\nThe required interface needs to be specified if the factory doesn\'t\nhave a __component_adapts__ attribute:\n\n    >>> components.unregisterAdapter(tests.A_2)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t have a __component_adapts__\n    attribute and no required specifications were specified \n\n    >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I3], IA2, u\'\', A_2, u\'\')\n    True\n\n    >>> for registration in sorted(components.registeredAdapters()):\n    ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<implementedBy zope.component.tests.U>,)\n    <InterfaceClass zope.component.tests.IA3> \n    zope.component
 .tests.A_3 Really class specific\n\nIf a factory is unregistered that is not registered, False is\nreturned:\n\n\n    >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])\n    False\n    >>> components.unregisterAdapter(tests.A12_1, required=[tests.U])\n    False\n\nThe factory can be omitted, to unregister *any* factory that matches\nspecified required and provided interfaces:\n\n    >>> components.unregisterAdapter(required=[tests.U], provided=tests.IA3)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [zope.component.tests.U], \n                        IA3, u\'\', A_3, \'Really class specific\')\n    True\n\n    >>> for registration in sorted(components.registeredAdapters()):\n    ...     print registration\n\nAdapters can be named:\n\n    >>> components.registerAdapter(tests.A1_12, provided=tests.IA2, \n    ...                            name=u\'test\')\n    Registered event:\n    AdapterRegistrat
 ion(<Components comps>, [I1], IA2, u\'test\', A1_12, u\'\')\n\n    >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2)\n    >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2, name=u\'test\')\n    A1_12(U1(9))\n\n    >>> components.queryAdapter(tests.U1(9), tests.IA2)\n    >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u\'test\')\n    A1_12(U1(9))\n    >>> components.getAdapter(tests.U1(9), tests.IA2, name=u\'test\')\n    A1_12(U1(9))\n\nIt is possible to look up all of the adapters that provide an\ninterface:\n\n    >>> components.registerAdapter(tests.A1_23, provided=tests.IA2, \n    ...                            name=u\'test 2\')\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'test 2\', A1_23, u\'\')\n\n    >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\'\')\n\n    >>> for name, adapter in sorted(com
 ponents.getAdapters((tests.U1(9), ), \n    ...                                                    tests.IA2)):\n    ...     print name, adapter\n     A1_12(U1(9))\n    test A1_12(U1(9))\n    test 2 A1_23(U1(9))\n\n\ngetAdapters is most commonly used as the basis of menu systems.\n\nIf an adapter factory returns None, it is equivalent to there being no\nfactory:\n\n    >>> components.registerAdapter(tests.noop, \n    ...                            required=[tests.IA1], provided=tests.IA2, \n    ...                            name=u\'test noop\')\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    AdapterRegistration(<Components comps>, [IA1], IA2, u\'test noop\', \n                        noop, u\'\')\n    >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u\'test noop\')\n\n    >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\'\')\n\n    >>> f
 or name, adapter in sorted(components.getAdapters((tests.U1(9), ), \n    ...                                                    tests.IA2)):\n    ...     print name, adapter\n     A1_12(U1(9))\n    test A1_12(U1(9))\n    test 2 A1_23(U1(9))\n\n\n    >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2, \n    ...                              name=u\'test\')\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'test\', A1_12, u\'\')\n    True\n    >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)\n    Unregistered event:\n    AdapterRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\'\')\n    True\n    >>> for registration in sorted(components.registeredAdapters()):\n    ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<InterfaceClass zope.component.tests.I1>,
 )\n    <InterfaceClass zope.component.tests.IA2> test 2\n    zope.component.tests.A1_23 \n    (<InterfaceClass zope.component.tests.IA1>,)\n    <InterfaceClass zope.component.tests.IA2> test noop\n    <function noop at 0xb79a1064> \n\n\nSubscribers\n-----------\n\nSubscribers provide a way to get multiple adapters of a given type.\nIn this regard, subscribers are like named adapters, except that there\nisn\'t any concept of the most specific adapter for a given name.\n\nSubscribers are registered by calling registerSubscriptionAdapter:\n\n    >>> components.registerSubscriptionAdapter(tests.A1_2)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, u\'\')\n\n    >>> components.registerSubscriptionAdapter(\n    ...     tests.A1_12, provided=tests.IA2)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_12, u\
 '\')\n\n    >>> components.registerSubscriptionAdapter(\n    ...     tests.A, [tests.I1], tests.IA2,\n    ...     info=\'a sample comment\')\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', \n                             A, \'a sample comment\')\n\nThe same rules, with regard to when required and provided interfaces\nhave to be specified apply as with adapters:\n\n    >>> components.registerSubscriptionAdapter(tests.A1_12)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single \n    interface and no provided interface was specified.\n\n    >>> components.registerSubscriptionAdapter(tests.A)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single interface and\n     no provided interface was specif
 ied.\n\n    >>> components.registerSubscriptionAdapter(tests.A, required=[tests.IA1])\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single interface\n    and no provided interface was specified.\n\nNote that we provided the info argument as a keyword argument above.\nThat\'s because there is a name argument that\'s reserved for future\nuse. We can give a name, as long as it is an empty string:\n\n    >>> components.registerSubscriptionAdapter(\n    ...     tests.A, [tests.I1], tests.IA2, u\'\', \'a sample comment\')\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', \n                             A, \'a sample comment\')\n\n    >>> components.registerSubscriptionAdapter(\n    ...     tests.A, [tests.I1], tests.IA2, u\'oops\', \'a sample comment\')\n    Traceback (most recent call last):\n    ..
 .\n    TypeError: Named subscribers are not yet supported\n\nSubscribers are looked up using the subscribers method:\n\n    >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):\n    ...    print s\n    A1_2(U1(1))\n    A1_12(U1(1))\n    A(U1(1),)\n    A(U1(1),)\n\nNote that, because we created multiple subscriptions for A, we got multiple\nsubscriber instances.\n\nAs with normal adapters, if a factory returns None, the result is skipped:\n\n    >>> components.registerSubscriptionAdapter(\n    ...     tests.noop, [tests.I1], tests.IA2)\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', noop, u\'\')\n\n    >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):\n    ...    print s\n    A1_2(U1(1))\n    A1_12(U1(1))\n    A(U1(1),)\n    A(U1(1),)\n\nWe can get registration information for subscriptions:\n\n    >>> for registration in sorted(\n    ...     components.registeredSubscriptionAdapters()):\n    ...     print 
 registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A a sample comment\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A a sample comment\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_12 \n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_2 \n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    <function noop at 0xb796ff7c> \n\nWe can also unregister subscriptions in much the same way we can for adapters:\n\n    >>> components.unregisterSubscriptionAdapter(tests.A1_2)\n    ... # doctest: +NORMA
 LIZE_WHITESPACE\n    Unregistered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, \'\')\n    True\n\n    >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):\n    ...    print s\n    A1_12(U1(1))\n    A(U1(1),)\n    A(U1(1),)\n\n    >>> for registration in sorted(\n    ...     components.registeredSubscriptionAdapters()):\n    ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A a sample comment\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A a sample comment\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_12 \n    (<InterfaceClass zope.component.tests.I1>
 ,)\n    <InterfaceClass zope.component.tests.IA2> \n    <function noop at 0xb796ff7c> \n\n    >>> components.unregisterSubscriptionAdapter(\n    ...     tests.A, [tests.I1], tests.IA2)\n    Unregistered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A, \'\')\n    True\n\n    >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):\n    ...    print s\n    A1_12(U1(1))\n\n    >>> for registration in sorted(\n    ...     components.registeredSubscriptionAdapters()):\n    ...     print registration.required\n    ...     print registration.provided, registration.name\n    ...     print registration.factory, registration.info\n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    zope.component.tests.A1_12 \n    (<InterfaceClass zope.component.tests.I1>,)\n    <InterfaceClass zope.component.tests.IA2> \n    <function noop at 0xb796ff7c> \n\nNote here that both registrations for A were removed.\n\nI
 f we omit the factory, we must specify the required and provided interfaces:\n\n    >>> components.unregisterSubscriptionAdapter(required=[tests.I1])\n    Traceback (most recent call last):\n    ...\n    TypeError: Must specify one of factory and provided\n\n    >>> components.unregisterSubscriptionAdapter(provided=tests.IA2)\n    Traceback (most recent call last):\n    ...\n    TypeError: Must specify one of factory and required\n\n    >>> components.unregisterSubscriptionAdapter(\n    ...     required=[tests.I1], provided=tests.IA2)\n    Unregistered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', None, \'\')\n    True\n\n    >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):\n    ...    print s\n\n    >>> for registration in sorted(\n    ...     components.registeredSubscriptionAdapters()):\n    ...     print registration.factory\n\nAs when registering, an error is raised if the registration\ninformation can\'t be determined from t
 he factory and isn\'t specified:\n\n    >>> components.unregisterSubscriptionAdapter(tests.A1_12)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single \n    interface and no provided interface was specified.\n\n    >>> components.unregisterSubscriptionAdapter(tests.A)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single interface and\n     no provided interface was specified.\n\n    >>> components.unregisterSubscriptionAdapter(tests.A, required=[tests.IA1])\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t implement a single interface\n    and no provided interface was specified.\n\nIf you unregister something that\'s not registered, nothing will be\nchanged and False will be returned:\n\n\
 n    >>> components.unregisterSubscriptionAdapter(\n    ...     required=[tests.I1], provided=tests.IA2)\n    False\n\nHandlers\n--------\n\nHandlers are used when you want to perform some function in response\nto an event.  Handlers aren\'t expected to return anything when called\nand are not registered to provide any interface.\n\n    >>> from zope import component\n    >>> @component.adapter(tests.I1)\n    ... def handle1(x):\n    ...     print \'handle1\', x\n\n    >>> components.registerHandler(handle1, info="First handler")\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    HandlerRegistration(<Components comps>, [I1], u\'\', \n                        handle1, \'First handler\')\n    >>> components.handle(tests.U1(1))\n    handle1 U1(1)\n\n    >>> @component.adapter(tests.I1, tests.I2)\n    ... def handle12(x, y):\n    ...     print \'handle12\', x, y\n\n    >>> components.registerHandler(handle12)\n    Registered event:\n    HandlerRegistration(<Com
 ponents comps>, [I1, I2], u\'\', handle12, u\'\')\n    >>> components.handle(tests.U1(1), tests.U12(2))\n    handle12 U1(1) U12(2)\n\nIf a handler doesn\'t document interfaces it handles, then \nthe required interfaces must be specified:\n\n    >>> def handle(*objects):\n    ...     print \'handle\', objects\n\n    >>> components.registerHandler(handle)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t have a __component_adapts__ \n    attribute and no required specifications were specified\n\n    >>> components.registerHandler(handle, required=[tests.I1], \n    ...                            info="a comment")\n    Registered event:\n    HandlerRegistration(<Components comps>, [I1], u\'\', handle, \'a comment\')\n\nHandlers can also be registered for classes:\n\n    >>> components.registerHandler(handle, required=[tests.U], \n    ...                            info="handle a class")\n    ..
 . # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    HandlerRegistration(<Components comps>, [zope.component.tests.U], u\'\', \n                        handle, \'handle a class\')\n\n\n    >>> components.handle(tests.U1(1))\n    handle (U1(1),)\n    handle1 U1(1)\n    handle (U1(1),)\n\nWe can list the handler registrations:\n\n    >>> for registration in components.registeredHandlers():\n    ...     print registration.required\n    ...     print registration.handler, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle1 at 0xb78f5bfc> First handler\n    (<InterfaceClass zope.component.tests.I1>,\n     <InterfaceClass zope.component.tests.I2>)\n    <function handle12 at 0xb78f5c34> \n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle at 0xb78f5ca4> a comment\n    (<implementedBy zope.component.tests.U>,)\n    <function handle at 0xb78f5ca4> handle a class\n\nand we can 
 unregister handlers:\n\n    >>> components.unregisterHandler(required=[tests.U])\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Unregistered event:\n    HandlerRegistration(<Components comps>, [zope.component.tests.U], u\'\', \n                        None, \'\')\n    True\n\n    >>> for registration in components.registeredHandlers():\n    ...     print registration.required\n    ...     print registration.handler, registration.info\n    ... # doctest: +NORMALIZE_WHITESPACE\n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle1 at 0xb78f5bfc> First handler\n    (<InterfaceClass zope.component.tests.I1>,\n     <InterfaceClass zope.component.tests.I2>)\n    <function handle12 at 0xb78f5c34> \n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle at 0xb78f5ca4> a comment\n\n    >>> components.unregisterHandler(handle12)\n    Unregistered event:\n    HandlerRegistration(<Components comps>, [I1, I2], u\'\', handle12, \'\')\n    True\n\n    >>> fo
 r registration in components.registeredHandlers():\n    ...     print registration.required\n    ...     print registration.handler, registration.info\n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle1 at 0xb78f5bfc> First handler\n    (<InterfaceClass zope.component.tests.I1>,)\n    <function handle at 0xb78f5ca4> a comment\n\n    >>> components.unregisterHandler(handle12)\n    False\n\n    >>> components.unregisterHandler()\n    Traceback (most recent call last):\n    ...\n    TypeError: Must specify one of factory and required\n\n    >>> components.registerHandler(handle)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Traceback (most recent call last):\n    ...\n    TypeError: The adapter factory doesn\'t have a __component_adapts__ \n    attribute and no required specifications were specified\n\nExtending\n---------\n\nComponent-management objects can extend other component-management\nobjects. \n\n    >>> c1 = registry.Components(\'1\')\n    >>> c1.
 __bases__\n    ()\n\n    >>> c2 = registry.Components(\'2\', (c1, ))\n    >>> c2.__bases__ == (c1, )\n    True\n\n    >>> c1.registerUtility(tests.U1(1))\n    Registered event:\n    UtilityRegistration(<Components 1>, I1, u\'\', 1, u\'\')\n\n    >>> c1.queryUtility(tests.I1)\n    U1(1)\n    >>> c2.queryUtility(tests.I1)\n    U1(1)\n    >>> c1.registerUtility(tests.U1(2))\n    Registered event:\n    UtilityRegistration(<Components 1>, I1, u\'\', 2, u\'\')\n\n    >>> c2.queryUtility(tests.I1)\n    U1(2)\n\nWe can use multiple inheritence:\n\n    >>> c3 = registry.Components(\'3\', (c1, ))\n    >>> c4 = registry.Components(\'4\', (c2, c3))\n    >>> c4.queryUtility(tests.I1)\n    U1(2)\n\n    >>> c1.registerUtility(tests.U12(1), tests.I2)\n    Registered event:\n    UtilityRegistration(<Components 1>, I2, u\'\', 1, u\'\')\n\n    >>> c4.queryUtility(tests.I2)\n    U12(1)\n\n    >>> c3.registerUtility(tests.U12(3), tests.I2)\n    Registered event:\n    UtilityRegistration(<Compone
 nts 3>, I2, u\'\', 3, u\'\')\n    >>> c4.queryUtility(tests.I2)\n    U12(3)\n\n    >>> c1.registerHandler(handle1, info="First handler")\n    Registered event:\n    HandlerRegistration(<Components 1>, [I1], u\'\', handle1, \'First handler\')\n\n    >>> c2.registerHandler(handle, required=[tests.U])\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    HandlerRegistration(<Components 2>, [zope.component.tests.U], u\'\', \n                        handle, u\'\')\n    \n    >>> @component.adapter(tests.I1)\n    ... def handle3(x):\n    ...     print \'handle3\', x\n    >>> c3.registerHandler(handle3)\n    Registered event:\n    HandlerRegistration(<Components 3>, [I1], u\'\', handle3, u\'\')\n    \n    >>> @component.adapter(tests.I1)\n    ... def handle4(x):\n    ...     print \'handle4\', x\n    >>> c4.registerHandler(handle4)\n    Registered event:\n    HandlerRegistration(<Components 4>, [I1], u\'\', handle4, u\'\')\n\n    >>> c4.handle(tests.U1(1))\n    hand
 le1 U1(1)\n    handle3 U1(1)\n    handle (U1(1),)\n    handle4 U1(1)\n\nRedispatch of registration events\n---------------------------------\n\nSome handlers are available that, if registered, redispatch\nregistration events to the objects being registered.  They depend on\nbeing dispatched to by the object-event dispatcher:\n\n    >>> from zope import component\n    >>> import zope.component.event\n    >>> zope.component.getGlobalSiteManager().registerHandler(\n    ...      zope.component.event.objectEventNotify)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Registered event:\n    HandlerRegistration(<BaseGlobalComponents base>, \n                        [IObjectEvent], u\'\', objectEventNotify, u\'\')\n\nTo see this, we\'ll first register a multi-handler to show is when\nhandlers are called on 2 objects:\n\n    >>> @zope.component.adapter(None, None)\n    ... def double_handler(o1, o2):\n    ...     print \'Double dispatch:\'\n    ...     print \' \', o1\n    ...     prin
 t \' \', o2\n    >>> zope.component.getGlobalSiteManager().registerHandler(double_handler)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Double dispatch:\n      HandlerRegistration(<BaseGlobalComponents base>, \n                          [Interface, Interface], u\'\', double_handler, u\'\')\n      Registered event:\n      HandlerRegistration(<BaseGlobalComponents base>, \n      [Interface, Interface], u\'\', double_handler, u\'\')\n    Registered event:\n    HandlerRegistration(<BaseGlobalComponents base>, \n                        [Interface, Interface], u\'\', double_handler, u\'\')\n\nIn the example above, the double_handler reported it\'s own registration. :)\n\nNow we\'ll register our handlers:\n\n    >>> zope.component.getGlobalSiteManager().registerHandler(\n    ...     registry.dispatchUtilityRegistrationEvent)\n    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS\n    Double dispatch:\n    ...\n\n    >>> zope.component.getGlobalSiteManager().registerHandler(\n    ...
      registry.dispatchAdapterRegistrationEvent)\n    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS\n    Double dispatch:\n    ...\n\n    >>> zope.component.getGlobalSiteManager().registerHandler(\n    ...     registry.dispatchSubscriptionAdapterRegistrationEvent)\n    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS\n    Double dispatch:\n    ...\n\n    >>> zope.component.getGlobalSiteManager().registerHandler(\n    ...     registry.dispatchHandlerRegistrationEvent)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Double dispatch:\n      HandlerRegistration(<BaseGlobalComponents base>, \n                          [IHandlerRegistration, IRegistrationEvent], u\'\', \n                          dispatchHandlerRegistrationEvent, u\'\')\n      Registered event:\n      HandlerRegistration(<BaseGlobalComponents base>, \n                          [IHandlerRegistration, IRegistrationEvent], u\'\', \n                          dispatchHandlerRegistrationEvent, u\'\')\n    Double dispatch:\
 n      <function dispatchHandlerRegistrationEvent at 0xb799f72c>\n      Registered event:\n      HandlerRegistration(<BaseGlobalComponents base>,\n                          [IHandlerRegistration, IRegistrationEvent], u\'\',\n                          dispatchHandlerRegistrationEvent, u\'\')\n    Registered event:\n    HandlerRegistration(<BaseGlobalComponents base>,\n                        [IHandlerRegistration, IRegistrationEvent], u\'\',\n                        dispatchHandlerRegistrationEvent, u\'\')\n\nIn the last example above, we can see that the registration of\ndispatchHandlerRegistrationEvent was handled by\ndispatchHandlerRegistrationEvent and redispatched.  This can be seen\nin the second double-dispatch output, where the first argument is the\nobject being registered, which is dispatchHandlerRegistrationEvent.\n\nIf we change some other registrations, we can the double dispatch\ntaking place:\n\n    >>> components.registerUtility(u5)\n    ... # doctest: +NORMAL
 IZE_WHITESPACE\n    Double dispatch:\n      UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n      Registered event:\n      UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n    Double dispatch:\n      U1(5)\n      Registered event:\n      UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n    Registered event:\n    UtilityRegistration(<Components comps>, I1, u\'\', 5, u\'\')\n\n    >>> components.registerAdapter(tests.A12_1)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Double dispatch:\n      AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\n      Registered event:\n      AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\n    Double dispatch:\n      zope.component.tests.A12_1\n      Registered event:\n      AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\n    Registered event:\n    AdapterRegistration(<Components comps>, [I1, I2], IA1, u\'\', A12_1, u\'\')\
 n\n    >>> components.registerSubscriptionAdapter(tests.A1_2)\n    ... # doctest: +NORMALIZE_WHITESPACE\n    Double dispatch:\n      SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, u\'\')\n      Registered event:\n      SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, u\'\')\n    Double dispatch:\n      zope.component.tests.A1_2\n      Registered event:\n      SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, u\'\')\n    Registered event:\n    SubscriptionRegistration(<Components comps>, [I1], IA2, u\'\', A1_2, u\'\')\n\nDownload\n**********************'
+p26
+sS'_pypi_ordering'
+p27
+I10
+sS'classifiers'
+p28
+(lp29
+sS'name'
+p30
+S'zope.component'
+p31
+sS'license'
+p32
+S'ZPL 2.1'
+p33
+sS'summary'
+p34
+S'Zope Component Architecture'
+p35
+sS'home_page'
+p36
+S'http://pypi.python.org/pypi/zope.component'
+p37
+sS'stable_version'
+p38
+NsS'requires'
+p39
+(lp40
+sS'cheesecake_installability_id'
+p41
+Nss(S'PIL'
+p42
+S'1.1.6'
+p43
+tp44
+(dp45
+S'maintainer'
+p46
+NsS'maintainer_email'
+p47
+NsS'cheesecake_code_kwalitee_id'
+p48
+NsS'keywords'
+p49
+NsS'author'
+p50
+S'Secret Labs AB (PythonWare)'
+p51
+sS'author_email'
+p52
+S'info at pythonware.com'
+p53
+sS'download_url'
+p54
+S'http://effbot.org/downloads/#Imaging'
+p55
+sS'platform'
+p56
+S'Python 1.5.2 and later.'
+p57
+sS'version'
+p58
+S'1.1.6'
+p59
+sS'obsoletes'
+p60
+(lp61
+sS'provides'
+p62
+(lp63
+sS'cheesecake_documentation_id'
+p64
+NsS'_pypi_hidden'
+p65
+I0
+sS'description'
+p66
+S'Python Imaging Library'
+p67
+sS'_pypi_ordering'
+p68
+I15
+sS'classifiers'
+p69
+(lp70
+S'Development Status :: 6 - Mature'
+p71
+aS'Topic :: Multimedia :: Graphics'
+p72
+aS'Topic :: Multimedia :: Graphics :: Capture :: Digital Camera'
+p73
+aS'Topic :: Multimedia :: Graphics :: Capture :: Scanners'
+p74
+aS'Topic :: Multimedia :: Graphics :: Capture :: Screen Capture'
+p75
+aS'Topic :: Multimedia :: Graphics :: Graphics Conversion'
+p76
+aS'Topic :: Multimedia :: Graphics :: Viewers'
+p77
+asS'name'
+p78
+S'PIL'
+p79
+sS'license'
+p80
+S'Python (MIT style)'
+p81
+sS'summary'
+p82
+S'Python Imaging Library'
+p83
+sS'home_page'
+p84
+S'http://www.pythonware.com/products/pil'
+p85
+sS'stable_version'
+p86
+NsS'requires'
+p87
+(lp88
+sS'cheesecake_installability_id'
+p89
+Nss(S'zope.interface'
+p90
+S'3.4.1'
+p91
+tp92
+(dp93
+S'maintainer'
+p94
+NsS'maintainer_email'
+p95
+NsS'cheesecake_code_kwalitee_id'
+p96
+NsS'keywords'
+p97
+NsS'author'
+p98
+S'Zope Corporation and Contributors'
+p99
+sS'author_email'
+p100
+S'zope3-dev at zope.org'
+p101
+sS'download_url'
+p102
+S'UNKNOWN'
+p103
+sS'platform'
+p104
+S'UNKNOWN'
+p105
+sS'version'
+p106
+S'3.4.1'
+p107
+sS'obsoletes'
+p108
+(lp109
+sS'provides'
+p110
+(lp111
+sS'cheesecake_documentation_id'
+p112
+NsS'_pypi_hidden'
+p113
+I1
+sS'description'
+p114
+S'***************\nZope Interfaces\n***************\n\n.. contents::\n\nInterfaces are a mechanism for labeling objects as conforming to a given\nAPI or contract.\n\nzope.interface Package Changes\n******************************\n\n===========================================\n3.4.1 (2007/10/02)\n===========================================\n\nFixed a setup bug that prevented installation from source on systems\nwithout setuptools.\n\n===========================================\n3.4.0 (2007/07/19)\n===========================================\n\nFinal release for 3.4.0.\n\n===========================================\n3.4.0b3 (2007/05/22)\n===========================================\n\nBug Fixes\n=========\n\n- Objects with picky custom comparison methods couldn\'t be added to\n  component registries.  Now, when checking whether an object is\n  already registered, identity comparison is used.\n\n===========================================\n3.3.0.1 (2007/01/03)\n=================
 ==========================\n\nBug Fixes\n=========\n\n- Made a reference to OverflowWarning, which disappeared in Python\n  2.5, conditional.\n\n===========================================\n3.3.0 (2007/01/03)\n===========================================\n\nNew Features\n============\n\n- The adapter-lookup algorithim was refactored to make it\n  much simpler and faster.  \n\n  Also, more of the adapter-lookup logic is implemented in C, making\n  debugging of application code easier, since there is less\n  infrastructre code to step through.\n\n- We now treat objects without interafce declarations as if they\n  declared that they provide zope.interface.Interface.\n\n- There are a number of richer new adapter-registration interfaces\n  that provide greater control and introspection.\n\n- Added a new interface decorator to zope.interface that allows the\n  setting of tagged values on an interface at definition time (see\n  zope.interface.taggedValue).\n\nBug Fixes\n=========\n\
 n- A bug in multi-adapter lookup sometimes caused incorrect adapters to\n  be returned.\n\n\n===========================================\nzope.interface version 3.2.0.2 (2006/04/15)\n===========================================\n\n- Fix packaging bug:  \'package_dir\' must be a *relative* path.\n\n\n===========================================\nzope.interface version 3.2.0.1 (2006/04/14)\n===========================================\n\n- Packaging change:  suppress inclusion of \'setup.cfg\' in \'sdist\' builds.\n\n\n=========================================\nzope.interface version 3.2.0 (2006/01/05)\n=========================================\n\n- Corresponds to the verison of the zope.interface package shipped as part of\n  the Zope 3.2.0 release.\n\n- TODO:  note other changes\n\n\n=========================================\nzope.interface version 3.1.0 (2005/10/03)\n=========================================\n\n- Corresponds to the verison of the zope.interface package shipped
  as part of\n  the Zope 3.1.0 release.\n\n- TODO:  note other changes\n\n- Made attribute resolution order consistent with component lookup order,\n  i.e. new-style class MRO semantics.\n\n- Deprecated \'isImplementedBy\' and \'isImplementedByInstancesOf\' APIs in\n  favor of \'implementedBy\' and \'providedBy\'.\n\n\n=========================================\nzope.interface version 3.0.1 (2005/07/27)\n=========================================\n\n- Corresponds to the verison of the zope.interface package shipped as part of\n  the Zope X3.0.1 release.\n\n- Fixed a bug reported by James Knight, which caused adapter registries\n  to fail occasionally to reflect declaration changes.\n\n\n=========================================\nzope.interface version 3.0.0 (2004/11/07)\n=========================================\n\n- Corresponds to the verison of the zope.interface package shipped as part of\n  the Zope X3.0.0 release.\n\nDetailed Documentation\n**********************\n\n======
 ====\nInterfaces\n==========\n\nInterfaces are objects that specify (document) the external behavior\nof objects that "provide" them.  An interface specifies behavior\nthrough:\n\n- Informal documentation in a doc string\n\n- Attribute definitions\n\n- Invariants, which are conditions that must hold for objects that\n  provide the interface\n\nAttribute definitions specify specific attributes. They define the\nattribute name and provide documentation and constraints of attribute\nvalues.  Attribute definitions can take a number of forms, as we\'ll\nsee below.\n\nDefining interfaces\n===================\n\nInterfaces are defined using Python class statements::\n\n  >>> import zope.interface\n  >>> class IFoo(zope.interface.Interface):\n  ...    """Foo blah blah"""\n  ...\n  ...    x = zope.interface.Attribute("""X blah blah""")\n  ...\n  ...    def bar(q, r=None):\n  ...        """bar blah blah"""\n\nIn the example above, we\'ve created an interface, `IFoo`.  We\nsubclassed `
 zope.interface.Interface`, which is an ancestor interface for\nall interfaces, much as `object` is an ancestor of all new-style\nclasses [#create]_.   The interface is not a class, it\'s an Interface,\nan instance of `InterfaceClass`::\n\n  >>> type(IFoo)\n  <class \'zope.interface.interface.InterfaceClass\'>\n\nWe can ask for the interface\'s documentation::\n\n  >>> IFoo.__doc__\n  \'Foo blah blah\'\n\nand its name::\n\n  >>> IFoo.__name__\n  \'IFoo\'\n\nand even its module::\n\n  >>> IFoo.__module__\n  \'__main__\'\n\nThe interface defined two attributes:\n\n`x`\n  This is the simplest form of attribute definition.  It has a name\n  and a doc string.  It doesn\'t formally specify anything else.\n\n`bar`\n  This is a method.  A method is defined via a function definition.  A\n  method is simply an attribute constrained to be a callable with a\n  particular signature, as provided by the function definition.\n\n  Note that `bar` doesn\'t take a `self` argument.  Interfaces d
 ocument\n  how an object is *used*.  When calling instance methods, you don\'t\n  pass a `self` argument, so a `self` argument isn\'t included in the\n  interface signature.  The `self` argument in instance methods is\n  really an implementation detail of Python instances. Other objects,\n  besides instances can provide interfaces and their methods might not\n  be instance methods. For example, modules can provide interfaces and\n  their methods are usually just functions.  Even instances can have\n  methods that are not instance methods.\n\nYou can access the attributes defined by an interface using mapping\nsyntax::\n\n  >>> x = IFoo[\'x\']\n  >>> type(x)\n  <class \'zope.interface.interface.Attribute\'>\n  >>> x.__name__\n  \'x\'\n  >>> x.__doc__\n  \'X blah blah\'\n\n  >>> IFoo.get(\'x\').__name__\n  \'x\'\n\n  >>> IFoo.get(\'y\')\n\nYou can use `in` to determine if an interface defines a name::\n\n  >>> \'x\' in IFoo\n  True\n\nYou can iterate over interfaces to get the
  names they define::\n\n  >>> names = list(IFoo)\n  >>> names.sort()\n  >>> names\n  [\'bar\', \'x\']\n\nRemember that interfaces aren\'t classes. You can\'t access attribute\ndefinitions as attributes of interfaces::\n\n  >>> IFoo.x\n  Traceback (most recent call last):\n    File "<stdin>", line 1, in ?\n  AttributeError: \'InterfaceClass\' object has no attribute \'x\'\n\nMethods provide access to the method signature::\n\n  >>> bar = IFoo[\'bar\']\n  >>> bar.getSignatureString()\n  \'(q, r=None)\'\n\nTODO\n  Methods really should have a better API.  This is something that\n  needs to be improved.\n\nDeclaring interfaces\n====================\n\nHaving defined interfaces, we can *declare* that objects provide\nthem.  Before we describe the details, lets define some terms:\n\n*provide*\n   We say that objects *provide* interfaces.  If an object provides an\n   interface, then the interface specifies the behavior of the\n   object. In other words, interfaces specify the beha
 vior of the\n   objects that provide them.\n\n*implement*\n   We normally say that classes *implement* interfaces.  If a class\n   implements an interface, then the instances of the class provide\n   the interface.  Objects provide interfaces that their classes\n   implement [#factory]_.  (Objects can provide interfaces directly,\n   in addition to what their classes implement.)\n\n   It is important to note that classes don\'t usually provide the\n   interfaces that they implement.\n\n   We can generalize this to factories.  For any callable object we\n   can declare that it produces objects that provide some interfaces\n   by saying that the factory implements the interfaces.\n\nNow that we\'ve defined these terms, we can talk about the API for\ndeclaring interfaces.\n\nDeclaring implemented interfaces\n--------------------------------\n\nThe most common way to declare interfaces is using the implements\nfunction in a class statement::\n\n  >>> class Foo:\n  ...     zope.i
 nterface.implements(IFoo)\n  ...\n  ...     def __init__(self, x=None):\n  ...         self.x = x\n  ...\n  ...     def bar(self, q, r=None):\n  ...         return q, r, self.x\n  ...\n  ...     def __repr__(self):\n  ...         return "Foo(%s)" % self.x\n\n\nIn this example, we declared that `Foo` implements `IFoo`. This means\nthat instances of `Foo` provide `IFoo`.  Having made this declaration,\nthere are several ways we can introspect the declarations.  First, we\ncan ask an interface whether it is implemented by a class::\n\n  >>> IFoo.implementedBy(Foo)\n  True\n\nAnd we can ask whether an interface is provided by an object::\n\n  >>> foo = Foo()\n  >>> IFoo.providedBy(foo)\n  True\n\nOf course, `Foo` doesn\'t provide `IFoo`, it implements it::\n\n  >>> IFoo.providedBy(Foo)\n  False\n\nWe can also ask what interfaces are implemented by an object::\n\n  >>> list(zope.interface.implementedBy(Foo))\n  [<InterfaceClass __main__.IFoo>]\n\nIt\'s an error to ask for interfa
 ces implemented by a non-callable\nobject::\n\n  >>> IFoo.implementedBy(foo)\n  Traceback (most recent call last):\n  ...\n  TypeError: (\'ImplementedBy called for non-factory\', Foo(None))\n\n  >>> list(zope.interface.implementedBy(foo))\n  Traceback (most recent call last):\n  ...\n  TypeError: (\'ImplementedBy called for non-factory\', Foo(None))\n\nSimilarly, we can ask what interfaces are provided by an object::\n\n  >>> list(zope.interface.providedBy(foo))\n  [<InterfaceClass __main__.IFoo>]\n  >>> list(zope.interface.providedBy(Foo))\n  []\n\nWe can declare interfaces implemented by other factories (besides\nclasses).  We do this using a Python-2.4-style decorator named\n`implementer`.  In versions of Python before 2.4, this looks like::\n\n  >>> def yfoo(y):\n  ...     foo = Foo()\n  ...     foo.y = y\n  ...     return foo\n  >>> yfoo = zope.interface.implementer(IFoo)(yfoo)\n\n  >>> list(zope.interface.implementedBy(yfoo))\n  [<InterfaceClass __main__.IFoo>]\n\nNote
  that the implementer decorator may modify it\'s argument. Callers\nshould not assume that a new object is created.\n\nAlso note that, at least for now, implementer can\'t be used with\nclasses::\n\n  >>> zope.interface.implementer(IFoo)(Foo)\n  ... # doctest: +NORMALIZE_WHITESPACE\n  Traceback (most recent call last):\n    ...\n  TypeError: Can\'t use implementer with classes.\n  Use one of the class-declaration functions instead.\n\nDeclaring provided interfaces\n-----------------------------\n\nWe can declare interfaces directly provided by objects.  Suppose that\nwe want to document what the `__init__` method of the `Foo` class\ndoes.  It\'s not *really* part of `IFoo`.  You wouldn\'t normally call\nthe `__init__` method on Foo instances.  Rather, the `__init__` method\nis part of the `Foo`\'s `__call__` method::\n\n  >>> class IFooFactory(zope.interface.Interface):\n  ...     """Create foos"""\n  ...\n  ...     def __call__(x=None):\n  ...         """Create a foo\n  ...
 \n  ...         The argument provides the initial value for x ...\n  ...         """\n\nIt\'s the class that provides this interface, so we declare the\ninterface on the class::\n\n  >>> zope.interface.directlyProvides(Foo, IFooFactory)\n\nAnd then, we\'ll see that Foo provides some interfaces::\n\n  >>> list(zope.interface.providedBy(Foo))\n  [<InterfaceClass __main__.IFooFactory>]\n  >>> IFooFactory.providedBy(Foo)\n  True\n\nDeclaring class interfaces is common enough that there\'s a special\ndeclaration function for it, `classProvides`, that allows the\ndeclaration from within a class statement::\n\n  >>> class Foo2:\n  ...     zope.interface.implements(IFoo)\n  ...     zope.interface.classProvides(IFooFactory)\n  ...\n  ...     def __init__(self, x=None):\n  ...         self.x = x\n  ...\n  ...     def bar(self, q, r=None):\n  ...         return q, r, self.x\n  ...\n  ...     def __repr__(self):\n  ...         return "Foo(%s)" % self.x\n\n  >>> list(zope.interface.provi
 dedBy(Foo2))\n  [<InterfaceClass __main__.IFooFactory>]\n  >>> IFooFactory.providedBy(Foo2)\n  True\n\nThere\'s a similar function, `moduleProvides`, that supports interface\ndeclarations from within module definitions.  For example, see the use\nof `moduleProvides` call in `zope.interface.__init__`, which declares that\nthe package `zope.interface` provides `IInterfaceDeclaration`.\n\nSometimes, we want to declare interfaces on instances, even though\nthose instances get interfaces from their classes.  Suppose we create\na new interface, `ISpecial`::\n\n  >>> class ISpecial(zope.interface.Interface):\n  ...     reason = zope.interface.Attribute("Reason why we\'re special")\n  ...     def brag():\n  ...         "Brag about being special"\n\nWe can make an existing foo instance special by providing `reason`\nand `brag` attributes::\n\n  >>> foo.reason = \'I just am\'\n  >>> def brag():\n  ...      return "I\'m special!"\n  >>> foo.brag = brag\n  >>> foo.reason\n  \'I just am\
 '\n  >>> foo.brag()\n  "I\'m special!"\n\nand by declaring the interface::\n\n  >>> zope.interface.directlyProvides(foo, ISpecial)\n\nthen the new interface is included in the provided interfaces::\n\n  >>> ISpecial.providedBy(foo)\n  True\n  >>> list(zope.interface.providedBy(foo))\n  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]\n\nWe can find out what interfaces are directly provided by an object::\n\n  >>> list(zope.interface.directlyProvidedBy(foo))\n  [<InterfaceClass __main__.ISpecial>]\n\n  >>> newfoo = Foo()\n  >>> list(zope.interface.directlyProvidedBy(newfoo))\n  []\n\nInherited declarations\n----------------------\n\nNormally, declarations are inherited::\n\n  >>> class SpecialFoo(Foo):\n  ...     zope.interface.implements(ISpecial)\n  ...     reason = \'I just am\'\n  ...     def brag(self):\n  ...         return "I\'m special because %s" % self.reason\n\n  >>> list(zope.interface.implementedBy(SpecialFoo))\n  [<InterfaceClass __main__.ISp
 ecial>, <InterfaceClass __main__.IFoo>]\n\n  >>> list(zope.interface.providedBy(SpecialFoo()))\n  [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]\n\nSometimes, you don\'t want to inherit declarations.  In that case, you\ncan use `implementsOnly`, instead of `implements`::\n\n  >>> class Special(Foo):\n  ...     zope.interface.implementsOnly(ISpecial)\n  ...     reason = \'I just am\'\n  ...     def brag(self):\n  ...         return "I\'m special because %s" % self.reason\n\n  >>> list(zope.interface.implementedBy(Special))\n  [<InterfaceClass __main__.ISpecial>]\n\n  >>> list(zope.interface.providedBy(Special()))\n  [<InterfaceClass __main__.ISpecial>]\n\nExternal declarations\n---------------------\n\nNormally, we make implementation declarations as part of a class\ndefinition. Sometimes, we may want to make declarations from outside\nthe class definition. For example, we might want to declare interfaces\nfor classes that we didn\'t write.  The function
  `classImplements` can\nbe used for this purpose::\n\n  >>> class C:\n  ...     pass\n\n  >>> zope.interface.classImplements(C, IFoo)\n  >>> list(zope.interface.implementedBy(C))\n  [<InterfaceClass __main__.IFoo>]\n\nWe can use `classImplementsOnly` to exclude inherited interfaces::\n\n  >>> class C(Foo):\n  ...     pass\n\n  >>> zope.interface.classImplementsOnly(C, ISpecial)\n  >>> list(zope.interface.implementedBy(C))\n  [<InterfaceClass __main__.ISpecial>]\n\n\n\nDeclaration Objects\n-------------------\n\nWhen we declare interfaces, we create *declaration* objects.  When we\nquery declarations, declaration objects are returned::\n\n  >>> type(zope.interface.implementedBy(Special))\n  <class \'zope.interface.declarations.Implements\'>\n\nDeclaration objects and interface objects are similar in many ways. In\nfact, they share a common base class.  The important thing to realize\nabout them is that they can be used where interfaces are expected in\ndeclarations. Here\'s a
  silly example::\n\n  >>> class Special2(Foo):\n  ...     zope.interface.implementsOnly(\n  ...          zope.interface.implementedBy(Foo),\n  ...          ISpecial,\n  ...          )\n  ...     reason = \'I just am\'\n  ...     def brag(self):\n  ...         return "I\'m special because %s" % self.reason\n\nThe declaration here is almost the same as\n``zope.interface.implements(ISpecial)``, except that the order of\ninterfaces in the resulting declaration is different::\n\n  >>> list(zope.interface.implementedBy(Special2))\n  [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]\n\n\nInterface Inheritance\n=====================\n\nInterfaces can extend other interfaces. They do this simply by listing\nthe other interfaces as base interfaces::\n\n  >>> class IBlat(zope.interface.Interface):\n  ...     """Blat blah blah"""\n  ...\n  ...     y = zope.interface.Attribute("y blah blah")\n  ...     def eek():\n  ...         """eek blah blah"""\n\n  >>> IBlat.__base
 s__\n  (<InterfaceClass zope.interface.Interface>,)\n\n  >>> class IBaz(IFoo, IBlat):\n  ...     """Baz blah"""\n  ...     def eek(a=1):\n  ...         """eek in baz blah"""\n  ...\n\n  >>> IBaz.__bases__\n  (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)\n\n  >>> names = list(IBaz)\n  >>> names.sort()\n  >>> names\n  [\'bar\', \'eek\', \'x\', \'y\']\n\nNote that `IBaz` overrides eek::\n\n  >>> IBlat[\'eek\'].__doc__\n  \'eek blah blah\'\n  >>> IBaz[\'eek\'].__doc__\n  \'eek in baz blah\'\n\nWe were careful to override eek in a compatible way.  When extending\nan interface, the extending interface should be compatible [#compat]_\nwith the extended interfaces.\n\nWe can ask whether one interface extends another::\n\n  >>> IBaz.extends(IFoo)\n  True\n  >>> IBlat.extends(IFoo)\n  False\n\nNote that interfaces don\'t extend themselves::\n\n  >>> IBaz.extends(IBaz)\n  False\n\nSometimes we wish they did, but we can, instead use `isOrExtends`::\n\n  >>> IBaz.isOr
 Extends(IBaz)\n  True\n  >>> IBaz.isOrExtends(IFoo)\n  True\n  >>> IFoo.isOrExtends(IBaz)\n  False\n\nWhen we iterate over an interface, we get all of the names it defines,\nincluding names defined by base interfaces. Sometimes, we want *just*\nthe names defined by the interface directly. We bane use the `names`\nmethod for that::\n\n  >>> list(IBaz.names())\n  [\'eek\']\n\nInheritance of attribute specifications\n---------------------------------------\n\nAn interface may override attribute definitions from base interfaces.\nIf two base interfaces define the same attribute, the attribute is\ninherited from the most specific interface. For example, with::\n\n  >>> class IBase(zope.interface.Interface):\n  ...\n  ...     def foo():\n  ...         "base foo doc"\n\n  >>> class IBase1(IBase):\n  ...     pass\n\n  >>> class IBase2(IBase):\n  ...\n  ...     def foo():\n  ...         "base2 foo doc"\n\n  >>> class ISub(IBase1, IBase2):\n  ...     pass\n\nISub\'s definition of foo 
 is the one from IBase2, since IBase2 is more\nspecific that IBase::\n\n  >>> ISub[\'foo\'].__doc__\n  \'base2 foo doc\'\n\nNote that this differs from a depth-first search.\n\nSometimes, it\'s useful to ask whether an interface defines an\nattribute directly.  You can use the direct method to get a directly\ndefined definitions::\n\n  >>> IBase.direct(\'foo\').__doc__\n  \'base foo doc\'\n\n  >>> ISub.direct(\'foo\')\n\nSpecifications\n--------------\n\nInterfaces and declarations are both special cases of specifications.\nWhat we described above for interface inheritance applies to both\ndeclarations and specifications.  Declarations actually extend the\ninterfaces that they declare::\n\n  >>> class Baz:\n  ...     zope.interface.implements(IBaz)\n\n  >>> baz_implements = zope.interface.implementedBy(Baz)\n  >>> baz_implements.__bases__\n  (<InterfaceClass __main__.IBaz>,)\n\n  >>> baz_implements.extends(IFoo)\n  True\n\n  >>> baz_implements.isOrExtends(IFoo)\n  True\n  >>>
  baz_implements.isOrExtends(baz_implements)\n  True\n\nSpecifications (interfaces and declarations) provide an `__sro__`\nthat lists the specification and all of it\'s ancestors::\n\n  >>> baz_implements.__sro__\n  (<implementedBy __main__.Baz>,\n   <InterfaceClass __main__.IBaz>,\n   <InterfaceClass __main__.IFoo>,\n   <InterfaceClass __main__.IBlat>,\n   <InterfaceClass zope.interface.Interface>)\n\n\nTagged Values\n=============\n\nInterfaces and attribute descriptions support an extension mechanism,\nborrowed from UML, called "tagged values" that lets us store extra\ndata::\n\n  >>> IFoo.setTaggedValue(\'date-modified\', \'2004-04-01\')\n  >>> IFoo.setTaggedValue(\'author\', \'Jim Fulton\')\n  >>> IFoo.getTaggedValue(\'date-modified\')\n  \'2004-04-01\'\n  >>> IFoo.queryTaggedValue(\'date-modified\')\n  \'2004-04-01\'\n  >>> IFoo.queryTaggedValue(\'datemodified\')\n  >>> tags = list(IFoo.getTaggedValueTags())\n  >>> tags.sort()\n  >>> tags\n  [\'author\', \'date-modified
 \']\n\nFunction attributes are converted to tagged values when method\nattribute definitions are created::\n\n  >>> class IBazFactory(zope.interface.Interface):\n  ...     def __call__():\n  ...         "create one"\n  ...     __call__.return_type = IBaz\n\n  >>> IBazFactory[\'__call__\'].getTaggedValue(\'return_type\')\n  <InterfaceClass __main__.IBaz>\n\nTagged values can also be defined from within an interface definition::\n\n  >>> class IWithTaggedValues(zope.interface.Interface):\n  ...     zope.interface.taggedValue(\'squish\', \'squash\')\n  >>> IWithTaggedValues.getTaggedValue(\'squish\')\n  \'squash\'\n\nInvariants\n==========\n\nInterfaces can express conditions that must hold for objects that\nprovide them. These conditions are expressed using one or more\ninvariants.  Invariants are callable objects that will be called with\nan object that provides an interface. An invariant raises an `Invalid`\nexception if the condition doesn\'t hold.  Here\'s an example::\n\n
   >>> class RangeError(zope.interface.Invalid):\n  ...     """A range has invalid limits"""\n  ...     def __repr__(self):\n  ...         return "RangeError(%r)" % self.args\n\n  >>> def range_invariant(ob):\n  ...     if ob.max < ob.min:\n  ...         raise RangeError(ob)\n\nGiven this invariant, we can use it in an interface definition::\n\n  >>> class IRange(zope.interface.Interface):\n  ...     min = zope.interface.Attribute("Lower bound")\n  ...     max = zope.interface.Attribute("Upper bound")\n  ...\n  ...     zope.interface.invariant(range_invariant)\n\nInterfaces have a method for checking their invariants::\n\n  >>> class Range(object):\n  ...     zope.interface.implements(IRange)\n  ...\n  ...     def __init__(self, min, max):\n  ...         self.min, self.max = min, max\n  ...\n  ...     def __repr__(self):\n  ...         return "Range(%s, %s)" % (self.min, self.max)\n\n  >>> IRange.validateInvariants(Range(1,2))\n  >>> IRange.validateInvariants(Range(1,1))\n  >
 >> IRange.validateInvariants(Range(2,1))\n  Traceback (most recent call last):\n  ...\n  RangeError: Range(2, 1)\n\nIf you have multiple invariants, you may not want to stop checking\nafter the first error.  If you pass a list to `validateInvariants`,\nthen a single `Invalid` exception will be raised with the list of\nexceptions as it\'s argument::\n\n  >>> errors = []\n  >>> IRange.validateInvariants(Range(2,1), errors)\n  Traceback (most recent call last):\n  ...\n  Invalid: [RangeError(Range(2, 1))]\n\nAnd the list will be filled with the individual exceptions::\n\n  >>> errors\n  [RangeError(Range(2, 1))]\n\n\n  >>> del errors[:]\n\nAdaptation\n==========\n\nInterfaces can be called to perform adaptation.\n\nThe sematics based on those of the PEP 246 adapt function.\n\nIf an object cannot be adapted, then a TypeError is raised::\n\n  >>> class I(zope.interface.Interface):\n  ...     pass\n\n  >>> I(0)\n  Traceback (most recent call last):\n  ...\n  TypeError: (\'Could no
 t adapt\', 0, <InterfaceClass __main__.I>)\n\n\n\nunless an alternate value is provided as a second positional argument::\n\n  >>> I(0, \'bob\')\n  \'bob\'\n\nIf an object already implements the interface, then it will be returned::\n\n  >>> class C(object):\n  ...     zope.interface.implements(I)\n\n  >>> obj = C()\n  >>> I(obj) is obj\n  True\n\nIf an object implements __conform__, then it will be used::\n\n  >>> class C(object):\n  ...     zope.interface.implements(I)\n  ...     def __conform__(self, proto):\n  ...          return 0\n\n  >>> I(C())\n  0\n\nAdapter hooks (see __adapt__) will also be used, if present::\n\n  >>> from zope.interface.interface import adapter_hooks\n  >>> def adapt_0_to_42(iface, obj):\n  ...     if obj == 0:\n  ...         return 42\n\n  >>> adapter_hooks.append(adapt_0_to_42)\n  >>> I(0)\n  42\n\n  >>> adapter_hooks.remove(adapt_0_to_42)\n  >>> I(0)\n  Traceback (most recent call last):\n  ...\n  TypeError: (\'Could not adapt\', 0, <Interface
 Class __main__.I>)\n\n__adapt__\n---------\n\n  >>> class I(zope.interface.Interface):\n  ...     pass\n\nInterfaces implement the PEP 246 __adapt__ method.\n\nThis method is normally not called directly. It is called by the PEP\n246 adapt framework and by the interface __call__ operator.\n\nThe adapt method is responsible for adapting an object to the\nreciever.\n\nThe default version returns None::\n\n  >>> I.__adapt__(0)\n\nunless the object given provides the interface::\n\n  >>> class C(object):\n  ...     zope.interface.implements(I)\n\n  >>> obj = C()\n  >>> I.__adapt__(obj) is obj\n  True\n\nAdapter hooks can be provided (or removed) to provide custom\nadaptation. We\'ll install a silly hook that adapts 0 to 42.\nWe install a hook by simply adding it to the adapter_hooks\nlist::\n\n  >>> from zope.interface.interface import adapter_hooks\n  >>> def adapt_0_to_42(iface, obj):\n  ...     if obj == 0:\n  ...         return 42\n\n  >>> adapter_hooks.append(adapt_0_to_42)
 \n  >>> I.__adapt__(0)\n  42\n\nHooks must either return an adapter, or None if no adapter can\nbe found.\n\nHooks can be uninstalled by removing them from the list::\n\n  >>> adapter_hooks.remove(adapt_0_to_42)\n  >>> I.__adapt__(0)\n\n\n.. [#create] The main reason we subclass `Interface` is to cause the\n             Python class statement to create an interface, rather\n             than a class.\n\n             It\'s possible to create interfaces by calling a special\n             interface class directly.  Doing this, it\'s possible\n             (and, on rare occasions, useful) to create interfaces\n             that don\'t descend from `Interface`.  Using this\n             technique is beyond the scope of this document.\n\n.. [#factory] Classes are factories.  They can be called to create\n              their instances.  We expect that we will eventually\n              extend the concept of implementation to other kinds of\n              factories, so that we can de
 clare the interfaces\n              provided by the objects created.\n\n.. [#compat] The goal is substitutability.  An object that provides an\n             extending interface should be substitutable for an object\n             that provides the extended interface.  In our example, an\n             object that provides IBaz should be usable whereever an\n             object that provides IBlat is expected.\n\n             The interface implementation doesn\'t enforce this.\n             but maybe it should do some checks.\n\n================\nAdapter Registry\n================\n\nAdapter registries provide a way to register objects that depend on\none or more interface specifications and provide (perhaps indirectly)\nsome interface.  In addition, the registrations have names. (You can\nthink of the names as qualifiers of the provided interfaces.)\n\nThe term "interface specification" refers both to interfaces and to\ninterface declarations, such as declarations of interface
 s implemented\nby a class.\n\n\nSingle Adapters\n===============\n\nLet\'s look at a simple example, using a single required specification::\n\n  >>> from zope.interface.adapter import AdapterRegistry\n  >>> import zope.interface\n\n  >>> class IR1(zope.interface.Interface):\n  ...     pass\n  >>> class IP1(zope.interface.Interface):\n  ...     pass\n  >>> class IP2(IP1):\n  ...     pass\n\n  >>> registry = AdapterRegistry()\n\nWe\'ll register an object that depends on IR1 and "provides" IP2::\n\n  >>> registry.register([IR1], IP2, \'\', 12)\n\nGiven the registration, we can look it up again::\n\n  >>> registry.lookup([IR1], IP2, \'\')\n  12\n\nNote that we used an integer in the example.  In real applications,\none would use some objects that actually depend on or provide\ninterfaces. The registry doesn\'t care about what gets registered, so\nwe\'ll use integers and strings to keep the examples simple. There is\none exception.  Registering a value of None unregisters any\np
 reviously-registered value.\n\nIf an object depends on a specification, it can be looked up with a\nspecification that extends the specification that it depends on::\n\n  >>> class IR2(IR1):\n  ...     pass\n  >>> registry.lookup([IR2], IP2, \'\')\n  12\n\nWe can use a class implementation specification to look up the object::\n\n  >>> class C2:\n  ...     zope.interface.implements(IR2)\n\n  >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, \'\')\n  12\n\n\nand it can be looked up for interfaces that its provided interface\nextends::\n\n  >>> registry.lookup([IR1], IP1, \'\')\n  12\n  >>> registry.lookup([IR2], IP1, \'\')\n  12\n\nBut if you require a specification that doesn\'t extend the specification the\nobject depends on, you won\'t get anything::\n\n  >>> registry.lookup([zope.interface.Interface], IP1, \'\')\n\nBy the way, you can pass a default value to lookup::\n\n  >>> registry.lookup([zope.interface.Interface], IP1, \'\', 42)\n  42\n\nIf you try to get 
 an interface the object doesn\'t provide, you also\nwon\'t get anything::\n\n  >>> class IP3(IP2):\n  ...     pass\n  >>> registry.lookup([IR1], IP3, \'\')\n\nYou also won\'t get anything if you use the wrong name::\n\n  >>> registry.lookup([IR1], IP1, \'bob\')\n  >>> registry.register([IR1], IP2, \'bob\', "Bob\'s 12")\n  >>> registry.lookup([IR1], IP1, \'bob\')\n  "Bob\'s 12"\n\nYou can leave the name off when doing a lookup::\n\n  >>> registry.lookup([IR1], IP1)\n  12\n\nIf we register an object that provides IP1::\n\n  >>> registry.register([IR1], IP1, \'\', 11)\n\nthen that object will be prefered over O(12)::\n\n  >>> registry.lookup([IR1], IP1, \'\')\n  11\n\nAlso, if we register an object for IR2, then that will be prefered\nwhen using IR2::\n\n  >>> registry.register([IR2], IP1, \'\', 21)\n  >>> registry.lookup([IR2], IP1, \'\')\n  21\n\nFinding out what, if anything, is registered\n--------------------------------------------\n\nWe can ask if there is an adapter reg
 istered for a collection of\ninterfaces. This is different than lookup, because it looks for an\nexact match.\n\n  >>> print registry.registered([IR1], IP1)\n  11\n\n  >>> print registry.registered([IR1], IP2)\n  12\n\n  >>> print registry.registered([IR1], IP2, \'bob\')\n  Bob\'s 12\n  \n\n  >>> print registry.registered([IR2], IP1)\n  21\n\n  >>> print registry.registered([IR2], IP2)\n  None\n\nIn the last example, None was returned because nothing was registered\nexactly for the given interfaces.\n\nlookup1\n-------\n\nLookup of single adapters is common enough that there is a specialized\nversion of lookup that takes a single required interface::\n\n  >>> registry.lookup1(IR2, IP1, \'\')\n  21\n  >>> registry.lookup1(IR2, IP1)\n  21\n\nActual Adaptation\n-----------------\n\nThe adapter registry is intended to support adaptation, where one\nobject that implements an interface is adapted to another object that\nsupports a different interface.  The adapter registry support
 s the\ncomputation of adapters. In this case, we have to register adapter\nfactories::\n\n   >>> class IR(zope.interface.Interface):\n   ...     pass\n\n   >>> class X:\n   ...     zope.interface.implements(IR)\n           \n   >>> class Y:\n   ...     zope.interface.implements(IP1)\n   ...     def __init__(self, context):\n   ...         self.context = context\n\n  >>> registry.register([IR], IP1, \'\', Y)\n\nIn this case, we registered a class as the factory. Now we can call\n`queryAdapter` to get the adapted object::\n\n  >>> x = X()\n  >>> y = registry.queryAdapter(x, IP1)\n  >>> y.__class__.__name__\n  \'Y\'\n  >>> y.context is x\n  True\n\nWe can register and lookup by name too::\n\n  >>> class Y2(Y):\n  ...     pass\n\n  >>> registry.register([IR], IP1, \'bob\', Y2)\n  >>> y = registry.queryAdapter(x, IP1, \'bob\')\n  >>> y.__class__.__name__\n  \'Y2\'\n  >>> y.context is x\n  True\n\nWhen the adapter factory produces `None`, then this is treated as if no\nadapter has
  been found. This allows us to prevent adaptation (when desired)\nand let the adapter factory determine whether adaptation is possible based on\nthe state of the object being adapted.\n\n  >>> def factory(context):\n  ...     if context.name == \'object\':\n  ...         return \'adapter\'\n  ...     return None\n\n  >>> class Object(object):\n  ...     zope.interface.implements(IR)\n  ...     name = \'object\'\n\n  >>> registry.register([IR], IP1, \'conditional\', factory) \n  >>> obj = Object()\n  >>> registry.queryAdapter(obj, IP1, \'conditional\')\n  \'adapter\'\n  >>> obj.name = \'no object\'\n  >>> registry.queryAdapter(obj, IP1, \'conditional\') is None\n  True\n  >>> registry.queryAdapter(obj, IP1, \'conditional\', \'default\')\n  \'default\'\n\nAn alternate method that provides the same function as `queryAdapter()` is\n`adapter_hook()`::\n\n  >>> y = registry.adapter_hook(IP1, x)\n  >>> y.__class__.__name__\n  \'Y\'\n  >>> y.context is x\n  True\n  >>> y = registry.
 adapter_hook(IP1, x, \'bob\')\n  >>> y.__class__.__name__\n  \'Y2\'\n  >>> y.context is x\n  True\n\nThe `adapter_hook()` simply switches the order of the object and\ninterface arguments.  It is used to hook into the interface call\nmechanism.\n\n\nDefault Adapters\n----------------\n  \nSometimes, you want to provide an adapter that will adapt anything.\nFor that, provide None as the required interface::\n\n  >>> registry.register([None], IP1, \'\', 1)\n  \nthen we can use that adapter for interfaces we don\'t have specific\nadapters for::\n\n  >>> class IQ(zope.interface.Interface):\n  ...     pass\n  >>> registry.lookup([IQ], IP1, \'\')\n  1\n\nOf course, specific adapters are still used when applicable::\n\n  >>> registry.lookup([IR2], IP1, \'\')\n  21\n\nClass adapters\n--------------\n\nYou can register adapters for class declarations, which is almost the\nsame as registering them for a class::\n\n  >>> registry.register([zope.interface.implementedBy(C2)], IP1, \'\', \
 'C21\')\n  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, \'\')\n  \'C21\'\n\nDict adapters\n-------------\n\nAt some point it was impossible to register dictionary-based adapters due a\nbug. Let\'s make sure this works now:\n\n  >>> adapter = {}\n  >>> registry.register((), IQ, \'\', adapter)\n  >>> registry.lookup((), IQ, \'\') is adapter\n  True\n\nUnregistering\n-------------\n\nYou can unregister by registering None, rather than an object::\n\n  >>> registry.register([zope.interface.implementedBy(C2)], IP1, \'\', None)\n  >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, \'\')\n  21\n\nOf course, this means that None can\'t be registered. This is an\nexception to the statement, made earlier, that the registry doesn\'t\ncare what gets registered.\n\nMulti-adapters\n==============\n\nYou can adapt multiple specifications::\n\n  >>> registry.register([IR1, IQ], IP2, \'\', \'1q2\')\n  >>> registry.lookup([IR1, IQ], IP2, \'\')\n  \'1q2\'\n  >>> regis
 try.lookup([IR2, IQ], IP1, \'\')\n  \'1q2\'\n\n  >>> class IS(zope.interface.Interface):\n  ...     pass\n  >>> registry.lookup([IR2, IS], IP1, \'\')\n\n  >>> class IQ2(IQ):\n  ...     pass\n\n  >>> registry.lookup([IR2, IQ2], IP1, \'\')\n  \'1q2\'\n\n  >>> registry.register([IR1, IQ2], IP2, \'\', \'1q22\')\n  >>> registry.lookup([IR2, IQ2], IP1, \'\')\n  \'1q22\'\n\nMulti-adaptation\n----------------\n\nYou can adapt multiple objects::\n\n  >>> class Q:\n  ...     zope.interface.implements(IQ)\n\nAs with single adapters, we register a factory, which is often a class::\n\n  >>> class IM(zope.interface.Interface):\n  ...     pass\n  >>> class M:\n  ...     zope.interface.implements(IM)\n  ...     def __init__(self, x, q):\n  ...         self.x, self.q = x, q\n  >>> registry.register([IR, IQ], IM, \'\', M)\n\nAnd then we can call `queryMultiAdapter` to compute an adapter::\n\n  >>> q = Q()\n  >>> m = registry.queryMultiAdapter((x, q), IM)\n  >>> m.__class__.__name__\n  \'M\'\n
   >>> m.x is x and m.q is q\n  True\n\nand, of course, we can use names::\n\n  >>> class M2(M):\n  ...     pass\n  >>> registry.register([IR, IQ], IM, \'bob\', M2)\n  >>> m = registry.queryMultiAdapter((x, q), IM, \'bob\')\n  >>> m.__class__.__name__\n  \'M2\'\n  >>> m.x is x and m.q is q\n  True\n  \nDefault Adapters\n----------------\n\nAs with single adapters, you can define default adapters by specifying\nNone for the *first* specification::\n\n  >>> registry.register([None, IQ], IP2, \'\', \'q2\')\n  >>> registry.lookup([IS, IQ], IP2, \'\')\n  \'q2\'\n\nNull Adapters\n=============\n\nYou can also adapt no specification::\n\n  >>> registry.register([], IP2, \'\', 2)\n  >>> registry.lookup([], IP2, \'\')\n  2\n  >>> registry.lookup([], IP1, \'\')\n  2\n\nListing named adapters\n----------------------\n\nAdapters are named. Sometimes, it\'s useful to get all of the named\nadapters for given interfaces::\n\n  >>> adapters = list(registry.lookupAll([IR1], IP1))\n  >>> adapt
 ers.sort()\n  >>> adapters\n  [(u\'\', 11), (u\'bob\', "Bob\'s 12")]\n\nThis works for multi-adapters too::\n\n  >>> registry.register([IR1, IQ2], IP2, \'bob\', \'1q2 for bob\')\n  >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))\n  >>> adapters.sort()\n  >>> adapters\n  [(u\'\', \'1q22\'), (u\'bob\', \'1q2 for bob\')]\n\nAnd even null adapters::\n\n  >>> registry.register([], IP2, \'bob\', 3)\n  >>> adapters = list(registry.lookupAll([], IP1))\n  >>> adapters.sort()\n  >>> adapters\n  [(u\'\', 2), (u\'bob\', 3)]\n\nSubscriptions\n=============\n\nNormally, we want to look up an object that most-closely matches a\nspecification.  Sometimes, we want to get all of the objects that\nmatch some specification.  We use subscriptions for this.  We\nsubscribe objects against specifications and then later find all of\nthe subscribed objects::\n\n  >>> registry.subscribe([IR1], IP2, \'sub12 1\')\n  >>> registry.subscriptions([IR1], IP2)\n  [\'sub12 1\']\n\nNote that, unlike re
 gular adapters, subscriptions are unnamed.\n\nYou can have multiple subscribers for the same specification::\n\n  >>> registry.subscribe([IR1], IP2, \'sub12 2\')\n  >>> registry.subscriptions([IR1], IP2)\n  [\'sub12 1\', \'sub12 2\']\n\nIf subscribers are registered for the same required interfaces, they\nare returned in the order of definition.\n\nYou can register subscribers for all specifications using None::\n\n  >>> registry.subscribe([None], IP1, \'sub_1\')\n  >>> registry.subscriptions([IR2], IP1)\n  [\'sub_1\', \'sub12 1\', \'sub12 2\']\n\nNote that the new subscriber is returned first.  Subscribers defined\nfor less general required interfaces are returned before subscribers\nfor more general interfaces.\n\nSubscriptions may be combined over multiple compatible specifications::\n\n  >>> registry.subscriptions([IR2], IP1)\n  [\'sub_1\', \'sub12 1\', \'sub12 2\']\n  >>> registry.subscribe([IR1], IP1, \'sub11\')\n  >>> registry.subscriptions([IR2], IP1)\n  [\'sub_1\', 
 \'sub12 1\', \'sub12 2\', \'sub11\']\n  >>> registry.subscribe([IR2], IP2, \'sub22\')\n  >>> registry.subscriptions([IR2], IP1)\n  [\'sub_1\', \'sub12 1\', \'sub12 2\', \'sub11\', \'sub22\']\n  >>> registry.subscriptions([IR2], IP2)\n  [\'sub12 1\', \'sub12 2\', \'sub22\']\n\nSubscriptions can be on multiple specifications::\n\n  >>> registry.subscribe([IR1, IQ], IP2, \'sub1q2\')\n  >>> registry.subscriptions([IR1, IQ], IP2)\n  [\'sub1q2\']\n  \nAs with single subscriptions and non-subscription adapters, you can\nspecify None for the first required interface, to specify a default::\n\n  >>> registry.subscribe([None, IQ], IP2, \'sub_q2\')\n  >>> registry.subscriptions([IS, IQ], IP2)\n  [\'sub_q2\']\n  >>> registry.subscriptions([IR1, IQ], IP2)\n  [\'sub_q2\', \'sub1q2\']\n\nYou can have subscriptions that are indepenent of any specifications::\n  \n  >>> list(registry.subscriptions([], IP1))\n  []\n\n  >>> registry.subscribe([], IP2, \'sub2\')\n  >>> registry.subscriptions([]
 , IP1)\n  [\'sub2\']\n  >>> registry.subscribe([], IP1, \'sub1\')\n  >>> registry.subscriptions([], IP1)\n  [\'sub2\', \'sub1\']\n  >>> registry.subscriptions([], IP2)\n  [\'sub2\']\n\nUnregistering subscribers\n-------------------------\n\nWe can unregister subscribers.  When unregistering a subscriber, we\ncan unregister a specific subscriber::\n\n  >>> registry.unsubscribe([IR1], IP1, \'sub11\')\n  >>> registry.subscriptions([IR1], IP1)\n  [\'sub_1\', \'sub12 1\', \'sub12 2\']\n\nIf we don\'t specify a value, then all subscribers matching the given\ninterfaces will be unsubscribed:\n\n  >>> registry.unsubscribe([IR1], IP2)\n  >>> registry.subscriptions([IR1], IP1)\n  [\'sub_1\']\n\n\nSubscription adapters\n---------------------\n\nWe normally register adapter factories, which then allow us to compute\nadapters, but with subscriptions, we get multiple adapters.  Here\'s an\nexample of multiple-object subscribers::\n\n  >>> registry.subscribe([IR, IQ], IM, M)\n  >>> registr
 y.subscribe([IR, IQ], IM, M2)\n\n  >>> subscribers = registry.subscribers((x, q), IM)\n  >>> len(subscribers)\n  2\n  >>> class_names = [s.__class__.__name__ for s in subscribers]\n  >>> class_names.sort()\n  >>> class_names\n  [\'M\', \'M2\']\n  >>> [(s.x is x and s.q is q) for s in subscribers]\n  [True, True]\n\nadapter factory subcribers can\'t return None values::\n\n  >>> def M3(x, y):\n  ...     return None\n\n  >>> registry.subscribe([IR, IQ], IM, M3)\n  >>> subscribers = registry.subscribers((x, q), IM)\n  >>> len(subscribers)\n  2\n\nHandlers\n--------\n\nA handler is a subscriber factory that doesn\'t produce any normal\noutput.  It returns None.  A handler is unlike adapters in that it does\nall of its work when the factory is called.\n\nTo register a handler, simply provide None as the provided interface::\n\n  >>> def handler(event):\n  ...     print \'handler\', event\n\n  >>> registry.subscribe([IR1], None, handler)\n  >>> registry.subscriptions([IR1], None) 
 == [handler]\n  True\n\n==========================\nUsing the Adapter Registry\n==========================\n\nThis is a small demonstration of the ``zope.interface`` package including its\nadapter registry. It is intended to provide a concrete but narrow example on\nhow to use interfaces and adapters outside of Zope 3.\n\nFirst we have to import the interface package::\n\n  >>> import zope.interface\n\nWe now develop an interface for our object, which is a simple file in this\ncase. For now we simply support one attribute, the body, which contains the\nactual file contents::\n\n  >>> class IFile(zope.interface.Interface):\n  ...\n  ...     body = zope.interface.Attribute(\'Contents of the file.\')\n  ...\n\nFor statistical reasons we often want to know the size of a file. However, it\nwould be clumsy to implement the size directly in the file object, since the\nsize really represents meta-data. Thus we create another interface that\nprovides the size of something::\n\n  >>> 
 class ISize(zope.interface.Interface):\n  ...\n  ...     def getSize():\n  ...         \'Return the size of an object.\'\n  ...\n\nNow we need to implement the file. It is essential that the object states\nthat it implements the `IFile` interface. We also provide a default body\nvalue (just to make things simpler for this example)::\n\n  >>> class File(object):\n  ...\n  ...      zope.interface.implements(IFile)\n  ...      body = \'foo bar\'\n  ...\n\nNext we implement an adapter that can provide the `ISize` interface given any\nobject providing `IFile`. By convention we use `__used_for__` to specify the\ninterface that we expect the adapted object to provide, in our case\n`IFile`. However, this attribute is not used for anything. If you have\nmultiple interfaces for which an adapter is used, just specify the interfaces\nvia a tuple.\n\nAgain by convention, the constructor of an adapter takes one argument, the\ncontext. The context in this case is an instance of `File` (pro
 viding `IFile`)\nthat is used to extract the size from. Also by convention the context is\nstored in an attribute named `context` on the adapter. The twisted community\nrefers to the context as the `original` object. However, you may feel free to\nuse a specific argument name, such as `file`::\n\n  >>> class FileSize(object):\n  ...\n  ...      zope.interface.implements(ISize)\n  ...      __used_for__ = IFile\n  ...\n  ...      def __init__(self, context):\n  ...          self.context = context\n  ...\n  ...      def getSize(self):\n  ...          return len(self.context.body)\n  ...\n\nNow that we have written our adapter, we have to register it with an adapter\nregistry, so that it can be looked up when needed. There is no such thing as a\nglobal registry; thus we have to instantiate one for our example manually::\n\n  >>> from zope.interface.adapter import AdapterRegistry\n  >>> registry = AdapterRegistry()\n\n\nThe registry keeps a map of what adapters implement based on
  another\ninterface, the object already provides. Therefore, we next have to register an\nadapter that adapts from `IFile` to `ISize`. The first argument to\nthe registry\'s `register()` method is a list of original interfaces.In our\ncause we have only one original interface, `IFile`. A list makes sense, since\nthe interface package has the concept of multi-adapters, which are adapters\nthat require multiple objects to adapt to a new interface. In these\nsituations, your adapter constructor will require an argument for each\nspecified interface.\n\nThe second argument is the interface the adapter provides, in our case\n`ISize`. The third argument is the name of the adapter. Since we do not care\nabout names, we simply leave it as an empty string. Names are commonly useful,\nif you have adapters for the same set of interfaces, but they are useful in\ndifferent situations. The last argument is simply the adapter class::\n\n  >>> registry.register([IFile], ISize, \'\', FileSiz
 e)\n\nYou can now use the the registry to lookup the adapter::\n\n  >>> registry.lookup1(IFile, ISize, \'\')\n  <class \'__main__.FileSize\'>\n\nLet\'s get a little bit more practical. Let\'s create a `File` instance and\ncreate the adapter using a registry lookup. Then we see whether the adapter\nreturns the correct size by calling `getSize()`::\n\n  >>> file = File()\n  >>> size = registry.lookup1(IFile, ISize, \'\')(file)\n  >>> size.getSize()\n  7\n\nHowever, this is not very practical, since I have to manually pass in the\narguments to the lookup method. There is some syntactic candy that will allow\nus to get an adapter instance by simply calling `ISize(file)`. To make use of\nthis functionality, we need to add our registry to the adapter_hooks list,\nwhich is a member of the adapters module. This list stores a collection of\ncallables that are automatically invoked when IFoo(obj) is called; their\npurpose is to locate adapters that implement an interface for a certain
 \ncontext instance.\n\nYou are required to implement your own adapter hook; this example covers one\nof the simplest hooks that use the registry, but you could implement one that\nused an adapter cache or persistent adapters, for instance. The helper hook is\nrequired to expect as first argument the desired output interface (for us\n`ISize`) and as the second argument the context of the adapter (here\n`file`). The function returns an adapter, i.e. a `FileSize` instance::\n\n  >>> def hook(provided, object):\n  ...     adapter = registry.lookup1(zope.interface.providedBy(object),\n  ...                                provided, \'\')\n  ...     return adapter(object)\n  ...\n\nWe now just add the hook to an `adapter_hooks` list::\n\n  >>> from zope.interface.interface import adapter_hooks\n  >>> adapter_hooks.append(hook)\n\nOnce the hook is registered, you can use the desired syntax::\n\n  >>> size = ISize(file)\n  >>> size.getSize()\n  7\n\nNow we have to cleanup after ourse
 lves, so that others after us have a clean\n`adapter_hooks` list::\n\n  >>> adapter_hooks.remove(hook)\n\nThat\'s it. I have intentionally left out a discussion of named adapters and\nmulti-adapters, since this text is intended as a practical and simple\nintroduction to Zope 3 interfaces and adapters. You might want to read the\n`adapter.txt` in the `zope.interface` package for a more formal, referencial\nand complete treatment of the package. Warning: People have reported that\n`adapter.txt` makes their brain feel soft!\n\nDownload\n**********************'
+p115
+sS'_pypi_ordering'
+p116
+I17
+sS'classifiers'
+p117
+(lp118
+sS'name'
+p119
+S'zope.interface'
+p120
+sS'license'
+p121
+S'ZPL 2.1'
+p122
+sS'summary'
+p123
+S'Zope 3 Interface Infrastructure'
+p124
+sS'home_page'
+p125
+S'http://www.python.org/pypi/zope.interface'
+p126
+sS'stable_version'
+p127
+NsS'requires'
+p128
+(lp129
+sS'cheesecake_installability_id'
+p130
+Nss(S'z3c.formdemo'
+p131
+S'1.1.0'
+p132
+tp133
+(dp134
+S'maintainer'
+p135
+NsS'maintainer_email'
+p136
+NsS'cheesecake_code_kwalitee_id'
+p137
+I5913
+sS'keywords'
+p138
+S'zope3 form widget'
+p139
+sS'author'
+p140
+S'Stephan Richter, Roger Ineichen and the Zope Community'
+p141
+sS'author_email'
+p142
+S'zope3-dev at zope.org'
+p143
+sS'download_url'
+p144
+S'UNKNOWN'
+p145
+sS'platform'
+p146
+S'UNKNOWN'
+p147
+sS'version'
+p148
+S'1.1.0'
+p149
+sS'obsoletes'
+p150
+(lp151
+sS'provides'
+p152
+(lp153
+sS'cheesecake_documentation_id'
+p154
+I5912
+sS'_pypi_hidden'
+p155
+I1
+sS'description'
+p156
+S'=====================================================\nDemo Applications for ``z3c.form`` and ``z3c.formui``\n=====================================================\n\nThis package contains several small demo applications for the ``z3c.form`` and\n``z3c.formui`` packages.\n\n* TABLE- versus DIV-based layout of all widgets.\n\n* A simple Hello World message application demonstrating the easiest way to\n  write add, edit and display forms.\n\n* A simple calculator showing the flexibility of the new action declaration\n  framework by declaring different classes of buttons.\n\n* A linear wizard shows off the sub-form capabilities of z3c.form. It also\n  demonstrates how one can overcome the short-coming of an object widget.\n\n* A simple table/spreadsheet that allows adding and editing as simple content\n  object. This demo also shows the usage of forms and ``zc.table`` at the same\n  time.\n\nRunning the Demo out of the box\n-------------------------------\n\nYou can also run 
 the demo directly without manually installing Zope 3::\n\n  $ svn co svn://svn.zope.org/repos/main/z3c.formdemo/trunk formdemo\n  $ cd formdemo\n  $ python bootstrap.py\n  $ ./bin/buildout\n  $ ./bin/demo fg\n\nThen access the demo site using:\n\n  http://localhost:8080/\n\n\n=======\nCHANGES\n=======\n\nVersion 1.1.0 (6/22/2007)\n-------------------------\n\n- Feature: New "SQL Message" demo shows how ``z3c.form`` can be used with\n  non-object data. Specificically, this small application demonstrates using a\n  Gadfly database using pure SQL calls without any ORM.\n\n- Feature: New "Address Book" demo that demonstrates more complex use cases,\n  such as subforms, composite widgets, and mappings/lists\n\n\nVersion 1.0.0 (5/24/2007)\n-------------------------\n\n- Initial Release'
+p157
+sS'_pypi_ordering'
+p158
+I103
+sS'classifiers'
+p159
+(lp160
+S'Development Status :: 4 - Beta'
+p161
+aS'Environment :: Web Environment'
+p162
+aS'Framework :: Zope3'
+p163
+aS'Intended Audience :: Developers'
+p164
+aS'License :: OSI Approved :: Zope Public License'
+p165
+aS'Natural Language :: English'
+p166
+aS'Operating System :: OS Independent'
+p167
+aS'Programming Language :: Python'
+p168
+aS'Topic :: Internet :: WWW/HTTP'
+p169
+asS'name'
+p170
+S'z3c.formdemo'
+p171
+sS'license'
+p172
+S'ZPL 2.1'
+p173
+sS'summary'
+p174
+S'A set of demo applications for z3c.form and z3c.formui'
+p175
+sS'home_page'
+p176
+S'http://svn.zope.org/z3c.formdemo'
+p177
+sS'stable_version'
+p178
+NsS'requires'
+p179
+(lp180
+sS'cheesecake_installability_id'
+p181
+I5911
+ss.
\ No newline at end of file

Modified: zope.kgs/trunk/src/zope/kgs/tests.py
===================================================================
--- zope.kgs/trunk/src/zope/kgs/tests.py	2008-12-07 00:05:53 UTC (rev 93733)
+++ zope.kgs/trunk/src/zope/kgs/tests.py	2008-12-07 00:07:26 UTC (rev 93734)
@@ -16,7 +16,8 @@
 $Id$
 """
 __docformat__ = 'restructuredtext'
-
+import os
+import pickle
 import unittest
 import urllib2
 import xmlrpclib
@@ -29,7 +30,7 @@
 class FakeServer(object):
     """Pretend Cheeseshop XML-RPC server."""
 
-    testdata = {
+    url_data = {
         ('z3c.formdemo', '1.1.0'): [
             dict(url="http://pypi.python.org/packages/2.4/z/z3c.formdemo/z3c.formdemo-1.1.0-py2.4.egg",
                  md5_digest="9d605bd559ea33ac57ce11f5c80fa3d3",
@@ -61,13 +62,20 @@
         ],
     }
 
+    releasedata = None
+
     def __init__(self, url):
-        pass
+        self.releasedata = pickle.load(
+            open(os.path.join(os.path.dirname(__file__),
+                              'release_data.dat'), 'r'))
 
     def package_urls(self, package_name, version):
-        return self.testdata.get((package_name, version), [])
+        return self.url_data.get((package_name, version), [])
 
+    def release_data(self, package_name, version):
+        return self.releasedata.get((package_name, version), [])
 
+
 testpages = {
 
     'http://cheeseshop.python.org/simple/PIL/': '''\



More information about the Checkins mailing list