Chris McDonough wrote:
> Martijn Faassen wrote:
>> 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.
> Can you provide an example? In my own libraries, very rarely does this
> I tend to only depend on components like this "at the edges"; eg. in I only
> to allow pluggability via the CA within an application or a framework, very
> rarely in a straight library.
Maybe because unlike you I don't know the difference between a framework
and a library very well. :)
Allows you to set up a utility that integrates with SQLAlchemy's scoped
session so you can have one database configuration per Zope site. This
is explicitly to support local configuration, but in order to use
SQLAlchemy at all in this way the utility has got to be there in some form.
Requires a utility ICurrentNeededInclusions to exist that somehow
maintains the resource inclusions that are needed (for instance on the
request object, but that's up to the utility).
Also needs a ILibraryUrl adapter to be defined on a resource in order to
render the URL for a resource.
A 'Relation' field for zope.schema that gets tracked by the zc.relation
Sets up a bunch of event handlers on IHasOutgoingRelations and
IHasIncomingRelations. If you define those interfaces on your objects
and use the Relation field in your schema, those relations are tracked.
Exporting zope.schema-driven content as XML and importing XML into an
object again. Offers a simple API to do this.
Registers a whole bunch of adapters for particular schema fields that
know how to import and export attributes on objects that implement this
> But if somehow it does happen, and I need to test the library, and the library
> relies on some utility external to itself being registered, I'll register a
> "dummy" utility for purposes of testing. I'll never use a "real"
> of the component during *unit* testing (although during integration testing
> use the real one instead of the dummy one of course).
Yes, I frequently do this, and frequently I load the ZCML (or grok
Anyway, we're not so interested in that distinction here, right? If the
library does integration testing (testing the real component also
defined by that library), this will need to be reflected in the
dependencies just like anything else.
>> 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.
> Minor nit: the configure.zcml won't *provide* any default implementation, but
> might point at one. This implementation may or may not live in the package
> the configure.zcml lives in.
Sure, yes, it registers it. In case the case of grokked libraries, it
provides *and* indicates the desire to do registration in the same place
(typically the python class).
> If some library comes along that thinks it knows enough to register mandatory
> arbitrary CA configuration, I'll classify it along with the Python stdlib
> "logging" module (which registers "atexit" handlers) or asyncore dispatchers
> (whose constructors register the dispatcher with a socket map); these
> tend to be wrong about the configuration they register under some circumstance
> and it probably would have been better for their authors to do less, pushing
> configuration more into some glue package or the application that uses them
> rather than down into the library itself. That would offer maximum
This argument works for hurry.resource and z3c.saconfig, where people
are expected to do their own registrations.
It doesn't work for z3c.relationfield:
If my library informs people that if they make their schema inherit
IOutgoingRelations they can use Relation fields on it and any objects
that implement that schema be tracked by a relation index automatically,
I can't really say that the event handlers are somehow "wrong" and
someone else would like to override them. People could hook up the event
handlers again for their own interfaces, sure, but the original ones
aren't in the way.
It also doesn't work for z3c.schema2xml:
The library's adapter registrations that know how to export a Text field
aren't somehow in the way and it'd be a major pain to request people to
reregister all these adapters themselves in an application. You can
still override this registration just fine as well.
> In particular, I'm pretty sure that to be maximally useful outside a Zope
> context (which may or may not be desireable for the maintainer), library
> packages should probably be broken up into two pieces: a piece that is a
> straight Python library that contains no ZCML, then some "glue" package that
> provides both an API to use the library in a Zope context along with
> some ZCML that is meant to be loaded by an application.
z3c.relationfield expects quite a few Zope-ish things to be around
(containers, zc.relation), so it doesn't really have the goal to be
useful outside a significantly non-Zope context.
z3c.schema2xml however is potentially very useful outside of a Zope
context, and it'd be overkill to split it up into a straight Python
library that contains no registrations and some glue package that then
does the registrations. Its use of the configuration system makes sense,
as you can easily plug into it to allow it to export other schema fields
it may not know about.
>> 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?
> No. He's saying that an application that makes use of some ZCML by inclusion
> from some package may need to load some metaconfiguration before the included
> file can be successfully used.
No. :) He said that any ZCML file which needs something like
zope.component to be present should signal that by either including the
meta.zcml of zope.component or by conditionally including it.
You're saying something else that fits the way ZCML has been in use from
the start, but Tres expressed himself very badly if he said the same thing.
>> 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
> I'll throw something out there: if a package *requires* configuration via ZCML
> to operate properly, I don't think it's really just a library (in the common
> Python sense). Instead, I think its either a framework itself or some plugin
> a framework. OTOH, if it just offers up some default configuration that
> be used to use the software, it might be a library.
Is this distinction useful in answering Dan's question?
In practice you could say that if the tests don't need the ZCML, then
the ZCML dependencies (zope.configuration, zope.componentzcml) shouldn't
be in the dependencies. If it does, they should be. :)
[snip my own analysis on whether the examples I gave above are libraries
or frameworks or neither or both; it's a side-track]
Zope-Dev maillist - Zope-Dev@zope.org
** No cross posts or HTML encoding! **
(Related lists -