| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 # urllib3/_collections.py |  | 
| 2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) |  | 
| 3 # |  | 
| 4 # This module is part of urllib3 and is released under |  | 
| 5 # the MIT License: http://www.opensource.org/licenses/mit-license.php |  | 
| 6 |  | 
| 7 from collections import MutableMapping |  | 
| 8 from threading import RLock |  | 
| 9 |  | 
| 10 try: # Python 2.7+ |  | 
| 11     from collections import OrderedDict |  | 
| 12 except ImportError: |  | 
| 13     from .packages.ordered_dict import OrderedDict |  | 
| 14 |  | 
| 15 |  | 
| 16 __all__ = ['RecentlyUsedContainer'] |  | 
| 17 |  | 
| 18 |  | 
| 19 _Null = object() |  | 
| 20 |  | 
| 21 |  | 
| 22 class RecentlyUsedContainer(MutableMapping): |  | 
| 23     """ |  | 
| 24     Provides a thread-safe dict-like container which maintains up to |  | 
| 25     ``maxsize`` keys while throwing away the least-recently-used keys beyond |  | 
| 26     ``maxsize``. |  | 
| 27 |  | 
| 28     :param maxsize: |  | 
| 29         Maximum number of recent elements to retain. |  | 
| 30 |  | 
| 31     :param dispose_func: |  | 
| 32         Every time an item is evicted from the container, |  | 
| 33         ``dispose_func(value)`` is called.  Callback which will get called |  | 
| 34     """ |  | 
| 35 |  | 
| 36     ContainerCls = OrderedDict |  | 
| 37 |  | 
| 38     def __init__(self, maxsize=10, dispose_func=None): |  | 
| 39         self._maxsize = maxsize |  | 
| 40         self.dispose_func = dispose_func |  | 
| 41 |  | 
| 42         self._container = self.ContainerCls() |  | 
| 43         self.lock = RLock() |  | 
| 44 |  | 
| 45     def __getitem__(self, key): |  | 
| 46         # Re-insert the item, moving it to the end of the eviction line. |  | 
| 47         with self.lock: |  | 
| 48             item = self._container.pop(key) |  | 
| 49             self._container[key] = item |  | 
| 50             return item |  | 
| 51 |  | 
| 52     def __setitem__(self, key, value): |  | 
| 53         evicted_value = _Null |  | 
| 54         with self.lock: |  | 
| 55             # Possibly evict the existing value of 'key' |  | 
| 56             evicted_value = self._container.get(key, _Null) |  | 
| 57             self._container[key] = value |  | 
| 58 |  | 
| 59             # If we didn't evict an existing value, we might have to evict the |  | 
| 60             # least recently used item from the beginning of the container. |  | 
| 61             if len(self._container) > self._maxsize: |  | 
| 62                 _key, evicted_value = self._container.popitem(last=False) |  | 
| 63 |  | 
| 64         if self.dispose_func and evicted_value is not _Null: |  | 
| 65             self.dispose_func(evicted_value) |  | 
| 66 |  | 
| 67     def __delitem__(self, key): |  | 
| 68         with self.lock: |  | 
| 69             value = self._container.pop(key) |  | 
| 70 |  | 
| 71         if self.dispose_func: |  | 
| 72             self.dispose_func(value) |  | 
| 73 |  | 
| 74     def __len__(self): |  | 
| 75         with self.lock: |  | 
| 76             return len(self._container) |  | 
| 77 |  | 
| 78     def __iter__(self): |  | 
| 79         raise NotImplementedError('Iteration over this class is unlikely to be t
    hreadsafe.') |  | 
| 80 |  | 
| 81     def clear(self): |  | 
| 82         with self.lock: |  | 
| 83             # Copy pointers to all values, then wipe the mapping |  | 
| 84             # under Python 2, this copies the list of values twice :-| |  | 
| 85             values = list(self._container.values()) |  | 
| 86             self._container.clear() |  | 
| 87 |  | 
| 88         if self.dispose_func: |  | 
| 89             for value in values: |  | 
| 90                 self.dispose_func(value) |  | 
| 91 |  | 
| 92     def keys(self): |  | 
| 93         with self.lock: |  | 
| 94             return self._container.keys() |  | 
| OLD | NEW | 
|---|