2626
2727"""
2828import random
29+ import threading
2930
3031from jmespath import lexer
3132from jmespath .compat import with_repr_method
@@ -74,6 +75,7 @@ class Parser(object):
7475 # _CACHE dict.
7576 _CACHE = {}
7677 _MAX_SIZE = 128
78+ _CACHE_LOCK = threading .Lock ()
7779
7880 def __init__ (self , lookahead = 2 ):
7981 self .tokenizer = None
@@ -87,7 +89,7 @@ def parse(self, expression):
8789 return cached
8890 parsed_result = self ._do_parse (expression )
8991 self ._CACHE [expression ] = parsed_result
90- if len ( self ._CACHE ) > self . _MAX_SIZE :
92+ if self ._is_cache_full () :
9193 self ._free_cache_entries ()
9294 return parsed_result
9395
@@ -488,9 +490,15 @@ def _raise_parse_error_maybe_eof(self, expected_type, token):
488490 raise exceptions .ParseError (
489491 lex_position , actual_value , actual_type , message )
490492
493+ def _is_cache_full (self ):
494+ return len (self ._CACHE ) > self ._MAX_SIZE
495+
491496 def _free_cache_entries (self ):
492- for key in random .sample (list (self ._CACHE .keys ()), int (self ._MAX_SIZE / 2 )):
493- self ._CACHE .pop (key , None )
497+ with self ._CACHE_LOCK :
498+ if self ._is_cache_full ():
499+ cache_keys = list (self ._CACHE .keys ())
500+ for key in random .sample (cache_keys , int (len (self ._CACHE )/ 2 )):
501+ self ._CACHE .pop (key , None )
494502
495503 @classmethod
496504 def purge (cls ):
0 commit comments