[Zope3-checkins] CVS: Zope3/src/zope/configuration - zopeconfigure.py:1.1 xmlconfig.py:1.13

Jim Fulton jim@zope.com
Thu, 31 Jul 2003 10:57:00 -0400


Update of /cvs-repository/Zope3/src/zope/configuration
In directory cvs.zope.org:/tmp/cvs-serv11047/src/zope/configuration

Modified Files:
	xmlconfig.py 
Added Files:
	zopeconfigure.py 
Log Message:
Split the Zope configuration directive implementation into a separate
file to provide documentation on how to write a grouping directive.

Change the name of the i18n_domain attribute to i18n_domain.

Combined the registration of the configure directive and the includes
directives.


=== Added File Zope3/src/zope/configuration/zopeconfigure.py ===
##############################################################################
#
# Copyright (c) 2001, 2002, 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Zope configure directive

This file contains the implementation of the Zope configure directive.
It is beoken out in a separate file to provide an example of a grouping
directive.

The zope configuration directive is a pure grouping directive.  It
doesn't compute any actions on it's own. Instead, it allows a package
to be specified, affecting the interpretation of relative dotted names
and file paths. It also allows an i18n domain to be specified.  The
information collected is used by subdirectives.

To define a grouping directive, we need to do 3 things:

- Define a schema for the parameters passed to the directive

- Define a handler class.

- Register the class

The parameter schema is given by IZopeConfigure. It specified a
package parameter and an i18n_domain paramter.  The package parameter
is specified as a ``GlobalObject``. This means it must be given as a
dotted name that can be resolved through import.  The i18n domain is
just a plan (not unicode) string.

The handler class has a constructor that takes a context to be adapted
and zero or more arguments (depending on the paramter schema).  The
handler class must implement
``zope.configuration.interfaces.IGroupingContext``, which defines
hooks ``before`` and ``after``, that are called with no arguments
before and after nested directives are processed.  If a grouping
directibe handler creates any actions, or does any computation, this
is normally done in either the ``before`` or ``after`` hooks.
Grouping handlers are normally decorators.

The base class,
``zope.configuration.config.GroupingContextDecorator``, is normally
used to define grouping directive handlers. It provides:

- An implementation of IConfigurationContext, which grouping directive
  handlers should normally implement,

- A default implementation of ``IGroupingContext`` that provides empty
  hooks.

- Decorator support that uses a ``__getattr__`` method to delegate
  attribute accesses to adapted contexts, and

- A constructor that sets the ``context`` attribute to the adapted
  context and assigns keyword arguments to attributes.

The ``ZopeConfigure`` provides handling for the ``configure``
directive. It subclasses GroupingContextDecorator, and overrides the
constructor to set the ``basepath`` attribute if a ``package`` argument
is provided. Note that it delegates the job of assigning paramters to
attribute to the ``GroupingContextDecorator`` constructor.

The last step is to register the directive using the meta
configuration directive.  If we wanted to register the Zope
``configure`` directive for the ``zope`` namespace, we'd use a
meta-configuration directive like::

  <meta:groupingDirective
     namespace="http://namespaces.zope.org/zope"
     name="configure"
     schema="zope.configuration.zopeconfigure.IZopeConfigure"
     handler="zope.configuration.zopeconfigure.ZopeConfigure"
     >
     Zope configure

     The ``configure`` node is normally used as the root node for a
     configuration file.  It can also be used to specify a package or
     internationalization domain for a group of directives within a
     file by grouping those directives.
  </meta:groupingDirective>

We use the groupingDirective meta-directive to register a grouping
directive. The parameters are self explanitory.  The textual contents
of the directive provides documentation text, exclusing parameter
documentation, which is provided by the schema.

(The Zope ``configuration`` directive is actually registered using a
lower-level Python API because it is registered for all namespaces,
which isn't supported using the meta-configuration directives.)

$Id: zopeconfigure.py,v 1.1 2003/07/31 14:56:55 jim Exp $
"""

import os
import zope.configuration.config as config
from zope import schema
from zope.interface import Interface, implements

class IZopeConfigure(Interface):

    package = config.fields.GlobalObject(
        __doc__=
        """Package

        The package to be used for evaluating relative imports and file names.
        """,
        required=False)

    i18n_domain = schema.BytesLine(
        __doc__=
        """Internationalization domain

        This is a name for the software project. It must be a legal file-system
        name as it will be used to contruct names for directories containing
        translation data.

        The domain defines a namespace for the message ids used by a project.
        """,
        required=False)

class ZopeConfigure(config.GroupingContextDecorator):

    def __init__(self, context, **kw):
        super(ZopeConfigure, self).__init__(context, **kw)
        if 'package' in kw:
            # if we have a package, we want to also define basepath
            # so we don't acquire one
            self.basepath = os.path.split(self.package.__file__)[0]


=== Zope3/src/zope/configuration/xmlconfig.py 1.12 => 1.13 ===
--- Zope3/src/zope/configuration/xmlconfig.py:1.12	Wed Jul 30 11:06:48 2003
+++ Zope3/src/zope/configuration/xmlconfig.py	Thu Jul 31 10:56:55 2003
@@ -33,6 +33,7 @@
 from xml.sax import SAXParseException
 from zope.configuration.exceptions import ConfigurationError
 from zope.interface import Interface, implements
+from zope.configuration.zopeconfigure import IZopeConfigure, ZopeConfigure
 
 logger = logging.getLogger("config")
 
@@ -229,56 +230,6 @@
                 ), sys.exc_info()[2]
 
 
-class IZopeConfigure(Interface):
-
-    package = config.fields.GlobalObject(__doc__="""Package
-
-        The package to be used for evaluating relative imports and file names.
-        """,
-        required=False)
-
-    domain = schema.BytesLine(__doc__="""Internationalization domain
-
-        This is a name for the software project. It must be a legal file-system
-        name as it will be used to contruct names for directories containing
-        translation data.
-
-        The domain defines a namespace for the message ids used by a project.
-        """,
-        required=False)
-
-class ZopeConfigure(config.GroupingContextDecorator):
-
-    implements(config.IConfigurationContext)
-
-    def __init__(self, context, **kw):
-        super(ZopeConfigure, self).__init__(context, **kw)
-        if 'package' in kw:
-            # if we have a package, we want to also define basepath
-            # so we don't acquire one
-            self.basepath = os.path.split(self.package.__file__)[0]
-
-
-def _register_configure(context):
-
-    # We have to use the direct definition function to define
-    # a directive for all namespaces.
-    config.defineGroupingDirective(
-        context,
-        name="zopeConfigure",
-        namespace="*",
-        schema=IZopeConfigure,
-        handler=ZopeConfigure,
-        )
-    config.defineGroupingDirective(
-        context,
-        name="configure",
-        namespace="*",
-        schema=IZopeConfigure,
-        handler=ZopeConfigure,
-        )
-
-
 def processxmlfile(file, context, testing=0):
     """Process a configuration file
 
@@ -420,14 +371,31 @@
     # and replace the new actions with the munched new actions:
     _context.actions[nactions:] = newactions
 
-def _registerIncludes(context):
-    # Register the include directives
+def registerCommonDirectives(context):
+    # We have to use the direct definition functions to define
+    # a directive for all namespaces.
+
     config.defineSimpleDirective(
         context, "include", IInclude, include, namespace="*")
+
     config.defineSimpleDirective(
         context, "includeOverrides", IInclude, includeOverrides, namespace="*")
 
-    _register_configure(context)
+    config.defineGroupingDirective(
+        context,
+        name="zopeConfigure",
+        namespace="*",
+        schema=IZopeConfigure,
+        handler=ZopeConfigure,
+        )
+
+    config.defineGroupingDirective(
+        context,
+        name="configure",
+        namespace="*",
+        schema=IZopeConfigure,
+        handler=ZopeConfigure,
+        )
 
 def file(name, package=None, context=None, execute=True):
     """Execute a zcml file
@@ -435,7 +403,7 @@
 
     if context is None:
         context = config.ConfigurationMachine()
-        _registerIncludes(context)
+        registerCommonDirectives(context)
         context.package = package
 
     include(context, name, package)
@@ -451,7 +419,7 @@
 
     if context is None:
         context = config.ConfigurationMachine()
-        _registerIncludes(context)
+        registerCommonDirectives(context)
 
     f = StringIO(s)
     f.name = name
@@ -471,7 +439,7 @@
 def _clearContext():
     global _context
     _context = config.ConfigurationMachine()
-    _registerIncludes(_context)
+    registerCommonDirectives(_context)
 
 def _getContext():
     global _context