@@ -185,24 +185,32 @@ def simplefilter(action, category=Warning, lineno=0, append=False):
185185        raise  ValueError ("lineno must be an int >= 0" )
186186    _add_filter (action , None , category , None , lineno , append = append )
187187
188+ def  _filters_mutated ():
189+     # Even though this function is 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+ 
188194def  _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 ()
201208
202209def  resetwarnings ():
203210    """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 ()
206214
207215class  _OptionError (Exception ):
208216    """Exception used by option processing helpers.""" 
@@ -353,64 +361,66 @@ def warn_explicit(message, category, filename, lineno,
353361        module  =  filename  or  "<unknown>" 
354362        if  module [- 3 :].lower () ==  ".py" :
355363            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 
361364    if  isinstance (message , Warning ):
362365        text  =  str (message )
363366        category  =  message .__class__ 
364367    else :
365368        text  =  message 
366369        message  =  category (message )
367370    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 ))
384418
385419    # Prime the linecache for formatting, in case the 
386420    # "file" is actually in a zipfile or something. 
387421    import  linecache 
388422    linecache .getlines (filename , module_globals )
389423
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 ))
414424    # Print message and context 
415425    msg  =  WarningMessage (message , category , filename , lineno , source )
416426    _showwarnmsg (msg )
@@ -488,11 +498,12 @@ def __enter__(self):
488498        if  self ._entered :
489499            raise  RuntimeError ("Cannot enter %r twice"  %  self )
490500        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 
496507        if  self ._filter  is  not None :
497508            simplefilter (* self ._filter )
498509        if  self ._record :
@@ -508,10 +519,11 @@ def __enter__(self):
508519    def  __exit__ (self , * exc_info ):
509520        if  not  self ._entered :
510521            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 
515527
516528
517529class  deprecated :
@@ -701,18 +713,36 @@ def extract():
701713# If either if the compiled regexs are None, match anything. 
702714try :
703715    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+     )
705720    defaultaction  =  _defaultaction 
706721    onceregistry  =  _onceregistry 
707722    _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+ 
708734except  ImportError :
709735    filters  =  []
710736    defaultaction  =  "default" 
711737    onceregistry  =  {}
712738
739+     import  _thread 
740+ 
741+     _lock  =  _thread .RLock ()
742+ 
713743    _filters_version  =  1 
714744
715-     def  _filters_mutated ():
745+     def  _filters_mutated_lock_held ():
716746        global  _filters_version 
717747        _filters_version  +=  1 
718748
0 commit comments