[Zope-dev] Buglet in Zope, or Bug in Python, you decide...

R. David Murray bitz@bitdance.com
Mon, 24 Jun 2002 21:11:57 -0400 (EDT)


Zope 2.5.1, Python 2.2.1 (yes, I know it's not supported yet <grin>).

I just spent a day tracking down a weird initialization problem
in Zope2.  If you have the following circumstances:

1) an instance of a calss from a Product already in the ZODB
2) your Product 'initialize' uses __import___ to do the import
	of the module containing the class that defines the instance
3) you introduce a bug into the module imported via __import__

then the end result is that the bug in the imported module is
completely swallowed.


The possible Zope buglet:

This happens because the ClassFactory does a bare try/except when
importing the module needed to resucitate the existing object.
This is a reasonable thing for it to do:  if the import fails
for *any* reason it marks the object as broken. It then
logs an error.

I did not, by the way, to figure out why the object got activated
before the install_products call (it was in the top level folder;
that may have something to do with it), but pretty much anything
that touched the Control_Panel (or maybe even app itself) triggered
the load.  I didn't try very hard to figure out why this was
happening.

When install_products *does* later run, in normal situations
the product install triggers the same error that ClassFactory saw,
and the developer gets to see the traceback for the bug
he introduced.  But because of the semantics of __import__
(see below), if __import__ was used to load the module-with-bug,
the traceback will *not* happen; and likely some other
error will instead, because the module was not completely loaded.

(NB: It took longer for me to find this bug than it should
have because I forgot to delete my Product from the Control_Panel;
because it was still in there from when it had been working,
ClassFactory did not print it's helpful error message.
I don't know why it didn't, and have not tried to find out).

To fix this theoretical buglet, it might be appropriate for
ClassFactory to log the error rather than just a generic "can't
load" error message.  Yes, normal errors will then appear in
stupid_log twice, but I'd rather two copys of a traceback than a
misleading one.


The Possible Python Bug:

The, um, interesting semantics of __import__ are demonstrated by
this short test program:

test.py
-------
try: module = __import__('test2')
except: pass
module = __import__('test2')
print dir(module)

test2.py
--------
aaa = 'bbb'
raise KeyError
bbb = 'ccc'

If you do 'import test' from the python shell, you will see that
you get no traceback from the second __import__, and further that
'aaa' and only 'aaa' is in the resulting module's __dict__.

It seems to me that this is a bug, but since __import__ is
normally-behind-the-scenes magic, there may be a good reason
for it.  However, if that is the case, how can I check,
when doing an __import__, that I've gotten a valid module?


Concluding Question:

So, which bug tracker does this one go in, zope's or python's?

--RDM