<?xml version="1.0" encoding="UTF-8" ?>
<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Project><name>grokcore.component</name>
<shortdesc>Grok-like configuration for basic components (adapters, utilities, subscribers)</shortdesc>
<description>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).

.. contents::

How to set up ``grokcore.component``
====================================

In 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 called
``site.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 from ``grokcore.component``, we'll
use the ``&lt;grok:grok /&gt;`` 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 from ``grokcore.component``::

  &lt;include package="grokcore.component" file="meta.zcml" /&gt;

Put this line somewhere to the top of ``site.zcml``, next to other
meta configuration includes.  Now, further down the line, we can tell
the machinery in ``grokcore.component`` to register all components in
your package (let's say it's called ``helloworld``)::

  &lt;grok:grok package="helloworld" /&gt;

To sum up, your ``site.zcml`` file should look like something like this::

  &lt;configure
      xmlns="http://namespaces.zope.org/zope"
      xmlns:grok="http://namespaces.zope.org/grok"&gt;

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

    &lt;!-- now load the configuration of packages that we depend on --&gt;
    &lt;include package="zope.barfoo" /&gt;
    &lt;include package="zope.somethingorother" /&gt;

    &lt;!-- finally load my components which are based on grokcore.component --&gt;
    &lt;grok:grok package="helloworld" /&gt;

  &lt;/configure&gt;

Examples
========

Adapter
-------

Here'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-adapter
-------------

Here's a multi-adapter that functions as a content provider as known
from the ``zope.contentprovider`` library.  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 update(self):
          pass

      def render(self):
          return u'&lt;p&gt;Hello World!&lt;/p&gt;'


Global utility
--------------

Here'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 in ``zope.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 adapter
--------------

Sometimes, 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 the ``z3c.form`` library, 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 the ``StaticWidgetAttribute`` factory. 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).

Subscriber
----------

Here we see a subscriber 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()


API overview
============

Base classes
------------

``Adapter``
    Base class for an adapter that adapts a single object (commonly
    referred to as the *context*).  Use the ``context`` directive to
    specify which object to adapt and the ``implements`` directive to
    specify which interface the adapter will provide.  If it's a named
    adapter, you may use the ``name`` directive to specify the name.

``MultiAdapter``
    Base class for an adapter that adapts *n* objects (where *n&gt;=1*).
    Use the ``adapts`` directive to specify which kinds of objects are
    adapted and the ``implements`` directive to specify which
    interface the adapter will provide.  If it's a named
    multi-adapter, you may use the ``name`` directive to specify the
    name.

``GlobalUtility``
    Base class for a globally registered utility.  Unless you use the
    ``direct`` directive to indicate that the class itself should be
    registered as a utility, the class will automatically be
    instantiated, therefore the constructor may not take any
    arguments.  Use the ``implements`` directive to specify which
    interface the utility provides, or if that is not unambiguous,
    also use the ``provides`` directive to specify which of the
    implemented interfaces should be used when registering the
    utility.  If it's a named utility, you may use the ``name``
    directive to specify the name.

``Context``
    Subclasses of this will automatically be found as potential
    contexts for adapters and other types of context-dependent
    components.


Class-level directives
----------------------

``implements(iface1, iface2, ...)``
    declares that a class implements the interfaces ``iface1``,
    ``iface2``, etc.  It is identical to
    ``zope.interface.implements``.

``implementsOnly(iface1, iface2, ...)``
    declares that a class *only* implements the interfaces ``iface1``,
    ``iface2``, etc.  It is identical to
    ``zope.interface.implementsOnly``.

``classProvides(iface1, iface2, ...)``
    declares that a class object (as opposed to instances of the class)
    provides the interfaces ``iface1``, ``iface2``, etc.  It is identical to
    ``zope.interface.classProvides``.

``context(iface_or_class)``
    declares the type of object that the adapter (or a similar
    context-dependent component) adapts.  This can either be an
    interface (in this case all objects providing this interface will
    be eligible contexts for the adapter) or a class (then only
    instances of that particular class are eligible).

``adapts(iface_or_class1, iface_or_class_2, ...)``
    declares the types of objects that a multi-adapter adapts.

``name(ascii_or_unicode)``
    declares the name of a named utility, named adapter, etc.

``title(ascii_or_unicode)``
    declares the human-readable title of a component (such as a
    permission, role, etc.)

``provides(iface)``
    declares the interface that a utility provides (as opposed to
    potentially multiple interfaces that the class implements).

``direct()``
    declares that a ``GlobalUtility`` class should be registered as a
    utility itself, rather than an instance of it.

``baseclass()``
    declares that a subclass of an otherwise automatically configured
    component should not be registered, and that it serves as a base
    class instead.


Module-level directives
-----------------------

``global_utility(class, [provides=iface, name=ascii_or_unicode, direct=bool])``
    registers an instance of ``class`` (or ``class`` itself, depending
    on the value of the ``direct`` parameter) as a global utility.
    This allows you to register global utilities that don't inherit
    from the ``GlobalUtility`` base class.

``global_adapter(factory, [adapts=tuple_of_interfaces, provides=iface, name=ascii_or_unicode])``
    registers the ``factory`` callable as a global adapter. The ``adapts``
    argument may be a tuple of interfaces or a single interface, if this is
    a single adapter. Both ``adapts`` and ``provides`` will be deduced from
    information annotated onto the factory if necessary. If no adapted
    interface can be determined, the current context will be assumed. The
    name defaults to u"". This allows you to register global adapters that
    don't inherit from the ``Adapter`` or ``MultiAdapter`` base classes.

Function decorators
-------------------

``@adapter(iface_or_class1, iface_or_class2, ..., name=u"name")``
    registers the function as an adapter for the specific interface. The
    ``name`` argument must be a keyword argument and is optional. If given,
    a named adapter is registered.

``@implementer(iface1, iface2, ...)```
    declares that the function implements a certain interface (or a
    number of interfaces).  This is useful when a function serves as an object
    factory, e.g. as an adapter.

``@provider(iface1, iface2, ...)```
    declares that the function object provides a certain interface (or a
    number of interfaces).  This is akin to calling directlyProvides() on
    the function object.

``@subscribe(iface_or_class1, iface_or_class2, ...)``
    declares that a function is to be registered as an event handler
    for the specified objects.  Normally, an event handler is simply
    registered as a subscriber for the event interface.  In case of
    object events, the event handler is registered as a subscriber for
    the object type and the event interface.

Changes
=======

2.0 (2009-09-16)
----------------

* Use a newer version of Martian that has better support for
  inheritance.  This is demonstrated in ``tests/inherit``.

* The ``ContextGrokker`` and the ``scan.py`` module have gone away
  thanks the newer Martian.

* Directive implementations (in their factory method) should *not*
  bind 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)
------------------

* The ``IGrokcoreComponentAPI`` interface was missing declarations for
  the ``title`` and ``description`` directives.

1.5 (2008-07-22)
----------------

* Fix https://bugs.launchpad.net/grok/+bug/242353: grokcore.component
  contains old-style test setup. There is no `register_all_tests`
  method in grokcore.component.testing anymore. Use z3c.testsetup
  instead.

* Allow functions that have been marked with @grok.subscribe also be
  registered with ``zope.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 of
  ``scan_for_classes``.

* Remove an unnecessary import ``methods_from_class`` from
  ``grokcore.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 from
  ``grokcore.component.util`` have been removed.  The functionality is
  mostly available from the directives themselves now.

* The ``baseclass`` directive has been moved to Martian.

* The ``order`` directive 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_component`` now looks for classes that implement
  a certain interface (such as ``IContext``), instead of taking a list
  of classes.  If looking for ``IContext``, it still will find
  ``Context`` subclasses, as these were also made to implement
  ``IContext``.

* Move the ``public_methods_from_class`` helper function back to Grok,
  it isn't used at all in ``grokcore.component``.

1.0.1 (2008-05-02)
------------------

* The grokkers for adapters and global utilities did not use the
  correct value for the *provided* interface 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 the ``global_utility()`` directive did immediate
  registrations instead of generating configuration actions.
  Therefore it did not provoke ``ConflictErrors`` for conflicting
  registrations.

* Improved documentation

1.0 (2008-05-01)
----------------

* Created ``grokcore.component`` in March 2008 by factoring basic
  component base classes and their directives and grokkers out of
  Grok.</description>
<download-page>http://pypi.python.org/pypi/grokcore.component</download-page>
<homepage rdf:resource="http://grok.zope.org" />
<maintainer><foaf:Person><foaf:name>Grok Team</foaf:name>
<foaf:mbox_sha1sum>22cd1dfb64e763412d361a860350d80bd6e7b039</foaf:mbox_sha1sum></foaf:Person></maintainer>
<release><Version><revision>2.0</revision></Version></release>
</Project></rdf:RDF>