23
23
else :
24
24
from StringIO import StringIO
25
25
26
+ try :
27
+ from threading import Lock
28
+ except ImportError :
29
+ from dummy_threading import Lock
30
+
31
+
26
32
__all__ = [
27
33
'assert_equal' , 'assert_almost_equal' , 'assert_approx_equal' ,
28
34
'assert_array_equal' , 'assert_array_less' , 'assert_string_equal' ,
@@ -42,6 +48,20 @@ class KnownFailureException(Exception):
42
48
pass
43
49
44
50
51
+ # Warning filtering is generally not threadsafe in python, this is also
52
+ # true for `catch_warnings` or `suppress_warinings`. In NumPy 1.12
53
+ # however, `assert_equal` and the array comparison asserts, use this
54
+ # to filter out some comparison warnings. Since removing this filter
55
+ # may also affect downstream projects and skimage (and possibly more)
56
+ # do parallel manual parallel testing using `assert_equal`, a quick fix
57
+ # seems to be to lock the less obvious threading trap. Ideally (in
58
+ # master this is the case), there should simply not be warning filter
59
+ # logic in the assert functions themself.
60
+ # While probably not perfectly safe in principle, it is sufficient
61
+ # in the case of skimage and probably most testing scenarios and the
62
+ # chance of deadlocks seems very unlikely.
63
+ _assert_comparison_lock = Lock ()
64
+
45
65
KnownFailureTest = KnownFailureException # backwards compat
46
66
verbose = 0
47
67
@@ -395,15 +415,17 @@ def assert_equal(actual,desired,err_msg='',verbose=True):
395
415
except (TypeError , ValueError , NotImplementedError ):
396
416
pass
397
417
398
- # Explicitly use __eq__ for comparison, ticket #2552
399
- with suppress_warnings () as sup :
418
+ # Put lock around the warning filter, see comment at lock definition
419
+ with _assert_comparison_lock , suppress_warnings () as sup :
400
420
# TODO: Better handling will to needed when change happens!
401
421
sup .filter (DeprecationWarning , ".*NAT ==" )
402
422
sup .filter (FutureWarning , ".*NAT ==" )
423
+ # Explicitly use __eq__ for comparison, ticket #2552
403
424
if not (desired == actual ):
404
425
raise AssertionError (msg )
405
426
406
427
428
+
407
429
def print_assert_equal (test_string , actual , desired ):
408
430
"""
409
431
Test if two objects are equal, and print an error message if test fails.
@@ -691,7 +713,8 @@ def safe_comparison(*args, **kwargs):
691
713
# pass (or maybe eventually catch the errors and return False, I
692
714
# dunno, that's a little trickier and we can figure that out when the
693
715
# time comes).
694
- with suppress_warnings () as sup :
716
+ # Note: Put a lock around warning filter (comment at lock definition)
717
+ with _assert_comparison_lock , suppress_warnings () as sup :
695
718
sup .filter (DeprecationWarning , ".*==" )
696
719
sup .filter (FutureWarning , ".*==" )
697
720
return comparison (* args , ** kwargs )
0 commit comments