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