Skip to content

Commit

Permalink
MAINT: Fix various VTK-9.4 related issues.
Browse files Browse the repository at this point in the history
This fixes TVTK build and test issues.
  • Loading branch information
prabhuramachandran committed Dec 18, 2024
1 parent a405de1 commit 7483790
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 34 deletions.
18 changes: 8 additions & 10 deletions docs/source/tvtk/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,19 +260,17 @@ tvtk wrapper object is created. The following illustrates this::
>>> cs = tvtk.ConeSource()
>>> o = cs.output
>>> m = tvtk.PolyDataMapper()
>>> m.input = o
>>> print(hash(o))
1109012188
>>> print(hash(m.input))
1109012188
>>> m.input_connection = cs.output_port
>>> print(id(o))
126526931186080
>>> print(id(m.input))
126526931186080
>>> del o
>>> print(hash(m.input))
1119694156
>>> print(id(m.input))
126526931186080

Thus, after `o` is garbage collected `m.input` no longer refers to the
original tvtk object and a new one is created. This is very similar
to VTK's behaviour. Changing this behaviour is tricky and there are no
plans currently to change this.
original tvtk object the old one is cached and returned.


tvtk and traits
Expand Down
7 changes: 4 additions & 3 deletions tvtk/code_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def generate_code(self):
# Write the wrapper files.
tree = wrap_gen.get_tree().tree

classes = []
classes = ['vtkObjectBase']
# This is another class we should not wrap and exists
# in version 8.1.0.
ignore = ['vtkOpenGLGL2PSHelperImpl'] + [
Expand All @@ -124,11 +124,12 @@ def generate_code(self):
if (name not in include and not name.startswith('vtk')) or \
name.startswith('vtkQt'):
continue
if not hasattr(vtk, name) or not hasattr(getattr(vtk, name), 'IsA'): # noqa
if not hasattr(vtk, name) or \
not hasattr(getattr(vtk, name), 'AddObserver'): # noqa
# We need to wrap VTK classes that are derived
# from vtkObjectBase, the others are
# straightforward VTK classes that can be used as
# such. All of these have an 'IsA' method so we
# such. All of these have an 'AddObserver' method so we
# check for that. Only the vtkObjectBase
# subclasses support observers etc. and hence only
# those make sense to wrap into TVTK.
Expand Down
10 changes: 5 additions & 5 deletions tvtk/messenger.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def connect(self, obj, event, callback):
"""
typ = type(callback)
key = hash(obj)
key = id(obj)
if not key in self._signals:
self._signals[key] = {}
signals = self._signals[key]
Expand Down Expand Up @@ -200,7 +200,7 @@ def disconnect(self, obj, event=None, callback=None, obj_is_hash=False):
if obj_is_hash:
key = obj
else:
key = hash(obj)
key = id(obj)
if not key in signals:
return
if callback is None:
Expand Down Expand Up @@ -282,11 +282,11 @@ def _get_signals(self, obj):
object.
"""
ret = self._signals.get(hash(obj))
ret = self._signals.get(id(obj))
if ret is None:
raise MessengerError(
"No such object: %s, has registered itself "\
"with the messenger."%obj
"No such object: %s, has registered itself "
"with the messenger." % obj
)
else:
return ret
Expand Down
4 changes: 2 additions & 2 deletions tvtk/pipeline/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ class TVTKLeafNode(TreeNodeObject):
__ = Python

def __hash__(self):
return hash(tvtk.to_vtk(self.object))
return id(tvtk.to_vtk(self.object))

def _get_name(self):
return self.object.__class__.__name__
Expand Down Expand Up @@ -496,7 +496,7 @@ def __del__(self):
pass

def __hash__(self):
return hash(tvtk.to_vtk(self.object))
return id(tvtk.to_vtk(self.object))

def _get_children_from_cache(self):
return [x for x in self.children_cache.values() if x is not None]
Expand Down
4 changes: 2 additions & 2 deletions tvtk/tests/test_messenger.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ def foo(self, o, e):
# Test if things behave sanely if a message was sent and one
# of the callbacks has been gc'd.
m = messenger.Messenger()
l1 = len(m._signals[hash(c1)]['foo'])
l1 = len(m._signals[id(c1)]['foo'])
#
del c
messenger.send(c1, 'foo')
#
l2 = len(m._signals[hash(c1)]['foo'])
l2 = len(m._signals[id(c1)]['foo'])
# Since 'c' is gc'd this callback should have been cleared
# out.
self.assertEqual(l2, l1 - 1)
Expand Down
27 changes: 16 additions & 11 deletions tvtk/tests/test_tvtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,22 +202,22 @@ def test_help_trait(self):
def test_object_cache(self):
"""Test if object cache works."""
cs = tvtk.ConeSource()
hash1 = hash(cs)
hash1 = id(cs)
o = cs.output
if hasattr(o, 'producer_port'):
src = o.producer_port.producer
else:
src = cs.executive.algorithm
self.assertEqual(src, cs)
self.assertEqual(hash1, hash(src))
self.assertEqual(hash1, id(src))
del cs, src
gc.collect()
# The test sometimes fails as VTK seems to generate objects with the
# same memory address and hash, we try to force it to allocate more
# objects so as to not end up reusing the same address and hash.
# same memory address and hash/id, we try to force it to allocate more
# objects so as to not end up reusing the same address and id.
junk = [tvtk.ConeSource() for i in range(50)]

# Now get another ConeSource and ensure the hash is different.
# Now get another ConeSource and ensure the id is different.
cs = tvtk.ConeSource()
o = cs.output
if hasattr(o, 'producer_port'):
Expand All @@ -230,8 +230,8 @@ def test_object_cache(self):
# For VTK 5.x this test is inconsistent, hence skipeed for 5.x
# See http://review.source.kitware.com/#/c/15095/
##############################################################
self.assertEqual(hash1 != hash(src), True)
self.assertEqual(hash(cs), hash(src))
self.assertEqual(hash1 != id(src), True)
self.assertEqual(id(cs), id(src))

# Test for a bug with collections and the object cache.
r = tvtk.Renderer()
Expand Down Expand Up @@ -565,7 +565,7 @@ def test_information_keys(self):
s = tvtk.StructuredPoints()
x = s.FIELD_ARRAY_TYPE()
y = tvtk.Information()
x.get(y)
y.get(x)

def test_parent_child_bounds(self):
"""CubeAxesActor2D's bounds should be writable."""
Expand Down Expand Up @@ -858,7 +858,13 @@ def get_min_max_value(vtk_klass, vtk_attr_name):
for name in self.names:
vtk_klass = getattr(vtk, name)
tvtk_klass_name = get_tvtk_name(name)

if vtk.vtk_version == '9.4.0':
if tvtk_klass_name.endswith('View'):
continue
if tvtk_klass_name in ['ImageViewer', 'ImageViewer2',
'OpenGLRenderWindow',
'RenderWindow']:
continue
try:
obj = getattr(tvtk, tvtk_klass_name)()
except Exception:
Expand All @@ -882,8 +888,7 @@ def get_min_max_value(vtk_klass, vtk_attr_name):
# tvtk.tvtk_classes.open_gl_cell_grid_render_request.shapes_to_draw
# uses strings
if isinstance(min_value, str):
name = "tvtk.tvtk_classes.open_gl_cell_grid_render_request"
assert name in repr(obj), (obj, trait_name)
assert 'cell_grid_render_request' in repr(obj), (obj, trait_name)
continue
with self.assertRaises(TraitError):
setattr(obj, trait_name, (min_value-1, max_value))
Expand Down
10 changes: 9 additions & 1 deletion tvtk/vtk_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@
try:
del vtkDGBoundsResponder, vtkDGOpenGLRenderer, vtkDGSidesResponder
except NameError:
pass
pass

if vtk_version == '9.4.0':
# Instantiating these using TVTK causes a crash on VTK 9.4.0 so skipping.
SKIP = ['vtkIOSSReader', 'vtkIOSSCellGridReader']
try:
del vtkIOSSReader, vtkIOSSCellGridReader
except NameError:
pass
18 changes: 18 additions & 0 deletions tvtk/wrapper_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,11 @@ def _write_trait_with_range(self, klass, out, vtk_attr_name):
'vtkLineIntegralConvolution2D.MaxNoiseValue$': (
True, True, '_write_line_integral_conv_2d_max_noise_value'
),
# In VTK 9.4, CellGridSidesQuery's Get/OutputDimensionControl is initialized
# to some random value this happens mostly on MacOS.
'vtkCellGridSidesQuery.OutputDimensionControl$': (
True, True, '_write_cell_grid_sides_query_od_control'
),
# In VTK 9.3, vtkCylinderSource's GetLatLongTesselation gives random values
# https://gitlab.kitware.com/vtk/vtk/-/issues/19252
'vtkCylinderSource.LatLongTessellation$': (
Expand Down Expand Up @@ -1927,6 +1932,19 @@ def _write_line_integral_conv_2d_max_noise_value(
vtk_set_meth = getattr(klass, 'Set' + vtk_attr_name)
self._write_trait(out, name, t_def, vtk_set_meth, mapped=False)

def _write_cell_grid_sides_query_od_control(self, klass, out, vtk_attr_name):
if vtk_attr_name != 'OutputDimensionControl':
raise RuntimeError(f"Wrong attribute name: {vtk_attr_name}")
if vtk_major_version >= 9:
message = ("vtkCellGridSidesQuery: "
"OutputDimensionControl not updatable "
"(VTK 9.4 bug - value not properly initialized)")
print(message)
t_def = 'tvtk_base.true_bool_trait'
name = self._reform_name(vtk_attr_name)
vtk_set_meth = getattr(klass, 'Set' + vtk_attr_name)
self._write_trait(out, name, t_def, vtk_set_meth, mapped=True)

def _write_cylinder_source_lat_long_tessellation(
self, klass, out, vtk_attr_name
):
Expand Down

0 comments on commit 7483790

Please sign in to comment.