| Index: third_party/requests/packages/urllib3/_collections.py
|
| diff --git a/third_party/requests/packages/urllib3/_collections.py b/third_party/requests/packages/urllib3/_collections.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b35a73672e8948bcb01e5b9c6fba187e41d2b742
|
| --- /dev/null
|
| +++ b/third_party/requests/packages/urllib3/_collections.py
|
| @@ -0,0 +1,94 @@
|
| +# urllib3/_collections.py
|
| +# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
|
| +#
|
| +# This module is part of urllib3 and is released under
|
| +# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
| +
|
| +from collections import MutableMapping
|
| +from threading import Lock
|
| +
|
| +try: # Python 2.7+
|
| + from collections import OrderedDict
|
| +except ImportError:
|
| + from .packages.ordered_dict import OrderedDict
|
| +
|
| +
|
| +__all__ = ['RecentlyUsedContainer']
|
| +
|
| +
|
| +_Null = object()
|
| +
|
| +
|
| +class RecentlyUsedContainer(MutableMapping):
|
| + """
|
| + Provides a thread-safe dict-like container which maintains up to
|
| + ``maxsize`` keys while throwing away the least-recently-used keys beyond
|
| + ``maxsize``.
|
| +
|
| + :param maxsize:
|
| + Maximum number of recent elements to retain.
|
| +
|
| + :param dispose_func:
|
| + Every time an item is evicted from the container,
|
| + ``dispose_func(value)`` is called. Callback which will get called
|
| + """
|
| +
|
| + ContainerCls = OrderedDict
|
| +
|
| + def __init__(self, maxsize=10, dispose_func=None):
|
| + self._maxsize = maxsize
|
| + self.dispose_func = dispose_func
|
| +
|
| + self._container = self.ContainerCls()
|
| + self._lock = Lock()
|
| +
|
| + def __getitem__(self, key):
|
| + # Re-insert the item, moving it to the end of the eviction line.
|
| + with self._lock:
|
| + item = self._container.pop(key)
|
| + self._container[key] = item
|
| + return item
|
| +
|
| + def __setitem__(self, key, value):
|
| + evicted_value = _Null
|
| + with self._lock:
|
| + # Possibly evict the existing value of 'key'
|
| + evicted_value = self._container.get(key, _Null)
|
| + self._container[key] = value
|
| +
|
| + # If we didn't evict an existing value, we might have to evict the
|
| + # least recently used item from the beginning of the container.
|
| + if len(self._container) > self._maxsize:
|
| + _key, evicted_value = self._container.popitem(last=False)
|
| +
|
| + if self.dispose_func and evicted_value is not _Null:
|
| + self.dispose_func(evicted_value)
|
| +
|
| + def __delitem__(self, key):
|
| + with self._lock:
|
| + value = self._container.pop(key)
|
| +
|
| + if self.dispose_func:
|
| + self.dispose_func(value)
|
| +
|
| + def __len__(self):
|
| + with self._lock:
|
| + return len(self._container)
|
| +
|
| + def __iter__(self):
|
| + raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.')
|
| +
|
| + def clear(self):
|
| + with self._lock:
|
| + # Copy pointers to all values, then wipe the mapping
|
| + # under Python 2, this copies the list of values twice :-|
|
| + values = list(self._container.values())
|
| + self._container.clear()
|
| +
|
| + if self.dispose_func:
|
| + for value in values:
|
| + self.dispose_func(value)
|
| +
|
| + def keys(self):
|
| + with self._lock:
|
| + return self._container.keys()
|
|
|