[Zope3-checkins] CVS: Zope3/lib/python/Zope/Configuration - meta.py:1.11
R. David Murray
bitz@bitdance.com
Wed, 18 Sep 2002 14:52:41 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Configuration
In directory cvs.zope.org:/tmp/cvs-serv13754
Modified Files:
meta.py
Log Message:
Add some more comments, and a missing __class__implements__ on
DirectiveNamespace. Also fix the spelling of InvalidDirectiveDefinition,
move it to the top of the file with the other exceptions, and give it
a doc string.
=== Zope3/lib/python/Zope/Configuration/meta.py 1.10 => 1.11 ===
--- Zope3/lib/python/Zope/Configuration/meta.py:1.10 Wed Sep 18 00:45:14 2002
+++ Zope3/lib/python/Zope/Configuration/meta.py Wed Sep 18 14:52:40 2002
@@ -22,47 +22,55 @@
from INonEmptyDirective import INonEmptyDirective
from ISubdirectiveHandler import ISubdirectiveHandler
-#_directives is a registry that holds information on zcml directives
-#and subdirectives. It is filled by the 'directives', 'directive' and
-#'subdirective' directives that are provided as the bootstrap
-#directives by the _clear function of this module.
-#
-#The top level of the registry is a dictionary keyed by two element
-#tuples. Each key tuple consists of a namespace designator (such as
-#http://namespaces.zope.org/zope) and a directive name. Thus, the
-#key that accesses the 'directive' directive is::
-#
-# (http://namespaces.zope.org/zope', 'directive')
-#
-#The value of a directive entry is a two element tuple consisting
-#of a callable and a (possibly empty) subdirective registry. The
-#callable is the object to be called to process the directive and
-#its parameters. The callable must be either an IEmptyDirective (in
-#which case the subdirective registry should be empty), or an
-#INonEmptyDirective (in which case there should be one or more entries
-#in the subdirective registry).
-#
-#A subdirective registry is also keyed by (ns, name) tuples. Handler
-#methods for subdirectives are looked up on the ISubdirectiveHandler
-#object that is returned by the INonEmptyDirective that handles
-#the directive to which the subdirective registry belongs.
-#INonEmptyDirective objects are thus most often classes.
-#
-#The value of an entry in the subdirective registry is a tuple of
-#two elements. The first element is a subdirective registry, and
-#the second is the name to be looked up to find the callable that
-#will handle the processing of the subdirective. That callable
-#should implement either IEmtpyDirective or INonEmptyDirective. The
-#accompanying sub-subdirective registry should be empty or not,
-#accordingly.
-
-_directives = {}
-
class InvalidDirective(Exception):
- "An invalid directive was used"
+ """An invalid directive was used"""
class BrokenDirective(Exception):
- "A directive is implemented incorrectly"
+ """A directive is implemented incorrectly"""
+
+class InvalidDirectiveDefinition(Exception):
+ """The definition of a directive is incomplete or incorrect"""
+
+
+#
+# Registry data structure and manipulation functions.
+#
+
+# _directives is a registry that holds information on zcml directives
+# and subdirectives. It is filled by the 'directives', 'directive' and
+# 'subdirective' directives that are provided as the bootstrap
+# directives by the _clear function of this module.
+#
+# The top level of the registry is a dictionary keyed by two element
+# tuples. Each key tuple consists of a namespace designator (such as
+# http://namespaces.zope.org/zope) and a directive name. Thus, the
+# key that accesses the 'directive' directive is::
+#
+# (http://namespaces.zope.org/zope', 'directive')
+#
+# The value of a directive entry is a two element tuple consisting
+# of a callable and a (possibly empty) subdirective registry. The
+# callable is the object to be called to process the directive and
+# its parameters. The callable must be either an IEmptyDirective (in
+# which case the subdirective registry should be empty), or an
+# INonEmptyDirective (in which case there should be one or more entries
+# in the subdirective registry).
+#
+# A subdirective registry is also keyed by (ns, name) tuples. Handler
+# methods for subdirectives are looked up on the ISubdirectiveHandler
+# object that is returned by the INonEmptyDirective that handles
+# the directive to which the subdirective registry belongs.
+# INonEmptyDirective objects are thus most often classes.
+#
+# The value of an entry in the subdirective registry is a tuple of
+# two elements. The first element is a subdirective registry, and
+# the second is the name to be looked up to find the callable that
+# will handle the processing of the subdirective. That callable
+# should implement either IEmtpyDirective or INonEmptyDirective. The
+# accompanying sub-subdirective registry should be empty or not,
+# accordingly.
+
+_directives = {}
def register(name, callable):
"""Register a top-level directive
@@ -114,19 +122,44 @@
directives[name] = subdirs, handler_method
return subdirs
-
+#
+# Parser handler methods. These methods are called by the code that
+# parses configuration data to process the directives and subdirectives.
+# 'begin' is called to start processing a directive. Its return
+# value should be saved. When the directive is closed (which will
+# be right away for IEmptyDirectives), that saved return value is
+# passed to end, which will return a list of actions to append to
+# the action list. Nested subdirectives are processed similarly,
+# except that 'sub' is called to start them rather than begin, and
+# the first argument passed to sub should be the tuple returned
+# by begin (or sub) for the enclosing (sub)directive (it will be
+# an ISubdirectiveHandler, subdirectiveregistry pair). The
+# end result will be a list of actions. See IEmptyDirective for a
+# description of the actions data structure.
+#
def _exe(callable, subs, context, kw):
+ """Helper function to turn an IxxxDirective into a (callable, subs) tuple
+ """
+
+ # We've either got an IEmptyDirective or an INonEmptyDirective here.
+ # For the former, we're going to get back a list of actions when
+ # we call it. For the latter, we're going to get back an
+ # ISubdirectiveHandler. We need to return something that end
+ # can call the first element of to get a list of actions.
+ # ISubdirectiveHandler qualifies, but we'll have to manufacture
+ # one if we got a list of actions. When we return the
+ # ISubdirectiveHandler, the parsing code calling begin/sub is
+ # going to pass the tuple along to sub in order to process the
+ # subdirectives.
+
r = callable(context, **kw)
if subs or INonEmptyDirective.isImplementedBy(callable):
return r, subs
else:
return (
- # We already have our list of actions, but we're expected to
- # provide a callable that returns one.
(lambda: r),
-
subs,
)
@@ -210,9 +243,9 @@
The argument is a return value from begin or sub. Its first
element is called to get a sequence of actions.
- The actions are normalized to a 4-element tuple with a
- descriminator, a callable, positional arguments, and keyword
- arguments.
+ The return value is a list of actions that are normalized to a
+ 4-element tuple with a descriminator, a callable, positional
+ arguments, and keyword arguments.
"""
actions = base[0]()
@@ -225,8 +258,20 @@
ractions.append(action)
return ractions
+
+#
+# The code below provides the implementation for the directives,
+# directive, and subdirective handlers. These will be called
+# via begin and sub when the code parsing a (meta) configuration
+# file encounters these directives. The association between
+# the directive names and the particular callables is set up
+# in _clear.
+#
+
class DirectiveNamespace:
+ __class_implements__ = INonEmptyDirective
+
def __init__(self, _context, namespace):
self._namespace = namespace
@@ -245,8 +290,6 @@
Directive.__implements__ = INonEmptyDirective
-class InvaliDirectiveDefinition(Exception): pass
-
class Subdirective:
"""This is the meta-meta-directive"""
#
@@ -266,9 +309,8 @@
namespace=None, handler_method=None):
namespace = namespace or self._namespace
if not namespace:
- raise InvaliDirectiveDefinition(name)
- #if not handler_method:
- # handler_method = name
+ raise InvalidDirectiveDefinition(name)
+ #If handler_method is None, registersub will use name.
subs = registersub(self._subs, (namespace, name), handler_method)
return Subdirective(subs)