| 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()
 | 
| 
 |