[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