Skip to content

Commit 046cd46

Browse files
authored
Merge pull request matplotlib#24522 from ianthomas23/pybind11_tri_module
Use pybind11 for tri module
2 parents ab3d63d + 5360353 commit 046cd46

File tree

10 files changed

+306
-676
lines changed

10 files changed

+306
-676
lines changed

.appveyor.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ branches:
1111

1212
clone_depth: 50
1313

14+
image: Visual Studio 2017
15+
1416
environment:
1517

1618
global:

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ jobs:
4242
# https://github.com/jazzband/pip-tools/pull/1681
4343
python -m pip install --upgrade \
4444
certifi contourpy cycler fonttools kiwisolver importlib_resources \
45-
numpy packaging pillow pyparsing python-dateutil setuptools-scm
45+
numpy packaging pillow pyparsing python-dateutil setuptools-scm \
46+
pybind11
4647
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
4748
4849
- name: Initialize CodeQL

.github/workflows/tests.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ jobs:
170170
-r requirements/testing/all.txt \
171171
${{ matrix.extra-requirements }}
172172
173+
# Preinstall pybind11 on no-build-isolation builds.
174+
if [[ "${{ matrix.name-suffix }}" == '(Minimum Versions)' ]]; then
175+
python -m pip install 'pybind11>=2.6'
176+
fi
177+
173178
# Install optional dependencies from PyPI.
174179
# Sphinx is needed to run sphinxext tests
175180
python -m pip install --upgrade sphinx

lib/matplotlib/tests/test_triangulation.py

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,29 @@ def test_triangulation_init():
7272
mtri.Triangulation(x, y, [[0, 1, -1]])
7373

7474

75+
def test_triangulation_set_mask():
76+
x = [-1, 0, 1, 0]
77+
y = [0, -1, 0, 1]
78+
triangles = [[0, 1, 2], [2, 3, 0]]
79+
triang = mtri.Triangulation(x, y, triangles)
80+
81+
# Check neighbors, which forces creation of C++ triangulation
82+
assert_array_equal(triang.neighbors, [[-1, -1, 1], [-1, -1, 0]])
83+
84+
# Set mask
85+
triang.set_mask([False, True])
86+
assert_array_equal(triang.mask, [False, True])
87+
88+
# Reset mask
89+
triang.set_mask(None)
90+
assert triang.mask is None
91+
92+
msg = r"mask array must have same length as triangles array"
93+
for mask in ([False, True, False], [False], [True], False, True):
94+
with pytest.raises(ValueError, match=msg):
95+
triang.set_mask(mask)
96+
97+
7598
def test_delaunay():
7699
# No duplicate points, regular grid.
77100
nx = 5
@@ -1166,55 +1189,62 @@ def test_internal_cpp_api():
11661189
# C++ Triangulation.
11671190
with pytest.raises(
11681191
TypeError,
1169-
match=r'function takes exactly 7 arguments \(0 given\)'):
1192+
match=r'__init__\(\): incompatible constructor arguments.'):
11701193
mpl._tri.Triangulation()
11711194

11721195
with pytest.raises(
11731196
ValueError, match=r'x and y must be 1D arrays of the same length'):
1174-
mpl._tri.Triangulation([], [1], [[]], None, None, None, False)
1197+
mpl._tri.Triangulation([], [1], [[]], (), (), (), False)
11751198

11761199
x = [0, 1, 1]
11771200
y = [0, 0, 1]
11781201
with pytest.raises(
11791202
ValueError,
11801203
match=r'triangles must be a 2D array of shape \(\?,3\)'):
1181-
mpl._tri.Triangulation(x, y, [[0, 1]], None, None, None, False)
1204+
mpl._tri.Triangulation(x, y, [[0, 1]], (), (), (), False)
11821205

11831206
tris = [[0, 1, 2]]
11841207
with pytest.raises(
11851208
ValueError,
11861209
match=r'mask must be a 1D array with the same length as the '
11871210
r'triangles array'):
1188-
mpl._tri.Triangulation(x, y, tris, [0, 1], None, None, False)
1211+
mpl._tri.Triangulation(x, y, tris, [0, 1], (), (), False)
11891212

11901213
with pytest.raises(
11911214
ValueError, match=r'edges must be a 2D array with shape \(\?,2\)'):
1192-
mpl._tri.Triangulation(x, y, tris, None, [[1]], None, False)
1215+
mpl._tri.Triangulation(x, y, tris, (), [[1]], (), False)
11931216

11941217
with pytest.raises(
11951218
ValueError,
11961219
match=r'neighbors must be a 2D array with the same shape as the '
11971220
r'triangles array'):
1198-
mpl._tri.Triangulation(x, y, tris, None, None, [[-1]], False)
1221+
mpl._tri.Triangulation(x, y, tris, (), (), [[-1]], False)
11991222

1200-
triang = mpl._tri.Triangulation(x, y, tris, None, None, None, False)
1223+
triang = mpl._tri.Triangulation(x, y, tris, (), (), (), False)
12011224

12021225
with pytest.raises(
12031226
ValueError,
1204-
match=r'z array must have same length as triangulation x and y '
1205-
r'array'):
1227+
match=r'z must be a 1D array with the same length as the '
1228+
r'triangulation x and y arrays'):
12061229
triang.calculate_plane_coefficients([])
12071230

1208-
with pytest.raises(
1209-
ValueError,
1210-
match=r'mask must be a 1D array with the same length as the '
1211-
r'triangles array'):
1212-
triang.set_mask([0, 1])
1231+
for mask in ([0, 1], None):
1232+
with pytest.raises(
1233+
ValueError,
1234+
match=r'mask must be a 1D array with the same length as the '
1235+
r'triangles array'):
1236+
triang.set_mask(mask)
1237+
1238+
triang.set_mask([True])
1239+
assert_array_equal(triang.get_edges(), np.empty((0, 2)))
1240+
1241+
triang.set_mask(()) # Equivalent to Python Triangulation mask=None
1242+
assert_array_equal(triang.get_edges(), [[1, 0], [2, 0], [2, 1]])
12131243

12141244
# C++ TriContourGenerator.
12151245
with pytest.raises(
12161246
TypeError,
1217-
match=r'function takes exactly 2 arguments \(0 given\)'):
1247+
match=r'__init__\(\): incompatible constructor arguments.'):
12181248
mpl._tri.TriContourGenerator()
12191249

12201250
with pytest.raises(
@@ -1232,7 +1262,8 @@ def test_internal_cpp_api():
12321262

12331263
# C++ TrapezoidMapTriFinder.
12341264
with pytest.raises(
1235-
TypeError, match=r'function takes exactly 1 argument \(0 given\)'):
1265+
TypeError,
1266+
match=r'__init__\(\): incompatible constructor arguments.'):
12361267
mpl._tri.TrapezoidMapTriFinder()
12371268

12381269
trifinder = mpl._tri.TrapezoidMapTriFinder(triang)

lib/matplotlib/tri/_triangulation.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,12 @@ def get_cpp_triangulation(self):
120120
from matplotlib import _tri
121121
if self._cpp_triangulation is None:
122122
self._cpp_triangulation = _tri.Triangulation(
123-
self.x, self.y, self.triangles, self.mask, self._edges,
124-
self._neighbors, not self.is_delaunay)
123+
# For unset arrays use empty tuple which has size of zero.
124+
self.x, self.y, self.triangles,
125+
self.mask if self.mask is not None else (),
126+
self._edges if self._edges is not None else (),
127+
self._neighbors if self._neighbors is not None else (),
128+
not self.is_delaunay)
125129
return self._cpp_triangulation
126130

127131
def get_masked_triangles(self):
@@ -229,7 +233,8 @@ def set_mask(self, mask):
229233

230234
# Set mask in C++ Triangulation.
231235
if self._cpp_triangulation is not None:
232-
self._cpp_triangulation.set_mask(self.mask)
236+
self._cpp_triangulation.set_mask(
237+
self.mask if self.mask is not None else ())
233238

234239
# Clear derived fields so they are recalculated when needed.
235240
self._edges = None

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ build-backend = "setuptools.build_meta"
33
requires = [
44
"certifi>=2020.06.20",
55
"oldest-supported-numpy",
6+
"pybind11>=2.6",
67
"setuptools_scm>=7",
78
]

setupext.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import textwrap
1717
import urllib.request
1818

19+
from pybind11.setup_helpers import Pybind11Extension
1920
from setuptools import Distribution, Extension
2021

2122
_log = logging.getLogger(__name__)
@@ -459,12 +460,12 @@ def get_extensions(self):
459460
add_libagg_flags(ext)
460461
yield ext
461462
# tri
462-
ext = Extension(
463+
ext = Pybind11Extension(
463464
"matplotlib._tri", [
464465
"src/tri/_tri.cpp",
465466
"src/tri/_tri_wrapper.cpp",
466-
])
467-
add_numpy_flags(ext)
467+
],
468+
cxx_std=11)
468469
yield ext
469470
# ttconv
470471
ext = Extension(

0 commit comments

Comments
 (0)