Lets step back and look at why we created ZCML. A primary goal of the
component architecture was to make it easier to reuse packages. A
major problem with Zope 2 products is that they are hard to
customize. The CMF made this a bit better with skins. You could
override selected scripts or templates provided by a product by
providing overriding versions in your own products or by customizing
through the web. You don't have to modify the original product. With
the component architecture, you can override at the level of
components. As with the CMF, we need to be able to override components
without modifying the original package.
The zope.configuration package provides a framework for defining and
overriding configurations. It *also* supports an XML syntax. It
supports other syntaxes too. (This support may have atrophied somewhat
from lack of use. :) In fact, the original syntax for
zope.configuration was a simple text-based syntax.
The configuration framework is based on computing sequences of
actions. When a ZCML file is processed, the individual handlers
compute lists of actions. These actions are accumulated as different
files are processed.
An action includes:
- a discriminator used to detect conflicting actions. Two or more
actions conflict of they have the same discriminator. An action may
have "None" as it's discriminator, in which case, it cannot conflict
with another action.
- callable, positional, and keyword arguments,
- include path used to resolve conflicts. If there is an action in a
set of conflicting actions whose include path is a proper prefix of
the include paths of all of the other conflicting actions, then the
conflict is resolved by keeping this action and discarding the other
actions. This is why a file that includes another file can have a
directive that overrides directives in the included file.
- info that documents the action.
- order (lame) that can be used to affect the order in which an action
executes. A very high number can be used to make an action execute
Configuration processing proceeds in 3 steps:
1. Actions are generated, typically by processing ZCML files.
(We'll ignore meta-configuration in this discussion. :)
2. Actions generated in step 1 are analyzed for conflicts.
If any conflicts can't be resolved, they are reported as errors.
The action info is used in the generation of these errors.
3. Actions are executed by calling their callables with their
positional and keyword arguments.
The resolution of conflicts in stage 2 is critical for achieving the
goal of the configuration framework, which is overriding. The way
actions are generated is not critical.
(Note that a flaw in this model is that we have no good way to undo
actions. We don't need this for normal execution, but it would be very
helpful for testing.)
Actions need not be generated by executing ZCML. They can be
generated by processing configuration files in other formats. They
could even be generated by Python code. I'm told that that's what
I'd have no problem with generating actions in Python. It would allow
greater control and would probably make action generation much faster.
If we did this, We'd probably want to improve the action-generation
API. We'd also need to think about how action info should be
generated, especially wrt error reporting.
Perhaps we should support both ZCML and python action generation.
Jim Fulton mailto:[EMAIL PROTECTED] Python Powered!
CTO (540) 361-1714 http://www.python.org
Zope Corporation http://www.zope.com http://www.zope.org
Zope3-dev mailing list