Skip to content

Commit 1c2a50f

Browse files
authored
Make VTK optional again (#4713)
VTK releases are sporadic so when macOS eagerly upgrades to a new Python version it breaks our install for some time.
1 parent 9f624cb commit 1c2a50f

File tree

5 files changed

+45
-7
lines changed

5 files changed

+45
-7
lines changed

docs/source/install.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,20 @@ To install Firedrake with SLEPc support you should:
426426

427427
$ pip install --no-binary h5py 'firedrake[check,slepc]'
428428

429+
VTK
430+
~~~
431+
432+
To install Firedrake with VTK, it should be installed using the ``vtk`` optional
433+
dependency. For example::
434+
435+
$ pip install --no-binary h5py 'firedrake[check,vtk]'
436+
437+
.. warning::
438+
439+
VTK make releases sporadically so will not always support the latest version
440+
of Python. This is commonly an issue on macOS where homebrew will use the
441+
latest Python very soon after it is released. To fix this you should use
442+
an older version of Python (e.g. 3.13 instead of 3.14).
429443

430444
PyTorch
431445
~~~~~~~

firedrake/output/vtk_output.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ def get_array(function):
347347
return array
348348

349349

350-
class VTKFile(object):
350+
class VTKFile:
351351
_header = (b'<?xml version="1.0" ?>\n'
352352
b'<VTKFile type="Collection" version="0.1" '
353353
b'byte_order="LittleEndian">\n'

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ dependencies = [
4242
"scipy",
4343
"sympy",
4444
"islpy>=2025.1.5; sys_platform == 'darwin'",
45-
"vtk",
4645
]
4746
classifiers = [
4847
"Development Status :: 5 - Production/Stable",
@@ -85,6 +84,7 @@ docs = [
8584
"sphinxcontrib-svg2pdfconverter",
8685
"sphinxcontrib-youtube",
8786
"sphinx-copybutton",
87+
"vtk", # needed to resolve API
8888
]
8989
jax = [
9090
"jax",
@@ -98,6 +98,9 @@ slepc = [
9898
torch = [ # requires passing '--extra-index-url' to work
9999
"torch",
100100
]
101+
vtk = [
102+
"vtk",
103+
]
101104

102105
# Dependencies needed to run the full test suite
103106
ci = [
@@ -117,6 +120,7 @@ ci = [
117120
"pytest-xdist",
118121
"slepc4py==3.24.0",
119122
"torch", # requires passing '--extra-index-url' to work
123+
"vtk",
120124
]
121125
docker = [ # Used in firedrake-vanilla container
122126
"ipympl", # needed for notebook testing
@@ -132,6 +136,7 @@ docker = [ # Used in firedrake-vanilla container
132136
"pytest-timeout",
133137
"pytest-xdist",
134138
"slepc4py==3.24.0",
139+
"vtk",
135140
]
136141

137142
[build-system]

tests/firedrake/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ def _skip_test_dependency(dependency):
6868
except ImportError:
6969
return skip
7070

71+
elif dependency == "vtk":
72+
try:
73+
import vtk # noqa: F401
74+
del vtk
75+
return not skip
76+
except ImportError:
77+
return skip
78+
7179
elif dependency in ("mumps", "hypre"):
7280
return dependency not in get_external_packages()
7381

@@ -83,6 +91,8 @@ def _skip_test_dependency(dependency):
8391
("jax", "skipjax", "JAX is not installed"),
8492
("matplotlib", "skipplot", "Matplotlib is not installed"),
8593
("netgen", "skipnetgen", "Netgen and ngsPETSc are not installed"),
94+
("vtk", "skipvtk", "VTK is not installed"),
95+
8696
)
8797

8898

@@ -118,6 +128,10 @@ def pytest_configure(config):
118128
"markers",
119129
"skipslepc: mark as skipped if slepc4py is not installed"
120130
)
131+
config.addinivalue_line(
132+
"markers",
133+
"skipvtk: mark as skipped if vtk is not installed"
134+
)
121135
config.addinivalue_line(
122136
"markers",
123137
"skiptorch: mark as skipped if PyTorch is not installed"

tests/firedrake/output/test_pvd_output.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,13 @@ def pvd(dumpdir):
4242
return VTKFile(f)
4343

4444

45+
@pytest.mark.skipvtk
46+
@pytest.mark.parallel([1, 3])
4547
def test_can_save_coordinates(mesh, pvd):
4648
pvd.write(mesh.coordinates)
4749

4850

49-
@pytest.mark.parallel
50-
def test_can_save_coordinates_parallel(mesh, pvd):
51-
pvd.write(mesh.coordinates)
52-
53-
51+
@pytest.mark.skipvtk
5452
@pytest.mark.parametrize("typ",
5553
["vector", "tensor", "tensor-3"])
5654
def test_bad_shape(typ, mesh, pvd):
@@ -67,11 +65,13 @@ def test_bad_shape(typ, mesh, pvd):
6765
pvd.write(f)
6866

6967

68+
@pytest.mark.skipvtk
7069
def test_bad_file_name(tmpdir):
7170
with pytest.raises(ValueError):
7271
VTKFile(str(tmpdir.join("foo.vtu")))
7372

7473

74+
@pytest.mark.skipvtk
7575
@pytest.mark.parametrize("space",
7676
["primal", "dual"])
7777
def test_different_functions(mesh, pvd, space):
@@ -89,6 +89,7 @@ def test_different_functions(mesh, pvd, space):
8989
pvd.write(g)
9090

9191

92+
@pytest.mark.skipvtk
9293
def test_multiple_functions(mesh, pvd):
9394
V = FunctionSpace(mesh, "DG", 0)
9495
P = FunctionSpace(mesh, "CG", 1)
@@ -104,6 +105,7 @@ def test_multiple_functions(mesh, pvd):
104105
pvd.write(g, f)
105106

106107

108+
@pytest.mark.skipvtk
107109
def test_different_meshes(mesh, pvd):
108110
V = VectorFunctionSpace(mesh, "DG", 1)
109111
f = Function(V)
@@ -114,6 +116,7 @@ def test_different_meshes(mesh, pvd):
114116
pvd.write(mesh.coordinates, mesh2.coordinates)
115117

116118

119+
@pytest.mark.skipvtk
117120
def test_bad_cell(pvd):
118121
mesh = UnitCubeMesh(1, 1, 1)
119122
mesh = ExtrudedMesh(mesh, layers=1)
@@ -122,6 +125,7 @@ def test_bad_cell(pvd):
122125
pvd.write(mesh.coordinates)
123126

124127

128+
@pytest.mark.skipvtk
125129
def test_not_function(mesh, pvd):
126130
c = Constant(1)
127131
with pytest.raises(ValueError):
@@ -134,6 +138,7 @@ def test_not_function(mesh, pvd):
134138
pvd.write(grad(f))
135139

136140

141+
@pytest.mark.skipvtk
137142
@pytest.mark.parametrize("space",
138143
["primal", "dual"])
139144
def test_append(mesh, tmpdir, space):

0 commit comments

Comments
 (0)