Package: grokcore.component
This package provides base classes of basic component types for the
Zope Component Architecture, as well as means for configuring and
registering them directly in Python (without ZCML).ContentsHow to set upgrokcore.componentimplementer()versusimplements()ExamplesAdapterMulti-adapterGlobal utilityGlobal adapterHandling eventsSubscriptionsChanges4.1 (2023-03-21)4.0 (2023-02-17)3.2.0 (2021-03-22)3.1 (2018-05-09)3.0.2 (2018-01-17)3.0.1 (2018-01-12)3.0 (2017-10-19)2.7 (2016-02-16)2.6.1 (2016-01-29)2.6 (2015-05-12)2.5 (2012-05-01)2.4 (2011-04-27)2.3 (2011-02-14)2.2 (2010-11-03)2.1 (2010-11-01)2.0 (2009-09-16)1.7 (2009-06-01)1.6 (2009-04-10)1.5.1 (2008-07-28)1.5 (2008-07-22)1.4 (2008-06-11)1.3 (2008-05-14)1.2.1 (2008-05-04)1.2 (2008-05-04)1.1 (2008-05-03)1.0.1 (2008-05-02)1.0 (2008-05-01)How to set upgrokcore.componentIn the following we assume you’re writing or extending an application
that does bootstrap configuration using ZCML.  There’s always a single
ZCML file that is executed when the application is started, which then
includes everything else.  Let’s assume this file is calledsite.zcml(that’s what it’s called in Zope), so that file is what
we’ll be editing.In order to register the components that you wrote using the base
classes and directives available fromgrokcore.component, we’ll
use the<grok:grok />ZCML directive.  But before we can use it,
we need to make sure it’s available to the ZCML machinery.  We do this
by including the meta configuration fromgrokcore.component:<include package="grokcore.component" file="meta.zcml" />Put this line somewhere to the top ofsite.zcml, next to other
meta configuration includes.  Now, further down the line, we can tell
the machinery ingrokcore.componentto register all components in
your package (let’s say it’s calledhelloworld):<grok:grok package="helloworld" />To sum up, yoursite.zcmlfile should look like something like this:<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:grok="http://namespaces.zope.org/grok">

  <!-- do the meta configuration to make the ZCML directives available -->
  <include package="zope.foobar" file="meta.zcml" />
  <include package="zope.frobnaz" file="meta.zcml" />
  <include package="grokcore.component" file="meta.zcml" />

  <!-- now load the configuration of packages that we depend on -->
  <include package="zope.barfoo" />
  <include package="zope.somethingorother" />

  <!-- finally load my components which are based on grokcore.component -->
  <grok:grok package="helloworld" />

</configure>There is an optionalexcludeon thegrokdirective. It allows to specify
names of packages or modules that if encountered won’t be grokked. These
names might contain unix shell-style wildcards.implementer()versusimplements()Note how the Python 3 compatibility brings a change in how thegrokcore.component.implements()directiveworks. When using this directive
you now have to make sure the component is grokkked, to have the underlying
mechanism to take effect.Alternatively you could start to use thegrokcore.component.implementer()class decoratorinstead. This will do the same thing, but does not require
your component to be grokkked and still have your component declare it
implements the given interface.ExamplesAdapterHere’s a simple adapter that may be useful in Zope.  It extracts the
languages that a user prefers from the request:import grokcore.component
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.i18n.interfaces import IUserPreferredLanguages

class CookieLanguage(grokcore.component.Adapter):
    """Extract the preferred language from a cookie"""
    grokcore.component.context(IBrowserRequest)
    grokcore.component.implements(IUserPreferredLanguages)

    # No need to implement __init__, it's already provided by the base class.

    def getPreferredLanguages(self):
        # This an adapter for the request, so self.context is the request.
        request = self.context

        # Extract the preferred language from a cookie:
        lang = request.cookies.get('language', 'en')

        # According to IUserPreferredLanguages, we must return a list.
        return [lang]Multi-adapterHere’s a multi-adapter that functions as a content provider as known
from thezope.contentproviderlibrary.  Content providers are
components that return snippets of HTML.  They’re multi-adapters for
the content object (model), the request and the view that they’re
supposed to be a part of:import grokcore.component
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.browser import IBrowserPage
from zope.contentprovider.interfaces import IContentProvider

class HelloWorldProvider(grokcore.component.MultiAdapter):
    """Display Hello World!"""
    grokcore.component.adapts(Interface, IBrowserRequest, IBrowserPage)
    grokcore.component.implements(IContentProvider)

    def __init__(self, context, request, view):
        pass

    def update(self):
        pass

    def render(self):
        return u'<p>Hello World!</p>'Global utilityHere’s a simple named utility, again from the Zope world.  It’s a
translation domain.  In other words, it contains translations of user
messages and is invoked when the i18n machinery needs to translate
something:import grokcore.component
from zope.i18n.interfaces import ITranslationDomain

class HelloWorldTranslationDomain(grokcore.component.GlobalUtility):
    grokcore.component.implements(ITranslationDomain)
    grokcore.component.name('helloworld')

    domain = u'helloworld'

    def translate(self, msgid, mapping=None, context=None,
                  target_language=None, default=None):
        if target_language is None:
            preferred = IUserPreferredLanguages(context)
            target_language = preferred.getPreferredLanguages()[0]

        translations = {'de': u'Hallo Welt',
                        'nl': u'Hallo Wereld'}
        return translations.get(target_language, u'Hello World')Of course, it’s silly to implement your own translation domain utility
if there are already implementations available inzope.i18n(one
that reads translations from a GNU gettext message catalog and a
simple implementation for tests).  Let’s try to reuse that
implementation and register an instance:import grokcore.component
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n.simpletranslationdomain import SimpleTranslationDomain

messages = {('de', u'Hello World'): u'Hallo Welt',
            ('nl', u'Hello World'): u'Hallo Wereld'}
helloworld_domain = SimpleTranslationDomain(u'helloworld', messages)

grokcore.component.global_utility(helloworld_domain,
                                  provides=ITranslationDomain,
                                  name='helloworld',
                                  direct=True)Global adapterSometimes, you may have an object that should be registered as an adapter
factory. It may have come from some other framework that configured that
adapter for you, say, or you may have a class that you instantiate many
times to get different variations on a particular adapter factory. In these
cases, subclassing grokcore.component.Adapter or MultiAdapter is not
possible. Instead, you can use the global_adapter() directive. Here is an
example drawing on thez3c.formlibrary, which provides an adapter factory
factory for named widget attributes:import zope.interface
import zope.schema
import grokcore.component
import z3c.form.widget import ComputedWidgetAttribute

class ISchema(Interface):
    """This schema will be used to power a z3c.form form"""

    field = zope.schema.TextLine(title=u"Sample field")

...

label_override = z3c.form.widget.StaticWidgetAttribute(
                      u"Override label", field=ISchema['field'])

grokcore.component.global_adapter(label_override, name=u"label")In the example above, the provided and adapted interfaces are deduced from the
object returned by theStaticWidgetAttributefactory. The full syntax
for global_adapter is:global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name")The factory must be a callable (the adapter factory). Adapted interfaces are
given as a tuple. You may use a single interface instead of a one-element
tuple for single adapters. The provided interface is given as shown. The name
defaults to u”” (an unnamed adapter).Handling eventsHere we see an event handler much like it occurs within Zope itself. It
subscribes to the modified event for all annotatable objects (in other words,
objects that can have metadata associated with them). When invoked, it updates
the Dublin Core ‘Modified’ property accordingly:import datetime
import grokcore.component
from zope.annotation.interfaces import IAnnotatable
from zope.lifecycleevent.interfaces import IObjectModifiedEvent
from zope.dublincore.interfaces import IZopeDublinCore

@grokcore.component.subscribe(IAnnotatable, IObjectModifiedEvent)
def updateDublinCoreAfterModification(obj, event):
    """Updated the Dublin Core 'Modified' property when a modified
    event is sent for an object."""
    IZopeDublinCore(obj).modified = datetime.datetime.utcnow()SubscriptionsSubscriptions look similar to Adapter, however, unlike regular adapters,
subscription adapters are used when we want all of the adapters that adapt an
object to a particular adapter.Analogous to MultiAdapter, there is a MultiSubscription component that “adapts”
multiple objects.Changes4.1 (2023-03-21)Upgrade to supportzope.interface >= 6.0by no longer importing removed
functions:classProvidesimplementsOnly4.0 (2023-02-17)Add support for Python 3.10, 3.11.Drop support for Python 2.7, 3.5, 3.6.3.2.0 (2021-03-22)Add support for Python 3.7 up to 3.9.Update tozope.component >= 5.Drop support for Python 3.4.3.1 (2018-05-09)Exposemartian.ignorethrough our API.3.0.2 (2018-01-17)Replace the use ofgrok.implements()with the@grok.implementer()directive throughout.3.0.1 (2018-01-12)Rearrange tests such that Travis CI can pick up all functional tests too.3.0 (2017-10-19)Add support for Python 3.5, 3.6, PyPy2 and PyPy3.Drop support for Python 2.6 and 3.3.2.7 (2016-02-16)Add ability to exclude more than one module or package using<grok:grokexclude="<names>"/>and allow to use unix shell-style
wildcards within.2.6.1 (2016-01-29)Make grokcore.component.implementer compatible with
zope.interface.implementer by allowing doing the adapter magic when
used on functions.2.6 (2015-05-12)Compatibility for python 3lPython 3 doesn’t support the directivezope.interface.implementsany more and is required to use the@implementerclass decorator instead.
This version of grokcore.components provides its owngrokcore.component.implementsdirective for both Python 2 and 3.
So this directive can still be used with the help of a grokker.
If you use grokcore.components >= 2.6  the new implementation will be used
while earlier versions used zope.interface.implements.2.5 (2012-05-01)Introduce provideUtility, providerAdapter, provideSubscriptionAdapter,
provideHandler and provideInterface in grokcore.component. These by default
delegate the registration of components to the global site manager like
was done before, but provide the possibility for custom registries for the
grokked components.Fix theglobal_adapterto properly use information annotated bygrok.adapter, and using the IContext object if it was not
specified. (Fix Launchpad issue #960097).Add akeyoption tosort_componentsthat behave likekeyoptions available on standard Python sort methods.2.4 (2011-04-27)Fix theglobal_adapterdirective implementation to accept an explicit
“empty” name for nameless adapter registrations (as it used to be that
providing an empty name in the registration would actually result in
registering a named adapter in case the factory has agrok.name).2.3 (2011-02-14)Implement the generic (Multi)Subscriptions components.2.2 (2010-11-03)The default values computation for the context directive and the provides
directive is now defined in the directives themselves. This means that where
the values for these directives is being retrieved, the “default_context”
function does not need to be passed along anymore for general cases.Analogous to this, when getting values for the provides directive the
“default_provides” function does not need to be passed along in the general
case.2.1 (2010-11-01)Made package comply to zope.org repository policy.Moved directives ‘order’ from grokcore.viewlet and ‘path’ from
grokcore.view to this very package.Tiny dependency adjustment: moved zope.event to test dependencies.Port from 1.x branch exclude parameter to the Grok ZCML directive.Port from 1.x branch the ignore of testing.py modules.2.0 (2009-09-16)Use a newer version of Martian that has better support for
inheritance.  This is demonstrated intests/inherit.TheContextGrokkerand thescan.pymodule have gone away
thanks the newer Martian.Directive implementations (in their factory method) shouldnotbind directives. Directive binding cannot take place at import time,
but only at grok time. Binding directives during import time (when
directives are executed) can lead to change problems. (we noticed
this during our refactoring to use the new Martian).Use 1.0b1 versions.cfg in Grok’s release info instead of a local
copy; a local copy for all grokcore packages is just too hard to
maintain.1.7 (2009-06-01)Add missing provider, global_adapter, implementsOnly, classProvides() to
the module interface so that they are included in __all__1.6 (2009-04-10)Add convenience imports for implementsOnly() and classProvides() class
declarations form zope.interface.Add support for registering global adapters at module level:grok.global_adapter(factory, (IAdapted1, IAdapted2,), IProvided, name=u"name")Only ‘factory’ is required. If only a single interface is adapted, the
second argument may be a single interface instead of a tuple. If the
component has declared adapted/provided interfaces, the second and third
arguments may be omitted.Add support for an @provider decorator to let a function directly provide
an interface:@grok.provider(IFoo, IBar)
def some_function():
    ...This is equivalent to doing alsoProvides(some_function, IFoo, IBar).Add support for named adapters with the @adapter decorator:@grok.adapter(IAdaptedOne, IAdaptedTwo, name=u"foo")
def some_function(one, two):
    ...1.5.1 (2008-07-28)TheIGrokcoreComponentAPIinterface was missing declarations for
thetitleanddescriptiondirectives.1.5 (2008-07-22)Fixhttps://bugs.launchpad.net/grok/+bug/242353: grokcore.component
contains old-style test setup. There is noregister_all_testsmethod in grokcore.component.testing anymore. Use z3c.testsetup
instead.Allow functions that have been marked with @grok.subscribe also be
registered withzope.component.provideHandler()manually.  This
is useful for unit tests where you may not want to grok a whole
module.Document grokcore.component’s public API in an interface,IGrokcoreComponentAPI.  When you now do:from grokcore.component import *only the items documented in that interface will be imported into
your local namespace.1.4 (2008-06-11)Ported class grokkers to make use of further improvements in Martian.
This requires Martian 0.10.1.3 (2008-05-14)Ported class grokkers to make use of the new declarative way of
retrieving directive information from a class.  This requires
Martian 0.9.6.1.2.1 (2008-05-04)Upgrade to Martian 0.9.5, which has a slight change in the signature ofscan_for_classes.Remove an unnecessary importmethods_from_classfromgrokcore.component.scan.1.2 (2008-05-04)Ported directives to Martian’s new directive implementation.  As a
result, nearly all helper functions that were available fromgrokcore.component.utilhave been removed.  The functionality is
mostly available from the directives themselves now.Thebaseclassdirective has been moved to Martian.Theorderdirective and its helper functions have been moved
back to Grok, as it was of no general use, but very specific to
viewlets.1.1 (2008-05-03)determine_module_componentnow looks for classes that implement
a certain interface (such asIContext), instead of taking a list
of classes.  If looking forIContext, it still will findContextsubclasses, as these were also made to implementIContext.Move thepublic_methods_from_classhelper function back to Grok,
it isn’t used at all ingrokcore.component.1.0.1 (2008-05-02)The grokkers for adapters and global utilities did not use the
correct value for theprovidedinterface in the configuration
action discriminator.  Because of this, uninformative and
potentially wrong conflict errors would occur, as well as no
conflict where a conflict should have occurred.The grokker for theglobal_utility()directive did immediate
registrations instead of generating configuration actions.
Therefore it did not provokeConflictErrorsfor conflicting
registrations.Improved documentation1.0 (2008-05-01)Createdgrokcore.componentin March 2008 by factoring basic
component base classes and their directives and grokkers out of
Grok.