[Zope3-dev] Nasty bugs

Guido van Rossum guido@python.org
Wed, 20 Mar 2002 02:52:17 -0500


I wondered, "why does the z3 root view display a broken image for
Folders?"

There's no single answer.  I found several bugs.  I don't know how to
fix them.

(1) The page template used,
    Zope3/lib/python/Zope/App/OFS/Folder/main.pt
    contains this text:

  	  <img alt="Folder" src="../../ZMI/www/folder_icon.gif"
 	       tal:condition="info/url"
 	       tal:attributes="src info/url" />

    which I believe is a cut-and-paste error, and should really be

  	  <img alt="Folder" src="../../ZMI/www/folder_icon.gif"
 	       tal:condition="info/icon"
 	       tal:attributes="src info/icon" />

(2) When I fixed that in my copy, I got a traceback, ending in
    "TypeError: len() of unsized object" in method evaluateBoolean()
    in class Context in module TALES, file
    Zope3/lib/python/Zope/PageTemplate/TALES.py (sorry, lost the lineno).
    Casual printing of the evaluation outcome showed that it was doing
    "not not None", which shouldn't trigger this error.
    Printing of its type showed that it's really a wrapper for None,
    and that using it in a Boolean context causes this error.
    Two questions come up:

    (2a) Why would None need to be wrapped?

    (2b) Why can't I use a wrapped None in a Boolean context?

    I can't answer (2a), but I understand (2b): the wrapper code
    supports sequence and mapping methods, but not numeric methods.
    Thus, when the wrapper is passed to PyObject_IsTrue(), its mapping
    or sequence length method is called, which calls PyObject_Length()
    on the wrapped object, which fails.

    I'm not sure how to fix this, short of adding an as_number
    structure to the wrapper type and only filling in the nb_nonzero
    slot.  I'm mailing Fred because AFAIK he wrote this code.
    (I did a quick hack which catches the error in wrap_length() and
    returns 0 instead, but that's obviously not right.)

    It's also possible that the answer to (2a) provides the fix,
    i.e. that None shouldn't have been wrapped.  I didn't pursue this.

    (A workaround in Python is to change evaluateBoolean() to first
    compare the outcome of evaluate() to None using "==", and if so,
    return 0.  But that seems fixing the symptom rather than the
    cause.)

(3) Looking carefully at the traceback, I noticed a strange warning
    inserted, in bold, under the pt_render entry:

       Warning: Macro expansion failed
       Warning: exceptions.TypeError: pt_render() takes at least 2
       non-keyword arguments (1 given)

    Tracking this down led me to the pt_errors() method in class
    PageTemplate in file
    Zope3/lib/python/Zope/PageTemplate/PageTemplate.py

    This is invoked during the traceback printing (via the
    PageTemplateTracebackSupplement class at the end of that file, an
    instance of which is stored in __traceback_supplement__ in
    pt_render(), as a special magic cookie for the traceback printing
    code).

    Note that the warning above complains about the call to
    pt_render() rather than (as it is supposed to do) showing the
    template source.  It looks like the signature for pt_render() has
    changed; cvs log shows this entry:

      ----------------------------
      revision 1.1.2.10
      date: 2002/02/01 22:09:21;  author: fdrake;  state: Exp;  lines: +36 -60
      Simplify the PageTemplate base class, restoring the ability to
      use it outside of the Zope application server.
      Added some information on how to subclass to the class docstring.
      Moved some of the helper classes to other modules, where they
      are actually needed (for Zope-specific behavior.
      ----------------------------

   (This is why Fred gets two copies of this mail. :-)  It seems that
   the pt_render() call in pt_error() is no longer valid, because it
   doesn't pass the positional namespace argument.

   There's one other call to pt_render() in the same file with the
   same problem; the function read() also tries to expand the macro
   source without supplying a namespace.  I tried various ways of
   supplying a default namespace but everything I tried immediately
   caused an evaluation error because something was missing from the
   namespace.

I could fix the bug in (1), but then the cure would be worse than
the problem (you'd get a traceback from the front page instead of a
broken image icon).

Please advise.

--Guido van Rossum (home page: http://www.python.org/~guido/)