Skip to content

Commit 452b839

Browse files
committed
Fix some linter errors
1 parent 04e8f83 commit 452b839

File tree

5 files changed

+50
-55
lines changed

5 files changed

+50
-55
lines changed

mapbox_earcut/__init__.pyi

Lines changed: 0 additions & 17 deletions
This file was deleted.

mapbox_earcut/py.typed

Whitespace-only changes.

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ requires = ["nanobind>=2.9.2", "scikit-build-core>=0.11.6"]
4646
build-backend = "scikit_build_core.build"
4747

4848
[tool.cibuildwheel]
49-
# These crash on GitHub Actions but work locally, skip for now
50-
test-skip = "pp310-win*"
5149
test-requires = ["pytest"]
5250
test-command = "pytest {package}/tests"
5351

pyrightconfig.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"pythonVersion": "3.9",
3+
"typeCheckingMode": "basic",
4+
"include": [
5+
"mapbox_earcut",
6+
"tests"
7+
],
8+
"reportInvalidTypeForm": "none"
9+
}

tests/test_threadsafety.py

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
"""
77

88
import sys
9-
from collections.abc import Callable
109
from concurrent.futures import ThreadPoolExecutor
1110
import threading
12-
from typing import Any
11+
from typing import Any, Callable, List, Optional, Tuple, Union
1312

1413
import mapbox_earcut as earcut
1514
import numpy as np
@@ -23,7 +22,7 @@ def run_threaded(
2322
pass_count: bool = False,
2423
pass_barrier: bool = False,
2524
outer_iterations: int = 1,
26-
prepare_args: Callable[[], list[Any]] | None = None,
25+
prepare_args: Optional[Callable[[], List[Any]]] = None,
2726
) -> None:
2827
"""
2928
Runs a function many times in parallel.
@@ -48,16 +47,19 @@ def run_threaded(
4847
if pass_barrier:
4948
barrier = threading.Barrier(num_threads)
5049
args.append(barrier)
50+
else:
51+
barrier = None
5152
if pass_count:
5253
all_args = [(func, i, *args) for i in range(num_threads)]
5354
else:
5455
all_args = [(func, *args) for i in range(num_threads)]
56+
57+
futures = []
5558
try:
56-
futures = []
5759
for arg in all_args:
5860
futures.append(tpe.submit(*arg))
5961
finally:
60-
if len(futures) < num_threads and pass_barrier:
62+
if len(futures) < num_threads and barrier is not None:
6163
barrier.abort()
6264
for f in futures:
6365
f.result()
@@ -68,15 +70,15 @@ def run_threaded(
6870

6971
def test_parallel_triangulate_float32_simple() -> None:
7072
"""Test that multiple threads can triangulate simple polygons simultaneously."""
71-
results: list[NDArray[np.uint32] | None] = [None] * 8
73+
results: List[Optional[NDArray[np.uint32]]] = [None] * 8
7274

7375
def closure(i: int, b: threading.Barrier) -> None:
7476
# Create per-thread data to avoid sharing arrays
7577
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.float32).reshape(-1, 2)
7678
rings = np.array([3])
7779

7880
# Synchronize all threads to maximize chance of race condition
79-
b.wait()
81+
_ = b.wait()
8082

8183
# Perform triangulation
8284
result = earcut.triangulate_float32(verts, rings)
@@ -92,17 +94,17 @@ def closure(i: int, b: threading.Barrier) -> None:
9294
assert result is not None, f"Thread {i} didn't produce a result"
9395
assert result.dtype == np.uint32
9496
assert result.shape == (3,)
95-
assert np.all(result == expected), f"Thread {i} got incorrect result"
97+
assert np.array_equal(result, expected), f"Thread {i} got incorrect result"
9698

9799

98100
def test_parallel_triangulate_float64_simple() -> None:
99101
"""Test that multiple threads can triangulate with float64 simultaneously."""
100-
results: list[NDArray[np.uint32] | None] = [None] * 8
102+
results: List[Optional[NDArray[np.uint32]]] = [None] * 8
101103

102104
def closure(i: int, b: threading.Barrier) -> None:
103105
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.float64).reshape(-1, 2)
104106
rings = np.array([3])
105-
b.wait()
107+
_ = b.wait()
106108
result = earcut.triangulate_float64(verts, rings)
107109
results[i] = result
108110

@@ -111,17 +113,17 @@ def closure(i: int, b: threading.Barrier) -> None:
111113
expected = np.array([1, 2, 0])
112114
for result in results:
113115
assert result is not None
114-
assert np.all(result == expected)
116+
assert np.array_equal(result, expected)
115117

116118

117119
def test_parallel_triangulate_int32_simple() -> None:
118120
"""Test that multiple threads can triangulate with int32 simultaneously."""
119-
results: list[NDArray[np.uint32] | None] = [None] * 8
121+
results: List[Optional[NDArray[np.uint32]]] = [None] * 8
120122

121123
def closure(i: int, b: threading.Barrier) -> None:
122124
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.int32).reshape(-1, 2)
123125
rings = np.array([3])
124-
b.wait()
126+
_ = b.wait()
125127
result = earcut.triangulate_int32(verts, rings)
126128
results[i] = result
127129

@@ -130,17 +132,17 @@ def closure(i: int, b: threading.Barrier) -> None:
130132
expected = np.array([1, 2, 0])
131133
for result in results:
132134
assert result is not None
133-
assert np.all(result == expected)
135+
assert np.array_equal(result, expected)
134136

135137

136138
def test_parallel_triangulate_int64_simple() -> None:
137139
"""Test that multiple threads can triangulate with int64 simultaneously."""
138-
results: list[NDArray[np.uint32] | None] = [None] * 8
140+
results: List[Optional[NDArray[np.uint32]]] = [None] * 8
139141

140142
def closure(i: int, b: threading.Barrier) -> None:
141143
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.int64).reshape(-1, 2)
142144
rings = np.array([3])
143-
b.wait()
145+
_ = b.wait()
144146
result = earcut.triangulate_int64(verts, rings)
145147
results[i] = result
146148

@@ -149,15 +151,15 @@ def closure(i: int, b: threading.Barrier) -> None:
149151
expected = np.array([1, 2, 0])
150152
for result in results:
151153
assert result is not None
152-
assert np.all(result == expected)
154+
assert np.array_equal(result, expected)
153155

154156

155157
# Complex polygon thread safety tests
156158

157159

158160
def test_parallel_triangulate_square() -> None:
159161
"""Test parallel triangulation of a square."""
160-
results: list[NDArray[np.uint32] | None] = [None] * 16
162+
results: List[Optional[NDArray[np.uint32]]] = [None] * 16
161163

162164
def closure(i: int, b: threading.Barrier) -> None:
163165
# Square polygon
@@ -166,7 +168,7 @@ def closure(i: int, b: threading.Barrier) -> None:
166168
).reshape(-1, 2)
167169
rings = np.array([4])
168170

169-
b.wait()
171+
_ = b.wait()
170172
result = earcut.triangulate_float32(verts, rings)
171173
results[i] = result
172174

@@ -183,7 +185,7 @@ def closure(i: int, b: threading.Barrier) -> None:
183185

184186
def test_parallel_triangulate_with_hole() -> None:
185187
"""Test parallel triangulation of a polygon with a hole."""
186-
results: list[NDArray[np.uint32] | None] = [None] * 8
188+
results: List[Optional[NDArray[np.uint32]]] = [None] * 8
187189

188190
def closure(i: int, b: threading.Barrier) -> None:
189191
# Outer square
@@ -195,7 +197,7 @@ def closure(i: int, b: threading.Barrier) -> None:
195197
verts = np.vstack([outer, inner]).reshape(-1, 2)
196198
rings = np.array([4, 8]) # First ring ends at 4, second at 8
197199

198-
b.wait()
200+
_ = b.wait()
199201
result = earcut.triangulate_float32(verts, rings)
200202
results[i] = result
201203

@@ -207,20 +209,20 @@ def closure(i: int, b: threading.Barrier) -> None:
207209
for result in results[1:]:
208210
assert result is not None
209211
assert result.shape == first_result.shape
210-
assert np.all(result == first_result)
212+
assert np.array_equal(result, first_result)
211213

212214

213215
def test_parallel_triangulate_complex_shape() -> None:
214216
"""Test parallel triangulation with a more complex polygon."""
215-
results: list[NDArray[np.uint32] | None] = [None] * 12
217+
results: List[Optional[NDArray[np.uint32]]] = [None] * 12
216218

217219
def closure(i: int, b: threading.Barrier) -> None:
218220
# Hexagon
219221
angles = np.linspace(0, 2 * np.pi, 7)[:-1] # 6 points
220222
verts = np.column_stack([np.cos(angles), np.sin(angles)]).astype(np.float64)
221223
rings = np.array([6])
222224

223-
b.wait()
225+
_ = b.wait()
224226
result = earcut.triangulate_float64(verts, rings)
225227
results[i] = result
226228

@@ -245,15 +247,16 @@ def test_high_contention_same_shape() -> None:
245247
to maximize the chance of exposing race conditions.
246248
"""
247249
num_threads = 32
248-
results: list[NDArray[np.uint32] | None] = [None] * num_threads
250+
results: List[Optional[NDArray[np.uint32]]] = [None] * num_threads
249251

250252
def closure(i: int, b: threading.Barrier) -> None:
251253
verts = np.array([[0, 0], [5, 0], [5, 5], [0, 5]], dtype=np.float32).reshape(
252254
-1, 2
253255
)
254256
rings = np.array([4])
255257

256-
b.wait()
258+
_ = b.wait()
259+
result = None
257260
# Run multiple times in each thread
258261
for _ in range(10):
259262
result = earcut.triangulate_float32(verts, rings)
@@ -275,12 +278,12 @@ def closure(i: int, b: threading.Barrier) -> None:
275278

276279
def test_mixed_operations() -> None:
277280
"""Test mixing different data types in parallel."""
278-
results: list[NDArray[np.uint32] | None] = [None] * 16
281+
results: List[Optional[NDArray[np.uint32]]] = [None] * 16
279282

280283
def closure(i: int, b: threading.Barrier) -> None:
281284
# Each thread uses a different dtype based on its index
282285
dtypes = [np.float32, np.float64, np.int32, np.int64]
283-
funcs: list[Callable[[Any, Any], NDArray[np.uint32]]] = [
286+
funcs: List[Callable[[Any, Any], NDArray[np.uint32]]] = [
284287
earcut.triangulate_float32,
285288
earcut.triangulate_float64,
286289
earcut.triangulate_int32,
@@ -293,7 +296,7 @@ def closure(i: int, b: threading.Barrier) -> None:
293296
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=dtype).reshape(-1, 2)
294297
rings = np.array([3])
295298

296-
b.wait()
299+
_ = b.wait()
297300
result = func(verts, rings)
298301
results[i] = result
299302

@@ -304,12 +307,12 @@ def closure(i: int, b: threading.Barrier) -> None:
304307
expected = np.array([1, 2, 0])
305308
for result in results:
306309
assert result is not None
307-
assert np.all(result == expected)
310+
assert np.array_equal(result, expected)
308311

309312

310313
def test_varying_sizes() -> None:
311314
"""Test with varying polygon sizes across threads."""
312-
results: list[NDArray[np.uint32] | None] = [None] * 20
315+
results: List[Optional[NDArray[np.uint32]]] = [None] * 20
313316

314317
def closure(i: int, b: threading.Barrier) -> None:
315318
# Create polygons of different sizes based on thread index
@@ -318,7 +321,7 @@ def closure(i: int, b: threading.Barrier) -> None:
318321
verts = np.column_stack([np.cos(angles), np.sin(angles)]).astype(np.float32)
319322
rings = np.array([num_sides])
320323

321-
b.wait()
324+
_ = b.wait()
322325
result = earcut.triangulate_float32(verts, rings)
323326
results[i] = result
324327

@@ -342,15 +345,15 @@ def closure(i: int, b: threading.Barrier) -> None:
342345

343346
def test_parallel_invalid_rings() -> None:
344347
"""Test that multiple threads can handle invalid input simultaneously."""
345-
exceptions: list[ValueError | None] = [None] * 8
348+
exceptions: List[Optional[ValueError]] = [None] * 8
346349

347350
def closure(i: int, b: threading.Barrier) -> None:
348351
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.float32).reshape(-1, 2)
349352
rings = np.array([5]) # Invalid: larger than verts
350353

351-
b.wait()
354+
_ = b.wait()
352355
try:
353-
earcut.triangulate_float32(verts, rings)
356+
_ = earcut.triangulate_float32(verts, rings)
354357
exceptions[i] = None
355358
except ValueError as e:
356359
exceptions[i] = e
@@ -365,7 +368,9 @@ def closure(i: int, b: threading.Barrier) -> None:
365368

366369
def test_parallel_mixed_valid_invalid() -> None:
367370
"""Test mixing valid and invalid inputs across threads."""
368-
results: list[tuple[str, NDArray[np.uint32] | ValueError] | None] = [None] * 16
371+
results: List[Optional[Tuple[str, Union[NDArray[np.uint32], ValueError]]]] = [
372+
None
373+
] * 16
369374

370375
def closure(i: int, b: threading.Barrier) -> None:
371376
verts = np.array([[0, 0], [1, 0], [1, 1]], dtype=np.float32).reshape(-1, 2)

0 commit comments

Comments
 (0)