[Zope-dev] Dependencies for ZCML
Martijn Faassen
faassen at startifact.com
Thu Mar 12 10:11:36 EDT 2009
Hey,
Tres Seaver wrote:
[snip]
> - -1 on having "configuration dependecies," including having mandatory
> tests that ZCML will load:
You mean mandatory ZCML loaded by tests? You seem to write the reverse
here, and I don't understand what that could mean.
> "mandatory configuration is a contradiction
> in terms." I therefore don't believe that tests which try to load ZCML
> are useful, at least for "library" pacakges (as opposed to "applications").
Yeah, I know you're a purist on this topic.
Here are some observations on configuration, mandatory or not, and ZCML.
Sometimes you can only test a library when a particular utility or
adapter or event handler is registered. The library uses this utility or
adapter in its own logic and while the utility or adapter is intended to
be replaceable (to make the library pluggable), it is mandatory to
actually register a component that fulfills the interface requirements
in order to use the library at all.
As a convenience to the users of this library, that library's
configure.zcml will provide default implementations (which may be the
right ones in most cases). This is a useful pattern.
I'll note another pattern. A library could define an interface, and a
few event handlers that react on this interface. Now if you use that
interface on your own objects, your object will trigger those event
handlers. Your interest as a library user is not directly in those event
handlers and you may be unaware of their existence, but they do maintain
something that is important to you as a user (an index, for example). So
this is an example of registrations that should be loaded in order to
use the library, and there's not even much interest here in overriding
those registrations - mandatory configuration.
Now when testing these libraries you could do three things:
* not use ZCML at all and recreate the effect of these registrations in
Python code.
* use the ZCML in the package's configure.zcml. (perhaps through
ftesting.zcml)
* construct ZCML in the tests itself and load it.
In fact there's a fourth way you could go and use martian-style
patterns, where you can manually 'grok' a component in tests that
inherits a particular base class.
We could argue that all ZCML in use in tests should be rewritten to
manual registrations from Python code. Is this indeed a useful exercise?
Doesn't that in some cases make tests harder to understand, as
lower-level APIs are in use that are not as recognizable as the
equivalent ZCML directives? (say, registering an event) Don't we place a
burden on the test writers to learn these APIs while they could use the
ones abstracted away behind ZCML instead?
I will also repeat my observation that if a package has ZCML in it that
never gets loaded by the tests of that package, that means that there
are no automatic tests for this ZCML. There is something in this package
that is not tested and can only be tested indirectly. Isn't that
something we try to avoid?
What do we gain dependency-wise by avoiding the loading of ZCML during
tests but do manual registrations instead? We *may* get rid of
dependencies on zope.configuration. If the definition of ZCML directives
were always strictly separated from the functionality that these
directives manipulate, then this would often be the case. In reality
this is frequently not so, however. We may also get rid of such "ZCML
directive definition only" packages, for instance zope.componentzcml.
> Any ZCML file which needs something like zope.component or zope.security
> to be present should signalt that by either including the meta.zcml
> (e.g., to define directives) or nesting the dependent directives inside
> a "conditional" block, whose predicate documents the requirement.
You're saying that we should be an include of the zope.component
'meta.zcml' in *all* ZCML files that register an adapter? This is
certainly not happening always now. That's like import before usage in
Python modules, right?
I'll note that martian-based code actually does use that pattern - any
package based on grokcore.* for instance automatically follows this
pattern.
I'll also note that with martian-based configuration the situation is
clear for setup.py: the dependencies needed for configuration are always
normal dependencies of a package.
With ZCML-based configuration the situation is far less clear.
So what does all of this mean for Dan's question? I don't know yet.
I think we should observe some packages. We strive for library-like
packages. More library-like packages should likely not have to do a lot
of work in their configure.zcml, but the amount of work is not always
zero. Dan, do you have any examples of packages where you are wondering
about what to do? Let's examine then and reason about how they could be
organized.
Regards,
Martijn
More information about the Zope-Dev
mailing list