summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTres Seaver <tseaver@palladion.com>2012-06-29 14:47:56 +0000
committerTres Seaver <tseaver@palladion.com>2012-06-29 14:47:56 +0000
commit2e39b26054c8c1da36886b7ba8ba0d346d62d2d7 (patch)
tree370e3c664f4bec9fb91effde230daf4cd56c6688 /src
parent33d9fc041301b310e4cf28f8e28b0f915c58d4fd (diff)
downloadzope-component-2e39b26054c8c1da36886b7ba8ba0d346d62d2d7.tar.gz
Merge tseaver-test_cleanup branch.
Diffstat (limited to 'src')
-rw-r--r--src/zope/component/README.txt402
-rw-r--r--src/zope/component/_api.py32
-rw-r--r--src/zope/component/_compat.py42
-rw-r--r--src/zope/component/_declaration.py16
-rw-r--r--src/zope/component/configure.txt13
-rw-r--r--src/zope/component/event.py24
-rw-r--r--src/zope/component/event.txt142
-rw-r--r--src/zope/component/eventtesting.py16
-rw-r--r--src/zope/component/factory.py8
-rw-r--r--src/zope/component/factory.txt131
-rw-r--r--src/zope/component/globalregistry.py21
-rw-r--r--src/zope/component/hooks.py50
-rw-r--r--src/zope/component/hooks.txt97
-rw-r--r--src/zope/component/index.txt22
-rw-r--r--src/zope/component/interface.py160
-rw-r--r--src/zope/component/interfaces.py13
-rw-r--r--src/zope/component/nexttesting.py104
-rw-r--r--src/zope/component/persistentregistry.py21
-rw-r--r--src/zope/component/persistentregistry.txt6
-rw-r--r--src/zope/component/registry.txt1117
-rw-r--r--src/zope/component/security.py93
-rw-r--r--src/zope/component/socketexample.txt597
-rw-r--r--src/zope/component/standalonetests.py93
-rw-r--r--src/zope/component/testfiles/adapter.py31
-rw-r--r--src/zope/component/testfiles/components.py14
-rw-r--r--src/zope/component/testfiles/views.py9
-rw-r--r--src/zope/component/testing.py12
-rw-r--r--src/zope/component/testlayer.py7
-rw-r--r--src/zope/component/testlayer.txt100
-rw-r--r--src/zope/component/tests.py1748
-rw-r--r--src/zope/component/tests/__init__.py1
-rw-r--r--src/zope/component/tests/examples.py150
-rw-r--r--src/zope/component/tests/test___init__.py92
-rw-r--r--src/zope/component/tests/test__api.py1204
-rw-r--r--src/zope/component/tests/test__declaration.py221
-rw-r--r--src/zope/component/tests/test_event.py66
-rw-r--r--src/zope/component/tests/test_factory.py111
-rw-r--r--src/zope/component/tests/test_globalregistry.py251
-rw-r--r--src/zope/component/tests/test_hookable.py141
-rw-r--r--src/zope/component/tests/test_hooks.py344
-rw-r--r--src/zope/component/tests/test_interface.py397
-rw-r--r--src/zope/component/tests/test_persistentregistry.py151
-rw-r--r--src/zope/component/tests/test_registry.py131
-rw-r--r--src/zope/component/tests/test_security.py249
-rw-r--r--src/zope/component/tests/test_standalone.py52
-rw-r--r--src/zope/component/tests/test_zcml.py1141
-rw-r--r--src/zope/component/zcml.py252
-rw-r--r--src/zope/component/zcml.txt1021
-rw-r--r--src/zope/component/zcml_conditional.txt612
49 files changed, 5078 insertions, 6650 deletions
diff --git a/src/zope/component/README.txt b/src/zope/component/README.txt
deleted file mode 100644
index ed43ad2..0000000
--- a/src/zope/component/README.txt
+++ /dev/null
@@ -1,402 +0,0 @@
-Zope Component Architecture
-===========================
-
-This package, together with `zope.interface`, provides facilities for
-defining, registering and looking up components. There are two basic
-kinds of components: adapters and utilities.
-
-Utilities
----------
-
-Utilities are just components that provide an interface and that are
-looked up by an interface and a name. Let's look at a trivial utility
-definition:
-
- >>> from zope import interface
-
- >>> class IGreeter(interface.Interface):
- ... def greet():
- ... "say hello"
-
- >>> class Greeter:
- ... interface.implements(IGreeter)
- ...
- ... def __init__(self, other="world"):
- ... self.other = other
- ...
- ... def greet(self):
- ... print "Hello", self.other
-
-We can register an instance this class using `provideUtility` [1]_:
-
- >>> from zope import component
- >>> greet = Greeter('bob')
- >>> component.provideUtility(greet, IGreeter, 'robert')
-
-In this example we registered the utility as providing the `IGreeter`
-interface with a name of 'bob'. We can look the interface up with
-either `queryUtility` or `getUtility`:
-
- >>> component.queryUtility(IGreeter, 'robert').greet()
- Hello bob
-
- >>> component.getUtility(IGreeter, 'robert').greet()
- Hello bob
-
-`queryUtility` and `getUtility` differ in how failed lookups are handled:
-
- >>> component.queryUtility(IGreeter, 'ted')
- >>> component.queryUtility(IGreeter, 'ted', 42)
- 42
- >>> component.getUtility(IGreeter, 'ted')
- ... # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<InterfaceClass ...IGreeter>, 'ted')
-
-If a component provides only one interface, as in the example above,
-then we can omit the provided interface from the call to `provideUtility`:
-
- >>> ted = Greeter('ted')
- >>> component.provideUtility(ted, name='ted')
- >>> component.queryUtility(IGreeter, 'ted').greet()
- Hello ted
-
-The name defaults to an empty string:
-
- >>> world = Greeter()
- >>> component.provideUtility(world)
- >>> component.queryUtility(IGreeter).greet()
- Hello world
-
-Adapters
---------
-
-Adapters are components that are computed from other components to
-adapt them to some interface. Because they are computed from other
-objects, they are provided as factories, usually classes. Here, we'll
-create a greeter for persons, so we can provide personalized greetings
-for different people:
-
- >>> class IPerson(interface.Interface):
- ... name = interface.Attribute("Name")
-
- >>> class PersonGreeter:
- ...
- ... component.adapts(IPerson)
- ... interface.implements(IGreeter)
- ...
- ... def __init__(self, person):
- ... self.person = person
- ...
- ... def greet(self):
- ... print "Hello", self.person.name
-
-The class defines a constructor that takes an argument for every
-object adapted.
-
-We used `component.adapts` to declare what we adapt. We can find
-out if an object declares that it adapts anything using adaptedBy:
-
- >>> list(component.adaptedBy(PersonGreeter)) == [IPerson]
- True
-
-If an object makes no declaration, then None is returned:
-
- >>> component.adaptedBy(Greeter()) is None
- True
-
-
-If we declare the interfaces adapted and if we provide only one
-interface, as in the example above, then we can provide the adapter
-very simply [1]_:
-
- >>> component.provideAdapter(PersonGreeter)
-
-For adapters that adapt a single interface to a single interface
-without a name, we can get the adapter by simply calling the
-interface:
-
- >>> class Person:
- ... interface.implements(IPerson)
- ...
- ... def __init__(self, name):
- ... self.name = name
-
- >>> IGreeter(Person("Sally")).greet()
- Hello Sally
-
-We can also provide arguments to be very specific about what
-how to register the adapter.
-
- >>> class BobPersonGreeter(PersonGreeter):
- ... name = 'Bob'
- ... def greet(self):
- ... print "Hello", self.person.name, "my name is", self.name
-
- >>> component.provideAdapter(
- ... BobPersonGreeter, [IPerson], IGreeter, 'bob')
-
-The arguments can also be provided as keyword arguments:
-
- >>> class TedPersonGreeter(BobPersonGreeter):
- ... name = "Ted"
-
- >>> component.provideAdapter(
- ... factory=TedPersonGreeter, adapts=[IPerson],
- ... provides=IGreeter, name='ted')
-
-For named adapters, use `queryAdapter`, or `getAdapter`:
-
- >>> component.queryAdapter(Person("Sally"), IGreeter, 'bob').greet()
- Hello Sally my name is Bob
-
- >>> component.getAdapter(Person("Sally"), IGreeter, 'ted').greet()
- Hello Sally my name is Ted
-
-If an adapter can't be found, `queryAdapter` returns a default value
-and `getAdapter` raises an error:
-
- >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank')
- >>> component.queryAdapter(Person("Sally"), IGreeter, 'frank', 42)
- 42
- >>> component.getAdapter(Person("Sally"), IGreeter, 'frank')
- ... # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ...
- ComponentLookupError: (...Person...>, <...IGreeter>, 'frank')
-
-Adapters can adapt multiple objects:
-
- >>> class TwoPersonGreeter:
- ...
- ... component.adapts(IPerson, IPerson)
- ... interface.implements(IGreeter)
- ...
- ... def __init__(self, person, greeter):
- ... self.person = person
- ... self.greeter = greeter
- ...
- ... def greet(self):
- ... print "Hello", self.person.name
- ... print "my name is", self.greeter.name
-
- >>> component.provideAdapter(TwoPersonGreeter)
-
-Note that the declaration-order of the Interfaces beeing adapted to is
-important for adapter look up. It must be the the same as the order of
-parameters given to the adapter and used to query the adapter. This is
-especially the case when different Interfaces are adapt to (opposed to
-this example).
-
-To look up a multi-adapter, use either `queryMultiAdapter` or
-`getMultiAdapter`:
-
- >>> component.queryMultiAdapter((Person("Sally"), Person("Bob")),
- ... IGreeter).greet()
- Hello Sally
- my name is Bob
-
-Adapters need not be classes. Any callable will do. We use the
-adapter decorator (in the Python 2.4 decorator sense) to declare that
-a callable object adapts some interfaces (or classes):
-
- >>> class IJob(interface.Interface):
- ... "A job"
-
- >>> class Job:
- ... interface.implements(IJob)
-
- >>> def personJob(person):
- ... return getattr(person, 'job', None)
- >>> personJob = interface.implementer(IJob)(personJob)
- >>> personJob = component.adapter(IPerson)(personJob)
-
-In Python 2.4, the example can be written:
-
- >>> @interface.implementer(IJob)
- ... @component.adapter(IPerson)
- ... def personJob(person):
- ... return getattr(person, 'job', None)
-
-which looks a bit nicer.
-
-In this example, the personJob function simply returns the person's
-`job` attribute if present, or None if it's not present. An adapter
-factory can return None to indicate that adaptation wasn't possible.
-Let's register this adapter and try it out:
-
- >>> component.provideAdapter(personJob)
- >>> sally = Person("Sally")
- >>> IJob(sally) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt', ...
-
-The adaptation failed because sally didn't have a job. Let's give her
-one:
-
- >>> job = Job()
- >>> sally.job = job
- >>> IJob(sally) is job
- True
-
-Subscription Adapters
----------------------
-
-Unlike regular adapters, subscription adapters are used when we want
-all of the adapters that adapt an object to a particular adapter.
-
-Consider a validation problem. We have objects and we want to assess
-whether they meet some sort of standards. We define a validation
-interface:
-
- >>> class IValidate(interface.Interface):
- ... def validate(ob):
- ... """Determine whether the object is valid
- ...
- ... Return a string describing a validation problem.
- ... An empty string is returned to indicate that the
- ... object is valid.
- ... """
-
-Perhaps we have documents:
-
- >>> class IDocument(interface.Interface):
- ... summary = interface.Attribute("Document summary")
- ... body = interface.Attribute("Document text")
-
- >>> class Document:
- ... interface.implements(IDocument)
- ... def __init__(self, summary, body):
- ... self.summary, self.body = summary, body
-
-Now, we may want to specify various validation rules for
-documents. For example, we might require that the summary be a single
-line:
-
- >>> class SingleLineSummary:
- ... component.adapts(IDocument)
- ... interface.implements(IValidate)
- ...
- ... def __init__(self, doc):
- ... self.doc = doc
- ...
- ... def validate(self):
- ... if '\n' in self.doc.summary:
- ... return 'Summary should only have one line'
- ... else:
- ... return ''
-
-Or we might require the body to be at least 1000 characters in length:
-
- >>> class AdequateLength:
- ... component.adapts(IDocument)
- ... interface.implements(IValidate)
- ...
- ... def __init__(self, doc):
- ... self.doc = doc
- ...
- ... def validate(self):
- ... if len(self.doc.body) < 1000:
- ... return 'too short'
- ... else:
- ... return ''
-
-We can register these as subscription adapters [1]_:
-
- >>> component.provideSubscriptionAdapter(SingleLineSummary)
- >>> component.provideSubscriptionAdapter(AdequateLength)
-
-We can then use the subscribers to validate objects:
-
- >>> doc = Document("A\nDocument", "blah")
- >>> [adapter.validate()
- ... for adapter in component.subscribers([doc], IValidate)
- ... if adapter.validate()]
- ['Summary should only have one line', 'too short']
-
- >>> doc = Document("A\nDocument", "blah" * 1000)
- >>> [adapter.validate()
- ... for adapter in component.subscribers([doc], IValidate)
- ... if adapter.validate()]
- ['Summary should only have one line']
-
- >>> doc = Document("A Document", "blah")
- >>> [adapter.validate()
- ... for adapter in component.subscribers([doc], IValidate)
- ... if adapter.validate()]
- ['too short']
-
-Handlers
---------
-
-Handlers are subscription adapter factories that don't produce
-anything. They do all of their work when called. Handlers
-are typically used to handle events.
-
-Event subscribers are different from other subscription adapters in
-that the caller of event subscribers doesn't expect to interact with
-them in any direct way. For example, an event publisher doesn't
-expect to get any return value. Because subscribers don't need to
-provide an API to their callers, it is more natural to define them
-with functions, rather than classes. For example, in a
-document-management system, we might want to record creation times for
-documents:
-
- >>> import datetime
-
- >>> def documentCreated(event):
- ... event.doc.created = datetime.datetime.utcnow()
-
-In this example, we have a function that takes an event and performs
-some processing. It doesn't actually return anything. This is a
-special case of a subscription adapter that adapts an event to
-nothing. All of the work is done when the adapter "factory" is
-called. We call subscribers that don't actually create anything
-"handlers". There are special APIs for registering and calling
-them.
-
-To register the subscriber above, we define a document-created event:
-
- >>> class IDocumentCreated(interface.Interface):
- ... doc = interface.Attribute("The document that was created")
-
- >>> class DocumentCreated:
- ... interface.implements(IDocumentCreated)
- ...
- ... def __init__(self, doc):
- ... self.doc = doc
-
-We'll also change our handler definition to:
-
- >>> def documentCreated(event):
- ... event.doc.created = datetime.datetime.utcnow()
-
- >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)
-
-Note that in Python 2.4, this can be written:
-
- >>> @component.adapter(IDocumentCreated)
- ... def documentCreated(event):
- ... event.doc.created = datetime.datetime.utcnow()
-
-This marks the handler as an adapter of `IDocumentCreated` events.
-
-Now we'll register the handler [1]_:
-
- >>> component.provideHandler(documentCreated)
-
-Now, if we can create an event and use the `handle` function to call
-handlers registered for the event:
-
- >>> component.handle(DocumentCreated(doc))
- >>> doc.created.__class__.__name__
- 'datetime'
-
-
-
-.. [1] CAUTION: This API should only be used from test or
- application-setup code. This API shouldn't be used by regular
- library modules, as component registration is a configuration
- activity.
diff --git a/src/zope/component/_api.py b/src/zope/component/_api.py
index 4cf573c..0ceba76 100644
--- a/src/zope/component/_api.py
+++ b/src/zope/component/_api.py
@@ -25,6 +25,7 @@ from zope.component.interfaces import IComponentRegistrationConvenience
from zope.component.interfaces import IFactory
from zope.component.interfaces import ComponentLookupError
from zope.component.interfaces import IComponentLookup
+from zope.component._compat import _BLANK
from zope.component._declaration import adaptedBy
from zope.component._declaration import adapter
from zope.component._declaration import adapts
@@ -33,7 +34,7 @@ from zope.component._declaration import adapts
# to our Python version if not.
try:
from zope.hookable import hookable
-except ImportError:
+except ImportError: #pragma NO COVER
from zope.component.hookable import hookable
# getSiteManager() returns a component registry. Although the term
@@ -42,6 +43,8 @@ except ImportError:
base = None
@hookable
def getSiteManager(context=None):
+ """ See IComponentArchitecture.
+ """
global base
if context is None:
if base is None:
@@ -52,7 +55,7 @@ def getSiteManager(context=None):
# to avoid the recursion implied by using a local `getAdapter()` call.
try:
return IComponentLookup(context)
- except TypeError, error:
+ except TypeError as error:
raise ComponentLookupError(*error.args)
# Adapter API
@@ -90,26 +93,26 @@ def queryAdapterInContext(object, interface, context, default=None):
return getSiteManager(context).queryAdapter(object, interface, '', default)
-def getAdapter(object, interface=Interface, name=u'', context=None):
+def getAdapter(object, interface=Interface, name=_BLANK, context=None):
adapter = queryAdapter(object, interface, name, None, context)
if adapter is None:
raise ComponentLookupError(object, interface, name)
return adapter
-def queryAdapter(object, interface=Interface, name=u'', default=None,
+def queryAdapter(object, interface=Interface, name=_BLANK, default=None,
context=None):
if context is None:
return adapter_hook(interface, object, name, default)
return getSiteManager(context).queryAdapter(object, interface, name,
default)
-def getMultiAdapter(objects, interface=Interface, name=u'', context=None):
+def getMultiAdapter(objects, interface=Interface, name=_BLANK, context=None):
adapter = queryMultiAdapter(objects, interface, name, context=context)
if adapter is None:
raise ComponentLookupError(objects, interface, name)
return adapter
-def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
+def queryMultiAdapter(objects, interface=Interface, name=_BLANK, default=None,
context=None):
try:
sitemanager = getSiteManager(context)
@@ -136,10 +139,7 @@ def subscribers(objects, interface, context=None):
return sitemanager.subscribers(objects, interface)
def handle(*objects):
- sitemanager = getSiteManager(None)
- # iterating over subscribers assures they get executed
- for ignored in sitemanager.subscribers(objects, None):
- pass
+ getSiteManager(None).subscribers(objects, None)
#############################################################################
# Register the component architectures adapter hook, with the adapter hook
@@ -150,7 +150,7 @@ def handle(*objects):
def adapter_hook(interface, object, name='', default=None):
try:
sitemanager = getSiteManager()
- except ComponentLookupError:
+ except ComponentLookupError: #pragma NO COVER w/o context, cannot test
# Oh blast, no site manager. This should *never* happen!
return None
return sitemanager.queryAdapter(object, interface, name, default)
@@ -216,13 +216,23 @@ def getNextUtility(context, interface, name=''):
# Factories
def createObject(__factory_name, *args, **kwargs):
+ """Invoke the named factory and return the result.
+
+ ``__factory_name`` is a positional-only argument.
+ """
context = kwargs.pop('context', None)
return getUtility(IFactory, __factory_name, context)(*args, **kwargs)
def getFactoryInterfaces(name, context=None):
+ """Return the interface provided by the named factory's objects
+
+ Result might be a single interface. XXX
+ """
return getUtility(IFactory, name, context).getInterfaces()
def getFactoriesFor(interface, context=None):
+ """Return info on all factories implementing the given interface.
+ """
utils = getSiteManager(context)
for (name, factory) in utils.getUtilitiesFor(IFactory):
interfaces = factory.getInterfaces()
diff --git a/src/zope/component/_compat.py b/src/zope/component/_compat.py
new file mode 100644
index 0000000..e889aae
--- /dev/null
+++ b/src/zope/component/_compat.py
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import sys
+import types
+
+if sys.version_info[0] < 3: #pragma NO COVER
+
+ import cPickle as _pickle
+
+ def _u(s):
+ return unicode(s, 'unicode_escape')
+
+ CLASS_TYPES = (type, types.ClassType)
+
+ PYTHON3 = False
+ PYTHON2 = True
+
+else: #pragma NO COVER
+
+ import pickle as _pickle
+
+ def _u(s):
+ return s
+
+ CLASS_TYPES = (type,)
+
+ PYTHON3 = True
+ PYTHON2 = False
+
+_BLANK = _u('')
diff --git a/src/zope/component/_declaration.py b/src/zope/component/_declaration.py
index 0a8b44d..b434d75 100644
--- a/src/zope/component/_declaration.py
+++ b/src/zope/component/_declaration.py
@@ -13,16 +13,17 @@
##############################################################################
"""Adapter declarations
"""
-import types
import sys
-class adapter:
+from zope.component._compat import CLASS_TYPES
+
+class adapter(object):
def __init__(self, *interfaces):
self.interfaces = interfaces
def __call__(self, ob):
- if isinstance(ob, _class_types):
+ if isinstance(ob, CLASS_TYPES):
ob.__component_adapts__ = _adapts_descr(self.interfaces)
else:
ob.__component_adapts__ = self.interfaces
@@ -33,11 +34,8 @@ def adapts(*interfaces):
frame = sys._getframe(1)
locals = frame.f_locals
- # Try to make sure we were called from a class def. In 2.2.0 we can't
- # check for __module__ since it doesn't seem to be added to the locals
- # until later on.
- if (locals is frame.f_globals) or (
- ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
+ # Ensure we were called from a class def.
+ if locals is frame.f_globals or '__module__' not in locals:
raise TypeError("adapts can be used only from a class definition.")
if '__component_adapts__' in locals:
@@ -48,8 +46,6 @@ def adapts(*interfaces):
def adaptedBy(ob):
return getattr(ob, '__component_adapts__', None)
-_class_types = type, types.ClassType
-
class _adapts_descr(object):
def __init__(self, interfaces):
self.interfaces = interfaces
diff --git a/src/zope/component/configure.txt b/src/zope/component/configure.txt
deleted file mode 100644
index 3088ab8..0000000
--- a/src/zope/component/configure.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Package configuration
-=====================
-
-The ``zope.component`` package provides a ZCML file that configures some basic
-components:
-
- >>> from zope.configuration.xmlconfig import XMLConfig
- >>> import zope.component
-
- >>> XMLConfig('configure.zcml', zope.component)()
-
- >>> len(list(zope.component.getGlobalSiteManager().registeredHandlers()))
- 5
diff --git a/src/zope/component/event.py b/src/zope/component/event.py
index 360507e..850e4fc 100644
--- a/src/zope/component/event.py
+++ b/src/zope/component/event.py
@@ -11,22 +11,26 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Implement Component Architecture-specific event dispatching, based
-on subscription adapters / handlers.
+"""Component Architecture-specific event dispatching
+
+Based on subscription adapters / handlers.
"""
-__docformat__ = 'restructuredtext'
-import zope.component.interfaces
-import zope.event
+from zope.event import subscribers as event_subscribers
+
+from zope.component.interfaces import IObjectEvent
+from zope.component._api import subscribers as component_subscribers
+from zope.component._declaration import adapter
def dispatch(*event):
- zope.component.subscribers(event, None)
+ component_subscribers(event, None)
-zope.event.subscribers.append(dispatch)
+event_subscribers.append(dispatch)
-@zope.component.adapter(zope.component.interfaces.IObjectEvent)
+@adapter(IObjectEvent)
def objectEventNotify(event):
- """Event subscriber to dispatch ObjectEvents to interested adapters."""
- zope.component.subscribers((event.object, event), None)
+ """Dispatch ObjectEvents to interested adapters.
+ """
+ component_subscribers((event.object, event), None)
diff --git a/src/zope/component/event.txt b/src/zope/component/event.txt
deleted file mode 100644
index c79cd21..0000000
--- a/src/zope/component/event.txt
+++ /dev/null
@@ -1,142 +0,0 @@
-Events
-======
-
-The Component Architecture provides a way to dispatch events to event
-handlers. Event handlers are registered as *subscribers*
-a.k.a. *handlers*.
-
-Before we can start we need to import ``zope.component.event`` to make
-the dispatching effective:
-
- >>> import zope.component.event
-
-Consider two event classes:
-
- >>> class Event1(object):
- ... pass
-
- >>> class Event2(Event1):
- ... pass
-
-Now consider two handlers for these event classes:
-
- >>> called = []
-
- >>> import zope.component
- >>> @zope.component.adapter(Event1)
- ... def handler1(event):
- ... called.append(1)
-
- >>> @zope.component.adapter(Event2)
- ... def handler2(event):
- ... called.append(2)
-
-We can register them with the Component Architecture:
-
- >>> zope.component.provideHandler(handler1)
- >>> zope.component.provideHandler(handler2)
-
-Now let's go through the events. We'll see that the handlers have been
-called accordingly:
-
- >>> from zope.event import notify
- >>> notify(Event1())
- >>> called
- [1]
-
- >>> del called[:]
- >>> notify(Event2())
- >>> called.sort()
- >>> called
- [1, 2]
-
-
-
-Object events
--------------
-
-
-The ``objectEventNotify`` function is a subscriber to dispatch
-ObjectEvents to interested adapters.
-
-First create an object class:
-
- >>> class IUseless(zope.interface.Interface):
- ... """Useless object"""
-
- >>> class UselessObject(object):
- ... """Useless object"""
- ... zope.interface.implements(IUseless)
-
-Then create an event class:
-
- >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent):
- ... """An object has been thrown away"""
-
- >>> class ObjectThrownEvent(zope.component.interfaces.ObjectEvent):
- ... """An object has been thrown away"""
- ... zope.interface.implements(IObjectThrownEvent)
-
-Create an object and an event:
-
- >>> hammer = UselessObject()
- >>> event = ObjectThrownEvent(hammer)
-
-Then notify the event to the subscribers.
-Since the subscribers list is empty, nothing happens.
-
- >>> zope.component.event.objectEventNotify(event)
-
-Now create an handler for the event:
-
- >>> events = []
- >>> def record(*args):
- ... events.append(args)
-
- >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent])
-
-The event is notified to the subscriber:
-
- >>> zope.component.event.objectEventNotify(event)
- >>> events == [(hammer, event)]
- True
-
-Following test demonstrates how a subscriber can raise an exception
-to prevent an action.
-
- >>> zope.component.provideHandler(zope.component.event.objectEventNotify)
-
-Let's create a container:
-
- >>> class ToolBox(dict):
- ... def __delitem__(self, key):
- ... notify(ObjectThrownEvent(self[key]))
- ... return super(ToolBox,self).__delitem__(key)
-
- >>> container = ToolBox()
-
-And put the object into the container:
-
- >>> container['Red Hammer'] = hammer
-
-Create an handler function that will raise an error when called:
-
- >>> class Veto(Exception):
- ... pass
-
- >>> def callback(item, event):
- ... assert(item == event.object)
- ... raise Veto
-
-Register the handler:
-
- >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent])
-
-Then if we try to remove the object, an ObjectThrownEvent is fired:
-
- >>> del container['Red Hammer']
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- raise Veto
- Veto
diff --git a/src/zope/component/eventtesting.py b/src/zope/component/eventtesting.py
index 1f0c109..0e0b757 100644
--- a/src/zope/component/eventtesting.py
+++ b/src/zope/component/eventtesting.py
@@ -20,10 +20,14 @@ from zope.component.registry import dispatchAdapterRegistrationEvent
from zope.component.registry import (
dispatchSubscriptionAdapterRegistrationEvent)
from zope.component.registry import dispatchHandlerRegistrationEvent
-from zope.testing import cleanup
+try:
+ from zope.testing.cleanup import addCleanUp
+except ImportError: #pragma NO COVER
+ def addCleanUp(x):
+ pass
events = []
-def getEvents(event_type=None, filter=None):
+def getEvents(event_type=None, filter=None): #pragma NO COVER going aaway
r = []
for event in events:
if event_type is not None and not event_type.providedBy(event):
@@ -34,11 +38,11 @@ def getEvents(event_type=None, filter=None):
return r
-def clearEvents():
+def clearEvents(): #pragma NO COVER going aaway
del events[:]
-cleanup.addCleanUp(clearEvents)
+addCleanUp(clearEvents)
-class PlacelessSetup:
+class PlacelessSetup: #pragma NO COVER going aaway
def setUp(self):
provideHandler(objectEventNotify)
@@ -48,5 +52,5 @@ class PlacelessSetup:
provideHandler(dispatchHandlerRegistrationEvent)
provideHandler(events.append, (None,))
-def setUp(test=None):
+def setUp(test=None): #pragma NO COVER going aaway
PlacelessSetup().setUp()
diff --git a/src/zope/component/factory.py b/src/zope/component/factory.py
index 0d27c4d..d9edce2 100644
--- a/src/zope/component/factory.py
+++ b/src/zope/component/factory.py
@@ -13,17 +13,19 @@
##############################################################################
"""Factory object
"""
-from zope.interface import implements, implementedBy
+from zope.interface import implementer
+from zope.interface import implementedBy
from zope.interface.declarations import Implements
from zope.component.interfaces import IFactory
+
+@implementer(IFactory)
class Factory(object):
"""Generic factory implementation.
The purpose of this implementation is to provide a quick way of creating
factories for classes, functions and other objects.
"""
- implements(IFactory)
def __init__(self, callable, title='', description='', interfaces=None):
self._callable = callable
@@ -41,5 +43,5 @@ class Factory(object):
return spec
return implementedBy(self._callable)
- def __repr__(self):
+ def __repr__(self): #pragma NO COVER
return '<%s for %s>' % (self.__class__.__name__, repr(self._callable))
diff --git a/src/zope/component/factory.txt b/src/zope/component/factory.txt
deleted file mode 100644
index 1067fef..0000000
--- a/src/zope/component/factory.txt
+++ /dev/null
@@ -1,131 +0,0 @@
-Factories
-=========
-
-
-The Factory Class
------------------
-
- >>> from zope.interface import Interface
- >>> class IFunction(Interface):
- ... pass
-
- >>> class IKlass(Interface):
- ... pass
-
- >>> from zope.interface import implements
- >>> class Klass(object):
- ... implements(IKlass)
- ...
- ... def __init__(self, *args, **kw):
- ... self.args = args
- ... self.kw = kw
-
- >>> from zope.component.factory import Factory
- >>> factory = Factory(Klass, 'Klass', 'Klassier')
- >>> factory2 = Factory(lambda x: x, 'Func', 'Function')
- >>> factory3 = Factory(lambda x: x, 'Func', 'Function', (IFunction,))
-
-Calling a Factory
-~~~~~~~~~~~~~~~~~
-
-Here we test whether the factory correctly creates the objects and
-including the correct handling of constructor elements.
-
-First we create a factory that creates instanace of the `Klass` class:
-
- >>> factory = Factory(Klass, 'Klass', 'Klassier')
-
-Now we use the factory to create the instance
-
- >>> kl = factory(1, 2, foo=3, bar=4)
-
-and make sure that the correct class was used to create the object:
-
- >>> kl.__class__
- <class 'Klass'>
-
-Since we passed in a couple positional and keyword arguments
-
- >>> kl.args
- (1, 2)
- >>> kl.kw
- {'foo': 3, 'bar': 4}
-
- >>> factory2(3)
- 3
- >>> factory3(3)
- 3
-
-
-Title and Description
-~~~~~~~~~~~~~~~~~~~~~
-
- >>> factory.title
- 'Klass'
- >>> factory.description
- 'Klassier'
- >>> factory2.title
- 'Func'
- >>> factory2.description
- 'Function'
- >>> factory3.title
- 'Func'
- >>> factory3.description
- 'Function'
-
-
-Provided Interfaces
-~~~~~~~~~~~~~~~~~~~
-
- >>> implemented = factory.getInterfaces()
- >>> implemented.isOrExtends(IKlass)
- True
- >>> list(implemented)
- [<InterfaceClass __builtin__.IKlass>]
-
- >>> implemented2 = factory2.getInterfaces()
- >>> list(implemented2)
- []
-
- >>> implemented3 = factory3.getInterfaces()
- >>> list(implemented3)
- [<InterfaceClass __builtin__.IFunction>]
-
-
-The Component Architecture Factory API
---------------------------------------
-
- >>> import zope.component
- >>> factory = Factory(Klass, 'Klass', 'Klassier')
- >>> gsm = zope.component.getGlobalSiteManager()
-
- >>> from zope.component.interfaces import IFactory
- >>> gsm.registerUtility(factory, IFactory, 'klass')
-
-Creating an Object
-~~~~~~~~~~~~~~~~~~
-
- >>> kl = zope.component.createObject('klass', 1, 2, foo=3, bar=4)
- >>> isinstance(kl, Klass)
- True
- >>> kl.args
- (1, 2)
- >>> kl.kw
- {'foo': 3, 'bar': 4}
-
-Accessing Provided Interfaces
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- >>> implemented = zope.component.getFactoryInterfaces('klass')
- >>> implemented.isOrExtends(IKlass)
- True
- >>> [iface for iface in implemented]
- [<InterfaceClass __builtin__.IKlass>]
-
-List of All Factories
-~~~~~~~~~~~~~~~~~~~~~
-
- >>> [(name, fac.__class__) for name, fac in
- ... zope.component.getFactoriesFor(IKlass)]
- [(u'klass', <class 'zope.component.factory.Factory'>)]
-
diff --git a/src/zope/component/globalregistry.py b/src/zope/component/globalregistry.py
index 4c2f3bd..0fae7fc 100644
--- a/src/zope/component/globalregistry.py
+++ b/src/zope/component/globalregistry.py
@@ -13,10 +13,12 @@
##############################################################################
"""Global components support
"""
-from zope.interface import implements
+from zope.interface import implementer
from zope.interface.adapter import AdapterRegistry
from zope.interface.registry import Components
+
from zope.component.interfaces import IComponentLookup
+from zope.component._compat import _BLANK
def GAR(components, registryName):
return getattr(components, registryName)
@@ -35,8 +37,8 @@ class GlobalAdapterRegistry(AdapterRegistry):
def __reduce__(self):
return GAR, (self.__parent__, self.__name__)
+@implementer(IComponentLookup)
class BaseGlobalComponents(Components):
- implements(IComponentLookup)
def _init_registries(self):
self.adapters = GlobalAdapterRegistry(self, 'adapters')
@@ -50,7 +52,7 @@ base = BaseGlobalComponents('base')
try:
from zope.testing.cleanup import addCleanUp
-except ImportError:
+except ImportError: #pragma NO COVER
pass
else:
addCleanUp(lambda: base.__init__('base'))
@@ -64,10 +66,10 @@ def getGlobalSiteManager():
# We eventually want to deprecate these in favor of using the global
# component registry directly.
-def provideUtility(component, provides=None, name=u''):
+def provideUtility(component, provides=None, name=_BLANK):
base.registerUtility(component, provides, name, event=False)
-def provideAdapter(factory, adapts=None, provides=None, name=''):
+def provideAdapter(factory, adapts=None, provides=None, name=_BLANK):
base.registerAdapter(factory, adapts, provides, name, event=False)
def provideSubscriptionAdapter(factory, adapts=None, provides=None):
@@ -75,12 +77,3 @@ def provideSubscriptionAdapter(factory, adapts=None, provides=None):
def provideHandler(factory, adapts=None):
base.registerHandler(factory, adapts, event=False)
-
-import zope.component._api # see http://www.zope.org/Collectors/Zope3-dev/674
-# Ideally, we will switch to an explicit adapter hook registration. For now,
-# if you provide an adapter, we want to make sure that the adapter hook is
-# registered, and that registration depends on code in _api, which itself
-# depends on code in this module. So, for now, we do another of these nasty
-# circular import workarounds. See also standalonetests.py, as run by
-# tests.py in StandaloneTests, for a test that fails without this hack, and
-# succeeds with it.
diff --git a/src/zope/component/hooks.py b/src/zope/component/hooks.py
index 39dbb2c..32bb641 100644
--- a/src/zope/component/hooks.py
+++ b/src/zope/component/hooks.py
@@ -17,17 +17,24 @@ __docformat__ = 'restructuredtext'
import contextlib
import threading
-import zope.component
try:
- import zope.security.proxy
-except ImportError:
- SECURITY_SUPPORT = False
-else:
- SECURITY_SUPPORT = True
+ from zope.security.proxy import removeSecurityProxy
+except ImportError: #pragma NO COVER
+ def removeSecurityProxy(x):
+ return x
+
+from zope.component.globalregistry import getGlobalSiteManager
+from zope.component.interfaces import ComponentLookupError
+from zope.component.interfaces import IComponentLookup
class read_property(object):
+ """Descriptor for property-like computed attributes.
+
+ Unlike the standard 'property', this descriptor allows assigning a
+ value to the instance, shadowing the property getter function.
+ """
def __init__(self, func):
self.func = func
@@ -39,20 +46,19 @@ class read_property(object):
class SiteInfo(threading.local):
site = None
- sm = zope.component.getGlobalSiteManager()
+ sm = getGlobalSiteManager()
+ @read_property
def adapter_hook(self):
adapter_hook = self.sm.adapters.adapter_hook
self.adapter_hook = adapter_hook
return adapter_hook
- adapter_hook = read_property(adapter_hook)
-
siteinfo = SiteInfo()
def setSite(site=None):
if site is None:
- sm = zope.component.getGlobalSiteManager()
+ sm = getGlobalSiteManager()
else:
# We remove the security proxy because there's no way for
@@ -62,8 +68,7 @@ def setSite(site=None):
# once site managers do less. There's probably no good reason why
# they can't be proxied. Well, except maybe for performance.
- if SECURITY_SUPPORT:
- site = zope.security.proxy.removeSecurityProxy(site)
+ site = removeSecurityProxy(site)
# The getSiteManager method is defined by IPossibleSite.
sm = site.getSiteManager()
@@ -103,34 +108,35 @@ def getSiteManager(context=None):
# We should really look look at this again though, especially
# once site managers do less. There's probably no good reason why
# they can't be proxied. Well, except maybe for performance.
- sm = zope.component.interfaces.IComponentLookup(
- context, zope.component.getGlobalSiteManager())
- if SECURITY_SUPPORT:
- sm = zope.security.proxy.removeSecurityProxy(sm)
+ sm = IComponentLookup(
+ context, getGlobalSiteManager())
+ sm = removeSecurityProxy(sm)
return sm
def adapter_hook(interface, object, name='', default=None):
try:
return siteinfo.adapter_hook(interface, object, name, default)
- except zope.component.interfaces.ComponentLookupError:
+ except ComponentLookupError:
return default
def setHooks():
- zope.component.adapter_hook.sethook(adapter_hook)
- zope.component.getSiteManager.sethook(getSiteManager)
+ from zope.component import _api
+ _api.adapter_hook.sethook(adapter_hook)
+ _api.getSiteManager.sethook(getSiteManager)
def resetHooks():
# Reset hookable functions to original implementation.
- zope.component.adapter_hook.reset()
- zope.component.getSiteManager.reset()
+ from zope.component import _api
+ _api.adapter_hook.reset()
+ _api.getSiteManager.reset()
# Clear the site thread global
clearSite = setSite
try:
from zope.testing.cleanup import addCleanUp
-except ImportError:
+except ImportError: #pragma NO COVER
pass
else:
addCleanUp(resetHooks)
diff --git a/src/zope/component/hooks.txt b/src/zope/component/hooks.txt
deleted file mode 100644
index 10a8bff..0000000
--- a/src/zope/component/hooks.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-==============================
-The current component registry
-==============================
-
-There can be any number of component registries in an application. One of them
-is the global component registry, and there is also the concept of a currently
-used component registry. Component registries other than the global one are
-associated with objects called sites. The ``zope.component.hooks`` module
-provides an API to set and access the current site as well as manipulate the
-adapter hook associated with it.
-
-As long as we haven't set a site, none is being considered current:
-
->>> from zope.component.hooks import getSite
->>> print getSite()
-None
-
-We can also ask for the current component registry (aka site manager
-historically); it will return the global one if no current site is set:
-
->>> from zope.component.hooks import getSiteManager
->>> getSiteManager()
-<BaseGlobalComponents base>
-
-Let's set a site now. A site has to be an object that provides the
-``getSiteManager`` method, which is specified by
-``zope.component.interfaces.IPossibleSite``:
-
->>> from zope.interface.registry import Components
->>> class Site(object):
-... def __init__(self):
-... self.registry = Components('components')
-... def getSiteManager(self):
-... return self.registry
-
->>> from zope.component.hooks import setSite
->>> site1 = Site()
->>> setSite(site1)
-
-After this, the newly set site is considered the currently active one:
-
->>> getSite() is site1
-True
->>> getSiteManager() is site1.registry
-True
-
-If we set another site, that one will be considered current:
-
->>> site2 = Site()
->>> site2.registry is not site1.registry
-True
->>> setSite(site2)
-
->>> getSite() is site2
-True
->>> getSiteManager() is site2.registry
-True
-
-Finally we can unset the site and the global component registry is used again:
-
->>> setSite()
->>> print getSite()
-None
->>> getSiteManager()
-<BaseGlobalComponents base>
-
-
-Context manager
-===============
-
-There also is a context manager for setting the site, which is especially
-useful when writing tests:
-
->>> import zope.component.hooks
->>> dummy = with_statement # support for Python-2.5
->>> print getSite()
-None
->>> with zope.component.hooks.site(site2):
-... getSite() is site2
-True
->>> print getSite()
-None
-
-The site is properly restored even if the body of the with statement
-raises an exception:
-
->>> print getSite()
-None
->>> with zope.component.hooks.site(site2):
-... getSite() is site2
-... raise ValueError('An error in the body')
-Traceback (most recent call last):
- ...
-ValueError: An error in the body
->>> print getSite()
-None
-
diff --git a/src/zope/component/index.txt b/src/zope/component/index.txt
deleted file mode 100644
index 5528b93..0000000
--- a/src/zope/component/index.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Welcome to zope.component's documentation!
-==========================================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- README
- socketexample
- event
- factory
- registry
- persistentregistry
- zcml
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
diff --git a/src/zope/component/interface.py b/src/zope/component/interface.py
index 416544c..bd44eee 100644
--- a/src/zope/component/interface.py
+++ b/src/zope/component/interface.py
@@ -13,78 +13,22 @@
##############################################################################
"""Interface utility functions
"""
-__docformat__ = 'restructuredtext'
-
-from types import ClassType
-
-import zope.component
-from zope.component.interfaces import ComponentLookupError
from zope.interface import alsoProvides
from zope.interface.interfaces import IInterface
-def provideInterface(id, interface, iface_type=None, info=''):
- """register Interface with global site manager as utility
-
- >>> gsm = zope.component.getGlobalSiteManager()
-
- >>> from zope.interface import Interface
- >>> from zope.interface.interfaces import IInterface
- >>> from zope.component.tests import ITestType
-
- >>> class I(Interface):
- ... pass
- >>> IInterface.providedBy(I)
- True
- >>> ITestType.providedBy(I)
- False
- >>> interfaces = gsm.getUtilitiesFor(ITestType)
- >>> list(interfaces)
- []
-
- # provide first interface type
- >>> provideInterface('', I, ITestType)
- >>> ITestType.providedBy(I)
- True
- >>> interfaces = list(gsm.getUtilitiesFor(ITestType))
- >>> [name for (name, iface) in interfaces]
- [u'zope.component.interface.I']
- >>> [iface.__name__ for (name, iface) in interfaces]
- ['I']
-
- # provide second interface type
- >>> class IOtherType(IInterface):
- ... pass
- >>> provideInterface('', I, IOtherType)
-
- >>> ITestType.providedBy(I)
- True
- >>> IOtherType.providedBy(I)
- True
- >>> interfaces = list(gsm.getUtilitiesFor(ITestType))
- >>> [name for (name, iface) in interfaces]
- [u'zope.component.interface.I']
- >>> interfaces = list(gsm.getUtilitiesFor(IOtherType))
- >>> [name for (name, iface) in interfaces]
- [u'zope.component.interface.I']
+from zope.component.globalregistry import getGlobalSiteManager
+from zope.component.interfaces import ComponentLookupError
+from zope.component._api import queryUtility
+from zope.component._compat import CLASS_TYPES
- >>> class I1(Interface):
- ... pass
- >>> provideInterface('', I1)
- >>> IInterface.providedBy(I1)
- True
- >>> ITestType.providedBy(I1)
- False
- >>> interfaces = list(gsm.getUtilitiesFor(ITestType))
- >>> [name for (name, iface) in interfaces]
- [u'zope.component.interface.I']
- >>> [iface.__name__ for (name, iface) in interfaces]
- ['I']
+def provideInterface(id, interface, iface_type=None, info=''):
+ """ Mark 'interface' as a named utilty providing 'iface_type'.
"""
if not id:
id = "%s.%s" % (interface.__module__, interface.__name__)
if not IInterface.providedBy(interface):
- if not isinstance(interface, (type, ClassType)):
+ if not isinstance(interface, CLASS_TYPES):
raise TypeError(id, "is not an interface or class")
return
@@ -95,33 +39,12 @@ def provideInterface(id, interface, iface_type=None, info=''):
else:
iface_type = IInterface
- gsm = zope.component.getGlobalSiteManager()
+ gsm = getGlobalSiteManager()
gsm.registerUtility(interface, iface_type, id, info)
def getInterface(context, id):
"""Return interface or raise ComponentLookupError
-
- >>> from zope.interface import Interface
- >>> from zope.component.tests import ITestType
-
- >>> class I4(Interface):
- ... pass
- >>> IInterface.providedBy(I4)
- True
- >>> ITestType.providedBy(I4)
- False
- >>> getInterface(None, 'zope.component.interface.I4')
- Traceback (most recent call last):
- ...
- ComponentLookupError: zope.component.interface.I4
- >>> provideInterface('', I4, ITestType)
- >>> ITestType.providedBy(I4)
- True
- >>> iface = queryInterface( """\
- """ 'zope.component.interface.I4')
- >>> iface.__name__
- 'I4'
"""
iface = queryInterface(id, None)
if iface is None:
@@ -130,51 +53,13 @@ def getInterface(context, id):
def queryInterface(id, default=None):
- """return interface or ``None``
-
- >>> from zope.interface import Interface
- >>> from zope.interface.interfaces import IInterface
- >>> from zope.component.tests import ITestType
-
- >>> class I3(Interface):
- ... pass
- >>> IInterface.providedBy(I3)
- True
- >>> ITestType.providedBy(I3)
- False
- >>> queryInterface('zope.component.interface.I3')
-
- >>> provideInterface('', I3, ITestType)
- >>> ITestType.providedBy(I3)
- True
- >>> iface = queryInterface('zope.component.interface.I3')
- >>> iface.__name__
- 'I3'
+ """Return an interface or ``None``
"""
- return zope.component.queryUtility(IInterface, id, default)
+ return queryUtility(IInterface, id, default)
def searchInterface(context, search_string=None, base=None):
"""Interfaces search
-
- >>> from zope.interface import Interface
- >>> from zope.interface.interfaces import IInterface
- >>> from zope.component.tests import ITestType
-
- >>> class I5(Interface):
- ... pass
- >>> IInterface.providedBy(I5)
- True
- >>> ITestType.providedBy(I5)
- False
- >>> searchInterface(None, 'zope.component.interface.I5')
- []
- >>> provideInterface('', I5, ITestType)
- >>> ITestType.providedBy(I5)
- True
- >>> iface = searchInterface(None, 'zope.component.interface.I5')
- >>> iface[0].__name__
- 'I5'
"""
return [iface_util[1] for iface_util in
searchInterfaceUtilities(context, search_string, base)]
@@ -182,32 +67,13 @@ def searchInterface(context, search_string=None, base=None):
def searchInterfaceIds(context, search_string=None, base=None):
"""Interfaces search
-
- >>> from zope.interface import Interface
- >>> from zope.interface.interfaces import IInterface
- >>> from zope.component.tests import ITestType
-
- >>> class I5(Interface):
- ... pass
- >>> IInterface.providedBy(I5)
- True
- >>> ITestType.providedBy(I5)
- False
- >>> searchInterface(None, 'zope.component.interface.I5')
- []
- >>> provideInterface('', I5, ITestType)
- >>> ITestType.providedBy(I5)
- True
- >>> iface = searchInterfaceIds(None, 'zope.component.interface.I5')
- >>> iface
- [u'zope.component.interface.I5']
"""
return [iface_util[0] for iface_util in
searchInterfaceUtilities(context, search_string, base)]
def searchInterfaceUtilities(context, search_string=None, base=None):
- gsm = zope.component.getGlobalSiteManager()
+ gsm = getGlobalSiteManager()
iface_utilities = gsm.getUtilitiesFor(IInterface)
if search_string:
@@ -217,7 +83,7 @@ def searchInterfaceUtilities(context, search_string=None, base=None):
find(search_string) >= 0)]
if base:
res = [iface_util for iface_util in iface_utilities
- if iface_util[1].extends(base)]
+ if iface_util[1].isOrExtends(base)]
else:
res = [iface_util for iface_util in iface_utilities]
return res
@@ -245,6 +111,8 @@ def nameToInterface(context, id):
def interfaceToName(context, interface):
if interface is None:
return 'None'
+ # XXX this search is pointless: we are always going to return the
+ # same value whether or not we find anything.
items = searchInterface(context, base=interface)
ids = [('%s.%s' %(iface.__module__, iface.__name__))
for iface in items
diff --git a/src/zope/component/interfaces.py b/src/zope/component/interfaces.py
index a13300f..90df100 100644
--- a/src/zope/component/interfaces.py
+++ b/src/zope/component/interfaces.py
@@ -38,6 +38,9 @@ from zope.interface.interfaces import Unregistered
from zope.interface.interfaces import IComponentRegistry
from zope.interface.interfaces import IComponents
+from zope.component._compat import _BLANK
+
+
class IComponentArchitecture(Interface):
"""The Component Architecture is defined by two key components: Adapters
and Utiltities. Both are managed by site managers. All other components
@@ -112,7 +115,7 @@ class IComponentArchitecture(Interface):
# Adapter API
def getAdapter(object,
- interface=Interface, name=u'',
+ interface=Interface, name=_BLANK,
context=None):
"""Get a named adapter to an interface for an object
@@ -167,7 +170,7 @@ class IComponentArchitecture(Interface):
named adapter methods with an empty string for a name.
"""
- def queryAdapter(object, interface=Interface, name=u'',
+ def queryAdapter(object, interface=Interface, name=_BLANK,
default=None, context=None):
"""Look for a named adapter to an interface for an object
@@ -204,7 +207,7 @@ class IComponentArchitecture(Interface):
"""
def queryMultiAdapter(objects,
- interface=Interface, name=u'',
+ interface=Interface, name=_BLANK,
default=None,
context=None):
"""Look for a multi-adapter to an interface for objects
@@ -316,7 +319,7 @@ class IComponentRegistrationConvenience(Interface):
activity.
"""
- def provideUtility(component, provides=None, name=u''):
+ def provideUtility(component, provides=None, name=_BLANK):
"""Register a utility globally
A utility is registered to provide an interface with a
@@ -332,7 +335,7 @@ class IComponentRegistrationConvenience(Interface):
"""
- def provideAdapter(factory, adapts=None, provides=None, name=u''):
+ def provideAdapter(factory, adapts=None, provides=None, name=_BLANK):
"""Register an adapter globally
An adapter is registered to provide an interface with a name
diff --git a/src/zope/component/nexttesting.py b/src/zope/component/nexttesting.py
deleted file mode 100644
index 8295c50..0000000
--- a/src/zope/component/nexttesting.py
+++ /dev/null
@@ -1,104 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2009 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Helper functions for testing utilities that use get/queryNextUtility.
-"""
-import zope.interface
-from zope.component.interfaces import IComponentLookup, IComponents
-
-
-class SiteManagerStub(object):
- zope.interface.implements(IComponents)
-
- __bases__ = ()
-
- def __init__(self):
- self._utils = {}
-
- def setNext(self, next):
- self.__bases__ = (next, )
-
- def provideUtility(self, iface, util, name=''):
- self._utils[(iface, name)] = util
-
- def queryUtility(self, iface, name='', default=None):
- return self._utils.get((iface, name), default)
-
-
-def testingNextUtility(utility, nextutility, interface, name='',
- sitemanager=None, nextsitemanager=None):
- """Provide a next utility for testing.
-
- This function sets up two utilities, so the get/queryNextUtility functions
- will see the second one as the "next" to the first one.
-
- To test it, we need to create a utility interface and implementation:
-
- >>> from zope.interface import Interface, implements
- >>> class IAnyUtility(Interface):
- ... pass
-
- >>> class AnyUtility(object):
- ... implements(IAnyUtility)
- ... def __init__(self, id):
- ... self.id = id
-
- >>> any1 = AnyUtility(1)
- >>> any1next = AnyUtility(2)
-
- Now, we can make the "any1next" be next to "any1".
-
- >>> testingNextUtility(any1, any1next, IAnyUtility)
-
- >>> from zope.component import getNextUtility
- >>> getNextUtility(any1, IAnyUtility) is any1next
- True
-
- It will work for named utilities as well.
-
- >>> testingNextUtility(any1, any1next, IAnyUtility, 'any')
- >>> getNextUtility(any1, IAnyUtility, 'any') is any1next
- True
-
- We can also provide our custom component registries:
-
- >>> sm = SiteManagerStub()
- >>> nextsm = SiteManagerStub()
-
- >>> testingNextUtility(any1, any1next, IAnyUtility,
- ... sitemanager=sm, nextsitemanager=nextsm)
-
- >>> IComponentLookup(any1) is sm
- True
- >>> IComponentLookup(any1next) is nextsm
- True
- >>> getNextUtility(any1, IAnyUtility) is any1next
- True
-
- """
- if sitemanager is None:
- sitemanager = SiteManagerStub()
- if nextsitemanager is None:
- nextsitemanager = SiteManagerStub()
- sitemanager.setNext(nextsitemanager)
-
- sitemanager.provideUtility(interface, utility, name)
- utility.__conform__ = (
- lambda iface:
- iface.isOrExtends(IComponentLookup) and sitemanager or None
- )
- nextsitemanager.provideUtility(interface, nextutility, name)
- nextutility.__conform__ = (
- lambda iface:
- iface.isOrExtends(IComponentLookup) and nextsitemanager or None
- )
diff --git a/src/zope/component/persistentregistry.py b/src/zope/component/persistentregistry.py
index d185680..b3edfa1 100644
--- a/src/zope/component/persistentregistry.py
+++ b/src/zope/component/persistentregistry.py
@@ -13,16 +13,13 @@
##############################################################################
"""Persistent component managers
"""
-import persistent.mapping
-import persistent.list
-import zope.interface.adapter
-
+from persistent import Persistent
+from persistent.mapping import PersistentMapping
+from persistent.list import PersistentList
+from zope.interface.adapter import VerifyingAdapterRegistry
from zope.interface.registry import Components
-class PersistentAdapterRegistry(
- zope.interface.adapter.VerifyingAdapterRegistry,
- persistent.Persistent,
- ):
+class PersistentAdapterRegistry(VerifyingAdapterRegistry, Persistent):
def changed(self, originally_changed):
if originally_changed is self:
@@ -48,7 +45,7 @@ class PersistentComponents(Components):
self.utilities = PersistentAdapterRegistry()
def _init_registrations(self):
- self._utility_registrations = persistent.mapping.PersistentMapping()
- self._adapter_registrations = persistent.mapping.PersistentMapping()
- self._subscription_registrations = persistent.list.PersistentList()
- self._handler_registrations = persistent.list.PersistentList()
+ self._utility_registrations = PersistentMapping()
+ self._adapter_registrations = PersistentMapping()
+ self._subscription_registrations = PersistentList()
+ self._handler_registrations = PersistentList()
diff --git a/src/zope/component/persistentregistry.txt b/src/zope/component/persistentregistry.txt
deleted file mode 100644
index bf0de9e..0000000
--- a/src/zope/component/persistentregistry.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Persistent Component Management
-===============================
-
-Persistent component management allows persistent management of
-components. From a usage point of view, there shouldn't be any new
-behavior beyond what's described in registry.txt.
diff --git a/src/zope/component/registry.txt b/src/zope/component/registry.txt
deleted file mode 100644
index 85933c8..0000000
--- a/src/zope/component/registry.txt
+++ /dev/null
@@ -1,1117 +0,0 @@
-Component-Management objects
-============================
-
-Component-management objects provide a higher-level
-component-management API over the basic adapter-registration API
-provided by the zope.interface package. In particular, it provides:
-
-- utilities
-
-- support for computing adapters, rather than just looking up adapter
- factories.
-
-- management of registration comments
-
-The zope.component.registry.Components class provides an
-implementation of zope.component.interfaces.IComponents that provides
-these features.
-
- >>> from zope.component import registry
- >>> from zope.component import tests
- >>> components = registry.Components('comps')
-
-As components are registered, events are generated. Let's register
-an event subscriber, so we can see the events generated:
-
- >>> import zope.event
- >>> def logevent(event):
- ... print event
- >>> zope.event.subscribers.append(logevent)
-
-Utilities
----------
-
-You can register Utilities using registerUtility:
-
- >>> components.registerUtility(tests.U1(1))
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
-
-Here we didn't specify an interface or name. An unnamed utility was
-registered for interface I1, since that is only interface implemented
-by the U1 class:
-
- >>> components.getUtility(tests.I1)
- U1(1)
-
-You can also register a utility using a factory instead of a utility instance:
-
- >>> def factory():
- ... return tests.U1(1)
- >>> components.registerUtility(factory=factory)
- Unregistered event:
- UtilityRegistration(<Components comps>, I1, u'', 1, None, u'')
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'')
-
-
-If a component implements other than one interface or no interface,
-then an error will be raised:
-
- >>> components.registerUtility(tests.U12(2))
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The utility doesn't provide a single interface and
- no provided interface was specified.
-
- >>> components.registerUtility(tests.A)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The utility doesn't provide a single interface and
- no provided interface was specified.
-
-
-We can provide an interface if desired:
-
- >>> components.registerUtility(tests.U12(2), tests.I2)
- Registered event:
- UtilityRegistration(<Components comps>, I2, u'', 2, None, u'')
-
-and we can specify a name:
-
- >>> components.registerUtility(tests.U12(3), tests.I2, u'three')
- Registered event:
- UtilityRegistration(<Components comps>, I2, u'three', 3, None, u'')
-
- >>> components.getUtility(tests.I2)
- U12(2)
-
- >>> components.getUtility(tests.I2, 'three')
- U12(3)
-
-If you try to get a utility that doesn't exist, you'll get a component
-lookup error:
-
- >>> components.getUtility(tests.I3)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError:
- (<InterfaceClass zope.component.tests.I3>, u'')
-
-Unless you use queryUtility:
-
- >>> components.queryUtility(tests.I3)
- >>> components.queryUtility(tests.I3, default=42)
- 42
-
-You can get information about registered utilities with the
-registeredUtilities method:
-
- >>> for registration in sorted(components.registeredUtilities()):
- ... print registration.provided, registration.name
- ... print registration.component, registration.info
- <InterfaceClass zope.component.tests.I1>
- U1(1)
- <InterfaceClass zope.component.tests.I2>
- U12(2)
- <InterfaceClass zope.component.tests.I2> three
- U12(3)
-
-Duplicate registrations replace existing ones:
-
- >>> components.registerUtility(tests.U1(4), info=u'use 4 now')
- Unregistered event:
- UtilityRegistration(<Components comps>, I1, u'', 1, <function factory at <SOME ADDRESS>>, u'')
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
- >>> components.getUtility(tests.I1)
- U1(4)
-
- >>> for registration in sorted(components.registeredUtilities()):
- ... print registration.provided, registration.name
- ... print registration.component, registration.info
- <InterfaceClass zope.component.tests.I1>
- U1(4) use 4 now
- <InterfaceClass zope.component.tests.I2>
- U12(2)
- <InterfaceClass zope.component.tests.I2> three
- U12(3)
-
-As shown in the this example, you can provide an "info" argumemnt when
-registering utilities. This provides extra documentation about the
-registration itself that is shown when listing registrations.
-
-You can also unregister utilities:
-
- >>> components.unregisterUtility(provided=tests.I1)
- Unregistered event:
- UtilityRegistration(<Components comps>, I1, u'', 4, None, u'use 4 now')
- True
-
-A boolean is returned indicating whether anything changed:
-
- >>> components.queryUtility(tests.I1)
- >>> for registration in sorted(components.registeredUtilities()):
- ... print registration.provided, registration.name
- ... print registration.component, registration.info
- <InterfaceClass zope.component.tests.I2>
- U12(2)
- <InterfaceClass zope.component.tests.I2> three
- U12(3)
-
-When you unregister, you can specify a component. If the component
-doesn't match the one registered, then nothing happens:
-
- >>> u5 = tests.U1(5)
- >>> components.registerUtility(u5)
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
- >>> components.unregisterUtility(tests.U1(6))
- False
- >>> components.queryUtility(tests.I1)
- U1(5)
- >>> components.unregisterUtility(u5)
- Unregistered event:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
- True
- >>> components.queryUtility(tests.I1)
-
-You can get the name and utility for all of the utilities that provide
-an interface using getUtilitiesFor:
-
- >>> sorted(components.getUtilitiesFor(tests.I2))
- [(u'', U12(2)), (u'three', U12(3))]
-
-getAllUtilitiesRegisteredFor is similar to getUtilitiesFor except that
-it includes utilities that are overridden. For example, we'll
-register a utility that for an extending interface of I2:
-
- >>> util = tests.U('ext')
- >>> components.registerUtility(util, tests.I2e)
- Registered event:
- UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
-
-We don't get the new utility for getUtilitiesFor:
-
- >>> sorted(components.getUtilitiesFor(tests.I2))
- [(u'', U12(2)), (u'three', U12(3))]
-
-but we do get it from getAllUtilitiesRegisteredFor:
-
- >>> sorted(map(str, components.getAllUtilitiesRegisteredFor(tests.I2)))
- ['U(ext)', 'U12(2)', 'U12(3)']
-
-Removing a utility also makes it disappear from getUtilitiesFor:
-
- >>> components.unregisterUtility(util, tests.I2e)
- Unregistered event:
- UtilityRegistration(<Components comps>, I2e, u'', ext, None, u'')
- True
- >>> list(components.getAllUtilitiesRegisteredFor(tests.I2e))
- []
-
-Adapters
---------
-
-You can register adapters with registerAdapter:
-
- >>> components.registerAdapter(tests.A12_1)
- Registered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-
-Here, we didn't specify required interfaces, a provided interface, or
-a name. The required interfaces were determined from the factory
-s __component_adapts__ attribute and the provided interface was
-determined by introspecting what the factory implements.
-
- >>> components.getMultiAdapter((tests.U1(6), tests.U12(7)), tests.IA1)
- A12_1(U1(6), U12(7))
-
-If a factory implements more than one interface, an exception will be
-raised:
-
- >>> components.registerAdapter(tests.A1_12)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
-Unless the provided interface is specified:
-
- >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
- Registered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
-
-If a factory doesn't declare an implemented interface, an exception will be
-raised:
-
- >>> components.registerAdapter(tests.A12_)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
-Unless the provided interface is specified:
-
- >>> components.registerAdapter(tests.A12_, provided=tests.IA2)
- Registered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
-
-The required interface needs to be specified in the registration if
-the factory doesn't have a __component_adapts__ attribute:
-
- >>> components.registerAdapter(tests.A_2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't have a __component_adapts__
- attribute and no required specifications were specified
-
-Unless the required specifications specified:
-
- >>> components.registerAdapter(tests.A_2, required=[tests.I3])
- Registered event:
- AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
-
-Classes can be specified in place of specifications, in which case the
-implementedBy specification for the class is used:
-
- >>> components.registerAdapter(tests.A_3, required=[tests.U],
- ... info="Really class specific")
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- AdapterRegistration(<Components comps>, [zope.component.tests.U], IA3, u'',
- A_3, 'Really class specific')
-
-We can see the adapters that have been registered using the
-registeredAdapters method:
-
- >>> for registration in sorted(components.registeredAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<InterfaceClass zope.component.tests.I1>,
- <InterfaceClass zope.component.tests.I2>)
- <InterfaceClass zope.component.tests.IA1>
- zope.component.tests.A12_1
- (<InterfaceClass zope.component.tests.I1>,
- <InterfaceClass zope.component.tests.I2>)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A12_
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_12
- (<InterfaceClass zope.component.tests.I3>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A_2
- (<implementedBy zope.component.tests.U>,)
- <InterfaceClass zope.component.tests.IA3>
- zope.component.tests.A_3 Really class specific
-
-As with utilities, we can provide registration information when
-registering adapters.
-
-If you try to fetch an adapter that isn't registered, you'll get a
-component-lookup error:
-
- >>> components.getMultiAdapter((tests.U(8), ), tests.IA1)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: ((U(8),),
- <InterfaceClass zope.component.tests.IA1>, u'')
-
-unless you use queryAdapter:
-
- >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1)
- >>> components.queryMultiAdapter((tests.U(8), ), tests.IA1, default=42)
- 42
-
-When looking up an adapter for a single object, you can use the
-slightly simpler getAdapter and queryAdapter calls:
-
- >>> components.getAdapter(tests.U1(9), tests.IA2)
- A1_12(U1(9))
-
- >>> components.queryAdapter(tests.U1(9), tests.IA2)
- A1_12(U1(9))
-
- >>> components.getAdapter(tests.U(8), tests.IA1)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: (U(8),
- <InterfaceClass zope.component.tests.IA1>, u'')
-
- >>> components.queryAdapter(tests.U(8), tests.IA2)
- >>> components.queryAdapter(tests.U(8), tests.IA2, default=42)
- 42
-
-You can unregister an adapter. If a factory is provided and if the
-rewuired and provided interfaces, can be infered, then they need not
-be provided:
-
- >>> components.unregisterAdapter(tests.A12_1)
- Unregistered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
- True
-
- >>> for registration in sorted(components.registeredAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<InterfaceClass zope.component.tests.I1>,
- <InterfaceClass zope.component.tests.I2>)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A12_
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_12
- (<InterfaceClass zope.component.tests.I3>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A_2
- (<implementedBy zope.component.tests.U>,)
- <InterfaceClass zope.component.tests.IA3>
- zope.component.tests.A_3 Really class specific
-
-A boolean is returned indicating whether a change was made.
-
-If a factory implements more than one interface, an exception will be
-raised:
-
- >>> components.unregisterAdapter(tests.A1_12)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
-Unless the provided interface is specified:
-
- >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
- Unregistered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
- True
-
-If a factory doesn't declare an implemented interface, an exception will be
-raised:
-
- >>> components.unregisterAdapter(tests.A12_)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
-Unless the provided interface is specified:
-
- >>> components.unregisterAdapter(tests.A12_, provided=tests.IA2)
- Unregistered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
- True
-
-The required interface needs to be specified if the factory doesn't
-have a __component_adapts__ attribute:
-
- >>> components.unregisterAdapter(tests.A_2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't have a __component_adapts__
- attribute and no required specifications were specified
-
- >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
- Unregistered event:
- AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
- True
-
- >>> for registration in sorted(components.registeredAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<implementedBy zope.component.tests.U>,)
- <InterfaceClass zope.component.tests.IA3>
- zope.component.tests.A_3 Really class specific
-
-If a factory is unregistered that is not registered, False is
-returned:
-
-
- >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
- False
- >>> components.unregisterAdapter(tests.A12_1, required=[tests.U])
- False
-
-The factory can be omitted, to unregister *any* factory that matches
-specified required and provided interfaces:
-
- >>> components.unregisterAdapter(required=[tests.U], provided=tests.IA3)
- ... # doctest: +NORMALIZE_WHITESPACE
- Unregistered event:
- AdapterRegistration(<Components comps>, [zope.component.tests.U],
- IA3, u'', A_3, 'Really class specific')
- True
-
- >>> for registration in sorted(components.registeredAdapters()):
- ... print registration
-
-Adapters can be named:
-
- >>> components.registerAdapter(tests.A1_12, provided=tests.IA2,
- ... name=u'test')
- Registered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
-
- >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2)
- >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2, name=u'test')
- A1_12(U1(9))
-
- >>> components.queryAdapter(tests.U1(9), tests.IA2)
- >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test')
- A1_12(U1(9))
- >>> components.getAdapter(tests.U1(9), tests.IA2, name=u'test')
- A1_12(U1(9))
-
-It is possible to look up all of the adapters that provide an
-interface:
-
- >>> components.registerAdapter(tests.A1_23, provided=tests.IA2,
- ... name=u'test 2')
- Registered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'test 2', A1_23, u'')
-
- >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
- Registered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
-
- >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
- ... tests.IA2)):
- ... print name, adapter
- A1_12(U1(9))
- test A1_12(U1(9))
- test 2 A1_23(U1(9))
-
-
-getAdapters is most commonly used as the basis of menu systems.
-
-If an adapter factory returns None, it is equivalent to there being no
-factory:
-
- >>> components.registerAdapter(tests.noop,
- ... required=[tests.IA1], provided=tests.IA2,
- ... name=u'test noop')
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- AdapterRegistration(<Components comps>, [IA1], IA2, u'test noop',
- noop, u'')
- >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test noop')
-
- >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
- Registered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
-
- >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ),
- ... tests.IA2)):
- ... print name, adapter
- A1_12(U1(9))
- test A1_12(U1(9))
- test 2 A1_23(U1(9))
-
-
- >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2,
- ... name=u'test')
- Unregistered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
- True
- >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
- Unregistered event:
- AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
- True
- >>> for registration in sorted(components.registeredAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2> test 2
- zope.component.tests.A1_23
- (<InterfaceClass zope.component.tests.IA1>,)
- <InterfaceClass zope.component.tests.IA2> test noop
- <function noop at 0xb79a1064>
-
-
-Subscribers
------------
-
-Subscribers provide a way to get multiple adapters of a given type.
-In this regard, subscribers are like named adapters, except that there
-isn't any concept of the most specific adapter for a given name.
-
-Subscribers are registered by calling registerSubscriptionAdapter:
-
- >>> components.registerSubscriptionAdapter(tests.A1_2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
-
- >>> components.registerSubscriptionAdapter(
- ... tests.A1_12, provided=tests.IA2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
-
- >>> components.registerSubscriptionAdapter(
- ... tests.A, [tests.I1], tests.IA2,
- ... info='a sample comment')
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
- A, 'a sample comment')
-
-The same rules, with regard to when required and provided interfaces
-have to be specified apply as with adapters:
-
- >>> components.registerSubscriptionAdapter(tests.A1_12)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
- >>> components.registerSubscriptionAdapter(tests.A)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single interface and
- no provided interface was specified.
-
- >>> components.registerSubscriptionAdapter(tests.A, required=[tests.IA1])
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single interface
- and no provided interface was specified.
-
-Note that we provided the info argument as a keyword argument above.
-That's because there is a name argument that's reserved for future
-use. We can give a name, as long as it is an empty string:
-
- >>> components.registerSubscriptionAdapter(
- ... tests.A, [tests.I1], tests.IA2, u'', 'a sample comment')
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'',
- A, 'a sample comment')
-
- >>> components.registerSubscriptionAdapter(
- ... tests.A, [tests.I1], tests.IA2, u'oops', 'a sample comment')
- Traceback (most recent call last):
- ...
- TypeError: Named subscribers are not yet supported
-
-Subscribers are looked up using the subscribers method:
-
- >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
- ... print s
- A1_2(U1(1))
- A1_12(U1(1))
- A(U1(1),)
- A(U1(1),)
-
-Note that, because we created multiple subscriptions for A, we got multiple
-subscriber instances.
-
-As with normal adapters, if a factory returns None, the result is skipped:
-
- >>> components.registerSubscriptionAdapter(
- ... tests.noop, [tests.I1], tests.IA2)
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', noop, u'')
-
- >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
- ... print s
- A1_2(U1(1))
- A1_12(U1(1))
- A(U1(1),)
- A(U1(1),)
-
-We can get registration information for subscriptions:
-
- >>> for registration in sorted(
- ... components.registeredSubscriptionAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A a sample comment
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A a sample comment
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_12
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_2
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- <function noop at 0xb796ff7c>
-
-We can also unregister subscriptions in much the same way we can for adapters:
-
- >>> components.unregisterSubscriptionAdapter(tests.A1_2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Unregistered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, '')
- True
-
- >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
- ... print s
- A1_12(U1(1))
- A(U1(1),)
- A(U1(1),)
-
- >>> for registration in sorted(
- ... components.registeredSubscriptionAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A a sample comment
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A a sample comment
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_12
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- <function noop at 0xb796ff7c>
-
- >>> components.unregisterSubscriptionAdapter(
- ... tests.A, [tests.I1], tests.IA2)
- Unregistered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A, '')
- True
-
- >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
- ... print s
- A1_12(U1(1))
-
- >>> for registration in sorted(
- ... components.registeredSubscriptionAdapters()):
- ... print registration.required
- ... print registration.provided, registration.name
- ... print registration.factory, registration.info
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- zope.component.tests.A1_12
- (<InterfaceClass zope.component.tests.I1>,)
- <InterfaceClass zope.component.tests.IA2>
- <function noop at 0xb796ff7c>
-
-Note here that both registrations for A were removed.
-
-If we omit the factory, we must specify the required and provided interfaces:
-
- >>> components.unregisterSubscriptionAdapter(required=[tests.I1])
- Traceback (most recent call last):
- ...
- TypeError: Must specify one of factory and provided
-
- >>> components.unregisterSubscriptionAdapter(provided=tests.IA2)
- Traceback (most recent call last):
- ...
- TypeError: Must specify one of factory and required
-
- >>> components.unregisterSubscriptionAdapter(
- ... required=[tests.I1], provided=tests.IA2)
- Unregistered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', None, '')
- True
-
- >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
- ... print s
-
- >>> for registration in sorted(
- ... components.registeredSubscriptionAdapters()):
- ... print registration.factory
-
-As when registering, an error is raised if the registration
-information can't be determined from the factory and isn't specified:
-
- >>> components.unregisterSubscriptionAdapter(tests.A1_12)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single
- interface and no provided interface was specified.
-
- >>> components.unregisterSubscriptionAdapter(tests.A)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single interface and
- no provided interface was specified.
-
- >>> components.unregisterSubscriptionAdapter(tests.A, required=[tests.IA1])
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't implement a single interface
- and no provided interface was specified.
-
-If you unregister something that's not registered, nothing will be
-changed and False will be returned:
-
-
- >>> components.unregisterSubscriptionAdapter(
- ... required=[tests.I1], provided=tests.IA2)
- False
-
-Handlers
---------
-
-Handlers are used when you want to perform some function in response
-to an event. Handlers aren't expected to return anything when called
-and are not registered to provide any interface.
-
- >>> from zope import component
- >>> @component.adapter(tests.I1)
- ... def handle1(x):
- ... print 'handle1', x
-
- >>> components.registerHandler(handle1, info="First handler")
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- HandlerRegistration(<Components comps>, [I1], u'',
- handle1, 'First handler')
- >>> components.handle(tests.U1(1))
- handle1 U1(1)
-
- >>> @component.adapter(tests.I1, tests.I2)
- ... def handle12(x, y):
- ... print 'handle12', x, y
-
- >>> components.registerHandler(handle12)
- Registered event:
- HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, u'')
- >>> components.handle(tests.U1(1), tests.U12(2))
- handle12 U1(1) U12(2)
-
-If a handler doesn't document interfaces it handles, then
-the required interfaces must be specified:
-
- >>> def handle(*objects):
- ... print 'handle', objects
-
- >>> components.registerHandler(handle)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't have a __component_adapts__
- attribute and no required specifications were specified
-
- >>> components.registerHandler(handle, required=[tests.I1],
- ... info="a comment")
- Registered event:
- HandlerRegistration(<Components comps>, [I1], u'', handle, 'a comment')
-
-Handlers can also be registered for classes:
-
- >>> components.registerHandler(handle, required=[tests.U],
- ... info="handle a class")
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- HandlerRegistration(<Components comps>, [zope.component.tests.U], u'',
- handle, 'handle a class')
-
-
- >>> components.handle(tests.U1(1))
- handle (U1(1),)
- handle1 U1(1)
- handle (U1(1),)
-
-We can list the handler registrations:
-
- >>> for registration in components.registeredHandlers():
- ... print registration.required
- ... print registration.handler, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle1 at 0xb78f5bfc> First handler
- (<InterfaceClass zope.component.tests.I1>,
- <InterfaceClass zope.component.tests.I2>)
- <function handle12 at 0xb78f5c34>
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle at 0xb78f5ca4> a comment
- (<implementedBy zope.component.tests.U>,)
- <function handle at 0xb78f5ca4> handle a class
-
-and we can unregister handlers:
-
- >>> components.unregisterHandler(required=[tests.U])
- ... # doctest: +NORMALIZE_WHITESPACE
- Unregistered event:
- HandlerRegistration(<Components comps>, [zope.component.tests.U], u'',
- None, '')
- True
-
- >>> for registration in components.registeredHandlers():
- ... print registration.required
- ... print registration.handler, registration.info
- ... # doctest: +NORMALIZE_WHITESPACE
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle1 at 0xb78f5bfc> First handler
- (<InterfaceClass zope.component.tests.I1>,
- <InterfaceClass zope.component.tests.I2>)
- <function handle12 at 0xb78f5c34>
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle at 0xb78f5ca4> a comment
-
- >>> components.unregisterHandler(handle12)
- Unregistered event:
- HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, '')
- True
-
- >>> for registration in components.registeredHandlers():
- ... print registration.required
- ... print registration.handler, registration.info
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle1 at 0xb78f5bfc> First handler
- (<InterfaceClass zope.component.tests.I1>,)
- <function handle at 0xb78f5ca4> a comment
-
- >>> components.unregisterHandler(handle12)
- False
-
- >>> components.unregisterHandler()
- Traceback (most recent call last):
- ...
- TypeError: Must specify one of factory and required
-
- >>> components.registerHandler(handle)
- ... # doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: The adapter factory doesn't have a __component_adapts__
- attribute and no required specifications were specified
-
-Extending
----------
-
-Component-management objects can extend other component-management
-objects.
-
- >>> c1 = registry.Components('1')
- >>> c1.__bases__
- ()
-
- >>> c2 = registry.Components('2', (c1, ))
- >>> c2.__bases__ == (c1, )
- True
-
- >>> c1.registerUtility(tests.U1(1))
- Registered event:
- UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
-
- >>> c1.queryUtility(tests.I1)
- U1(1)
- >>> c2.queryUtility(tests.I1)
- U1(1)
- >>> c1.registerUtility(tests.U1(2))
- Unregistered event:
- UtilityRegistration(<Components 1>, I1, u'', 1, None, u'')
- Registered event:
- UtilityRegistration(<Components 1>, I1, u'', 2, None, u'')
-
- >>> c2.queryUtility(tests.I1)
- U1(2)
-
-We can use multiple inheritence:
-
- >>> c3 = registry.Components('3', (c1, ))
- >>> c4 = registry.Components('4', (c2, c3))
- >>> c4.queryUtility(tests.I1)
- U1(2)
-
- >>> c1.registerUtility(tests.U12(1), tests.I2)
- Registered event:
- UtilityRegistration(<Components 1>, I2, u'', 1, None, u'')
-
- >>> c4.queryUtility(tests.I2)
- U12(1)
-
- >>> c3.registerUtility(tests.U12(3), tests.I2)
- Registered event:
- UtilityRegistration(<Components 3>, I2, u'', 3, None, u'')
- >>> c4.queryUtility(tests.I2)
- U12(3)
-
- >>> c1.registerHandler(handle1, info="First handler")
- Registered event:
- HandlerRegistration(<Components 1>, [I1], u'', handle1, 'First handler')
-
- >>> c2.registerHandler(handle, required=[tests.U])
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- HandlerRegistration(<Components 2>, [zope.component.tests.U], u'',
- handle, u'')
-
- >>> @component.adapter(tests.I1)
- ... def handle3(x):
- ... print 'handle3', x
- >>> c3.registerHandler(handle3)
- Registered event:
- HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
-
- >>> @component.adapter(tests.I1)
- ... def handle4(x):
- ... print 'handle4', x
- >>> c4.registerHandler(handle4)
- Registered event:
- HandlerRegistration(<Components 4>, [I1], u'', handle4, u'')
-
- >>> c4.handle(tests.U1(1))
- handle1 U1(1)
- handle3 U1(1)
- handle (U1(1),)
- handle4 U1(1)
-
-Redispatch of registration events
----------------------------------
-
-Some handlers are available that, if registered, redispatch
-registration events to the objects being registered. They depend on
-being dispatched to by the object-event dispatcher:
-
- >>> from zope import component
- >>> import zope.component.event
- >>> zope.component.getGlobalSiteManager().registerHandler(
- ... zope.component.event.objectEventNotify)
- ... # doctest: +NORMALIZE_WHITESPACE
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [IObjectEvent], u'', objectEventNotify, u'')
-
-To see this, we'll first register a multi-handler to show is when
-handlers are called on 2 objects:
-
- >>> @zope.component.adapter(None, None)
- ... def double_handler(o1, o2):
- ... print 'Double dispatch:'
- ... print ' ', o1
- ... print ' ', o2
- >>> zope.component.getGlobalSiteManager().registerHandler(double_handler)
- ... # doctest: +NORMALIZE_WHITESPACE
- Double dispatch:
- HandlerRegistration(<BaseGlobalComponents base>,
- [Interface, Interface], u'', double_handler, u'')
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [Interface, Interface], u'', double_handler, u'')
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [Interface, Interface], u'', double_handler, u'')
-
-In the example above, the double_handler reported it's own registration. :)
-
-Now we'll register our handlers:
-
- >>> zope.component.getGlobalSiteManager().registerHandler(
- ... registry.dispatchUtilityRegistrationEvent)
- ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
- Double dispatch:
- ...
-
- >>> zope.component.getGlobalSiteManager().registerHandler(
- ... registry.dispatchAdapterRegistrationEvent)
- ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
- Double dispatch:
- ...
-
- >>> zope.component.getGlobalSiteManager().registerHandler(
- ... registry.dispatchSubscriptionAdapterRegistrationEvent)
- ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
- Double dispatch:
- ...
-
- >>> zope.component.getGlobalSiteManager().registerHandler(
- ... registry.dispatchHandlerRegistrationEvent)
- ... # doctest: +NORMALIZE_WHITESPACE
- Double dispatch:
- HandlerRegistration(<BaseGlobalComponents base>,
- [IHandlerRegistration, IRegistrationEvent], u'',
- dispatchHandlerRegistrationEvent, u'')
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [IHandlerRegistration, IRegistrationEvent], u'',
- dispatchHandlerRegistrationEvent, u'')
- Double dispatch:
- <function dispatchHandlerRegistrationEvent at 0xb799f72c>
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [IHandlerRegistration, IRegistrationEvent], u'',
- dispatchHandlerRegistrationEvent, u'')
- Registered event:
- HandlerRegistration(<BaseGlobalComponents base>,
- [IHandlerRegistration, IRegistrationEvent], u'',
- dispatchHandlerRegistrationEvent, u'')
-
-In the last example above, we can see that the registration of
-dispatchHandlerRegistrationEvent was handled by
-dispatchHandlerRegistrationEvent and redispatched. This can be seen
-in the second double-dispatch output, where the first argument is the
-object being registered, which is dispatchHandlerRegistrationEvent.
-
-If we change some other registrations, we can the double dispatch
-taking place:
-
- >>> components.registerUtility(u5)
- ... # doctest: +NORMALIZE_WHITESPACE
- Double dispatch:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
- Double dispatch:
- U1(5)
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
- Registered event:
- UtilityRegistration(<Components comps>, I1, u'', 5, None, u'')
-
- >>> components.registerAdapter(tests.A12_1)
- ... # doctest: +NORMALIZE_WHITESPACE
- Double dispatch:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
- Registered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
- Double dispatch:
- zope.component.tests.A12_1
- Registered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
- Registered event:
- AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
-
- >>> components.registerSubscriptionAdapter(tests.A1_2)
- ... # doctest: +NORMALIZE_WHITESPACE
- Double dispatch:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
- Double dispatch:
- zope.component.tests.A1_2
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
- Registered event:
- SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
diff --git a/src/zope/component/security.py b/src/zope/component/security.py
index 85230fe..5c9707e 100644
--- a/src/zope/component/security.py
+++ b/src/zope/component/security.py
@@ -13,13 +13,15 @@
##############################################################################
"""zope.security support for the configuration handlers
"""
-__docformat__ = "reStructuredText"
-
from zope.interface import providedBy
-from zope.proxy import ProxyBase, getProxiedObject
-from zope.security.adapter import LocatingTrustedAdapterFactory, \
- LocatingUntrustedAdapterFactory, TrustedAdapterFactory
-from zope.security.checker import Checker, CheckerPublic, InterfaceChecker
+from zope.proxy import ProxyBase
+from zope.proxy import getProxiedObject
+from zope.security.adapter import LocatingTrustedAdapterFactory
+from zope.security.adapter import LocatingUntrustedAdapterFactory
+from zope.security.adapter import TrustedAdapterFactory
+from zope.security.checker import Checker
+from zope.security.checker import CheckerPublic
+from zope.security.checker import InterfaceChecker
from zope.security.proxy import Proxy
@@ -60,7 +62,8 @@ def proxify(ob, checker=None, provides=None, permission=None):
if checker is None:
if provides is None or permission is None:
- raise ValueError, 'Required arguments: checker or both provides and permissions'
+ raise ValueError('Required arguments: '
+ 'checker or both provides and permissions')
if permission == PublicPermission:
permission = CheckerPublic
checker = InterfaceChecker(provides, permission)
@@ -84,82 +87,6 @@ def protectedFactory(original_factory, provides, permission):
return factory
def securityAdapterFactory(factory, permission, locate, trusted):
- """
- If a permission is provided when wrapping the adapter, it will be
- wrapped in a LocatingAdapterFactory.
-
- >>> class Factory:
- ... pass
-
- If both locate and trusted are False and a non-public
- permission is provided, then the factory is wrapped into a
- LocatingUntrustedAdapterFactory:
-
- >>> factory = securityAdapterFactory(Factory, 'zope.AnotherPermission',
- ... locate=False, trusted=False)
-
- >>> isinstance(factory, LocatingUntrustedAdapterFactory)
- True
-
- If a PublicPermission is provided, then the factory is not touched.
-
- >>> factory = securityAdapterFactory(Factory, PublicPermission,
- ... locate=False, trusted=False)
-
- >>> factory is Factory
- True
-
- Same for CheckerPublic:
-
- >>> factory = securityAdapterFactory(Factory, CheckerPublic,
- ... locate=False, trusted=False)
-
- >>> factory is Factory
- True
-
- If the permission is None, the factory isn't touched:
-
- >>> factory = securityAdapterFactory(Factory, None,
- ... locate=False, trusted=False)
-
- >>> factory is Factory
- True
-
- If the factory is trusted and a no permission is provided then the
- adapter is wrapped into a TrustedAdapterFactory:
-
- >>> factory = securityAdapterFactory(Factory, None,
- ... locate=False, trusted=True)
-
- >>> isinstance(factory, TrustedAdapterFactory)
- True
-
- Same for PublicPermission:
-
- >>> factory = securityAdapterFactory(Factory, PublicPermission,
- ... locate=False, trusted=True)
-
- >>> isinstance(factory, TrustedAdapterFactory)
- True
-
- Same for CheckerPublic:
-
- >>> factory = securityAdapterFactory(Factory, CheckerPublic,
- ... locate=False, trusted=True)
-
- >>> isinstance(factory, TrustedAdapterFactory)
- True
-
- If the factory is trusted and a locate is true, then the
- adapter is wrapped into a LocatingTrustedAdapterFactory:
-
- >>> factory = securityAdapterFactory(Factory, 'zope.AnotherPermission',
- ... locate=True, trusted=True)
-
- >>> isinstance(factory, LocatingTrustedAdapterFactory)
- True
-
- """
if permission == PublicPermission:
permission = CheckerPublic
if locate or (permission is not None and permission is not CheckerPublic):
diff --git a/src/zope/component/socketexample.txt b/src/zope/component/socketexample.txt
deleted file mode 100644
index 11bb6fd..0000000
--- a/src/zope/component/socketexample.txt
+++ /dev/null
@@ -1,597 +0,0 @@
-The Zope 3 Component Architecture (Socket Example)
-==================================================
-
-The component architecture provides an application framework that provides its
-functionality through loosely-connected components. A *component* can be any
-Python object and has a particular purpose associated with it. Thus, in a
-component-based applications you have many small component in contrast to
-classical object-oriented development, where you have a few big objects.
-
-Components communicate via specific APIs, which are formally defined by
-interfaces, which are provided by the `zope.interface` package. *Interfaces*
-describe the methods and properties that a component is expected to
-provide. They are also used as a primary mean to provide developer-level
-documentation for the components. For more details about interfaces see
-`zope/interface/README.txt`.
-
-The two main types of components are *adapters* and *utilities*. They will be
-discussed in detail later in this document. Both component types are managed
-by the *site manager*, with which you can register and access these
-components. However, most of the site manager's functionality is hidden behind
-the component architecture's public API, which is documented in
-`IComponentArchitecture`.
-
-
-Adapters
---------
-
-Adapters are a well-established pattern. An *adapter* uses an object providing
-one interface to produce an object that provides another interface. Here an
-example: Imagine that you purchased an electric shaver in the US, and thus
-you require the US socket type. You are now traveling in Germany, where another
-socket style is used. You will need a device, an adapter, that converts from
-the German to the US socket style.
-
-The functionality of adapters is actually natively provided by the
-`zope.interface` package and is thus well documented there. The `human.txt`
-file provides a gentle introduction to adapters, whereby `adapter.txt` is
-aimed at providing a comprehensive insight into adapters, but is too abstract
-for many as an initial read. Thus, we will only explain adapters in the context
-of the component architecture's API.
-
-So let's say that we have a German socket
-
- >>> from zope.interface import Interface, implements
-
- >>> class IGermanSocket(Interface):
- ... pass
-
- >>> class Socket(object):
- ... def __repr__(self):
- ... return '<instance of %s>' %self.__class__.__name__
-
- >>> class GermanSocket(Socket):
- ... """German wall socket."""
- ... implements(IGermanSocket)
-
-and we want to convert it to an US socket
-
- >>> class IUSSocket(Interface):
- ... pass
-
-so that our shaver can be used in Germany. So we go to a German electronics
-store to look for an adapter that we can plug in the wall:
-
- >>> class GermanToUSSocketAdapter(Socket):
- ... implements(IUSSocket)
- ... __used_for__ = IGermanSocket
- ...
- ... def __init__(self, socket):
- ... self.context = socket
-
-Note that I could have called the passed in socket any way I like, but
-`context` is the standard name accepted.
-
-
-Single Adapters
-~~~~~~~~~~~~~~~
-
-Before we can use the adapter, we have to buy it and make it part of our
-inventory. In the component architecture we do this by registering the adapter
-with the framework, more specifically with the global site manager:
-
- >>> import zope.component
- >>> gsm = zope.component.getGlobalSiteManager()
- >>> gsm.registerAdapter(GermanToUSSocketAdapter, (IGermanSocket,), IUSSocket)
-
-`zope.component` is the component architecture API that is being
-presented by this file. You registered an adapter from `IGermanSocket`
-to `IUSSocket` having no name (thus the empty string).
-
-Anyways, you finally get back to your hotel room and shave, since you have not
-been able to shave in the plane. In the bathroom you discover a socket:
-
- >>> bathroomDE = GermanSocket()
- >>> IGermanSocket.providedBy(bathroomDE)
- True
-
-You now insert the adapter in the German socket
-
- >>> bathroomUS = zope.component.getAdapter(bathroomDE, IUSSocket, '')
-
-so that the socket now provides the US version:
-
- >>> IUSSocket.providedBy(bathroomUS)
- True
-
-Now you can insert your shaver and get on with your day.
-
-After a week you travel for a couple of days to the Prague and you notice that
-the Czech have yet another socket type:
-
- >>> class ICzechSocket(Interface):
- ... pass
-
- >>> class CzechSocket(Socket):
- ... implements(ICzechSocket)
-
- >>> czech = CzechSocket()
-
-You try to find an adapter for your shaver in your bag, but you fail, since
-you do not have one:
-
- >>> zope.component.getAdapter(czech, IUSSocket, '') \
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<instance of CzechSocket>,
- <InterfaceClass __builtin__.IUSSocket>,
- '')
-
-or the more graceful way:
-
- >>> marker = object()
- >>> socket = zope.component.queryAdapter(czech, IUSSocket, '', marker)
- >>> socket is marker
- True
-
-In the component architecture API any `get*` method will fail with a specific
-exception, if a query failed, whereby methods starting with `query*` will
-always return a `default` value after a failure.
-
-
-Named Adapters
-~~~~~~~~~~~~~~
-
-You are finally back in Germany. You also brought your DVD player and a couple
-DVDs with you, which you would like to watch. Your shaver was able to convert
-automatically from 110 volts to 240 volts, but your DVD player cannot. So you
-have to buy another adapter that also handles converting the voltage and the
-frequency of the AC current:
-
- >>> class GermanToUSSocketAdapterAndTransformer(object):
- ... implements(IUSSocket)
- ... __used_for__ = IGermanSocket
- ...
- ... def __init__(self, socket):
- ... self.context = socket
-
-Now, we need a way to keep the two adapters apart. Thus we register them with
-a name:
-
- >>> gsm.registerAdapter(GermanToUSSocketAdapter,
- ... (IGermanSocket,), IUSSocket, 'shaver',)
- >>> gsm.registerAdapter(GermanToUSSocketAdapterAndTransformer,
- ... (IGermanSocket,), IUSSocket, 'dvd')
-
-Now we simply look up the adapters using their labels (called *name*):
-
- >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'shaver')
- >>> socket.__class__ is GermanToUSSocketAdapter
- True
-
- >>> socket = zope.component.getAdapter(bathroomDE, IUSSocket, 'dvd')
- >>> socket.__class__ is GermanToUSSocketAdapterAndTransformer
- True
-
-Clearly, we do not have an adapter for the MP3 player
-
- >>> zope.component.getAdapter(bathroomDE, IUSSocket, 'mp3') \
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<instance of GermanSocket>,
- <InterfaceClass __builtin__.IUSSocket>,
- 'mp3')
-
-but you could use the 'dvd' adapter in this case of course. ;)
-
-Sometimes you want to know all adapters that are available. Let's say you want
-to know about all the adapters that convert a German to a US socket type:
-
- >>> sockets = list(zope.component.getAdapters((bathroomDE,), IUSSocket))
- >>> len(sockets)
- 3
- >>> names = [name for name, socket in sockets]
- >>> names.sort()
- >>> names
- [u'', u'dvd', u'shaver']
-
-`zope.component.getAdapters()` returns a list of tuples. The first
-entry of the tuple is the name of the adapter and the second is the
-adapter itself.
-
-
-Multi-Adapters
-~~~~~~~~~~~~~~
-
-After watching all the DVDs you brought at least twice, you get tired of them
-and you want to listen to some music using your MP3 player. But darn, the MP3
-player plug has a ground pin and all the adapters you have do not support
-that:
-
- >>> class IUSGroundedSocket(IUSSocket):
- ... pass
-
-So you go out another time to buy an adapter. This time, however, you do not
-buy yet another adapter, but a piece that provides the grounding plug:
-
- >>> class IGrounder(Interface):
- ... pass
-
- >>> class Grounder(object):
- ... implements(IGrounder)
- ... def __repr__(self):
- ... return '<instance of Grounder>'
-
-
-Then together they will provided a grounded us socket:
-
- >>> class GroundedGermanToUSSocketAdapter(object):
- ... implements(IUSGroundedSocket)
- ... __used_for__ = (IGermanSocket, IGrounder)
- ... def __init__(self, socket, grounder):
- ... self.socket, self.grounder = socket, grounder
-
-You now register the combination, so that you know you can create a
-`IUSGroundedSocket`:
-
- >>> gsm.registerAdapter(GroundedGermanToUSSocketAdapter,
- ... (IGermanSocket, IGrounder), IUSGroundedSocket, 'mp3')
-
-Given the grounder
-
- >>> grounder = Grounder()
-
-and a German socket
-
- >>> livingroom = GermanSocket()
-
-we can now get a grounded US socket:
-
- >>> socket = zope.component.getMultiAdapter((livingroom, grounder),
- ... IUSGroundedSocket, 'mp3')
-
- >>> socket.__class__ is GroundedGermanToUSSocketAdapter
- True
- >>> socket.socket is livingroom
- True
- >>> socket.grounder is grounder
- True
-
-Of course, you do not have a 'dvd' grounded US socket available:
-
- >>> zope.component.getMultiAdapter((livingroom, grounder),
- ... IUSGroundedSocket, 'dvd') \
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: ((<instance of GermanSocket>,
- <instance of Grounder>),
- <InterfaceClass __builtin__.IUSGroundedSocket>,
- 'dvd')
-
-
- >>> socket = zope.component.queryMultiAdapter(
- ... (livingroom, grounder), IUSGroundedSocket, 'dvd', marker)
- >>> socket is marker
- True
-
-Again, you might want to read `adapter.txt` in `zope.interface` for a more
-comprehensive coverage of multi-adapters.
-
-Subscribers
------------
-
-While subscribers are directly supported by the adapter registry and are
-adapters for all theoretical purposes, practically it might be better to think
-of them as separate components. Subscribers are particularly useful for
-events.
-
-Let's say one of our adapters overheated and caused a small fire:
-
- >>> class IFire(Interface):
- ... pass
-
- >>> class Fire(object):
- ... implements(IFire)
-
- >>> fire = Fire()
-
-We want to use all available objects to put out the fire:
-
- >>> class IFireExtinguisher(Interface):
- ... def extinguish():
- ... pass
-
- >>> class FireExtinguisher(object):
- ... def __init__(self, fire):
- ... pass
- ... def extinguish(self):
- ... "Place extinguish code here."
- ... print 'Used ' + self.__class__.__name__ + '.'
-
-Here some specific methods to put out the fire:
-
- >>> class PowderExtinguisher(FireExtinguisher):
- ... pass
- >>> gsm.registerSubscriptionAdapter(PowderExtinguisher,
- ... (IFire,), IFireExtinguisher)
-
- >>> class Blanket(FireExtinguisher):
- ... pass
- >>> gsm.registerSubscriptionAdapter(Blanket, (IFire,), IFireExtinguisher)
-
- >>> class SprinklerSystem(FireExtinguisher):
- ... pass
- >>> gsm.registerSubscriptionAdapter(SprinklerSystem,
- ... (IFire,), IFireExtinguisher)
-
-Now let use all these things to put out the fire:
-
- >>> extinguishers = zope.component.subscribers((fire,), IFireExtinguisher)
- >>> extinguishers.sort()
- >>> for extinguisher in extinguishers:
- ... extinguisher.extinguish()
- Used Blanket.
- Used PowderExtinguisher.
- Used SprinklerSystem.
-
-If no subscribers are found for a particular object, then an empty list is
-returned:
-
- >>> zope.component.subscribers((object(),), IFireExtinguisher)
- []
-
-
-Utilities
----------
-
-Utilities are the second type of component, the component architecture
-implements. *Utilities* are simply components that provide an interface. When
-you register an utility, you always register an instance (in contrast to a
-factory for adapters) since the initialization and setup process of a utility
-might be complex and is not well defined. In some ways a utility is much more
-fundamental than an adapter, because an adapter cannot be used without another
-component, but a utility is always self-contained. I like to think of
-utilities as the foundation of your application and adapters as components
-extending beyond this foundation.
-
-Back to our story...
-
-After your vacation is over you fly back home to Tampa, Florida. But it is
-August now, the middle of the Hurricane season. And, believe it or not, you are
-worried that you will not be able to shave when the power goes out for several
-days. (You just hate wet shavers.)
-
-So you decide to go to your favorite hardware store and by a Diesel-powered
-electric generator. The generator provides of course a US-style socket:
-
- >>> class Generator(object):
- ... implements(IUSSocket)
- ... def __repr__(self):
- ... return '<instance of Generator>'
-
- >>> generator = Generator()
-
-Like for adapters, we now have to add the newly-acquired generator to our
-inventory by registering it as a utility:
-
- >>> gsm.registerUtility(generator, IUSSocket)
-
-We can now get the utility using
-
- >>> utility = zope.component.getUtility(IUSSocket)
- >>> utility is generator
- True
-
-As you can see, it is very simple to register and retrieve utilities. If a
-utility does not exist for a particular interface, such as the German socket,
-then the lookup fails
-
- >>> zope.component.getUtility(IGermanSocket)
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<InterfaceClass __builtin__.IGermanSocket>, '')
-
-or more gracefully when specifying a default value:
-
- >>> default = object()
- >>> utility = zope.component.queryUtility(IGermanSocket, default=default)
- >>> utility is default
- True
-
-Note: The only difference between `getUtility()` and `queryUtility()` is the
-fact that you can specify a default value for the latter function, so that it
-will never cause a `ComponentLookupError`.
-
-
-Named Utilities
-~~~~~~~~~~~~~~~
-
-It is often desirable to have several utilities providing the same interface
-per site. This way you can implement any sort of registry using utilities. For
-this reason, utilities -- like adapters -- can be named.
-
-In the context of our story, we might want to do the following: You really do
-not trust gas stations either. What if the roads are blocked after a hurricane
-and the gas stations run out of oil. So you look for another renewable power
-source. Then you think about solar panels! After a storm there is usually very
-nice weather, so why not? Via the Web you order a set of 110V/120W solar
-panels that provide a regular US-style socket as output:
-
- >>> class SolarPanel(object):
- ... implements(IUSSocket)
- ... def __repr__(self):
- ... return '<instance of Solar Panel>'
-
- >>> panel = SolarPanel()
-
-Once it arrives, we add it to our inventory:
-
- >>> gsm.registerUtility(panel, IUSSocket, 'Solar Panel')
-
-You can now access the solar panel using
-
- >>> utility = zope.component.getUtility(IUSSocket, 'Solar Panel')
- >>> utility is panel
- True
-
-Of course, if a utility is not available, then the lookup will simply fail
-
- >>> zope.component.getUtility(IUSSocket, 'Wind Mill')
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<InterfaceClass __builtin__.IUSSocket>, 'Wind Mill')
-
-or more gracefully when specifying a default value:
-
- >>> default = object()
- >>> utility = zope.component.queryUtility(IUSSocket, 'Wind Mill',
- ... default=default)
- >>> utility is default
- True
-
-Now you want to look at all the utilities you have for a particular kind. The
-following API function will return a list of name/utility pairs:
-
- >>> utils = list(zope.component.getUtilitiesFor(IUSSocket))
- >>> utils.sort()
- >>> utils #doctest: +NORMALIZE_WHITESPACE
- [(u'', <instance of Generator>),
- (u'Solar Panel', <instance of Solar Panel>)]
-
-Another method of looking up all utilities is by using
-`getAllUtilitiesRegisteredFor(iface)`. This function will return an iterable
-of utilities (without names); however, it will also return overridden
-utilities. If you are not using multiple site managers, you will not actually
-need this method.
-
- >>> utils = list(zope.component.getAllUtilitiesRegisteredFor(IUSSocket))
- >>> utils.sort()
- >>> utils
- [<instance of Generator>, <instance of Solar Panel>]
-
-
-Factories
-~~~~~~~~~
-
-A *factory* is a special kind of utility that exists to create other
-components. A factory is always identified by a name. It also provides a title
-and description and is able to tell the developer what interfaces the created
-object will provide. The advantage of using a factory to create an object
-instead of directly instantiating a class or executing any other callable is
-that we can refer to the factory by name. As long as the name stays fixed, the
-implementation of the callable can be renamed or moved without a breakage in
-code.
-
-Let's say that our solar panel comes in parts and they have to be
-assembled. This assembly would be done by a factory, so let's create one for
-the solar panel. To do this, we can use a standard implementation of the
-`IFactory` interface:
-
- >>> from zope.component.factory import Factory
- >>> factory = Factory(SolarPanel,
- ... 'Solar Panel',
- ... 'This factory creates a solar panel.')
-
-Optionally, I could have also specified the interfaces that the created object
-will provide, but the factory class is smart enough to determine the
-implemented interface from the class. We now register the factory:
-
- >>> from zope.component.interfaces import IFactory
- >>> gsm.registerUtility(factory, IFactory, 'SolarPanel')
-
-We can now get a list of interfaces the produced object will provide:
-
- >>> ifaces = zope.component.getFactoryInterfaces('SolarPanel')
- >>> IUSSocket in ifaces
- True
-
-By the way, this is equivalent to
-
- >>> ifaces2 = factory.getInterfaces()
- >>> ifaces is ifaces2
- True
-
-Of course you can also just create an object:
-
- >>> panel = zope.component.createObject('SolarPanel')
- >>> panel.__class__ is SolarPanel
- True
-
-Note: Ignore the first argument (`None`) for now; it is the context of the
-utility lookup, which is usually an optional argument, but cannot be in this
-case, since all other arguments beside the `name` are passed in as arguments
-to the specified callable.
-
-Once you register several factories
-
- >>> gsm.registerUtility(Factory(Generator), IFactory, 'Generator')
-
-you can also determine, which available factories will create objects
-providing a certain interface:
-
- >>> factories = zope.component.getFactoriesFor(IUSSocket)
- >>> factories = [(name, factory.__class__) for name, factory in factories]
- >>> factories.sort()
- >>> factories #doctest: +NORMALIZE_WHITESPACE
- [(u'Generator', <class 'zope.component.factory.Factory'>),
- (u'SolarPanel', <class 'zope.component.factory.Factory'>)]
-
-
-Site Managers
--------------
-
-Why do we need site managers? Why is the component architecture API not
-sufficient? Some applications, including Zope 3, have a concept of
-locations. It is often desirable to have different configurations for these
-location; this can be done by overwriting existing or adding new component
-registrations. Site managers in locations below the root location, should be
-able to delegate requests to their parent locations. The root site manager is
-commonly known as *global site manager*, since it is always available. You can
-always get the global site manager using the API:
-
- >>> gsm = zope.component.getGlobalSiteManager()
-
- >>> from zope.component import globalSiteManager
- >>> gsm is globalSiteManager
- True
- >>> from zope.component.interfaces import IComponentLookup
- >>> IComponentLookup.providedBy(gsm)
- True
- >>> from zope.component.interfaces import IComponents
- >>> IComponents.providedBy(gsm)
- True
-
-You can also lookup at site manager in a given context. The only requirement
-is that the context can be adapted to a site manager. So let's create a
-special site manager:
-
- >>> from zope.component.globalregistry import BaseGlobalComponents
- >>> sm = BaseGlobalComponents()
-
-Now we create a context that adapts to the site manager via the `__conform__`
-method as specified in PEP 246.
-
- >>> class Context(object):
- ... def __init__(self, sm):
- ... self.sm = sm
- ... def __conform__(self, interface):
- ... if interface.isOrExtends(IComponentLookup):
- ... return self.sm
-
-We now instantiate the `Context` with our special site manager:
-
- >>> context = Context(sm)
- >>> context.sm is sm
- True
-
-We can now ask for the site manager of this context:
-
- >>> lsm = zope.component.getSiteManager(context)
- >>> lsm is sm
- True
-
-The site manager instance `lsm` is formally known as a *local site manager* of
-`context`.
diff --git a/src/zope/component/standalonetests.py b/src/zope/component/standalonetests.py
index 9b8385a..3b3c8fe 100644
--- a/src/zope/component/standalonetests.py
+++ b/src/zope/component/standalonetests.py
@@ -1,54 +1,49 @@
"""
-Standalone Tests
+See: https://bugs.launchpad.net/zope3/+bug/98401
"""
-import unittest
-import doctest
import sys
import pickle
-if __name__ == "__main__":
- sys.path = pickle.loads(sys.stdin.read())
-
-from zope import interface
-from zope.component.testing import setUp, tearDown
-
-class I1(interface.Interface):
- pass
-
-class I2(interface.Interface):
- pass
-
-class Ob(object):
- interface.implements(I1)
- def __repr__(self):
- return '<instance Ob>'
-
-ob = Ob()
-
-class Comp(object):
- interface.implements(I2)
- def __init__(self, context):
- self.context = context
-
-def providing_adapter_sets_adapter_hook():
- """
- A side effect of importing installs the adapter hook. See
- http://www.zope.org/Collectors/Zope3-dev/674.
-
- >>> import zope.component
- >>> zope.component.provideAdapter(Comp, (I1,), I2)
- >>> adapter = I2(ob)
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is ob
- True
- """
-
-
-def test_suite():
- return unittest.TestSuite((
- doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
- ))
-
-if __name__ == "__main__":
- unittest.main(defaultTest='test_suite')
+def write(x):
+ sys.stdout.write('%s\n' % x)
+
+if __name__ == "__main__": #pragma NO COVER (runs in subprocess)
+ #sys.path = pickle.loads(sys.stdin.read())
+ write('XXXXXXXXXX')
+ for p in sys.path:
+ write('- %s' % p)
+ write('XXXXXXXXXX')
+
+ import zope
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class I1(Interface):
+ pass
+
+ class I2(Interface):
+ pass
+
+ @implementer(I1)
+ class Ob(object):
+ def __repr__(self):
+ return '<instance Ob>'
+
+ ob = Ob()
+
+ @implementer(I2)
+ class Comp(object):
+ def __init__(self, context):
+ self.context = context
+
+ write('YYYYYYYYY')
+ for p in zope.__path__:
+ write('- %s' % p)
+ write('YYYYYYYYY')
+ import zope.component
+
+ zope.component.provideAdapter(Comp, (I1,), I2)
+ adapter = I2(ob)
+ write('ZZZZZZZZ')
+ assert adapter.__class__ is Comp
+ assert adapter.context is ob
diff --git a/src/zope/component/testfiles/adapter.py b/src/zope/component/testfiles/adapter.py
index 1fcdaf9..6728db1 100644
--- a/src/zope/component/testfiles/adapter.py
+++ b/src/zope/component/testfiles/adapter.py
@@ -13,22 +13,25 @@
##############################################################################
"""Sample adapter class for testing
"""
-import zope.interface
-import zope.component
-import components
-class I1(zope.interface.Interface):
+from zope.interface import Interface
+from zope.interface import implementer
+
+from zope.component import adapter
+from zope.component.testfiles import components
+
+class I1(Interface):
pass
-class I2(zope.interface.Interface):
+class I2(Interface):
pass
-class I3(zope.interface.Interface):
+class I3(Interface):
def f1(): pass
def f2(): pass
def f3(): pass
-class IS(zope.interface.Interface):
+class IS(Interface):
pass
@@ -36,23 +39,27 @@ class Adapter(object):
def __init__(self, *args):
self.context = args
+@implementer(I1)
class A1(Adapter):
- zope.interface.implements(I1)
+ pass
+@implementer(I2)
class A2(Adapter):
- zope.interface.implements(I2)
+ pass
+@adapter(components.IContent, I1, I2)
+@implementer(I3)
class A3(Adapter):
- zope.component.adapts(components.IContent, I1, I2)
- zope.interface.implements(I3)
+ pass
class A4:
pass
a4 = A4()
+@implementer(I1, I2)
class A5:
- zope.interface.implements(I1, I2)
+ pass
a5 = A5()
diff --git a/src/zope/component/testfiles/components.py b/src/zope/component/testfiles/components.py
index 3967b1e..efbd2fb 100644
--- a/src/zope/component/testfiles/components.py
+++ b/src/zope/component/testfiles/components.py
@@ -13,8 +13,10 @@
##############################################################################
"""Components for testing
"""
-from zope.interface import Interface, Attribute, implements
-from zope.component import adapts
+from zope.interface import Interface
+from zope.interface import Attribute
+from zope.interface import implementer
+from zope.component import adapter
class IAppb(Interface):
a = Attribute('test attribute')
@@ -31,12 +33,14 @@ class IApp3(IAppb):
class IContent(Interface): pass
+@implementer(IContent)
class Content(object):
- implements(IContent)
+ pass
+@adapter(IContent)
+@implementer(IApp)
class Comp(object):
- adapts(IContent)
- implements(IApp)
+ pass
def __init__(self, *args):
# Ignore arguments passed to constructor
diff --git a/src/zope/component/testfiles/views.py b/src/zope/component/testfiles/views.py
index d395f9f..a017b5f 100644
--- a/src/zope/component/testfiles/views.py
+++ b/src/zope/component/testfiles/views.py
@@ -13,7 +13,10 @@
##############################################################################
"""Views test.
"""
-from zope.interface import Interface, implements, directlyProvides
+
+from zope.interface import Interface
+from zope.interface import implementer
+from zope.interface import directlyProvides
class Request(object):
@@ -29,8 +32,8 @@ class IV(Interface):
class IC(Interface): pass
+@implementer(IV)
class V1(object):
- implements(IV)
def __init__(self, context, request):
self.context = context
@@ -46,6 +49,7 @@ class VZMI(V1):
def index(self):
return 'ZMI here'
+@implementer(IV)
class R1(object):
def index(self):
@@ -57,7 +61,6 @@ class R1(object):
def __init__(self, request):
pass
- implements(IV)
class RZMI(R1):
pass
diff --git a/src/zope/component/testing.py b/src/zope/component/testing.py
index 5fde361..d49f1cb 100644
--- a/src/zope/component/testing.py
+++ b/src/zope/component/testing.py
@@ -18,7 +18,17 @@
import zope.component.event
# we really don't need special setup now:
-from zope.testing.cleanup import CleanUp as PlacelessSetup
+try:
+ from zope.testing.cleanup import CleanUp as PlacelessSetup
+except ImportError:
+ class PlacelessSetup(object):
+ def cleanUp(self):
+ from zope.component.globalregistry import base
+ base.__init__('base')
+ def setUp(self):
+ self.cleanUp()
+ def tearDown(self):
+ self.cleanUp()
def setUp(test=None):
PlacelessSetup().setUp()
diff --git a/src/zope/component/testlayer.py b/src/zope/component/testlayer.py
index fb036d2..c73c959 100644
--- a/src/zope/component/testlayer.py
+++ b/src/zope/component/testlayer.py
@@ -15,7 +15,12 @@
import os
from zope.configuration import xmlconfig, config
-from zope.testing.cleanup import cleanUp
+try:
+ from zope.testing.cleanup import cleanUp
+except ImportError:
+ def cleanUp():
+ pass
+
from zope.component import provideHandler
from zope.component.hooks import setHooks
from zope.component.eventtesting import events, clearEvents
diff --git a/src/zope/component/testlayer.txt b/src/zope/component/testlayer.txt
deleted file mode 100644
index 1246ba7..0000000
--- a/src/zope/component/testlayer.txt
+++ /dev/null
@@ -1,100 +0,0 @@
-Layers
-======
-
-zope.component.testlayer defines two things:
-
-* a LayerBase that makes it easier and saner to use zope.testing's
- test layers.
-
-* a ZCMLLayer which lets you implement a layer that loads up some
- ZCML.
-
-LayerBase
----------
-
-We check whether our LayerBase can be used to create layers of our
-own. We do this simply by subclassing:
-
- >>> from zope.component.testlayer import LayerBase
- >>> class OurLayer(LayerBase):
- ... def setUp(self):
- ... super(OurLayer, self).setUp()
- ... print "setUp called"
- ... def tearDown(self):
- ... super(OurLayer, self).tearDown()
- ... print "tearDown called"
- ... def testSetUp(self):
- ... super(OurLayer, self).testSetUp()
- ... print "testSetUp called"
- ... def testTearDown(self):
- ... super(OurLayer, self).testTearDown()
- ... print "testTearDown called"
-
-Note that if we wanted to ensure that the methods of the superclass
-were called we have to use super(). In this case we actually wouldn't
-need to, as these methods do nothing at all, but we just ensure that
-they are there in the first place.
-
-Let's instantiate our layer. We need to supply it with the package the
-layer is defined in::
-
- >>> import zope.component
- >>> layer = OurLayer(zope.component)
-
-Now we run some tests with this layer:
-
- >>> import unittest
- >>> class TestCase(unittest.TestCase):
- ... layer = layer
- ...
- ... def testFoo(self):
- ... print "testFoo"
- >>> suite = unittest.TestSuite()
- >>> suite.addTest(unittest.makeSuite(TestCase))
- >>> from zope.testrunner.runner import Runner
- >>> runner = Runner(args=[], found_suites=[suite])
- >>> succeeded = runner.run()
- Running zope.component.OurLayer tests:
- Set up zope.component.OurLayer setUp called
- in ... seconds.
- testSetUp called
- testFoo
- testTearDown called
- Ran 1 tests with 0 failures and 0 errors in ... seconds.
- Tearing down left over layers:
- Tear down zope.component.OurLayer tearDown called
- in ... seconds.
-
-ZCMLLayer
----------
-
-We now want a layer that loads up some ZCML from a file. The default
-is ``ftesting.zcml``, but here we'll load a test ``testlayer.zcml``.
-
- >>> from zope.component.testlayer import ZCMLFileLayer
- >>> zcml_file_layer = ZCMLFileLayer(
- ... zope.component.testfiles,
- ... 'testlayer.zcml')
-
- >>> class TestCase(unittest.TestCase):
- ... layer = zcml_file_layer
- ...
- ... def testFoo(self):
- ... # we should now have the adapter registered
- ... from zope import component
- ... from zope.component.testfiles import components
- ... self.assert_(isinstance(
- ... components.IApp2(components.content), components.Comp2))
-
-Since the ZCML sets up an adapter, we expect the tests to pass::
-
- >>> suite = unittest.TestSuite()
- >>> suite.addTest(unittest.makeSuite(TestCase))
- >>> runner = Runner(args=[], found_suites=[suite])
- >>> succeeded = runner.run()
- Running zope.component.testfiles.ZCMLFileLayer tests:
- Set up zope.component.testfiles.ZCMLFileLayer in ... seconds.
- Ran 1 tests with 0 failures and 0 errors in ... seconds.
- Tearing down left over layers:
- Tear down zope.component.testfiles.ZCMLFileLayer in ... seconds.
-
diff --git a/src/zope/component/tests.py b/src/zope/component/tests.py
deleted file mode 100644
index c8c2906..0000000
--- a/src/zope/component/tests.py
+++ /dev/null
@@ -1,1748 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002, 2009 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Component Architecture Tests
-"""
-
-import __future__
-
-import doctest
-import persistent
-import re
-import sys
-import unittest
-import transaction
-from cStringIO import StringIO
-
-from zope import interface, component
-from zope.interface.verify import verifyObject
-from zope.interface.interfaces import IInterface
-from zope.testing import renormalizing
-from zope.testrunner.layer import UnitTests
-
-from zope.component.interfaces import ComponentLookupError
-from zope.component.interfaces import IComponentArchitecture
-from zope.component.interfaces import IComponentLookup
-from zope.component.testing import setUp, tearDown, PlacelessSetup
-import zope.component.persistentregistry
-import zope.component.globalregistry
-
-from zope.configuration.xmlconfig import XMLConfig, xmlconfig
-from zope.configuration.exceptions import ConfigurationError
-from zope.security.checker import ProxyFactory
-
-from zope.component.testfiles.adapter import A1, A2, A3
-from zope.component.testfiles.components import IContent, Content
-from zope.component.testfiles.components import IApp
-from zope.component.testfiles.views import Request, IC, IV, V1, R1, IR
-
-# side effect gets component-based event dispatcher installed.
-# we should obviously make this more explicit
-import zope.component.event
-
-class I1(interface.Interface):
- pass
-class I2(interface.Interface):
- pass
-class I2e(I2):
- pass
-class I3(interface.Interface):
- pass
-
-class ITestType(IInterface):
- pass
-
-class U:
-
- def __init__(self, name):
- self.__name__ = name
-
- def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__, self.__name__)
-
-class U1(U):
- interface.implements(I1)
-
-class U12(U):
- interface.implements(I1, I2)
-
-class IA1(interface.Interface):
- pass
-
-class IA2(interface.Interface):
- pass
-
-class IA3(interface.Interface):
- pass
-
-class A:
-
- def __init__(self, *context):
- self.context = context
-
- def __repr__(self):
- return "%s%r" % (self.__class__.__name__, self.context)
-
-class A12_1(A):
- component.adapts(I1, I2)
- interface.implements(IA1)
-
-class A12_(A):
- component.adapts(I1, I2)
-
-class A_2(A):
- interface.implements(IA2)
-
-class A_3(A):
- interface.implements(IA3)
-
-class A1_12(U):
- component.adapts(I1)
- interface.implements(IA1, IA2)
-
-class A1_2(U):
- component.adapts(I1)
- interface.implements(IA2)
-
-class A1_23(U):
- component.adapts(I1)
- interface.implements(IA1, IA3)
-
-def noop(*args):
- pass
-
-@component.adapter(I1)
-def handle1(x):
- print 'handle1', x
-
-def handle(*objects):
- print 'handle', objects
-
-@component.adapter(I1)
-def handle3(x):
- print 'handle3', x
-
-@component.adapter(I1)
-def handle4(x):
- print 'handle4', x
-
-class Ob(object):
- interface.implements(I1)
- def __repr__(self):
- return '<instance Ob>'
-
-
-ob = Ob()
-
-class Ob2(object):
- interface.implements(I2)
- def __repr__(self):
- return '<instance Ob2>'
-
-class Comp(object):
- interface.implements(I2)
- def __init__(self, context):
- self.context = context
-
-comp = Comp(1)
-
-class Comp2(object):
- interface.implements(I3)
- def __init__(self, context):
- self.context = context
-
-
-class ConformsToIComponentLookup(object):
- """This object allows the sitemanager to conform/adapt to
- `IComponentLookup` and thus to itself."""
-
- def __init__(self, sitemanager):
- self.sitemanager = sitemanager
-
- def __conform__(self, interface):
- """This method is specified by the adapter PEP to do the adaptation."""
- if interface is IComponentLookup:
- return self.sitemanager
-
-
-def testInterfaces():
- """Ensure that the component architecture API is provided by
- `zope.component`.
-
- >>> verifyObject(IComponentArchitecture, component)
- True
- """
-
-def test_getGlobalSiteManager():
- """One of the most important functions is to get the global site manager.
-
- >>> from zope.component.interfaces import IComponentLookup
- >>> from zope.component.globalregistry import base
-
- Get the global site manager via the CA API function:
-
- >>> gsm = component.getGlobalSiteManager()
-
- Make sure that the global site manager implements the correct interface
- and is the global site manager instance we expect to get.
-
- >>> IComponentLookup.providedBy(gsm)
- True
- >>> base is gsm
- True
-
- Finally, ensure that we always get the same global site manager, otherwise
- our component registry will always be reset.
-
- >>> component.getGlobalSiteManager() is gsm
- True
- """
-
-def test_getSiteManager():
- """Make sure that `getSiteManager()` always returns the correct site
- manager instance.
-
- We don't know anything about the default service manager, except that it
- is an `IComponentLookup`.
-
- >>> from zope.component.interfaces import IComponentLookup
- >>> IComponentLookup.providedBy(component.getSiteManager())
- True
-
- Calling `getSiteManager()` with no args is equivalent to calling it with a
- context of `None`.
-
- >>> component.getSiteManager() is component.getSiteManager(None)
- True
-
- If the context passed to `getSiteManager()` is not `None`, it is
- adapted to `IComponentLookup` and this adapter returned. So, we
- create a context that can be adapted to `IComponentLookup` using
- the `__conform__` API.
-
- Let's create the simplest stub-implementation of a site manager possible:
-
- >>> sitemanager = object()
-
- Now create a context that knows how to adapt to our newly created site
- manager.
-
- >>> context = ConformsToIComponentLookup(sitemanager)
-
- Now make sure that the `getSiteManager()` API call returns the correct
- site manager.
-
- >>> component.getSiteManager(context) is sitemanager
- True
-
- Using a context that is not adaptable to `IComponentLookup` should fail.
-
- >>> component.getSiteManager(ob) #doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
- Traceback (most recent call last):
- ...
- ComponentLookupError: ('Could not adapt', <instance Ob>,
- <InterfaceClass zope...interfaces.IComponentLookup>)
- """
-
-def testAdapterInContext(self):
- """The `getAdapterInContext()` and `queryAdapterInContext()` API functions
- do not only use the site manager to look up the adapter, but first tries
- to use the `__conform__()` method of the object to find an adapter as
- specified by PEP 246.
-
- Let's start by creating a component that support's the PEP 246's
- `__conform__()` method:
-
- >>> class Component(object):
- ... interface.implements(I1)
- ... def __conform__(self, iface, default=None):
- ... if iface == I2:
- ... return 42
- ... def __repr__(self):
- ... return '''<Component implementing 'I1'>'''
-
- >>> ob = Component()
-
- We also gave the component a custom representation, so it will be easier
- to use in these tests.
-
- We now have to create a site manager (other than the default global one)
- with which we can register adapters for `I1`.
-
- >>> from zope.component.globalregistry import BaseGlobalComponents
- >>> sitemanager = BaseGlobalComponents()
-
- Now we create a new `context` that knows how to get to our custom site
- manager.
-
- >>> context = ConformsToIComponentLookup(sitemanager)
-
- We now register an adapter from `I1` to `I3`:
-
- >>> sitemanager.registerAdapter(lambda x: 43, (I1,), I3, '')
-
- If an object implements the interface you want to adapt to,
- `getAdapterInContext()` should simply return the object.
-
- >>> component.getAdapterInContext(ob, I1, context)
- <Component implementing 'I1'>
- >>> component.queryAdapterInContext(ob, I1, context)
- <Component implementing 'I1'>
-
- If an object conforms to the interface you want to adapt to,
- `getAdapterInContext()` should simply return the conformed object.
-
- >>> component.getAdapterInContext(ob, I2, context)
- 42
- >>> component.queryAdapterInContext(ob, I2, context)
- 42
-
- If an adapter isn't registered for the given object and interface, and you
- provide no default, raise ComponentLookupError...
-
- >>> class I4(interface.Interface):
- ... pass
-
- >>> component.getAdapterInContext(ob, I4, context) \\
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<Component implementing 'I1'>,
- <InterfaceClass zope.component.tests.I4>)
-
- ...otherwise, you get the default:
-
- >>> component.queryAdapterInContext(ob, I4, context, 44)
- 44
-
- If you ask for an adapter for which something's registered you get the
- registered adapter
-
- >>> component.getAdapterInContext(ob, I3, context)
- 43
- >>> component.queryAdapterInContext(ob, I3, context)
- 43
- """
-
-def testAdapter():
- """The `getAdapter()` and `queryAdapter()` API functions are similar to
- `{get|query}AdapterInContext()` functions, except that they do not care
- about the `__conform__()` but also handle named adapters. (Actually, the
- name is a required argument.)
-
- If an adapter isn't registered for the given object and interface, and you
- provide no default, raise `ComponentLookupError`...
-
- >>> component.getAdapter(ob, I2, '') #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: (<instance Ob>,
- <InterfaceClass zope.component.tests.I2>,
- '')
-
- ...otherwise, you get the default
-
- >>> component.queryAdapter(ob, I2, '', '<default>')
- '<default>'
-
- Now get the global site manager and register an adapter from `I1` to `I2`
- without a name:
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, (I1,), I2, '')
-
- You should get a sensible error message if you forget that the 'requires'
- argument is supposed to be a sequence
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, I1, I2, '')
- Traceback (most recent call last):
- ...
- TypeError: the required argument should be a list of interfaces, not a single interface
-
- You can now simply access the adapter using the `getAdapter()` API
- function:
-
- >>> adapter = component.getAdapter(ob, I2, '')
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is ob
- True
- """
-
-def testInterfaceCall():
- """Here we test the `adapter_hook()` function that we registered with the
- `zope.interface` adapter hook registry, so that we can call interfaces to
- do adaptation.
-
- First, we need to register an adapter:
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, [I1], I2, '')
-
- Then we try to adapt `ob` to provide an `I2` interface by calling the `I2`
- interface with the obejct as first argument:
-
- >>> adapter = I2(ob)
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is ob
- True
-
- If no adapter is found, a `TypeError is raised...
-
- >>> I1(Ob2()) #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt', <instance Ob2>,
- <InterfaceClass zope.component.tests.I1>)
-
- ...unless we specify an alternative adapter:
-
- >>> marker = object()
- >>> I2(object(), marker) is marker
- True
- """
-
-def testNamedAdapter():
- """Make sure that adapters with names are correctly selected from the
- registry.
-
- First we register some named adapter:
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... lambda x: 0, [I1], I2, 'foo')
-
- If an adapter isn't registered for the given object and interface,
- and you provide no default, raise `ComponentLookupError`...
-
- >>> component.getAdapter(ob, I2, 'bar') \\
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError:
- (<instance Ob>, <InterfaceClass zope.component.tests.I2>, 'bar')
-
- ...otherwise, you get the default
-
- >>> component.queryAdapter(ob, I2, 'bar', '<default>')
- '<default>'
-
- But now we register an adapter for the object having the correct name
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, [I1], I2, 'bar')
-
- so that the lookup succeeds:
-
- >>> adapter = component.getAdapter(ob, I2, 'bar')
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is ob
- True
- """
-
-def testMultiAdapter():
- """Adapting a combination of 2 objects to an interface
-
- Multi-adapters adapt one or more objects to another interface. To make
- this demonstration non-trivial, we need to create a second object to be
- adapted:
-
- >>> ob2 = Ob2()
-
- Like for regular adapters, if an adapter isn't registered for the given
- objects and interface, and you provide no default, raise
- `ComponentLookupError`...
-
- >>> component.getMultiAdapter((ob, ob2), I3) \\
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError:
- ((<instance Ob>, <instance Ob2>),
- <InterfaceClass zope.component.tests.I3>,
- u'')
-
- ...otherwise, you get the default
-
- >>> component.queryMultiAdapter((ob, ob2), I3, default='<default>')
- '<default>'
-
- Note that the name is not a required attribute here.
-
- To test multi-adapters, we also have to create an adapter class that
- handles to context objects:
-
- >>> class DoubleAdapter(object):
- ... interface.implements(I3)
- ... def __init__(self, first, second):
- ... self.first = first
- ... self.second = second
-
- Now we can register the multi-adapter using
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... DoubleAdapter, (I1, I2), I3, '')
-
- Notice how the required interfaces are simply provided by a tuple. Now we
- can get the adapter:
-
- >>> adapter = component.getMultiAdapter((ob, ob2), I3)
- >>> adapter.__class__ is DoubleAdapter
- True
- >>> adapter.first is ob
- True
- >>> adapter.second is ob2
- True
- """
-
-def testAdapterForInterfaceNone():
- """Providing an adapter for None says that your adapter can adapt anything
- to `I2`.
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, (None,), I2, '')
-
- >>> adapter = I2(ob)
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is ob
- True
-
- It can really adapt any arbitrary object:
-
- >>> something = object()
- >>> adapter = I2(something)
- >>> adapter.__class__ is Comp
- True
- >>> adapter.context is something
- True
- """
-
-def testGetAdapters():
- """It is sometimes desireable to get a list of all adapters that are
- registered for a particular output interface, given a set of
- objects.
-
- Let's register some adapters first:
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, [I1], I2, '')
- >>> component.getGlobalSiteManager().registerAdapter(
- ... Comp, [None], I2, 'foo')
-
- Now we get all the adapters that are registered for `ob` that provide
- `I2`:
-
- >>> adapters = sorted(component.getAdapters((ob,), I2))
- >>> [(name, adapter.__class__.__name__) for name, adapter in adapters]
- [(u'', 'Comp'), (u'foo', 'Comp')]
-
- Note that the output doesn't include None values. If an adapter
- factory returns None, it is as if it wasn't present.
-
- >>> component.getGlobalSiteManager().registerAdapter(
- ... lambda context: None, [I1], I2, 'nah')
- >>> adapters = sorted(component.getAdapters((ob,), I2))
- >>> [(name, adapter.__class__.__name__) for name, adapter in adapters]
- [(u'', 'Comp'), (u'foo', 'Comp')]
-
- """
-
-def testUtility():
- """Utilities are components that simply provide an interface. They are
- instantiated at the time or before they are registered. Here we test the
- simple query interface.
-
- Before we register any utility, there is no utility available, of
- course. The pure instatiation of an object does not make it a utility. If
- you do not specify a default, you get a `ComponentLookupError`...
-
- >>> component.getUtility(I1) #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError: \
- (<InterfaceClass zope.component.tests.I1>, '')
-
- ...otherwise, you get the default
-
- >>> component.queryUtility(I1, default='<default>')
- '<default>'
- >>> component.queryUtility(I2, default='<default>')
- '<default>'
-
- Now we declare `ob` to be the utility providing `I1`
-
- >>> component.getGlobalSiteManager().registerUtility(ob, I1)
-
- so that the component is now available:
-
- >>> component.getUtility(I1) is ob
- True
- """
-
-def testNamedUtility():
- """Like adapters, utilities can be named.
-
- Just because you register an utility having no name
-
- >>> component.getGlobalSiteManager().registerUtility(ob, I1)
-
- does not mean that they are available when you specify a name:
-
- >>> component.getUtility(I1, name='foo') \\
- ... #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError:
- (<InterfaceClass zope.component.tests.I1>, 'foo')
-
-
- ...otherwise, you get the default
-
- >>> component.queryUtility(I1, name='foo', default='<default>')
- '<default>'
-
- Registering the utility under the correct name
-
- >>> component.getGlobalSiteManager().registerUtility(
- ... ob, I1, name='foo')
-
- really helps:
-
- >>> component.getUtility(I1, 'foo') is ob
- True
- """
-
-def test_getAllUtilitiesRegisteredFor():
- """Again, like for adapters, it is often useful to get a list of all
- utilities that have been registered for a particular interface. Utilities
- providing a derived interface are also listed.
-
- Thus, let's create a derivative interface of `I1`:
-
- >>> class I11(I1):
- ... pass
-
- >>> class Ob11(Ob):
- ... interface.implements(I11)
-
- >>> ob11 = Ob11()
- >>> ob_bob = Ob()
-
- Now we register the new utilities:
-
- >>> gsm = component.getGlobalSiteManager()
- >>> gsm.registerUtility(ob, I1)
- >>> gsm.registerUtility(ob11, I11)
- >>> gsm.registerUtility(ob_bob, I1, name='bob')
- >>> gsm.registerUtility(Comp(2), I2)
-
- We can now get all the utilities that provide interface `I1`:
-
- >>> uts = list(component.getAllUtilitiesRegisteredFor(I1))
- >>> uts = sorted([util.__class__.__name__ for util in uts])
- >>> uts
- ['Ob', 'Ob', 'Ob11']
-
- Note that `getAllUtilitiesRegisteredFor()` does not return the names of
- the utilities.
- """
-
-def testNotBrokenWhenNoSiteManager():
- """Make sure that the adapter lookup is not broken, when no site manager
- is available.
-
- Both of those things emit `DeprecationWarnings`.
-
- >>> I2(ob) #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- TypeError: ('Could not adapt',
- <instance Ob>,
- <InterfaceClass zope.component.tests.I2>)
-
-
- >>> I2(ob, 42)
- 42
- """
-
-
-def testNo__component_adapts__leakage():
- """
- We want to make sure that an `adapts()` call in a class definition
- doesn't affect instances.
-
- >>> class C:
- ... component.adapts()
-
- >>> C.__component_adapts__
- ()
- >>> C().__component_adapts__
- Traceback (most recent call last):
- ...
- AttributeError: __component_adapts__
- """
-
-def test_ability_to_pickle_globalsitemanager():
- """
- We need to make sure that it is possible to pickle the global site manager
- and its two global adapter registries.
-
- >>> from zope.component import globalSiteManager
- >>> import cPickle
- >>> pickle = cPickle.dumps(globalSiteManager)
- >>> sm = cPickle.loads(pickle)
- >>> sm is globalSiteManager
- True
-
- Now let's ensure that the registries themselves can be pickled as well:
-
- >>> pickle = cPickle.dumps(globalSiteManager.adapters)
- >>> adapters = cPickle.loads(pickle)
- >>> adapters is globalSiteManager.adapters
- True
- """
-
-def test_persistent_component_managers():
- """
-Here, we'll demonstrate that changes work even when data are stored in
-a database and when accessed from multiple connections.
-
-Start by setting up a database and creating two transaction
-managers and database connections to work with.
-
- >>> import ZODB.tests.util
- >>> db = ZODB.tests.util.DB()
- >>> import transaction
- >>> t1 = transaction.TransactionManager()
- >>> c1 = db.open(transaction_manager=t1)
- >>> r1 = c1.root()
- >>> t2 = transaction.TransactionManager()
- >>> c2 = db.open(transaction_manager=t2)
- >>> r2 = c2.root()
-
-Create a set of components registries in the database, alternating
-connections.
-
- >>> from zope.component.persistentregistry import PersistentComponents
-
- >>> _ = t1.begin()
- >>> r1[1] = PersistentComponents('1')
- >>> t1.commit()
-
- >>> _ = t2.begin()
- >>> r2[2] = PersistentComponents('2', (r2[1], ))
- >>> t2.commit()
-
- >>> _ = t1.begin()
- >>> r1[3] = PersistentComponents('3', (r1[1], ))
- >>> t1.commit()
-
- >>> _ = t2.begin()
- >>> r2[4] = PersistentComponents('4', (r2[2], r2[3]))
- >>> t2.commit()
-
- >>> _ = t1.begin()
- >>> r1[1].__bases__
- ()
- >>> r1[2].__bases__ == (r1[1], )
- True
-
- >>> r1[1].registerUtility(U1(1))
- >>> r1[1].queryUtility(I1)
- U1(1)
- >>> r1[2].queryUtility(I1)
- U1(1)
- >>> t1.commit()
-
- >>> _ = t2.begin()
- >>> r2[1].registerUtility(U1(2))
- >>> r2[2].queryUtility(I1)
- U1(2)
-
- >>> r2[4].queryUtility(I1)
- U1(2)
- >>> t2.commit()
-
-
- >>> _ = t1.begin()
- >>> r1[1].registerUtility(U12(1), I2)
- >>> r1[4].queryUtility(I2)
- U12(1)
- >>> t1.commit()
-
-
- >>> _ = t2.begin()
- >>> r2[3].registerUtility(U12(3), I2)
- >>> r2[4].queryUtility(I2)
- U12(3)
- >>> t2.commit()
-
- >>> _ = t1.begin()
-
- >>> r1[1].registerHandler(handle1, info="First handler")
- >>> r1[2].registerHandler(handle, required=[U])
-
- >>> r1[3].registerHandler(handle3)
-
- >>> r1[4].registerHandler(handle4)
-
- >>> r1[4].handle(U1(1))
- handle1 U1(1)
- handle3 U1(1)
- handle (U1(1),)
- handle4 U1(1)
-
- >>> t1.commit()
-
- >>> _ = t2.begin()
- >>> r2[4].handle(U1(1))
- handle1 U1(1)
- handle3 U1(1)
- handle (U1(1),)
- handle4 U1(1)
- >>> t2.abort()
-
- >>> db.close()
- """
-
-def persistent_registry_doesnt_scew_up_subsribers():
- """
- >>> import ZODB.tests.util
- >>> db = ZODB.tests.util.DB()
- >>> import transaction
- >>> t1 = transaction.TransactionManager()
- >>> c1 = db.open(transaction_manager=t1)
- >>> r1 = c1.root()
- >>> t2 = transaction.TransactionManager()
- >>> c2 = db.open(transaction_manager=t2)
- >>> r2 = c2.root()
-
- >>> from zope.component.persistentregistry import PersistentComponents
-
- >>> _ = t1.begin()
- >>> r1[1] = PersistentComponents('1')
- >>> r1[1].registerHandler(handle1)
- >>> r1[1].registerSubscriptionAdapter(handle1, provided=I2)
- >>> _ = r1[1].unregisterHandler(handle1)
- >>> _ = r1[1].unregisterSubscriptionAdapter(handle1, provided=I2)
- >>> t1.commit()
- >>> _ = t1.begin()
- >>> r1[1].registerHandler(handle1)
- >>> r1[1].registerSubscriptionAdapter(handle1, provided=I2)
- >>> t1.commit()
-
- >>> _ = t2.begin()
- >>> len(list(r2[1].registeredHandlers()))
- 1
- >>> len(list(r2[1].registeredSubscriptionAdapters()))
- 1
- >>> t2.abort()
-
- """
-
-
-
-class GlobalRegistry:
- pass
-
-base = zope.component.globalregistry.GlobalAdapterRegistry(
- GlobalRegistry, 'adapters')
-GlobalRegistry.adapters = base
-def clear_base():
- base.__init__(GlobalRegistry, 'adapters')
-
-class IFoo(interface.Interface):
- pass
-class Foo(persistent.Persistent):
- interface.implements(IFoo)
- name = ''
- def __init__(self, name=''):
- self.name = name
-
- def __repr__(self):
- return 'Foo(%r)' % self.name
-
-def test_deghostification_of_persistent_adapter_registries():
- """
-
-We want to make sure that we see updates corrextly.
-
- >>> len(base._v_subregistries)
- 0
-
- >>> import ZODB.tests.util
- >>> db = ZODB.tests.util.DB()
- >>> tm1 = transaction.TransactionManager()
- >>> c1 = db.open(transaction_manager=tm1)
- >>> r1 = zope.component.persistentregistry.PersistentAdapterRegistry(
- ... (base,))
- >>> r2 = zope.component.persistentregistry.PersistentAdapterRegistry((r1,))
- >>> c1.root()[1] = r1
- >>> c1.root()[2] = r2
- >>> tm1.commit()
- >>> r1._p_deactivate()
-
- >>> len(base._v_subregistries)
- 0
-
- >>> tm2 = transaction.TransactionManager()
- >>> c2 = db.open(transaction_manager=tm2)
- >>> r1 = c2.root()[1]
- >>> r2 = c2.root()[2]
-
- >>> r1.lookup((), IFoo, '')
-
- >>> base.register((), IFoo, '', Foo(''))
- >>> r1.lookup((), IFoo, '')
- Foo('')
-
- >>> r2.lookup((), IFoo, '1')
-
- >>> r1.register((), IFoo, '1', Foo('1'))
-
- >>> r2.lookup((), IFoo, '1')
- Foo('1')
-
- >>> r1.lookup((), IFoo, '2')
- >>> r2.lookup((), IFoo, '2')
-
- >>> base.register((), IFoo, '2', Foo('2'))
-
- >>> r1.lookup((), IFoo, '2')
- Foo('2')
-
- >>> r2.lookup((), IFoo, '2')
- Foo('2')
-
-Cleanup:
-
- >>> db.close()
- >>> clear_base()
-
- """
-
-
-def test_multi_handler_unregistration():
- """
- There was a bug where multiple handlers for the same required
- specification would all be removed when one of them was
- unregistered:
-
- >>> class I(zope.interface.Interface):
- ... pass
- >>> def factory1(event):
- ... print "| Factory 1 is here"
- >>> def factory2(event):
- ... print "| Factory 2 is here"
- >>> class Event(object):
- ... zope.interface.implements(I)
- >>> from zope.interface.registry import Components
- >>> registry = Components()
- >>> registry.registerHandler(factory1, [I,])
- >>> registry.registerHandler(factory2, [I,])
- >>> registry.handle(Event())
- | Factory 1 is here
- | Factory 2 is here
- >>> registry.unregisterHandler(factory1, [I,])
- True
- >>> registry.handle(Event())
- | Factory 2 is here
- """
-
-def test_next_utilities():
- """
- It is common for a utility to delegate its answer to a utility
- providing the same interface in one of the component registry's
- bases. Let's first create a global utility::
-
- >>> import zope.interface
- >>> class IMyUtility(zope.interface.Interface):
- ... pass
-
- >>> class MyUtility(ConformsToIComponentLookup):
- ... zope.interface.implements(IMyUtility)
- ... def __init__(self, id, sm):
- ... self.id = id
- ... self.sitemanager = sm
- ... def __repr__(self):
- ... return "%s('%s')" % (self.__class__.__name__, self.id)
-
- >>> from zope.component import getGlobalSiteManager
- >>> gsm = getGlobalSiteManager()
-
- >>> gutil = MyUtility('global', gsm)
- >>> gsm.registerUtility(gutil, IMyUtility, 'myutil')
-
- Now, let's create two registries and set up the bases hierarchy::
-
- >>> from zope.interface.registry import Components
- >>> sm1 = Components('sm1', bases=(gsm, ))
- >>> sm1_1 = Components('sm1_1', bases=(sm1, ))
-
- Now we create two utilities and insert them in our folder hierarchy:
-
- >>> util1 = MyUtility('one', sm1)
- >>> sm1.registerUtility(util1, IMyUtility, 'myutil')
- >>> IComponentLookup(util1) is sm1
- True
-
- >>> util1_1 = MyUtility('one-one', sm1_1)
- >>> sm1_1.registerUtility(util1_1, IMyUtility, 'myutil')
- >>> IComponentLookup(util1_1) is sm1_1
- True
-
- Now, if we ask `util1_1` for its next available utility we get the
- ``one`` utility::
-
- >>> from zope.component import getNextUtility
- >>> getNextUtility(util1_1, IMyUtility, 'myutil')
- MyUtility('one')
-
- Next we ask `util1` for its next utility and we should get the global version:
-
- >>> getNextUtility(util1, IMyUtility, 'myutil')
- MyUtility('global')
-
- However, if we ask the global utility for the next one, an error is raised
-
- >>> getNextUtility(gutil, IMyUtility,
- ... 'myutil') #doctest: +NORMALIZE_WHITESPACE
- Traceback (most recent call last):
- ...
- ComponentLookupError:
- No more utilities for <InterfaceClass zope.component.tests.IMyUtility>,
- 'myutil' have been found.
-
- You can also use `queryNextUtility` and specify a default:
-
- >>> from zope.component import queryNextUtility
- >>> queryNextUtility(gutil, IMyUtility, 'myutil', 'default')
- 'default'
-
- Let's now ensure that the function also works with multiple registries. First
- we create another base registry:
-
- >>> myregistry = Components()
-
- We now set up another utility into that registry:
-
- >>> custom_util = MyUtility('my_custom_util', myregistry)
- >>> myregistry.registerUtility(custom_util, IMyUtility, 'my_custom_util')
-
- We add it as a base to the local site manager:
-
- >>> sm1.__bases__ = (myregistry,) + sm1.__bases__
-
- Both the ``myregistry`` and global utilities should be available:
-
- >>> queryNextUtility(sm1, IMyUtility, 'my_custom_util')
- MyUtility('my_custom_util')
- >>> queryNextUtility(sm1, IMyUtility, 'myutil')
- MyUtility('global')
-
- Note, if the context cannot be converted to a site manager, the default is
- retruned:
-
- >>> queryNextUtility(object(), IMyUtility, 'myutil', 'default')
- 'default'
- """
-
-def dont_leak_utility_registrations_in__subscribers():
- """
-
- We've observed utilities getting left in _subscribers when they
- get unregistered.
-
- >>> import zope.interface.registry
- >>> reg = zope.interface.registry.Components()
- >>> class C:
- ... def __init__(self, name):
- ... self.name = name
- ... def __repr__(self):
- ... return "C(%s)" % self.name
-
- >>> c1 = C(1)
- >>> reg.registerUtility(c1, I1)
- >>> reg.registerUtility(c1, I1)
- >>> list(reg.getAllUtilitiesRegisteredFor(I1))
- [C(1)]
-
- >>> reg.unregisterUtility(provided=I1)
- True
- >>> list(reg.getAllUtilitiesRegisteredFor(I1))
- []
-
- >>> reg.registerUtility(c1, I1)
- >>> reg.registerUtility(C(2), I1)
-
- >>> list(reg.getAllUtilitiesRegisteredFor(I1))
- [C(2)]
-
- """
-
-def test_zcml_handler_site_manager():
- """
- The ZCML directives provided by zope.component use the ``getSiteManager``
- method to get the registry where to register the components. This makes
- possible to hook ``getSiteManager`` before loading a ZCML file:
-
- >>> from zope.interface.registry import Components
- >>> registry = Components()
- >>> def dummy(context=None):
- ... return registry
- >>> from zope.component import getSiteManager
- >>> ignore = getSiteManager.sethook(dummy)
-
- >>> from zope.component.testfiles.components import comp, IApp
- >>> from zope.component.zcml import handler
- >>> handler('registerUtility', comp, IApp, u'')
- >>> registry.getUtility(IApp) is comp
- True
- >>> ignore = getSiteManager.reset()
-
- """
-
-class StandaloneTests(unittest.TestCase):
- def testStandalone(self):
- import subprocess
- import sys
- import os
- import tempfile
- import pickle
-
- executable = os.path.abspath(sys.executable)
- program = os.path.join(os.path.dirname(__file__), 'standalonetests.py')
- process = subprocess.Popen([executable, program],
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- stdin=subprocess.PIPE)
- pickle.dump(sys.path, process.stdin)
- process.stdin.close()
-
- try:
- process.wait()
- except OSError, e:
- if e.errno != 4: # MacIntel raises apparently unimportant EINTR?
- raise # TODO verify sanity of a pass on EINTR :-/
- lines = process.stdout.readlines()
- process.stdout.close()
- success = True
- # Interpret the result: We scan the output from the end backwards
- # until we find either a line that says 'OK' (which means the tests
- # ran successfully) or a line that starts with quite a few dashes
- # (which means we didn't find a line that says 'OK' within the summary
- # of the test runner and the tests did not run successfully.)
- for l in reversed(lines):
- l = l.strip()
- if not l:
- continue
- if l.startswith('-----'):
- break
- if l.endswith('OK'):
- sucess = True
- if not success:
- self.fail(''.join(lines))
-
-class HookableTests(unittest.TestCase):
-
- def test_ctor_no_func(self):
- from zope.component.hookable import hookable
- self.assertRaises(TypeError, hookable)
-
- def test_ctor_simple(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- hooked = hookable(foo)
- self.failUnless(hooked.original is foo)
- self.failUnless(hooked.implementation is foo)
-
- def test_ctor_extra_arg(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- self.assertRaises(TypeError, hookable, foo, foo)
-
- def test_ctor_extra_arg(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- self.assertRaises(TypeError, hookable, foo, nonesuch=foo)
-
- def test_sethook(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- def bar():
- pass
- hooked = hookable(foo)
- hooked.sethook(bar)
- self.failUnless(hooked.original is foo)
- self.failUnless(hooked.implementation is bar)
-
- def test_reset(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- def bar():
- pass
- hooked = hookable(foo)
- hooked.sethook(bar)
- hooked.reset()
- self.failUnless(hooked.original is foo)
- self.failUnless(hooked.implementation is foo)
-
- def test_cant_assign_original(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- def bar():
- pass
- hooked = hookable(foo)
- try:
- hooked.original = bar
- except TypeError:
- pass
- except AttributeError:
- pass
- else:
- self.fail('Assigned original')
-
- def test_cant_delete_original(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- hooked = hookable(foo)
- try:
- del hooked.original
- except TypeError:
- pass
- except AttributeError:
- pass
- else:
- self.fail('Deleted original')
-
- def test_cant_assign_original(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- def bar():
- pass
- hooked = hookable(foo)
- try:
- hooked.implementation = bar
- except TypeError:
- pass
- except AttributeError:
- pass
- else:
- self.fail('Assigned implementation')
-
- def test_readonly_original(self):
- from zope.component.hookable import hookable
- def foo():
- pass
- hooked = hookable(foo)
- try:
- del hooked.implementation
- except TypeError:
- pass
- except AttributeError:
- pass
- else:
- self.fail('Deleted implementation')
-
-class Ob3(object):
- interface.implements(IC)
-
-template = """<configure
- xmlns='http://namespaces.zope.org/zope'
- i18n_domain='zope'>
- %s
- </configure>"""
-
-
-class ResourceViewTests(PlacelessSetup, unittest.TestCase):
-
- def setUp(self):
- super(ResourceViewTests, self).setUp()
- XMLConfig('meta.zcml', zope.component)()
- XMLConfig('meta.zcml', zope.security)()
-
- def testView(self):
- ob = Ob3()
- request = Request(IV)
- self.assertEqual(
- zope.component.queryMultiAdapter((ob, request), name=u'test'), None)
-
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"/>
- '''
- ))
-
- self.assertEqual(
- zope.component.queryMultiAdapter((ob, request),
- name=u'test').__class__,
- V1)
-
-
- def testMultiView(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.adapter.A3"
- for="zope.component.testfiles.views.IC
- zope.component.testfiles.adapter.I1
- zope.component.testfiles.adapter.I2"
- type="zope.component.testfiles.views.IV"/>
- '''
- ))
-
-
- ob = Ob3()
- a1 = A1()
- a2 = A2()
- request = Request(IV)
- view = zope.component.queryMultiAdapter((ob, a1, a2, request),
- name=u'test')
- self.assertEqual(view.__class__, A3)
- self.assertEqual(view.context, (ob, a1, a2, request))
-
-
- def testMultiView_fails_w_multiple_factories(self):
- self.assertRaises(
- ConfigurationError,
- xmlconfig,
- StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.adapter.A3
- zope.component.testfiles.adapter.A2"
- for="zope.component.testfiles.views.IC
- zope.component.testfiles.adapter.I1
- zope.component.testfiles.adapter.I2"
- type="zope.component.testfiles.views.IV"/>
- '''
- )
- )
-
- def testView_w_multiple_factories(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.adapter.A1
- zope.component.testfiles.adapter.A2
- zope.component.testfiles.adapter.A3
- zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"/>
- '''
- ))
-
- ob = Ob3()
-
- # The view should be a V1 around an A3, around an A2, around
- # an A1, anround ob:
- view = zope.component.queryMultiAdapter((ob, Request(IV)), name=u'test')
- self.assertEqual(view.__class__, V1)
- a3 = view.context
- self.assertEqual(a3.__class__, A3)
- a2 = a3.context[0]
- self.assertEqual(a2.__class__, A2)
- a1 = a2.context[0]
- self.assertEqual(a1.__class__, A1)
- self.assertEqual(a1.context[0], ob)
-
- def testView_fails_w_no_factories(self):
- self.assertRaises(ConfigurationError,
- xmlconfig,
- StringIO(template %
- '''
- <view name="test"
- factory=""
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"/>
- '''
- ),
- )
-
-
- def testViewThatProvidesAnInterface(self):
- ob = Ob3()
- self.assertEqual(
- zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
- None)
-
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IR"
- />
- '''
- ))
-
- self.assertEqual(
- zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test'),
- None)
-
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IR"
- provides="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.queryMultiAdapter((ob, Request(IR)), IV, u'test')
- self.assertEqual(v.__class__, V1)
-
-
- def testUnnamedViewThatProvidesAnInterface(self):
- ob = Ob3()
- self.assertEqual(
- zope.component.queryMultiAdapter((ob, Request(IR)), IV), None)
-
- xmlconfig(StringIO(template %
- '''
- <view factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IR"
- />
- '''
- ))
-
- v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
- self.assertEqual(v, None)
-
- xmlconfig(StringIO(template %
- '''
- <view factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IR"
- provides="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.queryMultiAdapter((ob, Request(IR)), IV)
- self.assertEqual(v.__class__, V1)
-
- def testViewHavingARequiredClass(self):
- xmlconfig(StringIO(template % (
- '''
- <view
- for="zope.component.testfiles.components.Content"
- type="zope.component.testfiles.views.IR"
- factory="zope.component.testfiles.adapter.A1"
- />
- '''
- )))
-
- content = Content()
- a1 = zope.component.getMultiAdapter((content, Request(IR)))
- self.assert_(isinstance(a1, A1))
-
- class MyContent:
- interface.implements(IContent)
-
- self.assertRaises(ComponentLookupError, zope.component.getMultiAdapter,
- (MyContent(), Request(IR)))
-
- def testInterfaceProtectedView(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- permission="zope.Public"
- allowed_interface="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
- name='test'))
- self.assertEqual(v.index(), 'V1 here')
- self.assertRaises(Exception, getattr, v, 'action')
-
- def testAttributeProtectedView(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- permission="zope.Public"
- allowed_attributes="action"
- />
- '''
- ))
-
- v = ProxyFactory(zope.component.getMultiAdapter((Ob3(), Request(IV)),
- name='test'))
- self.assertEqual(v.action(), 'done')
- self.assertRaises(Exception, getattr, v, 'index')
-
- def testInterfaceAndAttributeProtectedView(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- permission="zope.Public"
- allowed_attributes="action"
- allowed_interface="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
- self.assertEqual(v.index(), 'V1 here')
- self.assertEqual(v.action(), 'done')
-
- def testDuplicatedInterfaceAndAttributeProtectedView(self):
- xmlconfig(StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- permission="zope.Public"
- allowed_attributes="action index"
- allowed_interface="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.getMultiAdapter((Ob3(), Request(IV)), name='test')
- self.assertEqual(v.index(), 'V1 here')
- self.assertEqual(v.action(), 'done')
-
- def testIncompleteProtectedViewNoPermission(self):
- self.assertRaises(
- ConfigurationError,
- xmlconfig,
- StringIO(template %
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- allowed_attributes="action index"
- />
- '''
- ))
-
- def testViewUndefinedPermission(self):
- config = StringIO(template % (
- '''
- <view name="test"
- factory="zope.component.testfiles.views.V1"
- for="zope.component.testfiles.views.IC"
- type="zope.component.testfiles.views.IV"
- permission="zope.UndefinedPermission"
- allowed_attributes="action index"
- allowed_interface="zope.component.testfiles.views.IV"
- />
- '''
- ))
- self.assertRaises(ValueError, xmlconfig, config, testing=1)
-
- def testResource(self):
- ob = Ob3()
- self.assertEqual(
- zope.component.queryAdapter(Request(IV), name=u'test'), None)
- xmlconfig(StringIO(template % (
- '''
- <resource name="test"
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IV"/>
- '''
- )))
-
- self.assertEqual(
- zope.component.queryAdapter(Request(IV), name=u'test').__class__,
- R1)
-
- def testResourceThatProvidesAnInterface(self):
- ob = Ob3()
- self.assertEqual(zope.component.queryAdapter(Request(IR), IV, u'test'),
- None)
-
- xmlconfig(StringIO(template %
- '''
- <resource
- name="test"
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IR"
- />
- '''
- ))
-
- v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
- self.assertEqual(v, None)
-
- xmlconfig(StringIO(template %
- '''
- <resource
- name="test"
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IR"
- provides="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.queryAdapter(Request(IR), IV, name=u'test')
- self.assertEqual(v.__class__, R1)
-
- def testUnnamedResourceThatProvidesAnInterface(self):
- ob = Ob3()
- self.assertEqual(zope.component.queryAdapter(Request(IR), IV), None)
-
- xmlconfig(StringIO(template %
- '''
- <resource
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IR"
- />
- '''
- ))
-
- v = zope.component.queryAdapter(Request(IR), IV)
- self.assertEqual(v, None)
-
- xmlconfig(StringIO(template %
- '''
- <resource
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IR"
- provides="zope.component.testfiles.views.IV"
- />
- '''
- ))
-
- v = zope.component.queryAdapter(Request(IR), IV)
- self.assertEqual(v.__class__, R1)
-
- def testResourceUndefinedPermission(self):
-
- config = StringIO(template % (
- '''
- <resource name="test"
- factory="zope.component.testfiles.views.R1"
- type="zope.component.testfiles.views.IV"
- permission="zope.UndefinedPermission"/>
- '''
- ))
- self.assertRaises(ValueError, xmlconfig, config, testing=1)
-
-
-class ConditionalSecurityLayer(UnitTests):
-
- __name__ = 'ConditionalSecurity'
- __bases__ = ()
-
- def setUp(self):
- setUp()
- self.modules = {}
- for m in ('zope.security', 'zope.proxy'):
- self.modules[m] = sys.modules[m]
- sys.modules[m] = None
- import zope.component.zcml
- reload(zope.component.zcml)
-
- def tearDown(self):
- tearDown()
- for m in ('zope.security', 'zope.proxy'):
- sys.modules[m] = self.modules[m]
- import zope.component.zcml
- reload(zope.component.zcml)
-
-
-def setUpRegistryTests(tests):
- setUp()
-
-def tearDownRegistryTests(tests):
- tearDown()
- import zope.event
- zope.event.subscribers.pop()
-
-def clearZCML(test=None):
- tearDown()
- setUp()
- XMLConfig('meta.zcml', component)()
-
-def test_suite():
- checker = renormalizing.RENormalizing([
- (re.compile('at 0x[0-9a-fA-F]+'), 'at <SOME ADDRESS>'),
- (re.compile(r"<type 'exceptions.(\w+)Error'>:"),
- r'exceptions.\1Error:'),
- ])
-
- zcml_conditional = doctest.DocFileSuite('zcml_conditional.txt', checker=checker)
- zcml_conditional.layer = ConditionalSecurityLayer()
-
- with_globs = dict(with_statement=__future__.with_statement)
- hooks_conditional = doctest.DocFileSuite(
- 'hooks.txt', checker=checker, globs=with_globs)
- hooks_conditional.layer = ConditionalSecurityLayer()
-
- return unittest.TestSuite((
- doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
- unittest.makeSuite(HookableTests),
- doctest.DocTestSuite('zope.component.interface',
- setUp=setUp, tearDown=tearDown),
- doctest.DocTestSuite('zope.component.nexttesting'),
- doctest.DocFileSuite('README.txt',
- setUp=setUp, tearDown=tearDown),
- doctest.DocFileSuite('socketexample.txt',
- setUp=setUp, tearDown=tearDown),
- doctest.DocFileSuite('factory.txt',
- setUp=setUp, tearDown=tearDown),
- doctest.DocFileSuite('hooks.txt', checker=checker,
- setUp=setUp, tearDown=tearDown,
- globs=with_globs),
- doctest.DocFileSuite('event.txt',
- setUp=setUp, tearDown=tearDown),
- doctest.DocTestSuite('zope.component.security'),
- doctest.DocFileSuite('zcml.txt', checker=checker,
- setUp=setUp, tearDown=tearDown),
- doctest.DocFileSuite('configure.txt',
- setUp=setUp, tearDown=tearDown),
- doctest.DocFileSuite('testlayer.txt',
- optionflags=(doctest.ELLIPSIS +
- doctest.NORMALIZE_WHITESPACE +
- doctest.REPORT_NDIFF)),
- zcml_conditional,
- hooks_conditional,
- unittest.makeSuite(StandaloneTests),
- unittest.makeSuite(ResourceViewTests),
- ))
-
-if __name__ == "__main__":
- unittest.main(defaultTest='test_suite')
diff --git a/src/zope/component/tests/__init__.py b/src/zope/component/tests/__init__.py
new file mode 100644
index 0000000..65140f2
--- /dev/null
+++ b/src/zope/component/tests/__init__.py
@@ -0,0 +1 @@
+# tests package
diff --git a/src/zope/component/tests/examples.py b/src/zope/component/tests/examples.py
new file mode 100644
index 0000000..2b5e08c
--- /dev/null
+++ b/src/zope/component/tests/examples.py
@@ -0,0 +1,150 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002, 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Examples supporting Sphinx doctest snippets.
+"""
+import sys
+
+from zope.interface import Interface
+from zope.interface import implementer
+from zope.interface.interfaces import IInterface
+
+from zope.component._declaration import adapter
+from zope.component.testfiles.views import IC
+
+def write(x):
+ sys.stdout.write('%s\n' % x)
+
+class ITestType(IInterface):
+ pass
+
+
+class I1(Interface):
+ pass
+
+class I2(Interface):
+ pass
+
+class I3(Interface):
+ pass
+
+class I4(Interface):
+ pass
+
+class IGI(Interface):
+ pass
+
+class IQI(Interface):
+ pass
+
+class ISI(Interface):
+ pass
+
+class ISII(Interface):
+ pass
+
+def noop(*args):
+ pass
+
+class U(object):
+
+ def __init__(self, name):
+ self.__name__ = name
+
+ def __repr__(self):
+ return "%s(%s)" % (self.__class__.__name__, self.__name__)
+
+@implementer(I1)
+class U1(U):
+ pass
+
+@implementer(I1, I2)
+class U12(U):
+ pass
+
+@adapter(I1)
+def handle1(x):
+ write('handle1 %s' % x)
+
+def handle2(*objects):
+ write( 'handle2 ' + repr(objects))
+
+@adapter(I1)
+def handle3(x):
+ write( 'handle3 %s' % x)
+
+@adapter(I1)
+def handle4(x):
+ write( 'handle4 %s' % x)
+
+class GlobalRegistry:
+ pass
+
+from zope.component.globalregistry import GlobalAdapterRegistry
+base = GlobalAdapterRegistry(GlobalRegistry, 'adapters')
+GlobalRegistry.adapters = base
+def clear_base():
+ base.__init__(GlobalRegistry, 'adapters')
+
+
+@implementer(I1)
+class Ob(object):
+ def __repr__(self):
+ return '<instance Ob>'
+
+
+ob = Ob()
+
+@implementer(I2)
+class Ob2(object):
+ def __repr__(self):
+ return '<instance Ob2>'
+
+@implementer(IC)
+class Ob3(object):
+ pass
+
+@implementer(I2)
+class Comp(object):
+ def __init__(self, context):
+ self.context = context
+
+comp = Comp(1)
+
+@implementer(I3)
+class Comp2(object):
+ def __init__(self, context):
+ self.context = context
+
+
+class ConformsToIComponentLookup(object):
+ """Allow a dummy sitemanager to conform/adapt to `IComponentLookup`."""
+
+ def __init__(self, sitemanager):
+ self.sitemanager = sitemanager
+
+ def __conform__(self, interface):
+ """This method is specified by the adapter PEP to do the adaptation."""
+ from zope.component.interfaces import IComponentLookup
+ if interface is IComponentLookup:
+ return self.sitemanager
+
+
+def clearZCML(test=None):
+ from zope.configuration.xmlconfig import XMLConfig
+ import zope.component
+ from zope.component.testing import setUp
+ from zope.component.testing import tearDown
+ tearDown()
+ setUp()
+ XMLConfig('meta.zcml', zope.component)()
diff --git a/src/zope/component/tests/test___init__.py b/src/zope/component/tests/test___init__.py
new file mode 100644
index 0000000..f9553e6
--- /dev/null
+++ b/src/zope/component/tests/test___init__.py
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import unittest
+
+class Test_package(unittest.TestCase):
+
+ def test_module_conforms_to_IComponentArchitecture(self):
+ from zope.interface.verify import verifyObject
+ from zope.component.interfaces import IComponentArchitecture
+ import zope.component as zc
+ verifyObject(IComponentArchitecture, zc)
+
+ def test_module_conforms_to_IComponentRegistrationConvenience(self):
+ from zope.interface.verify import verifyObject
+ from zope.component.interfaces import IComponentRegistrationConvenience
+ import zope.component as zc
+ verifyObject(IComponentRegistrationConvenience, zc)
+
+
+class Test_Interface_call(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def test_miss(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertRaises(TypeError, IFoo, object())
+
+ def test_miss_w_default(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ marker = object()
+ self.assertTrue(IFoo(object(), marker) is marker)
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, '')
+ bar = Bar()
+ adapted = IFoo(bar)
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is bar)
+
+ def test_hit_registered_for_None(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (None,), IFoo, '')
+ ctx = object()
+ adapted = IFoo(ctx)
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is ctx)
+
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_package),
+ unittest.makeSuite(Test_Interface_call),
+ ))
diff --git a/src/zope/component/tests/test__api.py b/src/zope/component/tests/test__api.py
new file mode 100644
index 0000000..edcef69
--- /dev/null
+++ b/src/zope/component/tests/test__api.py
@@ -0,0 +1,1204 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Tests for z.c._api
+"""
+import unittest
+
+
+class Test_getSiteManager(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component._api import getSiteManager
+ return getSiteManager(*args, **kw)
+
+ def test_sm_is_IComponentLookup(self):
+ from zope.component.interfaces import IComponentLookup
+ sm = self._callFUT()
+ self.assertTrue(IComponentLookup.providedBy(sm))
+
+ def test_sm_is_singleton(self):
+ from zope.component.globalregistry import base
+ sm = self._callFUT()
+ self.assertTrue(sm is base)
+ self.assertTrue(self._callFUT() is sm)
+
+ def test_w_None(self):
+ self.assertTrue(self._callFUT(None) is self._callFUT())
+
+ def test_getSiteManager_w_conforming_context(self):
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ sitemanager = object()
+ context = ConformsToIComponentLookup(sitemanager)
+ self.assertTrue(self._callFUT(context) is sitemanager)
+
+ def test_getSiteManager_w_invalid_context_no_adapter(self):
+ from zope.component.interfaces import ComponentLookupError
+ self.assertRaises(ComponentLookupError, self._callFUT, object())
+
+ def test_getSiteManager_w_invalid_context_w_adapter(self):
+ from zope.interface import Interface
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component.interfaces import IComponentLookup
+ gsm = getGlobalSiteManager()
+ sm = object()
+ def _adapt(x):
+ return sm
+ gsm.registerAdapter(_adapt, (Interface,), IComponentLookup, '')
+ self.assertTrue(self._callFUT(object()) is sm)
+
+
+class Test_getAdapterInContext(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getAdapterInContext
+ return getAdapterInContext(*args, **kw)
+
+ def test_miss(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, object(), IFoo, context=None)
+
+ def test_hit_via_sm(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.registry import Components
+ from zope.component import getGlobalSiteManager
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Global(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(IFoo)
+ class Local(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ class Context(ConformsToIComponentLookup):
+ def __init__(self, sm):
+ self.sitemanager = sm
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(Global, (IBar,), IFoo, '')
+ sm1 = Components('sm1', bases=(gsm, ))
+ sm1.registerAdapter(Local, (IBar,), IFoo, '')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, context=Context(sm1))
+ self.assertTrue(adapted.__class__ is Local)
+ self.assertTrue(adapted.context is bar)
+
+
+class Test_queryAdapterInContext(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import queryAdapterInContext
+ return queryAdapterInContext(*args, **kw)
+
+ def test_miss(self):
+ from zope.interface import Interface
+ from zope.component import queryAdapterInContext
+ class IFoo(Interface):
+ pass
+ self.assertEqual(
+ queryAdapterInContext(object(), IFoo, context=None), None)
+
+ def test_w_object_conforming(self):
+ from zope.interface import Interface
+ from zope.component import queryAdapterInContext
+ class IFoo(Interface):
+ pass
+ _adapted = object()
+ class Foo(object):
+ def __conform__(self, iface, default=None):
+ if iface is IFoo:
+ return _adapted
+ return default
+ self.assertTrue(
+ queryAdapterInContext(Foo(), IFoo, context=None) is _adapted)
+
+ def test___conform___raises_TypeError_via_class(self):
+ from zope.interface import Interface
+ from zope.component import queryAdapterInContext
+ class IFoo(Interface):
+ pass
+ _adapted = object()
+ class Foo(object):
+ def __conform__(self, iface, default=None):
+ if iface is IFoo:
+ return _adapted
+ return default
+ # call via class, triggering TypeError
+ self.assertEqual(queryAdapterInContext(Foo, IFoo, context=None), None)
+
+ def test___conform___raises_TypeError_via_inst(self):
+ from zope.interface import Interface
+ from zope.component import queryAdapterInContext
+ class IFoo(Interface):
+ pass
+ _adapted = object()
+ class Foo(object):
+ def __conform__(self, iface, default=None):
+ raise TypeError
+ self.assertRaises(TypeError,
+ queryAdapterInContext, Foo(), IFoo, context=None)
+
+ def test_w_object_implementing(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import queryAdapterInContext
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ self.assertTrue(
+ queryAdapterInContext(foo, IFoo, context=None) is foo)
+
+
+class Test_getAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getAdapter
+ return getAdapter(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, object(), IFoo, '')
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, object(), IFoo, 'bar')
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, '')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, '')
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is bar)
+
+ def test_anonymous_hit_registered_for_None(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (None,), IFoo, '')
+ ctx = object()
+ adapted = self._callFUT(ctx, IFoo, '')
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is ctx)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, 'named')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, 'named')
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is bar)
+
+
+class Test_queryAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import queryAdapter
+ return queryAdapter(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT(object(), IFoo, '', '<default>'),
+ '<default>')
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT(object(), IFoo, 'bar'), None)
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, '')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, '')
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is bar)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class Baz(object):
+ def __init__(self, context):
+ self.context = context
+ getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, 'named')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, 'named')
+ self.assertTrue(adapted.__class__ is Baz)
+ self.assertTrue(adapted.context is bar)
+
+ def test_nested(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.registry import Components
+ from zope.component import getGlobalSiteManager
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Global(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(IFoo)
+ class Local(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ class Context(ConformsToIComponentLookup):
+ def __init__(self, sm):
+ self.sitemanager = sm
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(Global, (IBar,), IFoo, '')
+ sm1 = Components('sm1', bases=(gsm, ))
+ sm1.registerAdapter(Local, (IBar,), IFoo, '')
+ bar = Bar()
+ adapted = self._callFUT(bar, IFoo, '', context=Context(sm1))
+ self.assertTrue(adapted.__class__ is Local)
+ self.assertTrue(adapted.context is bar)
+
+
+class Test_getMultiAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getMultiAdapter
+ return getMultiAdapter(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, (object(), object()), IFoo, '')
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, (object(), object()), IFoo, 'bar')
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ @implementer(IFoo)
+ class FooAdapter(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ getGlobalSiteManager().registerAdapter(
+ FooAdapter, (IBar, IBaz), IFoo, '')
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, '')
+ self.assertTrue(adapted.__class__ is FooAdapter)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+ def test_anonymous_hit_registered_for_None(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IFoo)
+ class FooAdapter(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ getGlobalSiteManager().registerAdapter(
+ FooAdapter, (IBar, None), IFoo, '')
+ bar = Bar()
+ baz = object()
+ adapted = self._callFUT((bar, baz), IFoo, '')
+ self.assertTrue(adapted.__class__ is FooAdapter)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ @implementer(IFoo)
+ class FooAdapter(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ getGlobalSiteManager().registerAdapter(
+ FooAdapter, (IBar, IBaz), IFoo, 'named')
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, 'named')
+ self.assertTrue(adapted.__class__ is FooAdapter)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+
+class Test_queryMultiAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import queryMultiAdapter
+ return queryMultiAdapter(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT((object(), object()), IFoo, '',
+ '<default>'),
+ '<default>')
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT((object(), object()), IFoo, 'bar'),
+ None)
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ @implementer(IFoo)
+ class FooAdapter(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ getGlobalSiteManager().registerAdapter(
+ FooAdapter, (IBar, IBaz), IFoo, '')
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, '')
+ self.assertTrue(adapted.__class__ is FooAdapter)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ @implementer(IFoo)
+ class FooAdapter(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ getGlobalSiteManager().registerAdapter(
+ FooAdapter, (IBar, IBaz), IFoo, 'named')
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, 'named')
+ self.assertTrue(adapted.__class__ is FooAdapter)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+ def test_nested(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.registry import Components
+ from zope.component import getGlobalSiteManager
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ @implementer(IFoo)
+ class Global(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ @implementer(IFoo)
+ class Local(object):
+ def __init__(self, first, second):
+ self.first, self.second = first, second
+ class Context(ConformsToIComponentLookup):
+ def __init__(self, sm):
+ self.sitemanager = sm
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(Global, (IBar, IBaz), IFoo, '')
+ sm1 = Components('sm1', bases=(gsm, ))
+ sm1.registerAdapter(Local, (IBar, IBaz), IFoo, '')
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, '', context=Context(sm1))
+ self.assertTrue(adapted.__class__ is Local)
+ self.assertTrue(adapted.first is bar)
+ self.assertTrue(adapted.second is baz)
+
+ def test_wo_sitemanager(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ class Context(object):
+ def __conform__(self, iface):
+ raise ComponentLookupError
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, '', context=Context())
+ self.assertTrue(adapted is None)
+
+
+class Test_getAdapters(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getAdapters
+ return getAdapters(*args, **kw)
+
+ def test_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(list(self._callFUT((object(),), IFoo)), [])
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class BarAdapter(object):
+ def __init__(self, context):
+ self.context = context
+ class BazAdapter(object):
+ def __init__(self, context):
+ self.context = context
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(BarAdapter, (None,), IFoo)
+ gsm.registerAdapter(BazAdapter, (None,), IFoo, name='bar')
+ tuples = list(self._callFUT((object(),), IFoo))
+ self.assertEqual(len(tuples), 2)
+ names = [(x, y.__class__.__name__) for x, y in tuples]
+ self.assertTrue(('', 'BarAdapter') in names)
+ self.assertTrue(('bar', 'BazAdapter') in names)
+
+ def test_wo_sitemanager(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBar)
+ class Bar(object):
+ pass
+ @implementer(IBaz)
+ class Baz(object):
+ pass
+ class Context(object):
+ def __conform__(self, iface):
+ raise ComponentLookupError
+ bar = Bar()
+ baz = Baz()
+ adapted = self._callFUT((bar, baz), IFoo, context=Context())
+ self.assertEqual(adapted, [])
+
+
+class Test_subscribers(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import subscribers
+ return subscribers(*args, **kw)
+
+ def test_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ subscribers = self._callFUT((object,), IFoo)
+ self.assertEqual(subscribers, [])
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class BarAdapter(object):
+ def __init__(self, context):
+ self.context = context
+ class BazAdapter(object):
+ def __init__(self, context):
+ self.context = context
+ gsm = getGlobalSiteManager()
+ gsm.registerSubscriptionAdapter(BarAdapter, (None,), IFoo)
+ gsm.registerSubscriptionAdapter(BazAdapter, (None,), IFoo)
+ subscribers = self._callFUT((object(),), IFoo)
+ self.assertEqual(len(subscribers), 2)
+ names = [(x.__class__.__name__) for x in subscribers]
+ self.assertTrue('BarAdapter' in names)
+ self.assertTrue('BazAdapter' in names)
+
+ def test_wo_sitemanager(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ class Context(object):
+ def __conform__(self, iface):
+ raise ComponentLookupError
+ subscribers = self._callFUT((object,), IFoo, context=Context())
+ self.assertEqual(subscribers, [])
+
+
+class Test_handle(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import handle
+ return handle(*args, **kw)
+
+ def test_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ subscribers = self._callFUT((object,), IFoo) #doesn't raise
+
+ def test_hit(self):
+ from zope.component import getGlobalSiteManager
+ from zope.interface import Interface
+ from zope.interface import implementer
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ _called = []
+ def _bar(context):
+ _called.append('_bar')
+ def _baz(context):
+ _called.append('_baz')
+ gsm = getGlobalSiteManager()
+ gsm.registerHandler(_bar, (IFoo,))
+ gsm.registerHandler(_baz, (IFoo,))
+ self._callFUT(Foo())
+ self.assertEqual(len(_called), 2, _called)
+ self.assertTrue('_bar' in _called)
+ self.assertTrue('_baz' in _called)
+
+
+class Test_getUtility(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component._api import getUtility
+ return getUtility(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError, self._callFUT, IFoo)
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, IFoo, name='bar')
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ obj = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo)
+ self.assertTrue(self._callFUT(IFoo) is obj)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ obj = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo, name='bar')
+ self.assertTrue(self._callFUT(IFoo, name='bar') is obj)
+
+ def test_w_conforming_context(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ class SM(object):
+ def __init__(self, obj):
+ self._obj = obj
+ def queryUtility(self, interface, name, default):
+ return self._obj
+ class IFoo(Interface):
+ pass
+ obj1 = object()
+ obj2 = object()
+ sm = SM(obj2)
+ context = ConformsToIComponentLookup(sm)
+ getGlobalSiteManager().registerUtility(obj1, IFoo)
+ self.assertTrue(self._callFUT(IFoo, context=context) is obj2)
+
+
+class Test_queryUtility(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component._api import queryUtility
+ return queryUtility(*args, **kw)
+
+ def test_anonymous_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT(IFoo), None)
+
+ def test_anonymous_nonesuch_w_default(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ obj = object()
+ self.assertTrue(self._callFUT(IFoo, default=obj) is obj)
+
+ def test_named_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT(IFoo, name='bar'), None)
+
+ def test_named_nonesuch_w_default(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ obj = object()
+ self.assertTrue(self._callFUT(IFoo, name='bar', default=obj) is obj)
+
+ def test_anonymous_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ obj = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo)
+ self.assertTrue(self._callFUT(IFoo) is obj)
+
+ def test_named_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ obj = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo, name='bar')
+ self.assertTrue(self._callFUT(IFoo, name='bar') is obj)
+
+ def test_w_conforming_context(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ from zope.component.tests.examples import ConformsToIComponentLookup
+ class SM(object):
+ def __init__(self, obj):
+ self._obj = obj
+ def queryUtility(self, interface, name, default):
+ return self._obj
+ class IFoo(Interface):
+ pass
+ obj1 = object()
+ obj2 = object()
+ sm = SM(obj2)
+ context = ConformsToIComponentLookup(sm)
+ getGlobalSiteManager().registerUtility(obj1, IFoo)
+ self.assertTrue(self._callFUT(IFoo, context=context) is obj2)
+
+
+class Test_getUtilitiesFor(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component._api import getUtilitiesFor
+ return getUtilitiesFor(*args, **kw)
+
+ def test_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(list(self._callFUT(IFoo)), [])
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ obj = object()
+ obj1 = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo)
+ getGlobalSiteManager().registerUtility(obj1, IFoo, name='bar')
+ tuples = list(self._callFUT(IFoo))
+ self.assertEqual(len(tuples), 2)
+ self.assertTrue(('', obj) in tuples)
+ self.assertTrue(('bar', obj1) in tuples)
+
+
+class Test_getAllUtilitiesRegisteredFor(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getAllUtilitiesRegisteredFor
+ return getAllUtilitiesRegisteredFor(*args, **kw)
+
+ def test_nonesuch(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(list(self._callFUT(IFoo)), [])
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.component import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(IFoo):
+ pass
+ obj = object()
+ obj1 = object()
+ obj2 = object()
+ getGlobalSiteManager().registerUtility(obj, IFoo)
+ getGlobalSiteManager().registerUtility(obj1, IFoo, name='bar')
+ getGlobalSiteManager().registerUtility(obj2, IBar)
+ uts = list(self._callFUT(IFoo))
+ self.assertEqual(len(uts), 3)
+ self.assertTrue(obj in uts)
+ self.assertTrue(obj1 in uts)
+ self.assertTrue(obj2 in uts)
+
+
+class Test_getNextUtility(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getNextUtility
+ return getNextUtility(*args, **kw)
+
+ def test_global(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component.interface import ComponentLookupError
+ gsm = getGlobalSiteManager()
+ gutil = _makeMyUtility('global', gsm)
+ gsm.registerUtility(gutil, IMyUtility, 'myutil')
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, gutil, IMyUtility, 'myutil')
+
+ def test_nested(self):
+ from zope.component import getGlobalSiteManager
+ from zope.component.interfaces import IComponentLookup
+ from zope.interface.registry import Components
+ gsm = getGlobalSiteManager()
+ gutil = _makeMyUtility('global', gsm)
+ gsm.registerUtility(gutil, IMyUtility, 'myutil')
+ sm1 = Components('sm1', bases=(gsm, ))
+ sm1_1 = Components('sm1_1', bases=(sm1, ))
+ util1 = _makeMyUtility('one', sm1)
+ sm1.registerUtility(util1, IMyUtility, 'myutil')
+ self.assertTrue(IComponentLookup(util1) is sm1)
+ self.assertTrue(self._callFUT(util1, IMyUtility, 'myutil') is gutil)
+ util1_1 = _makeMyUtility('one-one', sm1_1)
+ sm1_1.registerUtility(util1_1, IMyUtility, 'myutil')
+ self.assertTrue(IComponentLookup(util1_1) is sm1_1)
+ self.assertTrue(self._callFUT(util1_1, IMyUtility, 'myutil') is util1)
+
+
+class Test_queryNextUtility(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import queryNextUtility
+ return queryNextUtility(*args, **kw)
+
+ def test_global(self):
+ from zope.component import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ gutil = _makeMyUtility('global', gsm)
+ gsm.registerUtility(gutil, IMyUtility, 'myutil')
+ self.assertEqual(self._callFUT(gutil, IMyUtility, 'myutil'), None)
+
+ def test_nested(self):
+ from zope.component import getGlobalSiteManager
+ from zope.interface.registry import Components
+ gsm = getGlobalSiteManager()
+ gutil = _makeMyUtility('global', gsm)
+ gsm.registerUtility(gutil, IMyUtility, 'myutil')
+ sm1 = Components('sm1', bases=(gsm, ))
+ sm1_1 = Components('sm1_1', bases=(sm1, ))
+ util1 = _makeMyUtility('one', sm1)
+ sm1.registerUtility(util1, IMyUtility, 'myutil')
+ util1_1 = _makeMyUtility('one-one', sm1_1)
+ sm1_1.registerUtility(util1_1, IMyUtility, 'myutil')
+ myregistry = Components()
+ custom_util = _makeMyUtility('my_custom_util', myregistry)
+ myregistry.registerUtility(custom_util, IMyUtility, 'my_custom_util')
+ sm1.__bases__ = (myregistry,) + sm1.__bases__
+ # Both the ``myregistry`` and global utilities should be available:
+ self.assertTrue(self._callFUT(sm1, IMyUtility, 'my_custom_util')
+ is custom_util)
+ self.assertTrue(self._callFUT(sm1, IMyUtility, 'myutil') is gutil)
+
+ def test_wo_sitemanager(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ class Context(object):
+ def __conform__(self, iface):
+ raise ComponentLookupError
+ self.assertEqual(self._callFUT(Context(), IFoo, 'myutil'), None)
+
+
+class Test_createObject(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import createObject
+ return createObject(*args, **kw)
+
+ def test_miss(self):
+ from zope.component.interfaces import ComponentLookupError
+ self.assertRaises(ComponentLookupError, self._callFUT, 'nonesuch')
+
+ def test_hit(self):
+ from zope.component.interfaces import IFactory
+ _object = object()
+ _factory_called = []
+ def _factory(*args, **kw):
+ _factory_called.append((args, kw))
+ return _object
+ class Context(object):
+ def __conform__(self, iface):
+ return self
+ def queryUtility(self, iface, name, default):
+ if iface is IFactory and name == 'test':
+ return _factory
+ return default
+ context = Context()
+ self.assertTrue(self._callFUT('test', context=context) is _object)
+ self.assertEqual(_factory_called, [((), {})])
+
+
+class Test_getFactoryInterfaces(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getFactoryInterfaces
+ return getFactoryInterfaces(*args, **kw)
+
+ def test_miss(self):
+ from zope.component.interfaces import ComponentLookupError
+ self.assertRaises(ComponentLookupError, self._callFUT, 'nonesuch')
+
+ def test_hit(self):
+ from zope.component.interfaces import IFactory
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class _Factory(object):
+ def getInterfaces(self):
+ return [IFoo]
+ class Context(object):
+ def __conform__(self, iface):
+ return self
+ def queryUtility(self, iface, name, default):
+ if iface is IFactory and name == 'test':
+ return _Factory()
+ return default
+ context = Context()
+ self.assertEqual(self._callFUT('test', context=context), [IFoo])
+
+
+class Test_getFactoriesFor(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component import getFactoriesFor
+ return getFactoriesFor(*args, **kw)
+
+ def test_no_factories_registered(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(list(self._callFUT(IFoo)), [])
+
+ def test_w_factory_returning_spec(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface import providedBy
+ from zope.component.interfaces import IFactory
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo, IBar)
+ class _Factory(object):
+ def getInterfaces(self):
+ return providedBy(self)
+ _factory = _Factory()
+ class Context(object):
+ def __conform__(self, iface):
+ return self
+ def getUtilitiesFor(self, iface):
+ if iface is IFactory:
+ return [('test', _factory)]
+ self.assertEqual(list(self._callFUT(IFoo, context=Context())),
+ [('test', _factory)])
+ self.assertEqual(list(self._callFUT(IBar, context=Context())),
+ [('test', _factory)])
+
+ def test_w_factory_returning_list_of_interfaces(self):
+ from zope.interface import Interface
+ from zope.component.interfaces import IFactory
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class _Factory(object):
+ def getInterfaces(self):
+ return [IFoo, IBar]
+ _factory = _Factory()
+ class Context(object):
+ def __conform__(self, iface):
+ return self
+ def getUtilitiesFor(self, iface):
+ if iface is IFactory:
+ return [('test', _factory)]
+ self.assertEqual(list(self._callFUT(IFoo, context=Context())),
+ [('test', _factory)])
+ self.assertEqual(list(self._callFUT(IBar, context=Context())),
+ [('test', _factory)])
+
+
+IMyUtility = None
+def _makeMyUtility(name, sm):
+ global IMyUtility
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.tests.examples import ConformsToIComponentLookup
+
+ if IMyUtility is None:
+ class IMyUtility(Interface):
+ pass
+
+ @implementer(IMyUtility)
+ class MyUtility(ConformsToIComponentLookup):
+ def __init__(self, id, sm):
+ self.id = id
+ self.sitemanager = sm
+
+ return MyUtility(name, sm)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_getSiteManager),
+ unittest.makeSuite(Test_getAdapterInContext),
+ unittest.makeSuite(Test_queryAdapterInContext),
+ unittest.makeSuite(Test_getAdapter),
+ unittest.makeSuite(Test_queryAdapter),
+ unittest.makeSuite(Test_getMultiAdapter),
+ unittest.makeSuite(Test_queryMultiAdapter),
+ unittest.makeSuite(Test_getAdapters),
+ unittest.makeSuite(Test_subscribers),
+ unittest.makeSuite(Test_handle),
+ unittest.makeSuite(Test_getUtility),
+ unittest.makeSuite(Test_queryUtility),
+ unittest.makeSuite(Test_getUtilitiesFor),
+ unittest.makeSuite(Test_getAllUtilitiesRegisteredFor),
+ unittest.makeSuite(Test_getNextUtility),
+ unittest.makeSuite(Test_queryNextUtility),
+ unittest.makeSuite(Test_createObject),
+ unittest.makeSuite(Test_getFactoryInterfaces),
+ unittest.makeSuite(Test_getFactoriesFor),
+ ))
+
diff --git a/src/zope/component/tests/test__declaration.py b/src/zope/component/tests/test__declaration.py
new file mode 100644
index 0000000..b6c0767
--- /dev/null
+++ b/src/zope/component/tests/test__declaration.py
@@ -0,0 +1,221 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test adapter declaration helpers
+"""
+import unittest
+
+class Test_adapter(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component._declaration import adapter
+ return adapter
+
+ def _makeOne(self, *interfaces):
+ return self._getTargetClass()(*interfaces)
+
+ def test_ctor_no_interfaces(self):
+ deco = self._makeOne()
+ self.assertEqual(list(deco.interfaces), [])
+
+ def test_ctor_w_interfaces(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ deco = self._makeOne(IFoo, IBar)
+ self.assertEqual(list(deco.interfaces), [IFoo, IBar])
+
+ def test__call___w_class(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @self._makeOne(IFoo, IBar)
+ class Baz(object):
+ pass
+ self.assertEqual(Baz.__component_adapts__, (IFoo, IBar))
+
+ def test__call___w_inst_of_decorated_class(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @self._makeOne(IFoo, IBar)
+ class Baz(object):
+ pass
+ baz = Baz()
+ self.assertRaises(AttributeError,
+ getattr, baz, '__component_adapts_')
+
+ def test__call___w_non_class(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class Baz(object):
+ pass
+ deco = self._makeOne(IFoo, IBar)
+ baz = deco(Baz())
+ self.assertEqual(baz.__component_adapts__, (IFoo, IBar))
+
+
+class Test_adapts(unittest.TestCase):
+
+ def _run_generated_code(self, code, globs, locs,
+ fails_under_py3k=True,
+ ):
+ import warnings
+ #from zope.component._compat import PYTHON3
+ PYTHON3 = False
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ if not PYTHON3:
+ exec(code, globs, locs)
+ self.assertEqual(len(log), 0) # no longer warn
+ return True
+ else:
+ try:
+ exec(code, globs, locs)
+ except TypeError:
+ return False
+ else:
+ if fails_under_py3k:
+ self.fail("Didn't raise TypeError")
+
+ def test_instances_not_affected(self):
+ from zope.component._declaration import adapts
+ class C(object):
+ adapts()
+
+ self.assertEqual(C.__component_adapts__, ())
+ def _try():
+ return C().__component_adapts__
+ self.assertRaises(AttributeError, _try)
+
+ def test_called_from_function(self):
+ import warnings
+ from zope.component._declaration import adapts
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ globs = {'adapts': adapts, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'def foo():',
+ ' adapts(IFoo)'
+ ])
+ if self._run_generated_code(CODE, globs, locs, False):
+ foo = locs['foo']
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ self.assertRaises(TypeError, foo)
+ self.assertEqual(len(log), 0) # no longer warn
+
+ def test_called_twice_from_class(self):
+ import warnings
+ from zope.component._declaration import adapts
+ from zope.interface import Interface
+ from zope.interface._compat import PYTHON3
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ globs = {'adapts': adapts, 'IFoo': IFoo, 'IBar': IBar}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' adapts(IFoo)',
+ ' adapts(IBar)',
+ ])
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs)
+ except TypeError:
+ if not PYTHON3:
+ self.assertEqual(len(log), 0) # no longer warn
+ else:
+ self.fail("Didn't raise TypeError")
+
+ def test_called_once_from_class(self):
+ from zope.component._declaration import adapts
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ globs = {'adapts': adapts, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' adapts(IFoo)',
+ ])
+ if self._run_generated_code(CODE, globs, locs):
+ Foo = locs['Foo']
+ spec = Foo.__component_adapts__
+ self.assertEqual(list(spec), [IFoo])
+
+
+class Test_adaptedBy(unittest.TestCase):
+
+ def _callFUT(self, obj):
+ from zope.component._declaration import adaptedBy
+ return adaptedBy(obj)
+
+ def test_obj_w_no_attr(self):
+ self.assertEqual(self._callFUT(object()), None)
+
+ def test__call___w_class(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class Baz(object):
+ __component_adapts__ = (IFoo, IBar)
+ self.assertEqual(self._callFUT(Baz), (IFoo, IBar))
+
+ def test__call___w_inst_of_decorated_class(self):
+ from zope.interface import Interface
+ from zope.component._declaration import _adapts_descr
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class Baz(object):
+ __component_adapts__ = _adapts_descr((IFoo, IBar))
+ baz = Baz()
+ self.assertEqual(self._callFUT(baz), None)
+
+ def test__call___w_non_class(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class Baz(object):
+ pass
+ baz = Baz()
+ baz.__component_adapts__ = (IFoo, IBar)
+ self.assertEqual(self._callFUT(baz), (IFoo, IBar))
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_adapter),
+ unittest.makeSuite(Test_adapts),
+ unittest.makeSuite(Test_adaptedBy),
+ ))
diff --git a/src/zope/component/tests/test_event.py b/src/zope/component/tests/test_event.py
new file mode 100644
index 0000000..0b250dc
--- /dev/null
+++ b/src/zope/component/tests/test_event.py
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test adapter declaration helpers
+"""
+import unittest
+
+class Test_dispatch(unittest.TestCase):
+
+ def test_it(self):
+ from zope.interface import Interface
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component.event import dispatch
+ _adapted = []
+ def _adapter(context):
+ _adapted.append(context)
+ return object()
+ gsm = getGlobalSiteManager()
+ gsm.registerHandler(_adapter, (Interface,))
+ del _adapted[:] # clear handler reg
+ event = object()
+ dispatch(event)
+ self.assertEqual(_adapted, [event])
+
+class Test_objectEventNotify(unittest.TestCase):
+
+ def test_it(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component.interfaces import IObjectEvent
+ from zope.component.event import objectEventNotify
+ _adapted = []
+ def _adapter(context, event):
+ _adapted.append((context, event))
+ return object()
+ gsm = getGlobalSiteManager()
+ gsm.registerHandler(_adapter, (Interface, IObjectEvent))
+ del _adapted[:] # clear handler reg
+ @implementer(IObjectEvent)
+ class _ObjectEvent(object):
+ def __init__(self, object):
+ self.object = object
+ context = object()
+ event = _ObjectEvent(context)
+ objectEventNotify(event)
+ self.assertEqual(_adapted, [(context, event)])
+
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_dispatch),
+ unittest.makeSuite(Test_objectEventNotify),
+ ))
+
diff --git a/src/zope/component/tests/test_factory.py b/src/zope/component/tests/test_factory.py
new file mode 100644
index 0000000..cda0191
--- /dev/null
+++ b/src/zope/component/tests/test_factory.py
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for z.c.factory
+"""
+import unittest
+
+
+class FactoryTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.factory import Factory
+ return Factory
+
+ def _makeOne(self, callable=None, *args, **kw):
+ if callable is None:
+ callable = _test_callable
+ return self._getTargetClass()(callable, *args, **kw)
+
+ def test_class_conforms_to_IFactory(self):
+ from zope.interface.verify import verifyClass
+ from zope.component.interfaces import IFactory
+ verifyClass(IFactory, self._getTargetClass())
+
+ def test_instance_conforms_to_IFactory(self):
+ from zope.interface.verify import verifyObject
+ from zope.component.interfaces import IFactory
+ verifyObject(IFactory, self._makeOne())
+
+ def test_ctor_defaults(self):
+ factory = self._makeOne()
+ self.assertEqual(factory._callable, _test_callable)
+ self.assertEqual(factory.title, '')
+ self.assertEqual(factory.description, '')
+ self.assertEqual(factory._interfaces, None)
+
+ def test_ctor_expclit(self):
+ factory = self._makeOne(_test_callable, 'TITLE', 'DESCRIPTION')
+ self.assertEqual(factory.title, 'TITLE')
+ self.assertEqual(factory.description, 'DESCRIPTION')
+
+ def test___call___no_args(self):
+ _called = []
+ def _callable(*args, **kw):
+ _called.append((args, kw))
+ factory = self._makeOne(_callable)
+ factory()
+ self.assertEqual(_called, [((), {})])
+
+ def test___call___positional_args(self):
+ _called = []
+ def _callable(*args, **kw):
+ _called.append((args, kw))
+ factory = self._makeOne(_callable)
+ factory('one', 'two')
+ self.assertEqual(_called, [(('one', 'two'), {})])
+
+ def test___call___keyword_args(self):
+ _called = []
+ def _callable(*args, **kw):
+ _called.append((args, kw))
+ factory = self._makeOne(_callable)
+ factory(foo='bar')
+ self.assertEqual(_called, [((), {'foo': 'bar'})])
+
+ def test_getInterfaces_explicit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class IBaz(Interface):
+ pass
+ @implementer(IBaz)
+ def _callable():
+ pass
+ factory = self._makeOne(_callable, interfaces=(IFoo, IBar))
+ spec = factory.getInterfaces()
+ self.assertEqual(spec.__name__, '_callable')
+ self.assertEqual(list(spec), [IFoo, IBar])
+
+ def test_getInterfaces_implicit(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ class IBaz(Interface):
+ pass
+ @implementer(IBaz)
+ def _callable():
+ pass
+ factory = self._makeOne(_callable)
+ spec = factory.getInterfaces()
+ self.assertEqual(list(spec), [IBaz])
+
+def _test_callable(*args, **kw):
+ pass
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(FactoryTests),
+ ))
diff --git a/src/zope/component/tests/test_globalregistry.py b/src/zope/component/tests/test_globalregistry.py
new file mode 100644
index 0000000..d55b4cb
--- /dev/null
+++ b/src/zope/component/tests/test_globalregistry.py
@@ -0,0 +1,251 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Tests for z.c._api
+"""
+import unittest
+
+class Test_getGlobalSiteManager(unittest.TestCase):
+
+ def _callFUT(self):
+ from zope.component.globalregistry import getGlobalSiteManager
+ return getGlobalSiteManager()
+
+ def test_gsm_is_IComponentLookup(self):
+ from zope.component.globalregistry import base
+ from zope.component.interfaces import IComponentLookup
+ gsm = self._callFUT()
+ self.assertTrue(gsm is base)
+ self.assertTrue(IComponentLookup.providedBy(gsm))
+
+ def test_gsm_is_singleton(self):
+ gsm = self._callFUT()
+ self.assertTrue(self._callFUT() is gsm)
+
+ def test_gsm_pickling(self):
+ from zope.component._compat import _pickle
+ gsm = self._callFUT()
+ dumped = _pickle.dumps(gsm)
+ loaded = _pickle.loads(dumped)
+ self.assertTrue(loaded is gsm)
+
+ dumped_utilities = _pickle.dumps(gsm.utilities)
+ loaded_utilities = _pickle.loads(dumped_utilities)
+ self.assertTrue(loaded_utilities is gsm.utilities)
+
+ dumped_adapters = _pickle.dumps(gsm.adapters)
+ loaded_adapters = _pickle.loads(dumped_adapters)
+ self.assertTrue(loaded_adapters is gsm.adapters)
+
+
+class Test_provideUtility(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.globalregistry import provideUtility
+ return provideUtility(*args, **kw)
+
+ def test_anonymous_no_provides(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ self._callFUT(foo)
+ gsm = getGlobalSiteManager()
+ self.assertTrue(gsm.getUtility(IFoo, '') is foo)
+
+ def test_named_w_provides(self):
+ from zope.interface import Interface
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ foo = Foo()
+ self._callFUT(foo, IFoo, 'named')
+ gsm = getGlobalSiteManager()
+ self.assertTrue(gsm.getUtility(IFoo, 'named') is foo)
+
+
+class Test_provideAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.globalregistry import provideAdapter
+ return provideAdapter(*args, **kw)
+
+ def test_anonymous_no_provides_no_adapts(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component._api import adapter
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ @adapter(IFoo)
+ @implementer(IBar)
+ class Bar(object):
+ def __init__(self, context):
+ self.context = context
+ self._callFUT(Bar)
+ gsm = getGlobalSiteManager()
+ foo = Foo()
+ adapted = gsm.getAdapter(foo, IBar)
+ self.assertTrue(isinstance(adapted, Bar))
+ self.assertTrue(adapted.context is foo)
+
+ def test_named_w_provides_w_adapts(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ class Bar(object):
+ def __init__(self, context):
+ self.context = context
+ self._callFUT(Bar, (IFoo,), IBar, 'test')
+ gsm = getGlobalSiteManager()
+ foo = Foo()
+ adapted = gsm.getAdapter(foo, IBar, name='test')
+ self.assertTrue(isinstance(adapted, Bar))
+ self.assertTrue(adapted.context is foo)
+
+
+class Test_provideSubscriptionAdapter(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.globalregistry import provideSubscriptionAdapter
+ return provideSubscriptionAdapter(*args, **kw)
+
+ def test_no_provides_no_adapts(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component._api import adapter
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ @adapter(IFoo)
+ @implementer(IBar)
+ class Bar(object):
+ def __init__(self, context):
+ self.context = context
+ self._callFUT(Bar)
+ gsm = getGlobalSiteManager()
+ foo = Foo()
+ adapted = gsm.subscribers((foo,), IBar)
+ self.assertEqual(len(adapted), 1)
+ self.assertTrue(isinstance(adapted[0], Bar))
+ self.assertTrue(adapted[0].context is foo)
+
+ def test_w_provides_w_adapts(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ class Bar(object):
+ def __init__(self, context):
+ self.context = context
+ self._callFUT(Bar, (IFoo,), IBar)
+ gsm = getGlobalSiteManager()
+ foo = Foo()
+ adapted = gsm.subscribers((foo,), IBar)
+ self.assertEqual(len(adapted), 1)
+ self.assertTrue(isinstance(adapted[0], Bar))
+ self.assertTrue(adapted[0].context is foo)
+
+
+class Test_provideHandler(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.globalregistry import provideHandler
+ return provideHandler(*args, **kw)
+
+ def test_no_adapts(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface import providedBy
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component._api import adapter
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ @adapter(IFoo)
+ def _handler(context):
+ assert 0, "DON'T GO HERE"
+ self._callFUT(_handler)
+ gsm = getGlobalSiteManager()
+ regs = list(gsm.registeredHandlers())
+ self.assertEqual(len(regs), 1)
+ hr = regs[0]
+ self.assertEqual(list(hr.required), list(providedBy(Foo())))
+ self.assertEqual(hr.name, '')
+ self.assertTrue(hr.factory is _handler)
+
+ def test_w_adapts(self):
+ from zope.interface import Interface
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ def _handler(context):
+ assert 0, "DON'T GO HERE"
+ self._callFUT(_handler, (IFoo,))
+ gsm = getGlobalSiteManager()
+ regs = list(gsm.registeredHandlers())
+ self.assertEqual(len(regs), 1)
+ hr = regs[0]
+ self.assertEqual(list(hr.required), [IFoo])
+ self.assertEqual(hr.name, '')
+ self.assertTrue(hr.factory is _handler)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_getGlobalSiteManager),
+ unittest.makeSuite(Test_provideUtility),
+ unittest.makeSuite(Test_provideAdapter),
+ unittest.makeSuite(Test_provideSubscriptionAdapter),
+ unittest.makeSuite(Test_provideHandler),
+ ))
diff --git a/src/zope/component/tests/test_hookable.py b/src/zope/component/tests/test_hookable.py
new file mode 100644
index 0000000..1201561
--- /dev/null
+++ b/src/zope/component/tests/test_hookable.py
@@ -0,0 +1,141 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Pure-Python hookable tests
+"""
+import unittest
+
+
+class HookableTests(unittest.TestCase):
+
+ def test_ctor_no_func(self):
+ from zope.component.hookable import hookable
+ self.assertRaises(TypeError, hookable)
+
+ def test_ctor_simple(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ hooked = hookable(foo)
+ self.failUnless(hooked.original is foo)
+ self.failUnless(hooked.implementation is foo)
+
+ def test_ctor_extra_arg(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ self.assertRaises(TypeError, hookable, foo, foo)
+
+ def test_ctor_extra_arg_miss(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ self.assertRaises(TypeError, hookable, foo, nonesuch=foo)
+
+ def test_sethook(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ def bar():
+ pass
+ hooked = hookable(foo)
+ hooked.sethook(bar)
+ self.failUnless(hooked.original is foo)
+ self.failUnless(hooked.implementation is bar)
+
+ def test_reset(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ def bar():
+ pass
+ hooked = hookable(foo)
+ hooked.sethook(bar)
+ hooked.reset()
+ self.failUnless(hooked.original is foo)
+ self.failUnless(hooked.implementation is foo)
+
+ def test_cant_assign_original(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ def bar():
+ pass
+ hooked = hookable(foo)
+ try:
+ hooked.original = bar
+ except TypeError:
+ pass
+ except AttributeError:
+ pass
+ else:
+ self.fail('Assigned original')
+
+ def test_cant_delete_original(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ hooked = hookable(foo)
+ try:
+ del hooked.original
+ except TypeError:
+ pass
+ except AttributeError:
+ pass
+ else:
+ self.fail('Deleted original')
+
+ def test_cant_assign_implementation(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ def bar():
+ pass
+ hooked = hookable(foo)
+ try:
+ hooked.implementation = bar
+ except TypeError:
+ pass
+ except AttributeError:
+ pass
+ else:
+ self.fail('Assigned implementation')
+
+ def test_cant_delete_implementation(self):
+ from zope.component.hookable import hookable
+ def foo():
+ pass
+ hooked = hookable(foo)
+ try:
+ del hooked.implementation
+ except TypeError:
+ pass
+ except AttributeError:
+ pass
+ else:
+ self.fail('Deleted implementation')
+
+ def test_ctor___call__(self):
+ from zope.component.hookable import hookable
+ _called = []
+ def foo(*args, **kw):
+ _called.append((args, kw))
+ hooked = hookable(foo)
+ hooked('one', 'two', bar='baz')
+ self.assertEqual(_called, [(('one', 'two'), {'bar': 'baz'})])
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(HookableTests),
+ ))
diff --git a/src/zope/component/tests/test_hooks.py b/src/zope/component/tests/test_hooks.py
new file mode 100644
index 0000000..b52b1c7
--- /dev/null
+++ b/src/zope/component/tests/test_hooks.py
@@ -0,0 +1,344 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for z.c.hooks
+"""
+import unittest
+
+
+class Test_read_property(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.hooks import read_property
+ return read_property
+
+ def test_via_instance(self):
+ class Foo(object):
+ @self._getTargetClass()
+ def bar(self):
+ return 'BAR'
+ foo = Foo()
+ self.assertEqual(foo.bar, 'BAR')
+ foo.bar = 'BAZ'
+ self.assertEqual(foo.bar, 'BAZ')
+ del foo.bar
+ self.assertEqual(foo.bar, 'BAR')
+
+ def test_via_class(self):
+ class Foo(object):
+ @self._getTargetClass()
+ def bar(self):
+ return 'BAR'
+ bar = Foo.bar
+ self.assertTrue(isinstance(bar, self._getTargetClass()))
+ self.assertEqual(bar.func(object()), 'BAR')
+
+
+class SiteInfoTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.hooks import SiteInfo
+ return SiteInfo
+
+ def _makeOne(self):
+ return self._getTargetClass()()
+
+ def test_initial(self):
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ si = self._makeOne()
+ self.assertEqual(si.site, None)
+ self.assertTrue(si.sm is gsm)
+
+ def test_adapter_hook(self):
+ _hook = object()
+ class _Registry(object):
+ adapter_hook = _hook
+ class _SiteManager(object):
+ adapters = _Registry()
+ si = self._makeOne()
+ si.sm = _SiteManager()
+ self.assertFalse('adapter_hook' in si.__dict__)
+ self.assertTrue(si.adapter_hook is _hook)
+ self.assertTrue('adapter_hook' in si.__dict__)
+ del si.adapter_hook
+ self.assertFalse('adapter_hook' in si.__dict__)
+
+
+class Test_setSite(unittest.TestCase):
+
+ def _callFUT(self, site):
+ from zope.component.hooks import setSite
+ return setSite(site)
+
+ def test_w_None(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ _SM2 = object()
+ _SITE = object()
+ _HOOK = object()
+ siteinfo = _DummySiteInfo()
+ siteinfo.sm = _SM2
+ siteinfo.site = _SITE
+ siteinfo.adapterhook = _HOOK
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self._callFUT(None)
+ self.assertTrue(siteinfo.sm is gsm)
+ self.assertTrue(siteinfo.site is None)
+ self.assertFalse('adapter_hook' in siteinfo.__dict__)
+
+ def test_w_site(self):
+ from zope.component import hooks
+ _SM2 = object()
+ class _Site(object):
+ def getSiteManager(self):
+ return _SM2
+ siteinfo = _DummySiteInfo()
+ _site = _Site()
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self._callFUT(_site)
+ self.assertTrue(siteinfo.sm is _SM2)
+ self.assertTrue(siteinfo.site is _site)
+ self.assertFalse('adapter_hook' in siteinfo.__dict__)
+
+
+class Test_getSite(unittest.TestCase):
+
+ def _callFUT(self):
+ from zope.component.hooks import getSite
+ return getSite()
+
+ def test_w_None(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ siteinfo = _DummySiteInfo()
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self.assertTrue(self._callFUT() is None)
+
+ def test_w_site(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ _SM2 = object()
+ _SITE = object()
+ siteinfo = _DummySiteInfo()
+ siteinfo.sm = _SM2
+ siteinfo.site = _SITE
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self.assertTrue(self._callFUT() is _SITE)
+
+
+class Test_site(unittest.TestCase):
+
+ def _callFUT(self, new_site):
+ from zope.component.hooks import site
+ return site(new_site)
+
+ def test_it(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ _SM2 = object()
+ class _Site(object):
+ def getSiteManager(self):
+ return _SM2
+ _site = _Site()
+ siteinfo = _DummySiteInfo()
+ self.assertTrue(siteinfo.site is None)
+ self.assertTrue(siteinfo.sm is _SM)
+ with _Monkey(hooks, siteinfo=siteinfo):
+ with self._callFUT(_site):
+ self.assertTrue(siteinfo.site is _site)
+ self.assertTrue(siteinfo.sm is _SM2)
+ self.assertTrue(siteinfo.site is None)
+ self.assertTrue(siteinfo.sm is gsm)
+
+
+class Test_getSiteManager(unittest.TestCase):
+
+ def _callFUT(self, context=None):
+ from zope.component.hooks import getSiteManager
+ return getSiteManager(context)
+
+ def test_default(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ _SM2 = object()
+ siteinfo = _DummySiteInfo()
+ siteinfo.sm = _SM2
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self.assertTrue(self._callFUT() is _SM2)
+
+ def test_w_explicit_context_no_IComponentLookup(self):
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ _SM2 = object()
+ siteinfo = _DummySiteInfo()
+ siteinfo.sm = _SM2
+ with _Monkey(hooks, siteinfo=siteinfo):
+ self.assertTrue(self._callFUT(object()) is gsm)
+
+ def test_w_explicit_context_w_IComponentLookup(self):
+ from zope.interface import Interface
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component.interfaces import IComponentLookup
+ class _Lookup(object):
+ def __init__(self, context):
+ self.context = context
+ gsm = getGlobalSiteManager()
+ gsm.registerAdapter(_Lookup, (Interface,), IComponentLookup, '')
+ _SM2 = object()
+ siteinfo = _DummySiteInfo()
+ siteinfo.sm = _SM2
+ context = object()
+ with _Monkey(hooks, siteinfo=siteinfo):
+ sm = self._callFUT(context)
+ self.assertTrue(isinstance(sm, _Lookup))
+ self.assertTrue(sm.context is context)
+
+
+class Test_adapter_hook(unittest.TestCase):
+
+ def _callFUT(self, interface, object, name='', default=None):
+ from zope.component.hooks import adapter_hook
+ return adapter_hook(interface, object, name, default)
+
+ def test_success(self):
+ from zope.interface import Interface
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ class IFoo(Interface):
+ pass
+ gsm = getGlobalSiteManager()
+ _ADAPTER = object()
+ _DEFAULT = object()
+ _CONTEXT = object()
+ _called = []
+ def _adapter_hook(interface, object, name, default):
+ _called.append((interface, object, name, default))
+ return _ADAPTER
+ siteinfo = _DummySiteInfo()
+ siteinfo.adapter_hook = _adapter_hook
+ with _Monkey(hooks, siteinfo=siteinfo):
+ adapter = self._callFUT(IFoo, _CONTEXT, 'bar', _DEFAULT)
+ self.assertTrue(adapter is _ADAPTER)
+ self.assertEqual(_called, [(IFoo, _CONTEXT, 'bar', _DEFAULT)])
+
+ def test_hook_raises(self):
+ from zope.interface import Interface
+ from zope.component import hooks
+ from zope.component.globalregistry import getGlobalSiteManager
+ from zope.component.interfaces import ComponentLookupError
+ class IFoo(Interface):
+ pass
+ gsm = getGlobalSiteManager()
+ _DEFAULT = object()
+ _CONTEXT = object()
+ _called = []
+ def _adapter_hook(interface, object, name, default):
+ _called.append((interface, object, name, default))
+ raise ComponentLookupError('testing')
+ siteinfo = _DummySiteInfo()
+ siteinfo.adapter_hook = _adapter_hook
+ with _Monkey(hooks, siteinfo=siteinfo):
+ adapter = self._callFUT(IFoo, _CONTEXT, 'bar', _DEFAULT)
+ self.assertTrue(adapter is _DEFAULT)
+ self.assertEqual(_called, [(IFoo, _CONTEXT, 'bar', _DEFAULT)])
+
+
+class Test_setHooks(unittest.TestCase):
+
+ def _callFUT(self):
+ from zope.component.hooks import setHooks
+ return setHooks()
+
+ def test_it(self):
+ import zope.component._api
+ from zope.component import hooks
+ class _Hook(object):
+ def __init__(self):
+ self._hooked = None
+ def sethook(self, value):
+ self._hooked = value
+ adapter_hook = _Hook()
+ getSiteManager = _Hook()
+ with _Monkey(zope.component._api,
+ adapter_hook=adapter_hook,
+ getSiteManager=getSiteManager):
+ self._callFUT()
+ self.assertEqual(adapter_hook._hooked, hooks.adapter_hook)
+ self.assertEqual(getSiteManager._hooked, hooks.getSiteManager)
+
+
+class Test_resetHooks(unittest.TestCase):
+
+ def _callFUT(self):
+ from zope.component.hooks import resetHooks
+ return resetHooks()
+
+ def test_it(self):
+ import zope.component._api
+ class _Hook(object):
+ def __init__(self):
+ self._reset = False
+ def reset(self):
+ self._reset = True
+ adapter_hook = _Hook()
+ getSiteManager = _Hook()
+ with _Monkey(zope.component._api,
+ adapter_hook=adapter_hook,
+ getSiteManager=getSiteManager):
+ self._callFUT()
+ self.assertTrue(adapter_hook._reset)
+ self.assertTrue(getSiteManager._reset)
+
+
+_SM = object()
+class _DummySiteInfo(object):
+ sm = _SM
+ site = None
+
+class _Monkey(object):
+ # context-manager for replacing module names in the scope of a test.
+ def __init__(self, module, **kw):
+ self.module = module
+ self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+ for key, value in kw.items():
+ setattr(module, key, value)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ for key, value in self.to_restore.items():
+ setattr(self.module, key, value)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_read_property),
+ unittest.makeSuite(SiteInfoTests),
+ unittest.makeSuite(Test_setSite),
+ unittest.makeSuite(Test_getSite),
+ unittest.makeSuite(Test_site),
+ unittest.makeSuite(Test_getSiteManager),
+ unittest.makeSuite(Test_adapter_hook),
+ unittest.makeSuite(Test_setHooks),
+ unittest.makeSuite(Test_resetHooks),
+ ))
+
diff --git a/src/zope/component/tests/test_interface.py b/src/zope/component/tests/test_interface.py
new file mode 100644
index 0000000..211974a
--- /dev/null
+++ b/src/zope/component/tests/test_interface.py
@@ -0,0 +1,397 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for z.c.interface
+"""
+import unittest
+
+
+class Test_provideInterface(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import provideInterface
+ return provideInterface(*args, **kw)
+
+ def test_w_interface_not_IInterface(self):
+ self.assertRaises(TypeError, self._callFUT, 'xxx', object())
+
+ def test_w_iface_type_not_IInterface(self):
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ class IFoo(Interface):
+ pass
+ IBar = InterfaceClass('IBar')
+ self.assertRaises(TypeError, self._callFUT, 'xxx', IFoo, IBar)
+
+ def test_w_class(self):
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IBar(IInterface):
+ pass
+ class Foo(object):
+ pass
+ self._callFUT('', Foo, IBar)
+ self.assertFalse(IBar.providedBy(Foo))
+ self.assertEqual(len(list(gsm.getUtilitiesFor(IBar))), 0)
+
+ def test_wo_name_w_iface_type(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ class IBar(IInterface):
+ pass
+ self._callFUT('', IFoo, IBar)
+ self.assertTrue(IBar.providedBy(IFoo))
+ nm = 'zope.component.tests.test_interface.IFoo'
+ self.assertTrue(gsm.getUtility(IBar, nm) is IFoo)
+
+ def test_w_name_wo_ifact_type(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ self._callFUT('foo', IFoo)
+ self.assertTrue(IInterface.providedBy(IFoo))
+ registered = gsm.getUtility(IInterface, name='foo')
+ self.assertTrue(registered is IFoo)
+
+
+class Test_getInterface(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import getInterface
+ return getInterface(*args, **kw)
+
+ def test_miss(self):
+ from zope.component.interfaces import ComponentLookupError
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, object(), 'nonesuch')
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertTrue(self._callFUT(object(), 'foo') is IFoo)
+
+
+class Test_queryInterface(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import queryInterface
+ return queryInterface(*args, **kw)
+
+ def test_miss(self):
+ _DEFAULT = object()
+ self.assertTrue(
+ self._callFUT('nonesuch', default=_DEFAULT) is _DEFAULT)
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertTrue(self._callFUT('foo') is IFoo)
+
+
+class Test_searchInterface(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import searchInterface
+ return searchInterface(*args, **kw)
+
+ def test_empty(self):
+ self.assertEqual(self._callFUT(object()), [])
+
+ def test_no_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertEqual(self._callFUT(object()), [IFoo])
+
+ def test_w_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), 'IFoo'), [IFoo])
+
+ def test_no_search_string_w_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IBase(Interface):
+ pass
+ class IFoo(IBase):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), base=IBase), [IFoo])
+
+
+class Test_searchInterfaceIds(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import searchInterfaceIds
+ return searchInterfaceIds(*args, **kw)
+
+ def test_empty(self):
+ self.assertEqual(self._callFUT(object()), [])
+
+ def test_no_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertEqual(self._callFUT(object()), ['foo'])
+
+ def test_w_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), 'IFoo'), ['foo'])
+
+ def test_no_search_string_w_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IBase(Interface):
+ pass
+ class IFoo(IBase):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), base=IBase), ['foo'])
+
+
+class Test_searchInterfaceUtilities(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import searchInterfaceUtilities
+ return searchInterfaceUtilities(*args, **kw)
+
+ def test_empty(self):
+ self.assertEqual(self._callFUT(object()), [])
+
+ def test_no_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertEqual(self._callFUT(object()), [('foo', IFoo)])
+
+ def test_w_search_string_no_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), 'IFoo'), [('foo', IFoo)])
+
+ def test_no_search_string_w_base(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IBase(Interface):
+ pass
+ class IFoo(IBase):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), base=IBase), [('foo', IFoo)])
+
+ def test_no_search_string_w_base_is_same(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ gsm.registerUtility(IBar, IInterface, 'bar')
+ self.assertEqual(self._callFUT(object(), base=IFoo), [('foo', IFoo)])
+
+
+class Test_getInterfaceAllDocs(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import getInterfaceAllDocs
+ return getInterfaceAllDocs(*args, **kw)
+
+ def test_w_class(self):
+ class Foo(object):
+ """DOCSTRING"""
+ bar = None
+ def baz(self):
+ """BAZ"""
+ self.assertEqual(self._callFUT(Foo),
+ 'zope.component.tests.test_interface.foo\n' +
+ 'docstring')
+
+ def test_w_interface_no_members(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ """DOCSTRING"""
+ self.assertEqual(self._callFUT(IFoo),
+ 'zope.component.tests.test_interface.ifoo\n' +
+ 'docstring')
+
+ def test_w_interface_w_members(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ class IFoo(Interface):
+ """DOCSTRING"""
+ bar = Attribute('bar', 'Do bar')
+ def baz(self):
+ """BAZ"""
+ self.assertEqual(self._callFUT(IFoo),
+ 'zope.component.tests.test_interface.ifoo\n' +
+ 'docstring\n' +
+ 'do bar\n' +
+ 'baz')
+
+
+class Test_nameToInterface(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import nameToInterface
+ return nameToInterface(*args, **kw)
+
+ def test_w_None(self):
+ self.assertTrue(self._callFUT(object(), 'None') is None)
+
+ def test_miss(self):
+ from zope.component.interfaces import ComponentLookupError
+ self.assertRaises(ComponentLookupError,
+ self._callFUT, object(), 'nonesuch')
+
+ def test_hit(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ found = self._callFUT(object(), 'foo')
+ self.assertTrue(found is IFoo)
+
+
+class Test_interfaceToName(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.interface import interfaceToName
+ return interfaceToName(*args, **kw)
+
+ def test_w_None(self):
+ self.assertEqual(self._callFUT(object(), None), 'None')
+
+ def test_w_unregistered(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ self.assertEqual(self._callFUT(object(), IFoo),
+ 'zope.component.tests.test_interface.IFoo')
+
+ def test_w_registered(self):
+ from zope.interface import Interface
+ from zope.interface.interfaces import IInterface
+ from zope.component.globalregistry import getGlobalSiteManager
+ gsm = getGlobalSiteManager()
+ class IFoo(Interface):
+ pass
+ gsm.registerUtility(IFoo, IInterface, 'foo')
+ self.assertEqual(self._callFUT(object(), IFoo),
+ 'zope.component.tests.test_interface.IFoo')
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_provideInterface),
+ unittest.makeSuite(Test_getInterface),
+ unittest.makeSuite(Test_queryInterface),
+ unittest.makeSuite(Test_searchInterface),
+ unittest.makeSuite(Test_searchInterfaceIds),
+ unittest.makeSuite(Test_searchInterfaceUtilities),
+ unittest.makeSuite(Test_getInterfaceAllDocs),
+ unittest.makeSuite(Test_nameToInterface),
+ unittest.makeSuite(Test_interfaceToName),
+ ))
+
diff --git a/src/zope/component/tests/test_persistentregistry.py b/src/zope/component/tests/test_persistentregistry.py
new file mode 100644
index 0000000..4cf162f
--- /dev/null
+++ b/src/zope/component/tests/test_persistentregistry.py
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for z.c.hooks
+"""
+import unittest
+
+
+class PersistentAdapterRegistryTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.persistentregistry import PersistentAdapterRegistry
+ return PersistentAdapterRegistry
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def _makeCache(self, jar):
+ # Borrowed from persistent.tests.test_pyPersistence.
+
+ class _Cache(object):
+ def __init__(self, jar):
+ self._jar = jar
+ self._mru = []
+ def mru(self, oid):
+ self._mru.append(oid)
+ def new_ghost(self, oid, obj):
+ obj._p_jar = self._jar
+ obj._p_oid = oid
+
+ return _Cache(jar)
+
+ def _makeJar(self):
+ # Borrowed from persistent.tests.test_pyPersistence.
+ from zope.interface import implements
+ from persistent.interfaces import IPersistentDataManager
+
+ class _Jar(object):
+ implements(IPersistentDataManager)
+ def __init__(self):
+ self._loaded = []
+ self._registered = []
+ def setstate(self, obj):
+ self._loaded.append(obj._p_oid)
+ def register(self, obj):
+ self._registered.append(obj._p_oid)
+
+ jar = _Jar()
+ jar._cache = self._makeCache(jar)
+ return jar
+
+ def _makeOneWithJar(self, dirty=False):
+ # Borrowed from persistent.tests.test_pyPersistence.
+ OID = _makeOctets('\x01' * 8)
+ inst = self._makeOne()
+ jar = self._makeJar()
+ jar._cache.new_ghost(OID, inst) # assigns _p_jar, _p_oid
+ return inst, jar, OID
+
+ def test_changed_original_is_not_us(self):
+ registry, jar, OID = self._makeOneWithJar()
+ self.assertEqual(registry._generation, 1)
+ registry.changed(object())
+ # 'originally_changed' is not us, but we are still dirty because
+ # '_generation' gets bumped.
+ self.assertEqual(registry._p_changed, True)
+ # base class gets called
+ self.assertEqual(registry._generation, 2)
+
+ def test_changed_original_is_us(self):
+ registry, jar, OID = self._makeOneWithJar()
+ self.assertEqual(registry._generation, 1)
+ registry.changed(registry)
+ # 'originally_changed' is not us, so not dirty
+ self.assertEqual(registry._p_changed, True)
+ # base class gets called
+ self.assertEqual(registry._generation, 2)
+
+ def test___getstate___simple(self):
+ registry, jar, OID = self._makeOneWithJar()
+ state = registry.__getstate__()
+ self.assertEqual(state['__bases__'], ())
+ self.assertEqual(state['_generation'], 1)
+ self.assertEqual(state['_provided'], {})
+ self.assertEqual(state['_adapters'], [])
+ self.assertEqual(state['_subscribers'], [])
+ self.assertEqual(state['ro'], [registry])
+
+ def test___getstate___skips_delegated_names(self):
+ registry, jar, OID = self._makeOneWithJar()
+ registry.names = lambda *args: ['a', 'b', 'c']
+ self.assertFalse('names' in registry.__getstate__())
+
+ def test___setstate___rebuilds__v_lookup(self):
+ registry, jar, OID = self._makeOneWithJar()
+ state = registry.__getstate__()
+ self.assertTrue('_v_lookup' in registry.__dict__)
+ registry._p_changed = None # clears volatile '_v_lookup'
+ self.assertFalse('_v_lookup' in registry.__dict__)
+ registry.__setstate__(state)
+ self.assertTrue('_v_lookup' in registry.__dict__)
+
+
+class PersistentComponentsTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.persistentregistry import PersistentComponents
+ return PersistentComponents
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_ctor_initializes_registries_and_registrations(self):
+ from persistent.mapping import PersistentMapping
+ from persistent.list import PersistentList
+ from zope.component.persistentregistry import PersistentAdapterRegistry
+ registry = self._makeOne()
+ self.assertTrue(isinstance(registry.adapters,
+ PersistentAdapterRegistry))
+ self.assertTrue(isinstance(registry.utilities,
+ PersistentAdapterRegistry))
+ self.assertTrue(isinstance(registry._adapter_registrations,
+ PersistentMapping))
+ self.assertTrue(isinstance(registry._utility_registrations,
+ PersistentMapping))
+ self.assertTrue(isinstance(registry._subscription_registrations,
+ PersistentList))
+ self.assertTrue(isinstance(registry._handler_registrations,
+ PersistentList))
+
+def _makeOctets(s):
+ import sys
+ if sys.version_info < (3,):
+ return bytes(s)
+ return bytes(s, 'ascii') #pragma NO COVERAGE
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(PersistentAdapterRegistryTests),
+ unittest.makeSuite(PersistentComponentsTests),
+ ))
diff --git a/src/zope/component/tests/test_registry.py b/src/zope/component/tests/test_registry.py
new file mode 100644
index 0000000..0ba6bd2
--- /dev/null
+++ b/src/zope/component/tests/test_registry.py
@@ -0,0 +1,131 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for z.c.registry
+"""
+import unittest
+
+
+class Test_dispatchUtilityRegistrationEvent(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.registry import dispatchUtilityRegistrationEvent
+ return dispatchUtilityRegistrationEvent(*args, **kw)
+
+ def test_it(self):
+ from zope.component import registry
+ class _Registration(object):
+ component = object()
+ _EVENT = object()
+ _handled = []
+ def _handle(*args):
+ _handled.append(args)
+ with _Monkey(registry, handle=_handle):
+ self._callFUT(_Registration(), _EVENT)
+ self.assertEqual(_handled, [(_Registration.component, _EVENT)])
+
+
+class Test_dispatchAdapterRegistrationEvent(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.registry import dispatchAdapterRegistrationEvent
+ return dispatchAdapterRegistrationEvent(*args, **kw)
+
+ def test_it(self):
+ from zope.component import registry
+ class _Registration(object):
+ def factory(self, *args, **kw):
+ pass
+ _registration = _Registration()
+ _EVENT = object()
+ _handled = []
+ def _handle(*args):
+ _handled.append(args)
+ with _Monkey(registry, handle=_handle):
+ self._callFUT(_registration, _EVENT)
+ self.assertEqual(_handled, [(_registration.factory, _EVENT)])
+
+
+class Test_dispatchSubscriptionAdapterRegistrationEvent(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.registry \
+ import dispatchSubscriptionAdapterRegistrationEvent
+ return dispatchSubscriptionAdapterRegistrationEvent(*args, **kw)
+
+ def test_it(self):
+ from zope.component import registry
+ class _Registration(object):
+ def factory(self, *args, **kw):
+ pass
+ _registration = _Registration()
+ _EVENT = object()
+ _handled = []
+ def _handle(*args):
+ _handled.append(args)
+ with _Monkey(registry, handle=_handle):
+ self._callFUT(_registration, _EVENT)
+ self.assertEqual(_handled, [(_registration.factory, _EVENT)])
+
+
+class Test_dispatchHandlerRegistrationEvent(unittest.TestCase):
+
+ from zope.component.testing import setUp, tearDown
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.registry import dispatchHandlerRegistrationEvent
+ return dispatchHandlerRegistrationEvent(*args, **kw)
+
+ def test_it(self):
+ from zope.component import registry
+ class _Registration(object):
+ def handler(self, *args, **kw):
+ pass
+ _registration = _Registration()
+ _EVENT = object()
+ _handled = []
+ def _handle(*args):
+ _handled.append(args)
+ with _Monkey(registry, handle=_handle):
+ self._callFUT(_registration, _EVENT)
+ self.assertEqual(_handled, [(_registration.handler, _EVENT)])
+
+
+class _Monkey(object):
+ # context-manager for replacing module names in the scope of a test.
+ def __init__(self, module, **kw):
+ self.module = module
+ self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+ for key, value in kw.items():
+ setattr(module, key, value)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ for key, value in self.to_restore.items():
+ setattr(self.module, key, value)
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_dispatchUtilityRegistrationEvent),
+ unittest.makeSuite(Test_dispatchAdapterRegistrationEvent),
+ unittest.makeSuite(Test_dispatchSubscriptionAdapterRegistrationEvent),
+ unittest.makeSuite(Test_dispatchHandlerRegistrationEvent),
+ ))
diff --git a/src/zope/component/tests/test_security.py b/src/zope/component/tests/test_security.py
new file mode 100644
index 0000000..df85129
--- /dev/null
+++ b/src/zope/component/tests/test_security.py
@@ -0,0 +1,249 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Pure-Python hookable tests
+"""
+import unittest
+
+
+class PermissionProxyTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.component.security import PermissionProxy
+ return PermissionProxy
+
+ def _makeOne(self, wrapped):
+ return self._getTargetClass()(wrapped)
+
+ def test_proxy_delegates___provided_by__(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface import providedBy
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ proxy = self._makeOne(foo)
+ self.assertEqual(providedBy(proxy), providedBy(foo))
+
+
+class Test__checker(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.security import _checker
+ return _checker(*args, **kw)
+
+ def test_no_allowed_attributes_no_allowed_interfaces(self):
+ from zope.security.checker import CheckerPublic
+ checker = self._callFUT(object(), 'zope.Public', (), ())
+ self.assertEqual(checker.get_permissions, {'__call__': CheckerPublic})
+ self.assertFalse(checker.set_permissions)
+
+ def test_w_allowed_interfaces(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ def baz(self):
+ pass
+ class ISpam(Interface):
+ def qux(self):
+ pass
+ checker = self._callFUT(object(), 'testing', (IFoo, ISpam), ())
+ self.assertEqual(checker.get_permissions,
+ {'bar': 'testing', 'baz': 'testing', 'qux': 'testing'})
+ self.assertFalse(checker.set_permissions)
+
+ def test_w_allowed_attributes(self):
+ checker = self._callFUT(object(), 'testing', (), ('foo', 'bar'))
+ self.assertEqual(checker.get_permissions,
+ {'foo': 'testing', 'bar': 'testing'})
+ self.assertFalse(checker.set_permissions)
+
+
+class Test_proxify(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.security import proxify
+ return proxify(*args, **kw)
+
+ def _makeContext(self):
+ class _Context(object):
+ def bar(self):
+ pass
+ return _Context()
+
+ def test_no_checker_no_provides(self):
+ ctx = self._makeContext()
+ self.assertRaises(ValueError, self._callFUT, ctx, permission='testing')
+
+ def test_no_checker_no_permission(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ ctx = self._makeContext()
+ self.assertRaises(ValueError, self._callFUT, ctx, provides=IFoo)
+
+ def test_no_checker_w_provides_and_permission_public(self):
+ from zope.interface import Interface
+ from zope.security.checker import CheckerPublic
+ from zope.proxy import getProxiedObject
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ ctx = self._makeContext()
+ proxy = self._callFUT(ctx, provides=IFoo, permission='zope.Public')
+ self.assertTrue(getProxiedObject(proxy) is ctx)
+ checker = proxy.__Security_checker__
+ self.assertEqual(checker.get_permissions, {'bar': CheckerPublic})
+ self.assertFalse(checker.set_permissions)
+
+ def test_no_checker_w_provides_and_permission_protected(self):
+ from zope.interface import Interface
+ from zope.proxy import getProxiedObject
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ ctx = self._makeContext()
+ proxy = self._callFUT(ctx, provides=IFoo, permission='testing')
+ self.assertTrue(getProxiedObject(proxy) is ctx)
+ checker = proxy.__Security_checker__
+ self.assertEqual(checker.get_permissions, {'bar': 'testing'})
+ self.assertFalse(checker.set_permissions)
+
+ def test_w_checker(self):
+ from zope.proxy import getProxiedObject
+ _CHECKER = object()
+ ctx = self._makeContext()
+ proxy = self._callFUT(ctx, _CHECKER)
+ self.assertTrue(getProxiedObject(proxy) is ctx)
+ self.assertTrue(proxy.__Security_checker__ is _CHECKER)
+
+
+class Test_protectedFactory(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.security import protectedFactory
+ return protectedFactory(*args, **kw)
+
+ def test_public_not_already_proxied(self):
+ from zope.interface import Interface
+ from zope.security.checker import CheckerPublic
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ class _Factory(object):
+ def bar(self):
+ pass
+ protected = self._callFUT(_Factory, IFoo, 'zope.Public')
+ self.assertTrue(protected.factory is _Factory)
+ foo = protected()
+ self.assertEqual(foo.__Security_checker__.get_permissions,
+ {'bar': CheckerPublic})
+
+ def test_nonpublic_already_proxied(self):
+ from zope.interface import Interface
+ from zope.security.proxy import getTestProxyItems
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ class _Factory(object):
+ __slots__ = ('one',)
+ def bar(self):
+ pass
+ protected = self._callFUT(_Factory, IFoo, 'testing')
+ self.assertTrue(protected.factory is _Factory)
+ foo = protected()
+ self.assertEqual(getTestProxyItems(foo), [('bar', 'testing')])
+
+
+class Test_securityAdapterFactory(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.security import securityAdapterFactory
+ return securityAdapterFactory(*args, **kw)
+
+ def test_no_permission_untrusted_no_location(self):
+ class _Factory(object):
+ pass
+ self.assertTrue(self._callFUT(_Factory, None, False, False)
+ is _Factory)
+
+ def test_public_untrusted_no_location(self):
+ class _Factory(object):
+ pass
+ self.assertTrue(self._callFUT(_Factory, 'zope.Public', False, False)
+ is _Factory)
+
+ def test_CheckerPublic_untrusted_no_location(self):
+ from zope.security.checker import CheckerPublic
+ class _Factory(object):
+ pass
+ self.assertTrue(self._callFUT(_Factory, CheckerPublic, False, False)
+ is _Factory)
+
+ def test_protected_untrusted_no_location(self):
+ from zope.security.adapter import LocatingUntrustedAdapterFactory
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, 'testing', False, False)
+ self.assertTrue(isinstance(proxy, LocatingUntrustedAdapterFactory))
+
+ def test_no_permission_trusted_no_location(self):
+ from zope.security.adapter import LocatingTrustedAdapterFactory
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, None, False, True)
+ self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
+
+ def test_public_trusted_no_location(self):
+ from zope.security.adapter import LocatingTrustedAdapterFactory
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, 'zope.Public', False, True)
+ self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
+
+ def test_CheckerPublic_trusted_no_location(self):
+ from zope.security.adapter import LocatingTrustedAdapterFactory
+ from zope.security.checker import CheckerPublic
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, CheckerPublic, False, True)
+ self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
+
+ def test_protected_trusted_no_location(self):
+ from zope.security.adapter import LocatingTrustedAdapterFactory
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, 'testing', False, True)
+ self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
+
+ def test_protected_trusted_w_location(self):
+ from zope.security.adapter import LocatingTrustedAdapterFactory
+ class _Factory(object):
+ pass
+ proxy = self._callFUT(_Factory, 'testing', True, True)
+ self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
+
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(PermissionProxyTests),
+ unittest.makeSuite(Test__checker),
+ unittest.makeSuite(Test_proxify),
+ unittest.makeSuite(Test_protectedFactory),
+ unittest.makeSuite(Test_securityAdapterFactory),
+ ))
diff --git a/src/zope/component/tests/test_standalone.py b/src/zope/component/tests/test_standalone.py
new file mode 100644
index 0000000..76ee068
--- /dev/null
+++ b/src/zope/component/tests/test_standalone.py
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002, 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Component Architecture Tests
+"""
+import unittest
+
+
+class StandaloneTests(unittest.TestCase):
+ def testStandalone(self):
+ # See: https://bugs.launchpad.net/zope3/+bug/98401
+ import subprocess
+ import sys
+ import os
+ import pickle
+
+ executable = os.path.abspath(sys.executable)
+ where = os.path.dirname(os.path.dirname(__file__))
+ program = os.path.join(where, 'standalonetests.py')
+ process = subprocess.Popen([executable, program],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE)
+ pickle.dump(sys.path, process.stdin)
+ process.stdin.close()
+
+ try:
+ rc = process.wait()
+ except OSError as e:
+ if e.errno != 4: # MacIntel raises apparently unimportant EINTR?
+ raise # TODO verify sanity of a pass on EINTR :-/
+ if rc != 0:
+ output = process.stdout.read()
+ sys.stderr.write('#' * 80 + '\n')
+ sys.stdout.write(output)
+ sys.stderr.write('#' * 80 + '\n')
+ self.fail('Output code: %d' % rc)
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(StandaloneTests),
+ ))
diff --git a/src/zope/component/tests/test_zcml.py b/src/zope/component/tests/test_zcml.py
new file mode 100644
index 0000000..f64e822
--- /dev/null
+++ b/src/zope/component/tests/test_zcml.py
@@ -0,0 +1,1141 @@
+##############################################################################
+#
+# Copyright (c) 2012 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for ZCML directives.
+"""
+import unittest
+
+
+def skipIfNoSecurity(testfunc):
+ try:
+ import zope.security
+ except ImportError:
+ return lambda self: None
+ return testfunc
+
+class Test_handler(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import handler
+ return handler(*args, **kw)
+
+ def test_uses_configured_site_manager(self):
+ from zope.interface.registry import Components
+ from zope.component import getSiteManager
+ from zope.component.testfiles.components import comp, IApp
+ from zope.component._compat import _BLANK
+
+ registry = Components()
+ def dummy(context=None):
+ return registry
+ getSiteManager.sethook(dummy)
+
+ try:
+ self._callFUT('registerUtility', comp, IApp, _BLANK)
+ self.assertTrue(registry.getUtility(IApp) is comp)
+ finally:
+ getSiteManager.reset()
+
+
+class Test__rolledUpFactory(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import _rolledUpFactory
+ return _rolledUpFactory(*args, **kw)
+
+ def test_with_one(self):
+ _OBJ = object()
+ _CREATED = object()
+ def _factory(obj):
+ return _CREATED
+ rolled = self._callFUT([_factory])
+ self.assertTrue(rolled.factory is _factory)
+ self.assertTrue(rolled(_OBJ) is _CREATED)
+
+ def test_with_multiple(self):
+ _OBJ = object()
+ _CREATED1 = object()
+ _CREATED2 = object()
+ _CREATED3 = object()
+ def _factory1(obj):
+ return _CREATED1
+ def _factory2(obj):
+ return _CREATED2
+ def _factory3(obj):
+ return _CREATED3
+ rolled = self._callFUT([_factory1, _factory2, _factory3])
+ self.assertTrue(rolled.factory is _factory1)
+ self.assertTrue(rolled(_OBJ) is _CREATED3)
+
+
+class Test_adapter(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import adapter
+ return adapter(*args, **kw)
+
+ def test_empty_factory(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IFoo(Interface):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, [], [Interface], IFoo)
+
+ def test_multiple_factory_multiple_for_(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ class Foo(object):
+ pass
+ class Bar(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, [Foo, Bar],
+ [Interface, IBar], IFoo)
+
+ def test_no_for__factory_not_adapts(self):
+ #@adapter(IFoo)
+ class _Factory(object):
+ def __init__(self, context):
+ self.context = context
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError, self._callFUT, _cfg_ctx, [_Factory])
+
+ def test_no_for__factory_adapts_no_provides_factory_not_implements(self):
+ from zope.interface import Interface
+ from zope.component._declaration import adapter
+ @adapter(Interface)
+ class _Factory(object):
+ def __init__(self, context):
+ self.context = context
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError, self._callFUT, _cfg_ctx, [_Factory])
+
+ def test_multiple_factory_single_for__w_name(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ class Bar(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [Foo, Bar], IFoo, [Interface], name='test')
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('adapter', (Interface,), IFoo, 'test'))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ self.assertEqual(action['args'][1].factory, Foo) #rolled up
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], 'test')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ @skipIfNoSecurity
+ def test_single_factory_single_for_w_permission(self):
+ from zope.interface import Interface
+ from zope.security.adapter import LocatingUntrustedAdapterFactory
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [Foo], IFoo, [Interface], permission='testing')
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('adapter', (Interface,), IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'protected_factory' plus
+ # 'LocatingUntrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy,
+ LocatingUntrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+ @skipIfNoSecurity
+ def test_single_factory_single_for_w_locate_no_permission(self):
+ from zope.interface import Interface
+ from zope.security.adapter import LocatingUntrustedAdapterFactory
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [Foo], IFoo, [Interface], locate=True)
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('adapter', (Interface,), IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'LocatingUntrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy,
+ LocatingUntrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+ @skipIfNoSecurity
+ def test_single_factory_single_for_w_trusted_no_permission(self):
+ from zope.interface import Interface
+ from zope.security.adapter import TrustedAdapterFactory
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [Foo], IFoo, [Interface], trusted=True)
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('adapter', (Interface,), IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'LocatingUntrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy, TrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+ def test_no_for__no_provides_factory_adapts_factory_implements(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component._declaration import adapter
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ @adapter(Interface)
+ @implementer(IFoo)
+ class _Factory(object):
+ def __init__(self, context):
+ self.context = context
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [_Factory])
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('adapter', (Interface,), IFoo, ''))
+ self.assertEqual(action['args'],
+ ('registerAdapter', _Factory, (Interface,), IFoo,
+ '', 'TESTING'))
+
+
+class Test_subscriber(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import subscriber
+ return subscriber(*args, **kw)
+
+ def test_no_factory_no_handler(self):
+ from zope.interface import Interface
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, (Interface,))
+
+ def test_no_factory_w_handler_w_provides(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ def _handler(*args):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, (Interface,),
+ handler=_handler, provides=IFoo)
+
+ def test_w_factory_w_handler(self):
+ from zope.interface import Interface
+ class Foo(object):
+ pass
+ def _handler(*args):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, (Interface,), Foo,
+ handler=_handler)
+
+ def test_w_factory_no_provides(self):
+ from zope.interface import Interface
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, (Interface,), Foo)
+
+ def test_w_factory_w_provides_no_for_factory_wo_adapter(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx,
+ factory=Foo, provides=IFoo)
+
+ def test_no_factory_w_handler_no_provides(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ def _handler(*args):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (Interface,), handler=_handler)
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'][0], 'registerHandler')
+ self.assertEqual(action['args'][1], _handler)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], 'TESTING')
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ def test_w_factory_w_provides(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ def _handler(*args):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (Interface,), Foo, provides=IFoo)
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'][0], 'registerSubscriptionAdapter')
+ self.assertEqual(action['args'][1], Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ @skipIfNoSecurity
+ def test_w_factory_w_provides_w_permission(self):
+ from zope.interface import Interface
+ from zope.security.adapter import LocatingUntrustedAdapterFactory
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (Interface,), Foo,
+ provides=IFoo, permission='testing')
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'][0], 'registerSubscriptionAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'protected_factory' plus
+ # 'LocatingUntrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy,
+ LocatingUntrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ @skipIfNoSecurity
+ def test_w_factory_w_provides_wo_permission_w_locate(self):
+ from zope.interface import Interface
+ from zope.security.adapter import LocatingUntrustedAdapterFactory
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (Interface,), Foo, provides=IFoo, locate=True)
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'][0], 'registerSubscriptionAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'protected_factory' plus
+ # 'LocatingUntrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy,
+ LocatingUntrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ @skipIfNoSecurity
+ def test_w_factory_w_provides_wo_permission_w_trusted(self):
+ from zope.interface import Interface
+ from zope.security.adapter import TrustedAdapterFactory
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (Interface,), Foo, provides=IFoo, trusted=True)
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'][0], 'registerSubscriptionAdapter')
+ factory_proxy = action['args'][1]
+ # Foo wraped by 'protected_factory' plus
+ # 'TrustedAdapterFactory'
+ self.assertTrue(isinstance(factory_proxy,
+ TrustedAdapterFactory))
+ self.assertTrue(factory_proxy.factory is Foo)
+ self.assertEqual(action['args'][2], (Interface,))
+ self.assertEqual(action['args'][3], IFoo)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+
+class Test_utility(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import utility
+ return utility(*args, **kw)
+
+ def test_w_factory_w_component(self):
+ class _Factory(object):
+ pass
+ _COMPONENT = object
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError, self._callFUT, _cfg_ctx,
+ factory=_Factory,
+ component=_COMPONENT)
+
+ def test_w_factory_wo_provides_factory_no_implements(self):
+ class _Factory(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, factory=_Factory)
+
+ def test_w_component_wo_provides_component_no_provides(self):
+ _COMPONENT = object
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(TypeError,
+ self._callFUT, _cfg_ctx, component=_COMPONENT)
+
+ def test_w_factory_w_provides(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, factory=Foo, provides=IFoo)
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the utility
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], ('utility', IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerUtility')
+ self.assertEqual(action['args'][1], None)
+ self.assertEqual(action['args'][2], IFoo)
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], 'TESTING')
+ self.assertEqual(action['kw'], {'factory': Foo})
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+
+ def test_w_factory_wo_provides_factory_implements(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, factory=Foo)
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the utility
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], ('utility', IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerUtility')
+ self.assertEqual(action['args'][1], None)
+ self.assertEqual(action['args'][2], IFoo)
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], 'TESTING')
+ self.assertEqual(action['kw'], {'factory': Foo})
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+
+ def test_w_component_w_provides_w_naem(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ _COMPONENT = object()
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, component=_COMPONENT,
+ name='test', provides=IFoo)
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the utility
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], ('utility', IFoo, 'test'))
+ self.assertEqual(action['args'][0], 'registerUtility')
+ self.assertEqual(action['args'][1], _COMPONENT)
+ self.assertEqual(action['args'][2], IFoo)
+ self.assertEqual(action['args'][3], 'test')
+ self.assertEqual(action['args'][4], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+
+ def test_w_component_wo_provides_component_provides(self):
+ from zope.interface import Interface
+ from zope.interface import directlyProvides
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ pass
+ class Foo(object):
+ pass
+ _COMPONENT = Foo()
+ directlyProvides(_COMPONENT, IFoo)
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, component=_COMPONENT)
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the utility
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], ('utility', IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerUtility')
+ self.assertEqual(action['args'][1], _COMPONENT)
+ self.assertEqual(action['args'][2], IFoo)
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+
+ @skipIfNoSecurity
+ def test_w_component_w_provides_w_permission(self):
+ from zope.interface import Interface
+ from zope.proxy import removeAllProxies
+ from zope.component.interface import provideInterface
+ from zope.component.security import PermissionProxy
+ from zope.component.zcml import handler
+ class IFoo(Interface):
+ def bar(self):
+ pass
+ class Foo(object):
+ def bar(self):
+ pass
+ _COMPONENT = Foo()
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, component=_COMPONENT,
+ provides=IFoo, permission='testing')
+ self.assertEqual(len(_cfg_ctx._actions), 2)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the utility
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'], ('utility', IFoo, ''))
+ self.assertEqual(action['args'][0], 'registerUtility')
+ component_proxy = action['args'][1]
+ self.assertTrue(isinstance(component_proxy, PermissionProxy))
+ self.assertTrue(removeAllProxies(component_proxy) is _COMPONENT)
+ self.assertEqual(component_proxy.__Security_checker__.get_permissions,
+ {'bar': 'testing'})
+ self.assertEqual(action['args'][2], IFoo)
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo))
+
+
+class Test_interface(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import interface
+ return interface(*args, **kw)
+
+ def test_wo_name_wo_type(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ class IFoo(Interface):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, IFoo)
+ self.assertEqual(len(_cfg_ctx._actions), 1)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IFoo, None))
+
+ def test_w_name_w_type(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ class IFoo(Interface):
+ pass
+ class IBar(Interface):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, IFoo, name='foo', type=IBar)
+ self.assertEqual(len(_cfg_ctx._actions), 1)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('foo', IFoo, IBar))
+
+
+class Test_view(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import view
+ return view(*args, **kw)
+
+ def test_w_allowed_interface_wo_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IViewType(Interface):
+ pass
+ class IView(Interface):
+ def foo():
+ pass
+ def bar():
+ pass
+ class _View(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, (_View,), IViewType, '',
+ for_=(Interface, Interface),
+ allowed_interface=IView)
+
+ def test_w_allowed_attributes_wo_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, (_View,), IViewType, '',
+ for_=(Interface, Interface),
+ allowed_attributes=('foo', 'bar'))
+
+ def test_w_factory_as_empty(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IViewType(Interface):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, (), IViewType, '',
+ for_=(Interface, Interface))
+
+ def test_w_multiple_factory_multiple_for_(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IViewType(Interface):
+ pass
+ class Foo(object):
+ pass
+ class Bar(object):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, (Foo, Bar), IViewType, '',
+ for_=(Interface, Interface))
+
+ def test_w_for__as_empty(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context):
+ self.context = context
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT, _cfg_ctx, (_View,), IViewType, '',
+ for_=())
+
+ def test_w_single_factory_single_for__wo_permission_w_name(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ from zope.component.interface import provideInterface
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context):
+ self.context = context
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, (_View,), IViewType, 'test', for_=(Interface,))
+ self.assertEqual(len(_cfg_ctx._actions), 4)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('view', (Interface, IViewType), 'test', Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ self.assertEqual(action['args'][1], _View)
+ self.assertEqual(action['args'][2], (Interface, IViewType))
+ self.assertEqual(action['args'][3], Interface)
+ self.assertEqual(action['args'][4], 'test')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the provided interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+ self.assertEqual(_cfg_ctx._actions[3][0], ())
+ action =_cfg_ctx._actions[3][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IViewType))
+
+ def test_w_multiple_factory_single_for__wo_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context):
+ self.context = context
+ class _View2(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [_View, _View2], IViewType, '',
+ for_=(Interface,))
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('view', (Interface, IViewType), '', Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory = action['args'][1]
+ self.assertTrue(factory.factory is _View)
+ context = object()
+ request = object()
+ view = factory(context, request)
+ self.assertTrue(isinstance(view, _View2))
+ self.assertTrue(view.request is request)
+ self.assertTrue(isinstance(view.context, _View))
+ self.assertTrue(view.context.context is context)
+ self.assertEqual(action['args'][2], (Interface, IViewType))
+ self.assertEqual(action['args'][3], Interface)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+ @skipIfNoSecurity
+ def test_w_single_factory_single_for__w_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [_View], IViewType, '', for_=(Interface,),
+ permission='testing')
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('view', (Interface, IViewType), '', Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory = action['args'][1]
+ context = object()
+ request = object()
+ view = factory(context, request)
+ self.assertTrue(view.context is context)
+ self.assertTrue(view.request is request)
+ self.assertTrue(factory.factory is _View)
+ self.assertEqual(action['args'][2], (Interface, IViewType))
+ self.assertEqual(action['args'][3], Interface)
+ self.assertEqual(action['args'][4], '')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+ @skipIfNoSecurity
+ def test_w_single_factory_single_for__w_permission_and_allowed_attrs(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ class IViewType(Interface):
+ pass
+ class _View(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ def bar(self):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [_View], IViewType, '', for_=(Interface,),
+ permission='testing', allowed_attributes=('bar',))
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('view', (Interface, IViewType), '', Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory = action['args'][1]
+ checker = factory.checker
+ self.assertEqual(checker.get_permissions, {'bar': 'testing'})
+
+ @skipIfNoSecurity
+ def test_w_single_factory_single_for__w_permission_and_allowed_iface(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ class IViewType(Interface):
+ def bar(self):
+ pass
+ class _View(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ def bar(self):
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, [_View], IViewType, '', for_=(Interface,),
+ permission='testing', allowed_interface=(IViewType,))
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the adapter
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('view', (Interface, IViewType), '', Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory = action['args'][1]
+ checker = factory.checker
+ self.assertEqual(checker.get_permissions, {'bar': 'testing'})
+
+
+class Test_resource(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.component.zcml import resource
+ return resource(*args, **kw)
+
+ def test_w_allowed_interface_wo_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IResourceType(Interface):
+ pass
+ class IView(Interface):
+ def foo():
+ pass
+ def bar():
+ pass
+ class _Resource(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT,
+ _cfg_ctx, (_Resource,), IResourceType, '',
+ allowed_interface=IView)
+
+ def test_w_allowed_attributes_wo_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import ComponentConfigurationError
+ class IResourceType(Interface):
+ pass
+ class _Resource(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self.assertRaises(ComponentConfigurationError,
+ self._callFUT,
+ _cfg_ctx, (_Resource,), IResourceType, '',
+ allowed_attributes=('foo', 'bar'))
+
+ def test_wo_permission_w_name(self):
+ from zope.interface import Interface
+ from zope.component.interface import provideInterface
+ from zope.component.zcml import handler
+ class IResourceType(Interface):
+ pass
+ class _Resource(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, _Resource, IResourceType, 'test')
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the resource
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('resource', 'test', IResourceType, Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ self.assertEqual(action['args'][1], _Resource)
+ self.assertEqual(action['args'][2], (IResourceType,))
+ self.assertEqual(action['args'][3], Interface)
+ self.assertEqual(action['args'][4], 'test')
+ self.assertEqual(action['args'][5], 'TESTING')
+ # Register the 'type' interface
+ self.assertEqual(_cfg_ctx._actions[1][0], ())
+ action =_cfg_ctx._actions[1][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', IResourceType))
+ # Register the required interface(s)
+ self.assertEqual(_cfg_ctx._actions[2][0], ())
+ action =_cfg_ctx._actions[2][1]
+ self.assertEqual(action['callable'], provideInterface)
+ self.assertEqual(action['discriminator'], None)
+ self.assertEqual(action['args'], ('', Interface))
+
+ @skipIfNoSecurity
+ def test_w_permission(self):
+ from zope.interface import Interface
+ from zope.component.zcml import handler
+ class IResourceType(Interface):
+ pass
+ class _Resource(object):
+ def __init__(self, context):
+ self.context = context
+ def foo():
+ pass
+ def bar():
+ pass
+ _cfg_ctx = _makeConfigContext()
+ self._callFUT(_cfg_ctx, _Resource, IResourceType, 'test',
+ permission='testing', allowed_attributes=('foo',))
+ self.assertEqual(len(_cfg_ctx._actions), 3)
+ self.assertEqual(_cfg_ctx._actions[0][0], ())
+ # Register the resource
+ action =_cfg_ctx._actions[0][1]
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(action['discriminator'],
+ ('resource', 'test', IResourceType, Interface))
+ self.assertEqual(action['args'][0], 'registerAdapter')
+ factory = action['args'][1]
+ self.assertTrue(factory.factory is _Resource)
+ context = object()
+ resource = factory(context)
+ checker = resource.__Security_checker__
+ self.assertEqual(checker.get_permissions, {'foo': 'testing'})
+ self.assertTrue(resource.context is context)
+ self.assertEqual(action['args'][2], (IResourceType,))
+ self.assertEqual(action['args'][3], Interface)
+ self.assertEqual(action['args'][4], 'test')
+ self.assertEqual(action['args'][5], 'TESTING')
+
+
+def _makeConfigContext():
+ class _Context(object):
+ info = 'TESTING'
+ def __init__(self):
+ self._actions = []
+ def action(self, *args, **kw):
+ self._actions.append((args, kw))
+ return _Context()
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(Test_handler),
+ unittest.makeSuite(Test__rolledUpFactory),
+ unittest.makeSuite(Test_adapter),
+ unittest.makeSuite(Test_subscriber),
+ unittest.makeSuite(Test_utility),
+ unittest.makeSuite(Test_interface),
+ unittest.makeSuite(Test_view),
+ unittest.makeSuite(Test_resource),
+ ))
diff --git a/src/zope/component/zcml.py b/src/zope/component/zcml.py
index 2b98b0f..d760ce1 100644
--- a/src/zope/component/zcml.py
+++ b/src/zope/component/zcml.py
@@ -13,42 +13,49 @@
##############################################################################
"""Component Architecture configuration handlers
"""
-__docformat__ = "reStructuredText"
-
-import warnings
-import zope.component
-import zope.configuration.fields
-import zope.interface
-import zope.schema
-
-from zope.component.interface import provideInterface
from zope.configuration.exceptions import ConfigurationError
+from zope.configuration.fields import Bool
+from zope.configuration.fields import GlobalInterface
+from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import PythonIdentifier
+from zope.configuration.fields import Tokens
from zope.i18nmessageid import MessageFactory
+from zope.interface import Interface
+from zope.interface import implementedBy
+from zope.interface import providedBy
+from zope.schema import TextLine
+
+from zope.component._api import getSiteManager
+from zope.component._declaration import adaptedBy
+from zope.component.interface import provideInterface
+from zope.component._compat import _BLANK
try:
- from zope.component.security import _checker, proxify, protectedFactory, \
- securityAdapterFactory
from zope.security.zcml import Permission
-except ImportError:
- SECURITY_SUPPORT = False
- from zope.schema import TextLine as Permission
+except ImportError: #pragma NO COVER
+ def _no_security(*args, **kw):
+ raise ConfigurationError("security proxied components are not "
+ "supported because zope.security is not available")
+ _checker = proxify = protectedFactory = security =_no_security
+ Permission = TextLine
else:
- SECURITY_SUPPORT = True
+ from zope.component.security import _checker
+ from zope.component.security import proxify
+ from zope.component.security import protectedFactory
+ from zope.component.security import securityAdapterFactory
_ = MessageFactory('zope')
-def check_security_support():
- if not SECURITY_SUPPORT:
- raise ConfigurationError("security proxied components are not "
- "supported because zope.security is not available")
+class ComponentConfigurationError(ValueError, ConfigurationError):
+ pass
def handler(methodName, *args, **kwargs):
- method = getattr(zope.component.getSiteManager(), methodName)
+ method = getattr(getSiteManager(), methodName)
method(*args, **kwargs)
-class IBasicComponentInformation(zope.interface.Interface):
+class IBasicComponentInformation(Interface):
- component = zope.configuration.fields.GlobalObject(
+ component = GlobalObject(
title=_("Component to use"),
description=_("Python name of the implementation object. This"
" must identify an object in a module using the"
@@ -63,7 +70,7 @@ class IBasicComponentInformation(zope.interface.Interface):
required=False,
)
- factory = zope.configuration.fields.GlobalObject(
+ factory = GlobalObject(
title=_("Factory"),
description=_("Python name of a factory which can create the"
" implementation object. This must identify an"
@@ -73,31 +80,31 @@ class IBasicComponentInformation(zope.interface.Interface):
required=False,
)
-class IAdapterDirective(zope.interface.Interface):
+class IAdapterDirective(Interface):
"""
Register an adapter
"""
- factory = zope.configuration.fields.Tokens(
+ factory = Tokens(
title=_("Adapter factory/factories"),
description=_("A list of factories (usually just one) that create"
" the adapter instance."),
required=True,
- value_type=zope.configuration.fields.GlobalObject()
+ value_type=GlobalObject()
)
- provides = zope.configuration.fields.GlobalInterface(
+ provides = GlobalInterface(
title=_("Interface the component provides"),
description=_("This attribute specifies the interface the adapter"
" instance must provide."),
required=False,
)
- for_ = zope.configuration.fields.Tokens(
+ for_ = Tokens(
title=_("Specifications to be adapted"),
description=_("This should be a list of interfaces or classes"),
required=False,
- value_type=zope.configuration.fields.GlobalObject(
+ value_type=GlobalObject(
missing_value=object(),
),
)
@@ -109,7 +116,7 @@ class IAdapterDirective(zope.interface.Interface):
required=False,
)
- name = zope.schema.TextLine(
+ name = TextLine(
title=_("Name"),
description=_("Adapters can have names.\n\n"
"This attribute allows you to specify the name for"
@@ -117,7 +124,7 @@ class IAdapterDirective(zope.interface.Interface):
required=False,
)
- trusted = zope.configuration.fields.Bool(
+ trusted = Bool(
title=_("Trusted"),
description=_("""Make the adapter a trusted adapter
@@ -131,7 +138,7 @@ class IAdapterDirective(zope.interface.Interface):
default=False,
)
- locate = zope.configuration.fields.Bool(
+ locate = Bool(
title=_("Locate"),
description=_("""Make the adapter a locatable adapter
@@ -158,7 +165,7 @@ def adapter(_context, factory, provides=None, for_=None, permission=None,
if for_ is None:
if len(factory) == 1:
- for_ = zope.component.adaptedBy(factory[0])
+ for_ = adaptedBy(factory[0])
if for_ is None:
raise TypeError("No for attribute was provided and can't "
@@ -168,7 +175,7 @@ def adapter(_context, factory, provides=None, for_=None, permission=None,
if provides is None:
if len(factory) == 1:
- p = list(zope.interface.implementedBy(factory[0]))
+ p = list(implementedBy(factory[0]))
if len(p) == 1:
provides = p[0]
@@ -180,19 +187,18 @@ def adapter(_context, factory, provides=None, for_=None, permission=None,
if len(factories) == 1:
factory = factories[0]
elif len(factories) < 1:
- raise ValueError("No factory specified")
+ raise ComponentConfigurationError("No factory specified")
elif len(factories) > 1 and len(for_) != 1:
- raise ValueError("Can't use multiple factories and multiple for")
+ raise ComponentConfigurationError(
+ "Can't use multiple factories and multiple for")
else:
factory = _rolledUpFactory(factories)
if permission is not None:
- check_security_support()
factory = protectedFactory(factory, provides, permission)
# invoke custom adapter factories
if locate or permission is not None or trusted:
- check_security_support()
factory = securityAdapterFactory(factory, permission, locate, trusted)
_context.action(
@@ -215,35 +221,35 @@ def adapter(_context, factory, provides=None, for_=None, permission=None,
args = ('', iface)
)
-class ISubscriberDirective(zope.interface.Interface):
+class ISubscriberDirective(Interface):
"""
Register a subscriber
"""
- factory = zope.configuration.fields.GlobalObject(
+ factory = GlobalObject(
title=_("Subscriber factory"),
description=_("A factory used to create the subscriber instance."),
required=False,
)
- handler = zope.configuration.fields.GlobalObject(
+ handler = GlobalObject(
title=_("Handler"),
description=_("A callable object that handles events."),
required=False,
)
- provides = zope.configuration.fields.GlobalInterface(
+ provides = GlobalInterface(
title=_("Interface the component provides"),
description=_("This attribute specifies the interface the adapter"
" instance must provide."),
required=False,
)
- for_ = zope.configuration.fields.Tokens(
+ for_ = Tokens(
title=_("Interfaces or classes that this subscriber depends on"),
description=_("This should be a list of interfaces or classes"),
required=False,
- value_type=zope.configuration.fields.GlobalObject(
+ value_type=GlobalObject(
missing_value = object(),
),
)
@@ -255,7 +261,7 @@ class ISubscriberDirective(zope.interface.Interface):
required=False,
)
- trusted = zope.configuration.fields.Bool(
+ trusted = Bool(
title=_("Trusted"),
description=_("""Make the subscriber a trusted subscriber
@@ -269,7 +275,7 @@ class ISubscriberDirective(zope.interface.Interface):
default=False,
)
- locate = zope.configuration.fields.Bool(
+ locate = Bool(
title=_("Locate"),
description=_("""Make the subscriber a locatable subscriber
@@ -298,20 +304,18 @@ def subscriber(_context, for_=None, factory=None, handler=None, provides=None,
"a factory")
if for_ is None:
- for_ = zope.component.adaptedBy(factory)
+ for_ = adaptedBy(factory)
if for_ is None:
raise TypeError("No for attribute was provided and can't "
"determine what the factory (or handler) adapts.")
if permission is not None:
- check_security_support()
factory = protectedFactory(factory, provides, permission)
for_ = tuple(for_)
# invoke custom adapter factories
if locate or permission is not None or trusted:
- check_security_support()
factory = securityAdapterFactory(factory, permission, locate, trusted)
if handler is not None:
@@ -319,14 +323,14 @@ def subscriber(_context, for_=None, factory=None, handler=None, provides=None,
discriminator = None,
callable = _handler,
args = ('registerHandler',
- handler, for_, u'', _context.info),
+ handler, for_, _BLANK, _context.info),
)
else:
_context.action(
discriminator = None,
callable = _handler,
args = ('registerSubscriptionAdapter',
- factory, for_, provides, u'', _context.info),
+ factory, for_, provides, _BLANK, _context.info),
)
if provides is not None:
@@ -348,13 +352,13 @@ def subscriber(_context, for_=None, factory=None, handler=None, provides=None,
class IUtilityDirective(IBasicComponentInformation):
"""Register a utility."""
- provides = zope.configuration.fields.GlobalInterface(
+ provides = GlobalInterface(
title=_("Provided interface"),
description=_("Interface provided by the utility."),
required=False,
)
- name = zope.schema.TextLine(
+ name = TextLine(
title=_("Name"),
description=_("Name of the registration. This is used by"
" application code when locating a utility."),
@@ -368,46 +372,45 @@ def utility(_context, provides=None, component=None, factory=None,
if provides is None:
if factory:
- provides = list(zope.interface.implementedBy(factory))
+ provides = list(implementedBy(factory))
else:
- provides = list(zope.interface.providedBy(component))
+ provides = list(providedBy(component))
if len(provides) == 1:
provides = provides[0]
else:
raise TypeError("Missing 'provides' attribute")
if permission is not None:
- check_security_support()
component = proxify(component, provides=provides, permission=permission)
_context.action(
discriminator = ('utility', provides, name),
callable = handler,
- args = ('registerUtility', component, provides, name),
+ args = ('registerUtility', component, provides, name, _context.info),
kw = dict(factory=factory),
)
_context.action(
discriminator = None,
callable = provideInterface,
- args = (provides.__module__ + '.' + provides.getName(), provides)
+ args = ('', provides),
)
-class IInterfaceDirective(zope.interface.Interface):
+class IInterfaceDirective(Interface):
"""
Define an interface
"""
- interface = zope.configuration.fields.GlobalInterface(
+ interface = GlobalInterface(
title=_("Interface"),
required=True,
)
- type = zope.configuration.fields.GlobalInterface(
+ type = GlobalInterface(
title=_("Interface type"),
required=False,
)
- name = zope.schema.TextLine(
+ name = TextLine(
title=_("Name"),
required=False,
)
@@ -419,15 +422,15 @@ def interface(_context, interface, type=None, name=''):
args = (name, interface, type)
)
-class IBasicViewInformation(zope.interface.Interface):
+class IBasicViewInformation(Interface):
"""This is the basic information for all views."""
- for_ = zope.configuration.fields.Tokens(
+ for_ = Tokens(
title=_("Specifications of the objects to be viewed"),
description=_("""This should be a list of interfaces or classes
"""),
required=True,
- value_type=zope.configuration.fields.GlobalObject(
+ value_type=GlobalObject(
missing_value=object(),
),
)
@@ -438,22 +441,13 @@ class IBasicViewInformation(zope.interface.Interface):
required=False,
)
- class_ = zope.configuration.fields.GlobalObject(
+ class_ = GlobalObject(
title=_("Class"),
description=_("A class that provides attributes used by the view."),
required=False,
)
- layer = zope.configuration.fields.GlobalInterface(
- title=_("The layer the view is in."),
- description=_("""
- A skin is composed of layers. It is common to put skin
- specific views in a layer named after the skin. If the 'layer'
- attribute is not supplied, it defaults to 'default'."""),
- required=False,
- )
-
- allowed_interface = zope.configuration.fields.Tokens(
+ allowed_interface = Tokens(
title=_("Interface that is also allowed if user has permission."),
description=_("""
By default, 'permission' only applies to viewing the view and
@@ -464,10 +458,10 @@ class IBasicViewInformation(zope.interface.Interface):
Multiple interfaces can be provided, separated by
whitespace."""),
required=False,
- value_type=zope.configuration.fields.GlobalInterface(),
+ value_type=GlobalInterface(),
)
- allowed_attributes = zope.configuration.fields.Tokens(
+ allowed_attributes = Tokens(
title=_("View attributes that are also allowed if the user"
" has permission."),
description=_("""
@@ -476,31 +470,31 @@ class IBasicViewInformation(zope.interface.Interface):
you can make the permission also apply to the extra attributes
on the view object."""),
required=False,
- value_type=zope.configuration.fields.PythonIdentifier(),
+ value_type=PythonIdentifier(),
)
-class IBasicResourceInformation(zope.interface.Interface):
+class IBasicResourceInformation(Interface):
"""
Basic information for resources
"""
- name = zope.schema.TextLine(
+ name = TextLine(
title=_("The name of the resource."),
description=_("The name shows up in URLs/paths. For example 'foo'."),
required=True,
- default=u'',
+ default=_BLANK,
)
- provides = zope.configuration.fields.GlobalInterface(
+ provides = GlobalInterface(
title=_("The interface this component provides."),
description=_("""
A view can provide an interface. This would be used for
views that support other views."""),
required=False,
- default=zope.interface.Interface,
+ default=Interface,
)
- type = zope.configuration.fields.GlobalInterface(
+ type = GlobalInterface(
title=_("Request type"),
required=True
)
@@ -509,28 +503,26 @@ class IBasicResourceInformation(zope.interface.Interface):
class IViewDirective(IBasicViewInformation, IBasicResourceInformation):
"""Register a view for a component"""
- factory = zope.configuration.fields.Tokens(
+ factory = Tokens(
title=_("Factory"),
required=False,
- value_type=zope.configuration.fields.GlobalObject(),
+ value_type=GlobalObject(),
)
-def view(_context, factory, type, name, for_, layer=None,
- permission=None, allowed_interface=None, allowed_attributes=None,
- provides=zope.interface.Interface):
+def view(_context, factory, type, name, for_,
+ permission=None,
+ allowed_interface=None,
+ allowed_attributes=None,
+ provides=Interface,
+ ):
if ((allowed_attributes or allowed_interface)
and (not permission)):
- raise ConfigurationError(
- "Must use name attribute with allowed_interface or "
- "allowed_attributes"
- )
-
- if not factory:
- raise ConfigurationError("No view factory specified.")
+ raise ComponentConfigurationError(
+ "'permission' required with 'allowed_interface' or "
+ "'allowed_attributes'")
if permission is not None:
- check_security_support()
checker = _checker(_context, permission,
allowed_interface, allowed_attributes)
@@ -549,7 +541,7 @@ def view(_context, factory, type, name, for_, layer=None,
if not for_:
- raise ValueError("No for interfaces specified");
+ raise ComponentConfigurationError("No for interfaces specified");
for_ = tuple(for_)
# Generate a single factory from multiple factories:
@@ -557,27 +549,18 @@ def view(_context, factory, type, name, for_, layer=None,
if len(factories) == 1:
factory = factories[0]
elif len(factories) < 1:
- raise ValueError("No factory specified")
+ raise ComponentConfigurationError("No view factory specified")
elif len(factories) > 1 and len(for_) > 1:
- raise ValueError("Can't use multiple factories and multiple for")
+ raise ComponentConfigurationError(
+ "Can't use multiple factories and multiple for")
else:
def factory(ob, request):
for f in factories[:-1]:
ob = f(ob)
return factories[-1](ob, request)
+ factory.factory = factories[0]
- # BBB 2006/02/18, to be removed after 12 months
- if layer is not None:
- for_ = for_ + (layer,)
- warnings.warn_explicit(
- "The 'layer' argument of the 'view' directive has been "
- "deprecated. Use the 'type' argument instead. If you have "
- "an existing 'type' argument IBrowserRequest, replace it with the "
- "'layer' argument (the layer subclasses IBrowserRequest). "
- "which subclasses BrowserRequest.",
- DeprecationWarning, _context.info.file, _context.info.line)
- else:
- for_ = for_ + (type,)
+ for_ = for_ + (type,)
_context.action(
discriminator = ('view', for_, name, provides),
@@ -585,12 +568,6 @@ def view(_context, factory, type, name, for_, layer=None,
args = ('registerAdapter',
factory, for_, provides, name, _context.info),
)
- if type is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', type)
- )
_context.action(
discriminator = None,
@@ -612,67 +589,52 @@ class IResourceDirective(IBasicComponentInformation,
IBasicResourceInformation):
"""Register a resource"""
- layer = zope.configuration.fields.GlobalInterface(
- title=_("The layer the resource is in."),
- required=False,
- )
-
- allowed_interface = zope.configuration.fields.Tokens(
+ allowed_interface = Tokens(
title=_("Interface that is also allowed if user has permission."),
required=False,
- value_type=zope.configuration.fields.GlobalInterface(),
+ value_type=GlobalInterface(),
)
- allowed_attributes = zope.configuration.fields.Tokens(
+ allowed_attributes = Tokens(
title=_("View attributes that are also allowed if user"
" has permission."),
required=False,
- value_type=zope.configuration.fields.PythonIdentifier(),
+ value_type=PythonIdentifier(),
)
-def resource(_context, factory, type, name, layer=None,
+def resource(_context, factory, type, name,
permission=None,
allowed_interface=None, allowed_attributes=None,
- provides=zope.interface.Interface):
+ provides=Interface):
if ((allowed_attributes or allowed_interface)
and (not permission)):
- raise ConfigurationError(
+ raise ComponentConfigurationError(
"Must use name attribute with allowed_interface or "
"allowed_attributes"
)
if permission is not None:
- check_security_support()
checker = _checker(_context, permission,
allowed_interface, allowed_attributes)
def proxyResource(request, factory=factory, checker=checker):
return proxify(factory(request), checker)
+ proxyResource.factory = factory
factory = proxyResource
- if layer is not None:
- warnings.warn_explicit(
- "The 'layer' argument of the 'resource' directive has been "
- "deprecated. Use the 'type' argument instead.",
- DeprecationWarning, _context.info.file, _context.info.line)
- type = layer
-
_context.action(
discriminator = ('resource', name, type, provides),
callable = handler,
args = ('registerAdapter',
- factory, (type,), provides, name, _context.info),
- )
+ factory, (type,), provides, name, _context.info))
_context.action(
discriminator = None,
callable = provideInterface,
- args = (type.__module__ + '.' + type.__name__, type)
- )
+ args = ('', type))
_context.action(
discriminator = None,
callable = provideInterface,
- args = (provides.__module__ + '.' + provides.__name__, type)
- )
+ args = ('', provides))
diff --git a/src/zope/component/zcml.txt b/src/zope/component/zcml.txt
deleted file mode 100644
index 7a51e6d..0000000
--- a/src/zope/component/zcml.txt
+++ /dev/null
@@ -1,1021 +0,0 @@
-ZCML directives
-===============
-
-Components may be registered using the registration API exposed by
-``zope.component`` (provideAdapter, provideUtility, etc.). They may
-also be registered using configuration files. The common way to do
-that is by using ZCML (Zope Configuration Markup Language), an XML
-spelling of component registration.
-
-In ZCML, each XML element is a *directive*. There are different
-top-level directives that let us register components. We will
-introduce them one by one here.
-
-This helper will let us easily execute ZCML snippets:
-
- >>> from cStringIO import StringIO
- >>> from zope.configuration.xmlconfig import xmlconfig
- >>> def runSnippet(snippet):
- ... template = """\
- ... <configure xmlns='http://namespaces.zope.org/zope'
- ... i18n_domain="zope">
- ... %s
- ... </configure>"""
- ... xmlconfig(StringIO(template % snippet))
-
-adapter
--------
-
-Adapters play a key role in the Component Architecture. In ZCML, they
-are registered with the <adapter /> directive.
-
- >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
- >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
- >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
-
-Before we register the first test adapter, we can verify that adapter
-lookup doesn't work yet:
-
- >>> from zope.component.tests import clearZCML
- >>> clearZCML()
- >>> from zope.component.testfiles.components import IApp
- >>> IApp(Content(), None) is None
- True
-
-Then we register the adapter and see that the lookup works:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
-
- >>> IApp(Content()).__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-It is also possible to give adapters names. Then the combination of
-required interface, provided interface and name makes the adapter
-lookup unique. The name is supplied using the ``name`` argument to
-the <adapter /> directive:
-
- >>> from zope.component.tests import clearZCML
- >>> clearZCML()
- >>> import zope.component
- >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
- True
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... name="test"
- ... />''')
-
- >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-Adapter factories
-~~~~~~~~~~~~~~~~~
-
-It is possible to supply more than one adapter factory. In this case,
-during adapter lookup each factory will be called and the return value
-will be given to the next factory. The return value of the last
-factory is returned as the result of the adapter lookup. For examle:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2
- ... zope.component.testfiles.adapter.A3"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
-
-The resulting adapter is an A3, around an A2, around an A1, around the
-adapted object:
-
- >>> content = Content()
- >>> a3 = IApp(content)
- >>> a3.__class__ is A3
- True
-
- >>> a2 = a3.context[0]
- >>> a2.__class__ is A2
- True
-
- >>> a1 = a2.context[0]
- >>> a1.__class__ is A1
- True
-
- >>> a1.context[0] is content
- True
-
-Of course, if no factory is provided at all, we will get an error:
-
- >>> runSnippet('''
- ... <adapter
- ... factory=""
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
- ValueError: No factory specified
-
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The <adapter /> directive can figure out from the in-line Python
-declaration (using ``zope.component.adapts()`` or
-``zope.component.adapter()`` as well as ``zope.interface.implements``)
-what the adapter should be registered for and what it provides::
-
- >>> clearZCML()
- >>> IApp(Content(), None) is None
- True
-
- >>> runSnippet('''
- ... <adapter factory="zope.component.testfiles.components.Comp" />''')
-
- >>> IApp(Content()).__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-Of course, if the adapter has no ``implements()`` declaration, ZCML
-can't figure out what it provides:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A4"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
- TypeError: Missing 'provides' attribute
-
-On the other hand, if the factory implements more than one interface,
-ZCML can't figure out what it should provide either:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A5"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
- TypeError: Missing 'provides' attribute
-
-A not so common edge case is registering adapters directly for
-classes, not for interfaces. For example:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.Content"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... />''')
-
- >>> content = Content()
- >>> a1 = zope.component.getAdapter(content, I1, '')
- >>> isinstance(a1, A1)
- True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
- >>> import zope.interface
- >>> class MyContent:
- ... zope.interface.implements(IContent)
- >>> zope.component.getAdapter(MyContent(), I1, '') # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ...
- ComponentLookupError: ...
-
-Multi-adapters
-~~~~~~~~~~~~~~
-
-Conventional adapters adapt one object to provide another interface.
-Multi-adapters adapt several objects at once:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1
- ... zope.component.testfiles.adapter.I2"
- ... provides="zope.component.testfiles.adapter.I3"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> content = Content()
- >>> a1 = A1()
- >>> a2 = A2()
- >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-You can even adapt an empty list of objects (we call this a
-null-adapter):
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for=""
- ... provides="zope.component.testfiles.adapter.I3"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> a3 = zope.component.queryMultiAdapter((), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == ()
- True
-
-Even with multi-adapters, ZCML can figure out the ``for`` and
-``provides`` parameters from the Python declarations:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter factory="zope.component.testfiles.adapter.A3" />''')
-
- >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-Chained factories are not supported for multi-adapters, though:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1
- ... zope.component.testfiles.adapter.I2"
- ... provides="zope.component.testfiles.components.IApp"
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
- ValueError: Can't use multiple factories and multiple for
-
-And neither for null-adapters:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for=""
- ... provides="zope.component.testfiles.components.IApp"
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
- ValueError: Can't use multiple factories and multiple for
-
-Protected adapters
-~~~~~~~~~~~~~~~~~~
-
-Adapters can be protected with a permission. First we have to define
-a permission for which we'll have to register the <permission />
-directive:
-
- >>> clearZCML()
- >>> IApp(Content(), None) is None
- True
-
- >>> import zope.security
- >>> from zope.configuration.xmlconfig import XMLConfig
- >>> XMLConfig('meta.zcml', zope.security)()
- >>> runSnippet('''
- ... <permission
- ... id="y.x"
- ... title="XY"
- ... description="Allow XY."
- ... />
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... permission="y.x"
- ... />''')
-
-We see that the adapter is a location proxy now so that the
-appropriate permissions can be found from the context:
-
- >>> IApp(Content()).__class__
- <class 'zope.component.testfiles.components.Comp'>
- >>> type(IApp(Content()))
- <class 'zope.location.location.LocationProxy'>
-
-We can also go about it a different way. Let's make a public adapter
-and wrap the adapter in a security proxy. That often happens when
-an adapter is turned over to untrusted code:
-
- >>> clearZCML()
- >>> IApp(Content(), None) is None
- True
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... permission="zope.Public"
- ... />''')
-
- >>> from zope.security.checker import ProxyFactory
- >>> adapter = ProxyFactory(IApp(Content()))
- >>> from zope.security.proxy import getTestProxyItems
- >>> items = [item[0] for item in getTestProxyItems(adapter)]
- >>> items
- ['a', 'f']
-
- >>> from zope.security.proxy import removeSecurityProxy
- >>> removeSecurityProxy(adapter).__class__ is Comp
- True
-
-Of course, this still works when we let the ZCML directive handler
-figure out ``for`` and ``provides`` from the Python declarations:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... permission="zope.Public"
- ... />''')
-
- >>> adapter = ProxyFactory(IApp(Content()))
- >>> [item[0] for item in getTestProxyItems(adapter)]
- ['a', 'f']
- >>> removeSecurityProxy(adapter).__class__ is Comp
- True
-
-It also works with multi adapters:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A3"
- ... provides="zope.component.testfiles.adapter.I3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1
- ... zope.component.testfiles.adapter.I2"
- ... permission="zope.Public"
- ... />''')
-
- >>> content = Content()
- >>> a1 = A1()
- >>> a2 = A2()
- >>> a3 = ProxyFactory(zope.component.queryMultiAdapter((content, a1, a2), I3))
- >>> a3.__class__ == A3
- True
- >>> [item[0] for item in getTestProxyItems(a3)]
- ['f1', 'f2', 'f3']
-
-It's probably not worth mentioning, but when we try to protect an
-adapter with a permission that doesn't exist, we'll obviously get an
-error:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... permission="zope.UndefinedPermission"
- ... />''')
- Traceback (most recent call last):
- ...
- ConfigurationExecutionError: exceptions.ValueError: ('Undefined permission id', 'zope.UndefinedPermission')
- in:
- File "<string>", line 4.2-9.8
- Could not read source.
-
-Trusted adapters
-~~~~~~~~~~~~~~~~
-
-Trusted adapters are adapters that are trusted to do anything with the
-objects they are given so that these objects are not security-proxied.
-They are registered using the ``trusted`` argument to the <adapter />
-directive:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... trusted="yes"
- ... />''')
-
-With an unproxied object, it's business as usual:
-
- >>> ob = Content()
- >>> type(I1(ob)) is A1
- True
-
-With a security-proxied object, however, we get a security-proxied
-adapter:
-
- >>> p = ProxyFactory(ob)
- >>> a = I1(p)
- >>> type(a)
- <type 'zope.security._proxy._Proxy'>
-
-While the adapter is security-proxied, the object it adapts is now
-proxy-free. The adapter has umlimited access to it:
-
- >>> a = removeSecurityProxy(a)
- >>> type(a) is A1
- True
- >>> a.context[0] is ob
- True
-
-We can also protect the trusted adapter with a permission:
-
- >>> clearZCML()
- >>> XMLConfig('meta.zcml', zope.security)()
- >>> runSnippet('''
- ... <permission
- ... id="y.x"
- ... title="XY"
- ... description="Allow XY."
- ... />
- ... <adapter
- ... for="zope.component.testfiles.components.IContent"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... permission="y.x"
- ... trusted="yes"
- ... />''')
-
-Again, with an unproxied object, it's business as usual:
-
- >>> ob = Content()
- >>> type(I1(ob)) is A1
- True
-
-With a security-proxied object, we again get a security-proxied
-adapter:
-
- >>> p = ProxyFactory(ob)
- >>> a = I1(p)
- >>> type(a)
- <type 'zope.security._proxy._Proxy'>
-
-Since we protected the adapter with a permission, we now encounter a
-location proxy behind the security proxy:
-
- >>> a = removeSecurityProxy(a)
- >>> type(a)
- <class 'zope.location.location.LocationProxy'>
- >>> a.context[0] is ob
- True
-
-There's one exception to all of this: When you use the public
-permission (``zope.Public``), there will be no location proxy:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... permission="zope.Public"
- ... trusted="yes"
- ... />''')
-
- >>> ob = Content()
- >>> p = ProxyFactory(ob)
- >>> a = I1(p)
- >>> type(a)
- <type 'zope.security._proxy._Proxy'>
-
- >>> a = removeSecurityProxy(a)
- >>> type(a) is A1
- True
-
-We can also explicitply pass the ``locate`` argument to make sure we
-get location proxies:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... trusted="yes"
- ... locate="yes"
- ... />''')
-
- >>> ob = Content()
- >>> p = ProxyFactory(ob)
- >>> a = I1(p)
- >>> type(a)
- <type 'zope.security._proxy._Proxy'>
-
- >>> a = removeSecurityProxy(a)
- >>> type(a)
- <class 'zope.location.location.LocationProxy'>
-
-
-subscriber
-----------
-
-With the <subscriber /> directive you can register subscription
-adapters or event subscribers with the adapter registry. Consider
-this very typical example of a <subscriber /> directive:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />''')
-
- >>> content = Content()
- >>> a1 = A1()
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1)
- True
-
-Note how ZCML provides some additional information when registering
-components, such as the ZCML filename and line numbers:
-
- >>> sm = zope.component.getSiteManager()
- >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
- ... if reg.provided is IS][0]
- >>> print doc
- File "<string>", line 4.2-9.8
- Could not read source.
-
-The "fun" behind subscription adapters/subscribers is that when
-several ones are declared for the same for/provides, they are all
-found. With regular adapters, the most specific one (and in doubt the
-one registered last) wins. Consider these two subscribers:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A2"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />''')
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> len(subscribers)
- 2
- >>> sorted([a.__class__.__name__ for a in subscribers])
- ['A2', 'A3']
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like the <adapter /> directive, the <subscriber /> directive can
-figure out from the in-line Python declaration (using
-``zope.component.adapts()`` or ``zope.component.adapter()``) what the
-subscriber should be registered for:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> content = Content()
- >>> a2 = A2()
- >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
-
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-In the same way the directive can figure out what a subscriber
-provides:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber handler="zope.component.testfiles.adapter.A3" />''')
-
- >>> sm = zope.component.getSiteManager()
- >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
- >>> a3 is A3
- True
-
-A not so common edge case is declaring subscribers directly for
-classes, not for interfaces. For example:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... for="zope.component.testfiles.components.Content"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... />''')
-
- >>> subs = list(zope.component.subscribers((Content(),), I1))
- >>> isinstance(subs[0], A1)
- True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
- >>> list(zope.component.subscribers((MyContent(),), I1))
- []
-
-Protected subscribers
-~~~~~~~~~~~~~~~~~~~~~
-
-Subscribers can also be protected with a permission. First we have to
-define a permission for which we'll have to register the <permission />
-directive:
-
- >>> clearZCML()
- >>> XMLConfig('meta.zcml', zope.security)()
- >>> runSnippet('''
- ... <permission
- ... id="y.x"
- ... title="XY"
- ... description="Allow XY."
- ... />
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... permission="y.x"
- ... />''')
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> type(a3)
- <class 'zope.location.location.LocationProxy'>
- >>> a3.context == (content, a1)
- True
-
-Trusted subscribers
-~~~~~~~~~~~~~~~~~~~
-
-Like trusted adapters, trusted subscribers are subscribers that are
-trusted to do anything with the objects they are given so that these
-objects are not security-proxied. In analogy to the <adapter />
-directive, they are registered using the ``trusted`` argument to the
-<subscriber /> directive:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... trusted="yes"
- ... />''')
-
-With an unproxied object, it's business as usual:
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1)
- True
- >>> type(a3) is A3
- True
-
-Now with a proxied object. We will see that the subscriber has
-unproxied access to it, but the subscriber itself is proxied:
-
- >>> p = ProxyFactory(content)
- >>> a3 = zope.component.subscribers((p, a1), IS)[0]
- >>> type(a3)
- <type 'zope.security._proxy._Proxy'>
-
-There's no location proxy behind the security proxy:
-
- >>> removeSecurityProxy(a3).context[0] is content
- True
- >>> type(removeSecurityProxy(a3)) is A3
- True
-
-If you want the trusted subscriber to be located, you'll also have to
-use the ``locate`` argument:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... trusted="yes"
- ... locate="yes"
- ... />''')
-
-Again, it's business as usual with an unproxied object:
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1)
- True
- >>> type(a3) is A3
- True
-
-With a proxied object, we again get a security-proxied subscriber:
-
- >>> p = ProxyFactory(content)
- >>> a3 = zope.component.subscribers((p, a1), IS)[0]
-
- >>> type(a3)
- <type 'zope.security._proxy._Proxy'>
-
- >>> removeSecurityProxy(a3).context[0] is content
- True
-
-However, thanks to the ``locate`` argument, we now have a location
-proxy behind the security proxy:
-
- >>> type(removeSecurityProxy(a3))
- <class 'zope.location.location.LocationProxy'>
-
-Event subscriber (handlers)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes, subscribers don't need to be adapters that actually provide
-anything. It's enough that a callable is called for a certain event.
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... handler="zope.component.testfiles.adapter.Handler"
- ... />''')
-
-In this case, simply getting the subscribers is enough to invoke them:
-
- >>> list(zope.component.subscribers((content, a1), None))
- []
- >>> content.args == ((a1,),)
- True
-
-
-utility
--------
-
-Apart from adapters (and subscription adapters), the Component
-Architecture knows a second kind of component: utilities. They are
-registered using the <utility /> directive.
-
-Before we register the first test utility, we can verify that utility
-lookup doesn't work yet:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
-Then we register the utility:
-
- >>> runSnippet('''
- ... <utility
- ... component="zope.component.testfiles.components.comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... />''')
- >>> zope.component.getUtility(IApp) is comp
- True
-
-Like adapters, utilities can also have names. There can be more than
-one utility registered for a certain interface, as long as they each
-have a different name.
-
-First, we make sure that there's no utility yet:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp, 'test') is None
- True
-
-Then we register it:
-
- >>> runSnippet('''
- ... <utility
- ... component="zope.component.testfiles.components.comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... name="test"
- ... />''')
- >>> zope.component.getUtility(IApp, 'test') is comp
- True
-
-Utilities can also be registered from a factory. In this case, the
-ZCML handler calls the factory (without any arguments) and registers
-the returned value as a utility. Typically, you'd pass a class for
-the factory:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
- >>> runSnippet('''
- ... <utility
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... />''')
- >>> zope.component.getUtility(IApp).__class__ is Comp
- True
-
-Declaring ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like other directives, <utility /> can also figure out which interface
-a utility provides from the Python declaration:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.components.comp" />''')
- >>> zope.component.getUtility(IApp) is comp
- True
-
-It won't work if the component that is to be registered doesn't
-provide anything:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.adapter.a4" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
- TypeError: Missing 'provides' attribute
-
-Or if more than one interface is provided (then the ZCML directive
-handler doesn't know under which the utility should be registered):
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.adapter.a5" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
- TypeError: Missing 'provides' attribute
-
-We can repeat the same drill for utility factories:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.components.Comp" />''')
- >>> zope.component.getUtility(IApp).__class__ is Comp
- True
-
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.adapter.A4" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
- TypeError: Missing 'provides' attribute
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.adapter.A5" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
- TypeError: Missing 'provides' attribute
-
-Protected utilities
-~~~~~~~~~~~~~~~~~~~
-
-TODO::
-
- def testProtectedUtility(self):
- """Test that we can protect a utility.
-
- Also:
- Check that multiple configurations for the same utility and
- don't interfere.
- """
- self.assertEqual(zope.component.queryUtility(IV), None)
- xmlconfig(StringIO(template % (
- '''
- <permission id="tell.everyone" title="Yay" />
- <utility
- component="zope.component.testfiles.components.comp"
- provides="zope.component.testfiles.components.IApp"
- permission="tell.everyone"
- />
- <permission id="top.secret" title="shhhh" />
- <utility
- component="zope.component.testfiles.components.comp"
- provides="zope.component.testfiles.components.IAppb"
- permission="top.secret"
- />
- '''
- )))
-
- utility = ProxyFactory(zope.component.getUtility(IApp))
- items = getTestProxyItems(utility)
- self.assertEqual(items, [('a', 'tell.everyone'),
- ('f', 'tell.everyone')
- ])
- self.assertEqual(removeSecurityProxy(utility), comp)
-
- def testUtilityUndefinedPermission(self):
- config = StringIO(template % (
- '''
- <utility
- component="zope.component.testfiles.components.comp"
- provides="zope.component.testfiles.components.IApp"
- permission="zope.UndefinedPermission"
- />
- '''
- ))
- self.assertRaises(ValueError, xmlconfig, config,
- testing=1)
-
-interface
----------
-
-The <interface /> directive lets us register an interface. Interfaces
-are registered as named utilities. We therefore needn't go though all
-the lookup details again, it is sufficient to see whether the
-directive handler emits the right actions.
-
-First we provide a stub configuration context:
-
- >>> import re, pprint
- >>> atre = re.compile(' at [0-9a-fA-Fx]+')
- >>> class Context(object):
- ... actions = ()
- ... def action(self, discriminator, callable, args):
- ... self.actions += ((discriminator, callable, args), )
- ... def __repr__(self):
- ... stream = StringIO()
- ... pprinter = pprint.PrettyPrinter(stream=stream, width=60)
- ... pprinter.pprint(self.actions)
- ... r = stream.getvalue()
- ... return (''.join(atre.split(r))).strip()
- >>> context = Context()
-
-Then we provide a test interface that we'd like to register:
-
- >>> from zope.interface import Interface
- >>> class I(Interface):
- ... pass
-
-It doesn't yet provide ``ITestType``:
-
- >>> from zope.component.tests import ITestType
- >>> ITestType.providedBy(I)
- False
-
-However, after calling the directive handler...
-
- >>> from zope.component.zcml import interface
- >>> interface(context, I, ITestType)
- >>> context
- ((None,
- <function provideInterface>,
- ('',
- <InterfaceClass __builtin__.I>,
- <InterfaceClass zope.component.tests.ITestType>)),)
-
-...it does provide ``ITestType``:
-
- >>> from zope.interface.interfaces import IInterface
- >>> ITestType.extends(IInterface)
- True
- >>> IInterface.providedBy(I)
- True
diff --git a/src/zope/component/zcml_conditional.txt b/src/zope/component/zcml_conditional.txt
deleted file mode 100644
index 243f14b..0000000
--- a/src/zope/component/zcml_conditional.txt
+++ /dev/null
@@ -1,612 +0,0 @@
-ZCML directives without zope.security support
-=============================================
-
-This tests run without zope.security available:
-
- >>> from zope.component.zcml import check_security_support
- >>> check_security_support()
- Traceback (most recent call last):
- ...
- ConfigurationError: security proxied components are not supported because zope.security is not available
-
-Components may be registered using the registration API exposed by
-``zope.component`` (provideAdapter, provideUtility, etc.). They may
-also be registered using configuration files. The common way to do
-that is by using ZCML (Zope Configuration Markup Language), an XML
-spelling of component registration.
-
-In ZCML, each XML element is a *directive*. There are different
-top-level directives that let us register components. We will
-introduce them one by one here.
-
-This helper will let us easily execute ZCML snippets:
-
- >>> from cStringIO import StringIO
- >>> from zope.configuration.xmlconfig import xmlconfig
- >>> def runSnippet(snippet):
- ... template = """\
- ... <configure xmlns='http://namespaces.zope.org/zope'
- ... i18n_domain="zope">
- ... %s
- ... </configure>"""
- ... xmlconfig(StringIO(template % snippet))
-
-adapter
--------
-
-Adapters play a key role in the Component Architecture. In ZCML, they
-are registered with the <adapter /> directive.
-
- >>> from zope.component.testfiles.adapter import A1, A2, A3, Handler
- >>> from zope.component.testfiles.adapter import I1, I2, I3, IS
- >>> from zope.component.testfiles.components import IContent, Content, Comp, comp
-
-Before we register the first test adapter, we can verify that adapter
-lookup doesn't work yet:
-
- >>> from zope.component.tests import clearZCML
- >>> clearZCML()
- >>> from zope.component.testfiles.components import IApp
- >>> IApp(Content(), None) is None
- True
-
-Then we register the adapter and see that the lookup works:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
-
- >>> IApp(Content()).__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-It is also possible to give adapters names. Then the combination of
-required interface, provided interface and name makes the adapter
-lookup unique. The name is supplied using the ``name`` argument to
-the <adapter /> directive:
-
- >>> from zope.component.tests import clearZCML
- >>> clearZCML()
- >>> import zope.component
- >>> zope.component.queryAdapter(Content(), IApp, 'test') is None
- True
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... name="test"
- ... />''')
-
- >>> zope.component.getAdapter(Content(), IApp, 'test').__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-Adapter factories
-~~~~~~~~~~~~~~~~~
-
-It is possible to supply more than one adapter factory. In this case,
-during adapter lookup each factory will be called and the return value
-will be given to the next factory. The return value of the last
-factory is returned as the result of the adapter lookup. For examle:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2
- ... zope.component.testfiles.adapter.A3"
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
-
-The resulting adapter is an A3, around an A2, around an A1, around the
-adapted object:
-
- >>> content = Content()
- >>> a3 = IApp(content)
- >>> a3.__class__ is A3
- True
-
- >>> a2 = a3.context[0]
- >>> a2.__class__ is A2
- True
-
- >>> a1 = a2.context[0]
- >>> a1.__class__ is A1
- True
-
- >>> a1.context[0] is content
- True
-
-Of course, if no factory is provided at all, we will get an error:
-
- >>> runSnippet('''
- ... <adapter
- ... factory=""
- ... provides="zope.component.testfiles.components.IApp"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-8.8
- ValueError: No factory specified
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The <adapter /> directive can figure out from the in-line Python
-declaration (using ``zope.component.adapts()`` or
-``zope.component.adapter()`` as well as ``zope.interface.implements``)
-what the adapter should be registered for and what it provides::
-
- >>> clearZCML()
- >>> IApp(Content(), None) is None
- True
-
- >>> runSnippet('''
- ... <adapter factory="zope.component.testfiles.components.Comp" />''')
-
- >>> IApp(Content()).__class__
- <class 'zope.component.testfiles.components.Comp'>
-
-Of course, if the adapter has no ``implements()`` declaration, ZCML
-can't figure out what it provides:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A4"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
- TypeError: Missing 'provides' attribute
-
-On the other hand, if the factory implements more than one interface,
-ZCML can't figure out what it should provide either:
-
- >>> runSnippet('''
- ... <adapter
- ... factory="zope.component.testfiles.adapter.A5"
- ... for="zope.component.testfiles.components.IContent"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
- TypeError: Missing 'provides' attribute
-
-A not so common edge case is registering adapters directly for
-classes, not for interfaces. For example:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.Content"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... />''')
-
- >>> content = Content()
- >>> a1 = zope.component.getAdapter(content, I1, '')
- >>> isinstance(a1, A1)
- True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
- >>> import zope.interface
- >>> class MyContent:
- ... zope.interface.implements(IContent)
- >>> zope.component.getAdapter(MyContent(), I1, '') # doctest: +ELLIPSIS
- Traceback (most recent call last):
- ...
- ComponentLookupError: ...
-
-Multi-adapters
-~~~~~~~~~~~~~~
-
-Conventional adapters adapt one object to provide another interface.
-Multi-adapters adapt several objects at once:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1
- ... zope.component.testfiles.adapter.I2"
- ... provides="zope.component.testfiles.adapter.I3"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> content = Content()
- >>> a1 = A1()
- >>> a2 = A2()
- >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-You can even adapt an empty list of objects (we call this a
-null-adapter):
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for=""
- ... provides="zope.component.testfiles.adapter.I3"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> a3 = zope.component.queryMultiAdapter((), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == ()
- True
-
-Even with multi-adapters, ZCML can figure out the ``for`` and
-``provides`` parameters from the Python declarations:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter factory="zope.component.testfiles.adapter.A3" />''')
-
- >>> a3 = zope.component.queryMultiAdapter((content, a1, a2), I3)
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-Chained factories are not supported for multi-adapters, though:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1
- ... zope.component.testfiles.adapter.I2"
- ... provides="zope.component.testfiles.components.IApp"
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-11.8
- ValueError: Can't use multiple factories and multiple for
-
-And neither for null-adapters:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <adapter
- ... for=""
- ... provides="zope.component.testfiles.components.IApp"
- ... factory="zope.component.testfiles.adapter.A1
- ... zope.component.testfiles.adapter.A2"
- ... />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-9.8
- ValueError: Can't use multiple factories and multiple for
-
-subscriber
-----------
-
-With the <subscriber /> directive you can register subscription
-adapters or event subscribers with the adapter registry. Consider
-this very typical example of a <subscriber /> directive:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />''')
-
- >>> content = Content()
- >>> a1 = A1()
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1)
- True
-
-Note how ZCML provides some additional information when registering
-components, such as the ZCML filename and line numbers:
-
- >>> sm = zope.component.getSiteManager()
- >>> doc = [reg.info for reg in sm.registeredSubscriptionAdapters()
- ... if reg.provided is IS][0]
- >>> print doc
- File "<string>", line 4.2-9.8
- Could not read source.
-
-The "fun" behind subscription adapters/subscribers is that when
-several ones are declared for the same for/provides, they are all
-found. With regular adapters, the most specific one (and in doubt the
-one registered last) wins. Consider these two subscribers:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A2"
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... />''')
-
- >>> subscribers = zope.component.subscribers((content, a1), IS)
- >>> len(subscribers)
- 2
- >>> sorted([a.__class__.__name__ for a in subscribers])
- ['A2', 'A3']
-
-Declaring ``for`` and ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like the <adapter /> directive, the <subscriber /> directive can
-figure out from the in-line Python declaration (using
-``zope.component.adapts()`` or ``zope.component.adapter()``) what the
-subscriber should be registered for:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... provides="zope.component.testfiles.adapter.IS"
- ... factory="zope.component.testfiles.adapter.A3"
- ... />''')
-
- >>> content = Content()
- >>> a2 = A2()
- >>> subscribers = zope.component.subscribers((content, a1, a2), IS)
-
- >>> a3 = subscribers[0]
- >>> a3.__class__ is A3
- True
- >>> a3.context == (content, a1, a2)
- True
-
-In the same way the directive can figure out what a subscriber
-provides:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber handler="zope.component.testfiles.adapter.A3" />''')
-
- >>> sm = zope.component.getSiteManager()
- >>> a3 = sm.adapters.subscriptions((IContent, I1, I2), None)[0]
- >>> a3 is A3
- True
-
-A not so common edge case is declaring subscribers directly for
-classes, not for interfaces. For example:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... for="zope.component.testfiles.components.Content"
- ... provides="zope.component.testfiles.adapter.I1"
- ... factory="zope.component.testfiles.adapter.A1"
- ... />''')
-
- >>> subs = list(zope.component.subscribers((Content(),), I1))
- >>> isinstance(subs[0], A1)
- True
-
-This time, any object providing ``IContent`` won't work if it's not an
-instance of the ``Content`` class:
-
- >>> list(zope.component.subscribers((MyContent(),), I1))
- []
-
-Event subscriber (handlers)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes, subscribers don't need to be adapters that actually provide
-anything. It's enough that a callable is called for a certain event.
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <subscriber
- ... for="zope.component.testfiles.components.IContent
- ... zope.component.testfiles.adapter.I1"
- ... handler="zope.component.testfiles.adapter.Handler"
- ... />''')
-
-In this case, simply getting the subscribers is enough to invoke them:
-
- >>> list(zope.component.subscribers((content, a1), None))
- []
- >>> content.args == ((a1,),)
- True
-
-
-utility
--------
-
-Apart from adapters (and subscription adapters), the Component
-Architecture knows a second kind of component: utilities. They are
-registered using the <utility /> directive.
-
-Before we register the first test utility, we can verify that utility
-lookup doesn't work yet:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
-Then we register the utility:
-
- >>> runSnippet('''
- ... <utility
- ... component="zope.component.testfiles.components.comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... />''')
- >>> zope.component.getUtility(IApp) is comp
- True
-
-Like adapters, utilities can also have names. There can be more than
-one utility registered for a certain interface, as long as they each
-have a different name.
-
-First, we make sure that there's no utility yet:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp, 'test') is None
- True
-
-Then we register it:
-
- >>> runSnippet('''
- ... <utility
- ... component="zope.component.testfiles.components.comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... name="test"
- ... />''')
- >>> zope.component.getUtility(IApp, 'test') is comp
- True
-
-Utilities can also be registered from a factory. In this case, the
-ZCML handler calls the factory (without any arguments) and registers
-the returned value as a utility. Typically, you'd pass a class for
-the factory:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
- >>> runSnippet('''
- ... <utility
- ... factory="zope.component.testfiles.components.Comp"
- ... provides="zope.component.testfiles.components.IApp"
- ... />''')
- >>> zope.component.getUtility(IApp).__class__ is Comp
- True
-
-Declaring ``provides`` in Python
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Like other directives, <utility /> can also figure out which interface
-a utility provides from the Python declaration:
-
- >>> clearZCML()
- >>> zope.component.queryUtility(IApp) is None
- True
-
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.components.comp" />''')
- >>> zope.component.getUtility(IApp) is comp
- True
-
-It won't work if the component that is to be registered doesn't
-provide anything:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.adapter.a4" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
- TypeError: Missing 'provides' attribute
-
-Or if more than one interface is provided (then the ZCML directive
-handler doesn't know under which the utility should be registered):
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility component="zope.component.testfiles.adapter.a5" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.61
- TypeError: Missing 'provides' attribute
-
-We can repeat the same drill for utility factories:
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.components.Comp" />''')
- >>> zope.component.getUtility(IApp).__class__ is Comp
- True
-
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.adapter.A4" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
- TypeError: Missing 'provides' attribute
-
- >>> clearZCML()
- >>> runSnippet('''
- ... <utility factory="zope.component.testfiles.adapter.A5" />''')
- Traceback (most recent call last):
- ...
- ZopeXMLConfigurationError: File "<string>", line 4.2-4.59
- TypeError: Missing 'provides' attribute
-
-interface
----------
-
-The <interface /> directive lets us register an interface. Interfaces
-are registered as named utilities. We therefore needn't go though all
-the lookup details again, it is sufficient to see whether the
-directive handler emits the right actions.
-
-First we provide a stub configuration context:
-
- >>> import re, pprint
- >>> atre = re.compile(' at [0-9a-fA-Fx]+')
- >>> class Context(object):
- ... actions = ()
- ... def action(self, discriminator, callable, args):
- ... self.actions += ((discriminator, callable, args), )
- ... def __repr__(self):
- ... stream = StringIO()
- ... pprinter = pprint.PrettyPrinter(stream=stream, width=60)
- ... pprinter.pprint(self.actions)
- ... r = stream.getvalue()
- ... return (''.join(atre.split(r))).strip()
- >>> context = Context()
-
-Then we provide a test interface that we'd like to register:
-
- >>> from zope.interface import Interface
- >>> class I(Interface):
- ... pass
-
-It doesn't yet provide ``ITestType``:
-
- >>> from zope.component.tests import ITestType
- >>> ITestType.providedBy(I)
- False
-
-However, after calling the directive handler...
-
- >>> from zope.component.zcml import interface
- >>> interface(context, I, ITestType)
- >>> context
- ((None,
- <function provideInterface>,
- ('',
- <InterfaceClass __builtin__.I>,
- <InterfaceClass zope.component.tests.ITestType>)),)
-
-...it does provide ``ITestType``:
-
- >>> from zope.interface.interfaces import IInterface
- >>> ITestType.extends(IInterface)
- True
- >>> IInterface.providedBy(I)
- True