Misleading exception handling in nodes.py

33 views
Skip to first unread message

Ryszard Kubiak

unread,
Jun 13, 2015, 4:23:55 PM6/13/15
to sphin...@googlegroups.com
Hello Sphinx Developers,

I am writing after spending several days on searching an error in my Sphinx extension. The latex writer reported that some of my .rst files did not exist. I discovered that in all of the problematic files a directive of my own was used. The html writer didn't signal any problems with them.
I knew that there was something wrong about my code but also that the Sphinx's error messages were misleading.

My erroneous directive generate a node of a class 'div_box' of myself, based on docutils's container:

  class div_box(nodes.container):

I wrote the __init__ like this: 

  def __init__(self, container_class):
      nodes.container.__init__(self)
      self.container_class = container_class

With __init__ so defined Sphinx's method 'inline_all_toctrees' from nodes.py raises an exception. The exception comes from within 'tree.deepcopy()'.
That deepcopy is a Sphinx method. It is written a generic style which is OK. Still, there bmay be problems with classes defined using multiple inheritance. And, the 'container' class inherits after General and Element. My __init__ should be given more arguments, as the Element.__init__  expects.

Apparently, it was my fault. Still, I also think that Sphinx's way the exception raised by 'deepcopy' is handled is misleading.  This is how it's done:

   except Exception:
       builder.warn('toctree contains ref to nonexisting '
           'file %r' % includefile,
           builder.env.doc2path(docname))

Whatever the reason of the exception is Sphinx reports that a file does not exist. I had to print the actual exception message in order to learn where the problem was.

   except Exception as detail:
       print "Exception detail", detail
       builder.warn('toctree contains ref to nonexisting '
           'file %r' % includefile,
           builder.env.doc2path(docname))

I suggest extending the error message with the actual exception cause.

Best Regards,
Ryszard



Matthias Geier

unread,
Dec 7, 2015, 12:57:14 PM12/7/15
to sphinx-dev
Dear list.

I had the same problem as Ryszard (see below).

It would be very helpful to change the exception message "toctree contains ref to nonexisting ..." in this case.

After some desperate searching I've found this message, and thanks to it, I managed to get my class working by adding (unused) *args and **kwargs to my __init__() method.

This made me wonder: is it discouraged to add __init__() to a custom node class?

I had a related problem when I created a new child node in the __init__() method of my node class. It seems that deepcopy() calls __init__() again and I ended up with two copies of the children node instead of one.

I worked around this by implementing a classmethod for creating instances of my node class, but IMHO it would be much clearer to put this kind of initialization into the __init__() method.

But probably I'm misunderstanding how custom node classes are supposed to be used ...

I created a custom class to wrap a literal_block node, because I wanted to have the original visit/depart function from literal_block and also custom visit/depart functions on top of that.

Is there a better way to "extend" a node (like the literal_block node) with custom visit/depart functions?

cheers,
Matthias
Reply all
Reply to author
Forward
0 new messages