Skip to content

Commit

Permalink
MAINT: Compat for vtk 9.4
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner committed Dec 17, 2024
1 parent 40c6010 commit 57ab29d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 41 deletions.
47 changes: 23 additions & 24 deletions .github/workflows/run-mayavi-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,53 @@ jobs:
tests:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-13]
python-version: ['3.9']
qt-api: ['pyqt5']
vtk: ['vtk<9.3']
# Always test against the latest VTK, NumPy, and Qt bindings
os: [ubuntu-latest, windows-latest, macos-13, macos-15]
python-version: ['3.12']
qt-api: ['pyside6'] # prefer the modern bindings
vtk: ['vtk>=9.4'] # always prefer the latest
# Then add some backward compat checks
include:
- python-version: '3.12'
# PyQt6 and vtk 9.3
- python-version: '3.10'
qt-api: 'pyqt6'
os: ubuntu-latest
vtk: 'vtk>=9.3'
- python-version: '3.12'
vtk: 'vtk==9.3'
- python-version: '3.10'
qt-api: 'pyqt6'
os: macos-14 # arm64
vtk: 'vtk>=9.3'
- python-version: '3.12'
vtk: 'vtk==9.3'
- python-version: '3.10'
qt-api: 'pyqt6'
os: windows-latest
vtk: 'vtk>=9.3'
vtk: 'vtk==9.3'
- python-version: '3.11'
qt-api: 'pyqt6'
os: ubuntu-latest
vtk: 'vtk>=9.3'
- python-version: '3.10'
qt-api: 'pyside6'
vtk: 'vtk==9.3'
# PyQt5 and vtk 9.2 (and one oldest Python)
- python-version: '3.9'
qt-api: 'pyqt5'
os: ubuntu-latest
vtk: 'vtk<9.3'
vtk: 'vtk==9.2.5'
- python-version: '3.10'
qt-api: 'pyside6'
qt-api: 'pyqt5'
os: windows-latest
vtk: 'vtk<9.3'
vtk: 'vtk==9.2.5'
- python-version: '3.10'
qt-api: 'pyside6'
os: macos-13
vtk: 'vtk<9.3'
vtk: 'vtk==9.2.5'
# Some old NumPys
- python-version: '3.12'
qt-api: 'pyside6'
os: ubuntu-latest
vtk: 'vtk>=9.3'
vtk: 'vtk==9.3'
numpy: 'numpy==1.26.4'
- python-version: '3.12'
qt-api: 'pyside6'
os: windows-latest
vtk: 'vtk>=9.3'
numpy: 'numpy==2.0.2'
- python-version: '3.12'
qt-api: 'pyside6'
os: windows-latest
vtk: 'vtk>=9.3'
vtk: 'vtk==9.3'
numpy: 'numpy==1.26.4'
fail-fast: false
defaults:
Expand Down
6 changes: 4 additions & 2 deletions tvtk/code_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
..code-block:: console
$ python -m tvtk.code_gen -szvno $PWD/tvtk
$ VTK_PARSER_VERBOSE=1 python -m tvtk.code_gen -szvno $PWD/tvtk
On failures you can then for example do ``import pdb; pdb.pm()`` to do
post-mortem debugging.
post-mortem debugging. If there are segfaults, the VTK_PARSER_VERBOSE=1 should help
point to the culprit, which often needs to be worked around in
``vtk_parser.py::VTKMethodParser._find_get_set_methods``.
Exceptions to behaviors based on VTK versions and bugs etc. live in ``wrapper_gen.py``
and ``tvtk_parser.py``.
Expand Down
39 changes: 24 additions & 15 deletions tvtk/vtk_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@

import collections.abc
import re
import types
import os

# Local imports (these are relative imports for a good reason).
from . import class_tree
from . import vtk_module as vtk
from .common import is_version_9
from .common import vtk_major_version, vtk_minor_version


class VTKMethodParser:
Expand Down Expand Up @@ -632,7 +631,7 @@ def _find_get_set_methods(self, klass, methods):
# vtkProp.Get/SetAllocatedRenderTime is private and
# SetAllocatedRenderTime takes two args, don't wrap it.
continue
elif (not is_version_9()) and (
elif vtk_major_version < 9 and (
(klass_name == 'vtkGenericAttributeCollection' and
method[3:] == 'AttributesToInterpolate') or
(klass_name == 'vtkOverlappingAMR' and
Expand Down Expand Up @@ -668,20 +667,18 @@ def _find_get_set_methods(self, klass, methods):

# Find the default and range of the values.
if gsm:
if self._verbose:
print(f'Instantiating {klass}')
obj = self._get_instance(klass)
# print('got instance', obj.__class__)
if obj:
for key, value in gsm.items():
if not is_version_9() and (
if vtk_major_version < 9 and (
# Evil hack, these classes segfault!
(klass_name in ['vtkPolyData', 'vtkContext2D']) or
# On VTK 8.1.0 this segfaults when uninitialized.
(klass_name == 'vtkContextMouseEvent' and
key == 'Interactor')):
default = None
elif not is_version_9() and (
elif vtk_major_version < 9 and (
klass_name == 'vtkHyperOctree' and
key == 'Dimension'):
# This class breaks standard VTK conventions.
Expand All @@ -695,17 +692,26 @@ def _find_get_set_methods(self, klass, methods):
# vtkGenericAttributeCollection.GetAttributesToInterpolate
# might only be a problem if VTK is built in debug mode,
# but let's keep it just to be safe.
elif is_version_9() and (
elif vtk_major_version == 9 and (
# Still broken on 9.4
(klass_name == 'vtkHigherOrderTetra' and
key == 'ParametricCoords') or
key == 'ParametricCoords' and vtk_minor_version < 5) or
(klass_name == 'vtkGenericAttributeCollection' and
key == 'AttributesToInterpolate') or
key == 'AttributesToInterpolate' and vtk_minor_version < 4) or
(klass_name == 'vtkPlotBar' and
key == 'LookupTable') or
key == 'LookupTable' and vtk_minor_version < 4) or
(klass_name == 'vtkLagrangianParticleTracker' and
key == 'IntegrationModel') or
key == 'IntegrationModel' and vtk_minor_version < 4) or
False): # just to simplify indentation/updates
default = None

# vtkGenericCell().GetCellFaces() segfaults on 9.4
elif (
(vtk_major_version, vtk_minor_version) == (9, 4)
and klass_name == "vtkGenericCell"
and key == "CellFaces"
):
default = None
else:
try:
if self._verbose:
Expand All @@ -715,7 +721,7 @@ def _find_get_set_methods(self, klass, methods):
default = None

# If we don't turn these into integers, they won't instantiate
if is_version_9():
if vtk_major_version == 9:
if klass_name == "vtkAxisActor":
if key in (
"AxisOnOrigin", "Use2DMode", "UseTextActor3D",
Expand Down Expand Up @@ -765,7 +771,7 @@ def _find_get_methods(self, klass, methods):
meths.remove(method)
return meths

def _get_instance(self, klass):
def _get_instance(self, klass, *, do_print=True):
"""Given a VTK class, `klass`, returns an instance of the
class.
Expand All @@ -774,6 +780,8 @@ def _get_instance(self, klass):
the 'state' methods and the ranges for the Get/Set methods.
"""
if self._verbose and do_print:
print(f'Instantiating {klass}')
obj = None
try:
obj = klass()
Expand All @@ -783,7 +791,8 @@ def _get_instance(self, klass):
n = t.get_node(klass.__name__)
if n is not None:
for c in n.children:
obj = self._get_instance(t.get_class(c.name))
obj = self._get_instance(t.get_class(c.name), do_print=False)
if obj:
print(f" Using super {t.get_class(c.name)} instead of {klass}")
break
return obj

0 comments on commit 57ab29d

Please sign in to comment.