@@ -185,24 +185,32 @@ def simplefilter(action, category=Warning, lineno=0, append=False):
185
185
raise ValueError ("lineno must be an int >= 0" )
186
186
_add_filter (action , None , category , None , lineno , append = append )
187
187
188
+ def _filters_mutated ():
189
+ # Even though this function is not part of the public API, it's used by
190
+ # a fair amount of user code.
191
+ with _lock :
192
+ _filters_mutated_lock_held ()
193
+
188
194
def _add_filter (* item , append ):
189
- # Remove possible duplicate filters, so new one will be placed
190
- # in correct place. If append=True and duplicate exists, do nothing.
191
- if not append :
192
- try :
193
- filters .remove (item )
194
- except ValueError :
195
- pass
196
- filters .insert (0 , item )
197
- else :
198
- if item not in filters :
199
- filters .append (item )
200
- _filters_mutated ()
195
+ with _lock :
196
+ if not append :
197
+ # Remove possible duplicate filters, so new one will be placed
198
+ # in correct place. If append=True and duplicate exists, do nothing.
199
+ try :
200
+ filters .remove (item )
201
+ except ValueError :
202
+ pass
203
+ filters .insert (0 , item )
204
+ else :
205
+ if item not in filters :
206
+ filters .append (item )
207
+ _filters_mutated_lock_held ()
201
208
202
209
def resetwarnings ():
203
210
"""Clear the list of warning filters, so that no filters are active."""
204
- filters [:] = []
205
- _filters_mutated ()
211
+ with _lock :
212
+ filters [:] = []
213
+ _filters_mutated_lock_held ()
206
214
207
215
class _OptionError (Exception ):
208
216
"""Exception used by option processing helpers."""
@@ -353,64 +361,66 @@ def warn_explicit(message, category, filename, lineno,
353
361
module = filename or "<unknown>"
354
362
if module [- 3 :].lower () == ".py" :
355
363
module = module [:- 3 ] # XXX What about leading pathname?
356
- if registry is None :
357
- registry = {}
358
- if registry .get ('version' , 0 ) != _filters_version :
359
- registry .clear ()
360
- registry ['version' ] = _filters_version
361
364
if isinstance (message , Warning ):
362
365
text = str (message )
363
366
category = message .__class__
364
367
else :
365
368
text = message
366
369
message = category (message )
367
370
key = (text , category , lineno )
368
- # Quick test for common case
369
- if registry .get (key ):
370
- return
371
- # Search the filters
372
- for item in filters :
373
- action , msg , cat , mod , ln = item
374
- if ((msg is None or msg .match (text )) and
375
- issubclass (category , cat ) and
376
- (mod is None or mod .match (module )) and
377
- (ln == 0 or lineno == ln )):
378
- break
379
- else :
380
- action = defaultaction
381
- # Early exit actions
382
- if action == "ignore" :
383
- return
371
+ with _lock :
372
+ if registry is None :
373
+ registry = {}
374
+ if registry .get ('version' , 0 ) != _filters_version :
375
+ registry .clear ()
376
+ registry ['version' ] = _filters_version
377
+ # Quick test for common case
378
+ if registry .get (key ):
379
+ return
380
+ # Search the filters
381
+ for item in filters :
382
+ action , msg , cat , mod , ln = item
383
+ if ((msg is None or msg .match (text )) and
384
+ issubclass (category , cat ) and
385
+ (mod is None or mod .match (module )) and
386
+ (ln == 0 or lineno == ln )):
387
+ break
388
+ else :
389
+ action = defaultaction
390
+ # Early exit actions
391
+ if action == "ignore" :
392
+ return
393
+
394
+ if action == "error" :
395
+ raise message
396
+ # Other actions
397
+ if action == "once" :
398
+ registry [key ] = 1
399
+ oncekey = (text , category )
400
+ if onceregistry .get (oncekey ):
401
+ return
402
+ onceregistry [oncekey ] = 1
403
+ elif action in {"always" , "all" }:
404
+ pass
405
+ elif action == "module" :
406
+ registry [key ] = 1
407
+ altkey = (text , category , 0 )
408
+ if registry .get (altkey ):
409
+ return
410
+ registry [altkey ] = 1
411
+ elif action == "default" :
412
+ registry [key ] = 1
413
+ else :
414
+ # Unrecognized actions are errors
415
+ raise RuntimeError (
416
+ "Unrecognized action (%r) in warnings.filters:\n %s" %
417
+ (action , item ))
384
418
385
419
# Prime the linecache for formatting, in case the
386
420
# "file" is actually in a zipfile or something.
387
421
import linecache
388
422
linecache .getlines (filename , module_globals )
389
423
390
- if action == "error" :
391
- raise message
392
- # Other actions
393
- if action == "once" :
394
- registry [key ] = 1
395
- oncekey = (text , category )
396
- if onceregistry .get (oncekey ):
397
- return
398
- onceregistry [oncekey ] = 1
399
- elif action in {"always" , "all" }:
400
- pass
401
- elif action == "module" :
402
- registry [key ] = 1
403
- altkey = (text , category , 0 )
404
- if registry .get (altkey ):
405
- return
406
- registry [altkey ] = 1
407
- elif action == "default" :
408
- registry [key ] = 1
409
- else :
410
- # Unrecognized actions are errors
411
- raise RuntimeError (
412
- "Unrecognized action (%r) in warnings.filters:\n %s" %
413
- (action , item ))
414
424
# Print message and context
415
425
msg = WarningMessage (message , category , filename , lineno , source )
416
426
_showwarnmsg (msg )
@@ -488,30 +498,32 @@ def __enter__(self):
488
498
if self ._entered :
489
499
raise RuntimeError ("Cannot enter %r twice" % self )
490
500
self ._entered = True
491
- self ._filters = self ._module .filters
492
- self ._module .filters = self ._filters [:]
493
- self ._module ._filters_mutated ()
494
- self ._showwarning = self ._module .showwarning
495
- self ._showwarnmsg_impl = self ._module ._showwarnmsg_impl
501
+ with _lock :
502
+ self ._filters = self ._module .filters
503
+ self ._module .filters = self ._filters [:]
504
+ self ._module ._filters_mutated_lock_held ()
505
+ self ._showwarning = self ._module .showwarning
506
+ self ._showwarnmsg_impl = self ._module ._showwarnmsg_impl
507
+ if self ._record :
508
+ log = []
509
+ self ._module ._showwarnmsg_impl = log .append
510
+ # Reset showwarning() to the default implementation to make sure
511
+ # that _showwarnmsg() calls _showwarnmsg_impl()
512
+ self ._module .showwarning = self ._module ._showwarning_orig
513
+ else :
514
+ log = None
496
515
if self ._filter is not None :
497
516
simplefilter (* self ._filter )
498
- if self ._record :
499
- log = []
500
- self ._module ._showwarnmsg_impl = log .append
501
- # Reset showwarning() to the default implementation to make sure
502
- # that _showwarnmsg() calls _showwarnmsg_impl()
503
- self ._module .showwarning = self ._module ._showwarning_orig
504
- return log
505
- else :
506
- return None
517
+ return log
507
518
508
519
def __exit__ (self , * exc_info ):
509
520
if not self ._entered :
510
521
raise RuntimeError ("Cannot exit %r without entering first" % self )
511
- self ._module .filters = self ._filters
512
- self ._module ._filters_mutated ()
513
- self ._module .showwarning = self ._showwarning
514
- self ._module ._showwarnmsg_impl = self ._showwarnmsg_impl
522
+ with _lock :
523
+ self ._module .filters = self ._filters
524
+ self ._module ._filters_mutated_lock_held ()
525
+ self ._module .showwarning = self ._showwarning
526
+ self ._module ._showwarnmsg_impl = self ._showwarnmsg_impl
515
527
516
528
517
529
class deprecated :
@@ -701,18 +713,36 @@ def extract():
701
713
# If either if the compiled regexs are None, match anything.
702
714
try :
703
715
from _warnings import (filters , _defaultaction , _onceregistry ,
704
- warn , warn_explicit , _filters_mutated )
716
+ warn , warn_explicit ,
717
+ _filters_mutated_lock_held ,
718
+ _acquire_lock , _release_lock ,
719
+ )
705
720
defaultaction = _defaultaction
706
721
onceregistry = _onceregistry
707
722
_warnings_defaults = True
723
+
724
+ class _Lock :
725
+ def __enter__ (self ):
726
+ _acquire_lock ()
727
+ return self
728
+
729
+ def __exit__ (self , * args ):
730
+ _release_lock ()
731
+
732
+ _lock = _Lock ()
733
+
708
734
except ImportError :
709
735
filters = []
710
736
defaultaction = "default"
711
737
onceregistry = {}
712
738
739
+ import _thread
740
+
741
+ _lock = _thread .RLock ()
742
+
713
743
_filters_version = 1
714
744
715
- def _filters_mutated ():
745
+ def _filters_mutated_lock_held ():
716
746
global _filters_version
717
747
_filters_version += 1
718
748
0 commit comments