summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-06-26 09:24:29 -0500
committerJason Madden <jamadden@gmail.com>2020-06-26 09:24:29 -0500
commitb2962c1613fb409661d853f9d0e41212fdc0a812 (patch)
tree485ef0a991daf6d903f56e101fa9c818438bf781
parent7f69616898ea1c68d424e6d1fadaa5737c102a74 (diff)
downloadzope-component-doc-module.tar.gz
Reference documentation improvementsdoc-module
- Make it possible to use :mod:`zope.component` - Provide a concise list of all the available APIs in that module and link them to their in-depth descriptions. - Fix several xref errors - Add documentation for setHooks/resetHooks. This also makes it possible to get useful help at the REPL or command line: $ python -c 'import zope.component; help(zope.component.getAdapters)' Help on function getAdapters in module zope.component._api: getAdapters(objects, provided, context=None) Look for all matching adapters to a provided interface for objects Return a list of adapters that match. If an adapter is named, only the most specific adapter of a given name is returned. .. seealso:: Function `~zope.component.getAdapters` for notes, and `~zope.component.interfaces.IComponentArchitecture` for the defining interface.
-rw-r--r--docs/api.rst7
-rw-r--r--docs/api/adapter.rst49
-rw-r--r--docs/api/hooks.rst8
-rw-r--r--docs/api/module.rst12
-rw-r--r--docs/api/utility.rst13
-rw-r--r--docs/hooks.rst33
-rw-r--r--docs/testlayer.rst2
-rw-r--r--src/zope/component/__init__.py18
-rw-r--r--src/zope/component/_api.py25
-rw-r--r--src/zope/component/_declaration.py9
-rw-r--r--src/zope/component/globalregistry.py9
-rw-r--r--src/zope/component/hooks.py29
-rw-r--r--src/zope/component/interfaces.py27
13 files changed, 205 insertions, 36 deletions
diff --git a/docs/api.rst b/docs/api.rst
index 286255f..9b7fee0 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -1,10 +1,12 @@
-:mod:`zope.component` API Reference
-===================================
+=====================================
+ ``zope.component`` API Reference
+=====================================
.. toctree::
:maxdepth: 2
+ api/module
api/interfaces
api/sitemanager
api/utility
@@ -13,3 +15,4 @@
api/interface
api/security
api/persistent
+ api/hooks
diff --git a/docs/api/adapter.rst b/docs/api/adapter.rst
index 8b3d563..c3245dd 100644
--- a/docs/api/adapter.rst
+++ b/docs/api/adapter.rst
@@ -1,15 +1,24 @@
-Adapter Registration APIs
-=========================
+===========================
+ Adapter Registration APIs
+===========================
+
+This document covers a specific subset of the APIs in :mod:`zope.component`.
+
+.. currentmodule:: zope.component
.. testsetup::
from zope.component.testing import setUp
setUp()
-.. autofunction:: zope.component.provideUtility
+.. autofunction:: zope.component.provideAdapter
+
+.. autofunction:: zope.component.provideHandler
+
+.. autofunction:: zope.component.provideSubscriptionAdapter
Conforming Adapter Lookup
--------------------------
+=========================
.. autofunction:: zope.component.getAdapterInContext
@@ -21,7 +30,7 @@ context object to see if it already conforms to the requested interface.
If so, the object is returned immediately. Otherwise, the adapter factory
is looked up in the site manager, and called.
-Let's start by creating a component that supports the `__conform__()` method:
+Let's start by creating a component that supports the ``__conform__()`` method:
.. doctest::
@@ -39,14 +48,14 @@ 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`.
+with which we can register adapters for ``I1``.
.. doctest::
>>> from zope.component.globalregistry import BaseGlobalComponents
>>> sitemanager = BaseGlobalComponents()
-Now we create a new `context` that knows how to get to our custom site
+Now we create a new ``context`` that knows how to get to our custom site
manager.
.. doctest::
@@ -111,7 +120,7 @@ registered adapter:
43
Named Adapter Lookup
---------------------
+====================
.. autofunction:: zope.component.getAdapter
@@ -141,7 +150,7 @@ returns the default:
>>> queryAdapter(ob, I2, '', '<default>')
'<default>'
-The 'requires' argument to `registerAdapter` must be a sequence, rather than
+The 'requires' argument to ``registerAdapter`` must be a sequence, rather than
a single interface:
.. doctest::
@@ -154,7 +163,7 @@ a single interface:
...
TypeError: the required argument should be a list of interfaces, not a single interface
-After register an adapter from `I1` to `I2` with the global site manager:
+After register an adapter from ``I1`` to ``I2`` with the global site manager:
.. doctest::
@@ -208,10 +217,10 @@ After registering under that name:
True
Invoking an Interface to Perform Adapter Lookup
------------------------------------------------
+===============================================
:mod:`zope.component` registers an adapter hook with
-:mod:`zope.interface.interface`, allowing a convenient spelling for
+`zope.interface.interface.adapter_hooks`, allowing a convenient spelling for
adapter lookup: just "call" the interface, passing the context:
.. doctest::
@@ -241,10 +250,10 @@ unless we pass a default:
True
Registering Adapters For Arbitrary Objects
-------------------------------------------
+==========================================
Providing an adapter for None says that your adapter can adapt anything
-to `I2`.
+to ``I2``.
.. doctest::
@@ -267,7 +276,7 @@ It can really adapt any arbitrary object:
True
Looking Up Adapters Using Multiple Objects
-------------------------------------------
+==========================================
.. autofunction:: zope.component.getMultiAdapter
@@ -284,7 +293,7 @@ adapted:
As with regular adapters, if an adapter isn't registered for the given
objects and interface, the :func:`~zope.component.getMultiAdapter` API
-raises `ComponentLookupError`:
+raises `zope.interface.interfaces.ComponentLookupError`:
.. doctest::
@@ -342,7 +351,7 @@ Now we can get the adapter:
Finding More Than One Adapter
------------------------------
+=============================
.. autofunction:: zope.component.getAdapters
@@ -388,17 +397,17 @@ factory returns None, it is as if it wasn't present.
Subscription Adapters
----------------------
+=====================
.. autofunction:: zope.component.subscribers
Event handlers
---------------
+==============
.. autofunction:: zope.component.handle
Helpers for Declaring / Testing Adapters
-----------------------------------------
+========================================
.. autofunction:: zope.component.adapter
diff --git a/docs/api/hooks.rst b/docs/api/hooks.rst
new file mode 100644
index 0000000..7c4d888
--- /dev/null
+++ b/docs/api/hooks.rst
@@ -0,0 +1,8 @@
+==========================================================
+ ``zope.component.hooks``: The current component registry
+==========================================================
+
+.. seealso:: :doc:`../hooks` for narrative documentation and examples.
+
+.. automodule:: zope.component.hooks
+ :noindex:
diff --git a/docs/api/module.rst b/docs/api/module.rst
new file mode 100644
index 0000000..1828f4e
--- /dev/null
+++ b/docs/api/module.rst
@@ -0,0 +1,12 @@
+============================================
+ ``zope.component``: Module-level functions
+============================================
+
+This document provides a summary of the APIs available directly from
+``zope.component``. For more details, see the remaining documentation.
+
+.. These are generally explored in more detail in
+ specific documentation, so default indexing should go
+ to that instead of here.
+.. automodule:: zope.component
+ :noindex:
diff --git a/docs/api/utility.rst b/docs/api/utility.rst
index a6000b8..cbc4e17 100644
--- a/docs/api/utility.rst
+++ b/docs/api/utility.rst
@@ -1,5 +1,8 @@
-Utility Registration APIs
-=========================
+===========================
+ Utility Registration APIs
+===========================
+
+.. autofunction:: zope.component.provideUtility
.. autofunction:: zope.component.getUtility
@@ -56,7 +59,7 @@ Now the component is available:
Named Utilities
----------------
+===============
Registering a utility without a name does not mean that it is available
when looking for the utility with a name:
@@ -84,7 +87,7 @@ Registering the utility under the correct name makes it available:
True
Querying Multiple Utilities
----------------------------
+===========================
.. autofunction:: zope.component.getUtilitiesFor
@@ -159,7 +162,7 @@ the utilities.
Delegated Utility Lookup
-------------------------
+========================
.. autofunction:: zope.component.getNextUtility
diff --git a/docs/hooks.rst b/docs/hooks.rst
index a2a77c7..382e69b 100644
--- a/docs/hooks.rst
+++ b/docs/hooks.rst
@@ -74,6 +74,39 @@ If we set another site, that one will be considered current:
>>> getSiteManager() is site2.registry
True
+However, the default `zope.component.getSiteManager` function isn't
+yet aware of this:
+
+.. doctest::
+
+ >>> from zope.component import getSiteManager as global_getSiteManager
+ >>> global_getSiteManager()
+ <BaseGlobalComponents base>
+
+To integrate that with the notion of the current site, we need to call ``setHooks``:
+
+.. autofunction:: setHooks
+
+.. doctest::
+
+ >>> from zope.component.hooks import setHooks
+ >>> setHooks()
+ >>> getSiteManager() is site2.registry
+ True
+ >>> global_getSiteManager() is site2.registry
+ True
+
+This can be reversed using ``resetHooks``:
+
+.. autofunction:: resetHooks
+
+.. doctest::
+
+ >>> from zope.component.hooks import resetHooks
+ >>> resetHooks()
+ >>> global_getSiteManager()
+ <BaseGlobalComponents base>
+
Finally we can unset the site and the global component registry is used again:
.. doctest::
diff --git a/docs/testlayer.rst b/docs/testlayer.rst
index 598cac3..ccf8ebe 100644
--- a/docs/testlayer.rst
+++ b/docs/testlayer.rst
@@ -4,6 +4,8 @@
.. currentmodule:: zope.component.testlayer
+.. module:: zope.component.testlayer
+
``zope.component.testlayer`` defines two things:
* a `LayerBase` that makes it easier and saner to use zope.testing's
diff --git a/src/zope/component/__init__.py b/src/zope/component/__init__.py
index 77e12cc..6aee904 100644
--- a/src/zope/component/__init__.py
+++ b/src/zope/component/__init__.py
@@ -11,7 +11,16 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Zope 3 Component Architecture
+"""
+Zope 3 Component Architecture
+
+This module provides an implementation of
+:class:`~zope.component.interfaces.IComponentArchitecture`, using the
+current :mod:`site <zope.component.hooks>`.
+
+This module also provides an implementation of
+:class:`~zope.component.interfaces.IComponentRegistrationConvenience`
+using the `global site manager <getGlobalSiteManager>`_.
"""
from zope.interface import Interface
from zope.interface import implementedBy
@@ -58,4 +67,9 @@ from zope.component._declaration import adapter
from zope.component._declaration import adapts
moduleProvides(IComponentArchitecture, IComponentRegistrationConvenience)
-__all__ = tuple(IComponentArchitecture)
+__all__ = tuple(IComponentArchitecture) + tuple(IComponentRegistrationConvenience) + (
+ 'named',
+ 'adapts',
+ 'adapter',
+ 'adaptedBy',
+)
diff --git a/src/zope/component/_api.py b/src/zope/component/_api.py
index a7d423a..7e39ffc 100644
--- a/src/zope/component/_api.py
+++ b/src/zope/component/_api.py
@@ -21,12 +21,15 @@ from zope.interface.interfaces import ComponentLookupError
from zope.interface.interfaces import IComponentLookup
from zope.component.interfaces import IFactory
+from zope.component.interfaces import inherits_arch_docs as inherits_docs
+
# getSiteManager() returns a component registry. Although the term
# "site manager" is deprecated in favor of "component registry",
# the old term is kept around to maintain a stable API.
base = None
@hookable
+@inherits_docs
def getSiteManager(context=None):
""" See IComponentArchitecture.
"""
@@ -44,13 +47,14 @@ def getSiteManager(context=None):
raise ComponentLookupError(*error.args)
# Adapter API
-
+@inherits_docs
def getAdapterInContext(object, interface, context):
adapter = queryAdapterInContext(object, interface, context)
if adapter is None:
raise ComponentLookupError(object, interface)
return adapter
+@inherits_docs
def queryAdapterInContext(object, interface, context, default=None):
conform = getattr(object, '__conform__', None)
if conform is not None:
@@ -78,12 +82,14 @@ def queryAdapterInContext(object, interface, context, default=None):
return getSiteManager(context).queryAdapter(object, interface, '', default)
+@inherits_docs
def getAdapter(object, interface=Interface, name=u'', context=None):
adapter = queryAdapter(object, interface, name, None, context)
if adapter is None:
raise ComponentLookupError(object, interface, name)
return adapter
+@inherits_docs
def queryAdapter(object, interface=Interface, name=u'', default=None,
context=None):
if context is None:
@@ -91,12 +97,14 @@ def queryAdapter(object, interface=Interface, name=u'', default=None,
return getSiteManager(context).queryAdapter(object, interface, name,
default)
+@inherits_docs
def getMultiAdapter(objects, interface=Interface, name=u'', context=None):
adapter = queryMultiAdapter(objects, interface, name, context=context)
if adapter is None:
raise ComponentLookupError(objects, interface, name)
return adapter
+@inherits_docs
def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
context=None):
try:
@@ -107,6 +115,7 @@ def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
return sitemanager.queryMultiAdapter(objects, interface, name, default)
+@inherits_docs
def getAdapters(objects, provided, context=None):
try:
sitemanager = getSiteManager(context)
@@ -115,6 +124,7 @@ def getAdapters(objects, provided, context=None):
return []
return sitemanager.getAdapters(objects, provided)
+@inherits_docs
def subscribers(objects, interface, context=None):
try:
sitemanager = getSiteManager(context)
@@ -123,6 +133,7 @@ def subscribers(objects, interface, context=None):
return []
return sitemanager.subscribers(objects, interface)
+@inherits_docs
def handle(*objects):
getSiteManager(None).subscribers(objects, None)
@@ -146,26 +157,29 @@ zope.interface.interface.adapter_hooks.append(adapter_hook)
# Utility API
-
+@inherits_docs
def getUtility(interface, name='', context=None):
utility = queryUtility(interface, name, context=context)
if utility is not None:
return utility
raise ComponentLookupError(interface, name)
+@inherits_docs
def queryUtility(interface, name='', default=None, context=None):
return getSiteManager(context).queryUtility(interface, name, default)
+@inherits_docs
def getUtilitiesFor(interface, context=None):
return getSiteManager(context).getUtilitiesFor(interface)
-
+@inherits_docs
def getAllUtilitiesRegisteredFor(interface, context=None):
return getSiteManager(context).getAllUtilitiesRegisteredFor(interface)
_marker = object()
+@inherits_docs
def queryNextUtility(context, interface, name='', default=None):
"""Query for the next available utility.
@@ -184,7 +198,7 @@ def queryNextUtility(context, interface, name='', default=None):
return util
return default
-
+@inherits_docs
def getNextUtility(context, interface, name=''):
"""Get the next available utility.
@@ -200,6 +214,7 @@ def getNextUtility(context, interface, name=''):
# Factories
+@inherits_docs
def createObject(__factory_name, *args, **kwargs):
"""Invoke the named factory and return the result.
@@ -208,6 +223,7 @@ def createObject(__factory_name, *args, **kwargs):
context = kwargs.pop('context', None)
return getUtility(IFactory, __factory_name, context)(*args, **kwargs)
+@inherits_docs
def getFactoryInterfaces(name, context=None):
"""Return the interface provided by the named factory's objects
@@ -215,6 +231,7 @@ def getFactoryInterfaces(name, context=None):
"""
return getUtility(IFactory, name, context).getInterfaces()
+@inherits_docs
def getFactoriesFor(interface, context=None):
"""Return info on all factories implementing the given interface.
"""
diff --git a/src/zope/component/_declaration.py b/src/zope/component/_declaration.py
index db3d1c3..5e75d85 100644
--- a/src/zope/component/_declaration.py
+++ b/src/zope/component/_declaration.py
@@ -18,7 +18,13 @@ import sys
from zope.component._compat import CLASS_TYPES
class adapter(object):
+ """
+ Decorator that declares that the decorated object adapts the given
+ *interfaces*.
+ This is commonly used in conjunction with :obj:`zope.interface.implementer`
+ to declare what adapting the *interfaces* will provide.
+ """
def __init__(self, *interfaces):
self.interfaces = interfaces
@@ -44,6 +50,9 @@ def adapts(*interfaces):
locals['__component_adapts__'] = _adapts_descr(interfaces)
def adaptedBy(ob):
+ """
+ Return the *interfaces* that *ob* will adapt, as declared by :obj:`adapter`.
+ """
return getattr(ob, '__component_adapts__', None)
def getName(ob):
diff --git a/src/zope/component/globalregistry.py b/src/zope/component/globalregistry.py
index 80b0d72..d48d39b 100644
--- a/src/zope/component/globalregistry.py
+++ b/src/zope/component/globalregistry.py
@@ -13,11 +13,11 @@
##############################################################################
"""Global components support
"""
-from zope.interface import implementer
from zope.interface.adapter import AdapterRegistry
from zope.interface.registry import Components
-from zope.interface.interfaces import IComponentLookup
+from zope.component.interfaces import inherits_arch_docs
+from zope.component.interfaces import inherits_reg_docs
def GAR(components, registryName):
@@ -59,6 +59,7 @@ else:
del addCleanUp
globalSiteManager = base
+@inherits_arch_docs
def getGlobalSiteManager():
return globalSiteManager
@@ -66,14 +67,18 @@ def getGlobalSiteManager():
# We eventually want to deprecate these in favor of using the global
# component registry directly.
+@inherits_reg_docs
def provideUtility(component, provides=None, name=u''):
base.registerUtility(component, provides, name, event=False)
+@inherits_reg_docs
def provideAdapter(factory, adapts=None, provides=None, name=u''):
base.registerAdapter(factory, adapts, provides, name, event=False)
+@inherits_reg_docs
def provideSubscriptionAdapter(factory, adapts=None, provides=None):
base.registerSubscriptionAdapter(factory, adapts, provides, event=False)
+@inherits_reg_docs
def provideHandler(factory, adapts=None):
base.registerHandler(factory, adapts, event=False)
diff --git a/src/zope/component/hooks.py b/src/zope/component/hooks.py
index 3c44d2d..b1ce3f8 100644
--- a/src/zope/component/hooks.py
+++ b/src/zope/component/hooks.py
@@ -30,6 +30,14 @@ from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import ComponentLookupError
from zope.interface.interfaces import IComponentLookup
+__all__ = [
+ 'setSite',
+ 'getSite',
+ 'site',
+ 'getSiteManager',
+ 'setHooks',
+ 'resetHooks',
+]
class read_property(object):
"""Descriptor for property-like computed attributes.
@@ -130,11 +138,32 @@ def adapter_hook(interface, object, name='', default=None):
def setHooks():
+ """
+ Make `zope.component.getSiteManager` and interface adaptation
+ respect the current site.
+
+ Most applications will want to be sure te call this early in their
+ startup sequence. Test code that uses these APIs should also arrange to
+ call this.
+
+ .. seealso:: :mod:`zope.component.testlayer`
+ """
from zope.component import _api
_api.adapter_hook.sethook(adapter_hook)
_api.getSiteManager.sethook(getSiteManager)
def resetHooks():
+ """
+ Reset `zope.component.getSiteManager` and interface adaptation to
+ their original implementations that are unaware of the current
+ site.
+
+ Use caution when calling this; most code will not need to call
+ this. If code using the global API executes following this, it
+ will most likely use the base global component registry instead of
+ a site-specific registry it was expected. This can lead to
+ failures in adaptation and utility lookup.
+ """
# Reset hookable functions to original implementation.
from zope.component import _api
_api.adapter_hook.reset()
diff --git a/src/zope/component/interfaces.py b/src/zope/component/interfaces.py
index f602476..15fbb55 100644
--- a/src/zope/component/interfaces.py
+++ b/src/zope/component/interfaces.py
@@ -11,7 +11,11 @@
# FOR A PARTICULAR PURPOSE.
#
############################################################################
-"""Component and Component Architecture Interfaces
+"""
+Component and Component Architecture Interfaces
+
+The `IComponentArchitecture` and `IComponentRegistrationConvenience` interfaces
+are provided by `zope.component` directly.
"""
from zope.interface import Attribute
from zope.interface import Interface
@@ -380,3 +384,24 @@ class IFactory(Interface):
created by this factory will implement. If the callable's Implements
instance cannot be created, an empty Implements instance is returned.
"""
+
+
+# Internal helpers
+
+def _inherits_docs(func, iface):
+ doc = iface[func.__name__].__doc__
+ # By adding the ..seealso:: we get a link from our overview page
+ # to the specific narrative place where the function is described, because
+ # our overview page uses :noindex:
+ doc += "\n .. seealso::"
+ doc += "\n Function `~zope.component.%s` for notes, and " % (func.__name__,)
+ doc += "\n `~zope.component.interfaces.%s` for the defining interface." % (iface.__name__,)
+ doc += "\n"
+ func.__doc__ = doc
+ return func
+
+def inherits_arch_docs(func):
+ return _inherits_docs(func, IComponentArchitecture)
+
+def inherits_reg_docs(func):
+ return _inherits_docs(func, IComponentRegistrationConvenience)