etetoolkit / ete

Python package for building, comparing, annotating, manipulating and visualising trees. It provides a comprehensive API and a collection of command line tools, including utilities to work with the NCBI taxonomy tree.
http://etetoolkit.org
GNU General Public License v3.0
773 stars 216 forks source link

Ete3 show crashes because AttrFace does not load the _bounding_rect attribute #681

Closed Gullumluvl closed 1 year ago

Gullumluvl commented 1 year ago

I am using Python 3.10 and:

It think that the correct test ete3/treeview/faces#L372 in AttrFace.get_bounding_rect() should be:

if current_text != self._bounding_rect_text or not self._bounding_rect_text:

Reproduce:

Trying to show a tree with an AttrFace triggers the fatal error:

import ete3

tree = ete3.Tree('((a,b)x,c)r;', format=1)
nameface = ete3.faces.AttrFace('name')

def mylayout(node):
    ete3.faces.add_face_to_node(nameface, node, column=0)

tree.show(mylayout) 
  File "/usr/local/lib/python3.10/dist-packages/ete3/coretype/tree.py", line 1363, in show
    drawer.show_tree(self, layout=layout,
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/drawer.py", line 76, in show_tree
    tree_item, n2i, n2f = render(t, img)
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/qt4_render.py", line 268, in render
    update_node_faces(n, n2f, img)
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/qt4_face_render.py", line 389, in update_node_faces
    faceblock[position] = _FaceGroupItem(all_faces, node, as_grid=as_grid)
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/qt4_face_render.py", line 101, in __init__
    self.update_columns_size()
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/qt4_face_render.py", line 143, in update_columns_size
    width = f._width() + f.margin_right + f.margin_left
  File "/usr/local/lib/python3.10/dist-packages/ete3/treeview/faces.py", line 332, in _width
    return self.get_bounding_rect().width()
AttributeError: 'NoneType' object has no attribute 'width'

In my case it occured when both current_text and self._bounding_rect_text equal "", causing _load_bounding_rect to be skipped.

Other possible bug, maybe related:

At the lines 308 and 313, I believe the intended test should be:

 if self._bounding_rect is None:
 # instead of: 'if not self._bounding_rect'

because QRectF evaluates as False when it has a null width or height (occurs when current_text is "").

Gullumluvl commented 1 year ago

Looks like it's solved in release 3.1.3. Thanks.