|
18 | 18 | import pytest
|
19 | 19 | import contextlib
|
20 | 20 | import numpy
|
| 21 | +import concurrent.futures |
21 | 22 |
|
22 | 23 | from pathlib import Path
|
23 | 24 | from numpy._utils import asunicode
|
@@ -258,9 +259,17 @@ def __init__(self):
|
258 | 259 |
|
259 | 260 | def check_compilers(self):
|
260 | 261 | if (not self.compilers_checked) and (not sys.platform == "cygwin"):
|
261 |
| - self.has_c = check_language("c") |
262 |
| - self.has_f77 = check_language("fortran", fortran77_code) |
263 |
| - self.has_f90 = check_language("fortran", fortran90_code) |
| 262 | + with concurrent.futures.ThreadPoolExecutor() as executor: |
| 263 | + futures = [ |
| 264 | + executor.submit(check_language, "c"), |
| 265 | + executor.submit(check_language, "fortran", fortran77_code), |
| 266 | + executor.submit(check_language, "fortran", fortran90_code) |
| 267 | + ] |
| 268 | + |
| 269 | + self.has_c = futures[0].result() |
| 270 | + self.has_f77 = futures[1].result() |
| 271 | + self.has_f90 = futures[2].result() |
| 272 | + |
264 | 273 | self.compilers_checked = True
|
265 | 274 |
|
266 | 275 | checker = CompilerChecker()
|
@@ -343,44 +352,40 @@ class F2PyTest:
|
343 | 352 | only = []
|
344 | 353 | suffix = ".f"
|
345 | 354 | module = None
|
| 355 | + _has_c_compiler = None |
| 356 | + _has_f77_compiler = None |
| 357 | + _has_f90_compiler = None |
346 | 358 |
|
347 | 359 | @property
|
348 | 360 | def module_name(self):
|
349 | 361 | cls = type(self)
|
350 | 362 | return f'_{cls.__module__.rsplit(".",1)[-1]}_{cls.__name__}_ext_module'
|
351 | 363 |
|
352 |
| - def setup_method(self): |
| 364 | + @classmethod |
| 365 | + def setup_class(cls): |
353 | 366 | if sys.platform == "win32":
|
354 | 367 | pytest.skip("Fails with MinGW64 Gfortran (Issue #9673)")
|
| 368 | + F2PyTest._has_c_compiler = has_c_compiler() |
| 369 | + F2PyTest._has_f77_compiler = has_f77_compiler() |
| 370 | + F2PyTest._has_f90_compiler = has_f90_compiler() |
355 | 371 |
|
| 372 | + def setup_method(self): |
356 | 373 | if self.module is not None:
|
357 | 374 | return
|
358 | 375 |
|
359 |
| - # Check compiler availability first |
360 |
| - if not has_c_compiler(): |
361 |
| - pytest.skip("No C compiler available") |
362 |
| - |
363 |
| - codes = [] |
364 |
| - if self.sources: |
365 |
| - codes.extend(self.sources) |
366 |
| - if self.code is not None: |
| 376 | + codes = self.sources if self.sources else [] |
| 377 | + if self.code: |
367 | 378 | codes.append(self.suffix)
|
368 | 379 |
|
369 |
| - needs_f77 = False |
370 |
| - needs_f90 = False |
371 |
| - needs_pyf = False |
372 |
| - for fn in codes: |
373 |
| - if str(fn).endswith(".f"): |
374 |
| - needs_f77 = True |
375 |
| - elif str(fn).endswith(".f90"): |
376 |
| - needs_f90 = True |
377 |
| - elif str(fn).endswith(".pyf"): |
378 |
| - needs_pyf = True |
379 |
| - if needs_f77 and not has_f77_compiler(): |
| 380 | + needs_f77 = any(str(fn).endswith(".f") for fn in codes) |
| 381 | + needs_f90 = any(str(fn).endswith(".f90") for fn in codes) |
| 382 | + needs_pyf = any(str(fn).endswith(".pyf") for fn in codes) |
| 383 | + |
| 384 | + if needs_f77 and not self._has_f77_compiler: |
380 | 385 | pytest.skip("No Fortran 77 compiler available")
|
381 |
| - if needs_f90 and not has_f90_compiler(): |
| 386 | + if needs_f90 and not self._has_f90_compiler: |
382 | 387 | pytest.skip("No Fortran 90 compiler available")
|
383 |
| - if needs_pyf and not (has_f90_compiler() or has_f77_compiler()): |
| 388 | + if needs_pyf and not (self._has_f90_compiler or self._has_f77_compiler): |
384 | 389 | pytest.skip("No Fortran compiler available")
|
385 | 390 |
|
386 | 391 | # Build the module
|
|
0 commit comments