summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Petrov <andrey.petrov@shazow.net>2012-07-22 11:45:04 -0700
committerAndrey Petrov <andrey.petrov@shazow.net>2012-07-22 11:45:04 -0700
commit8fc94d7a0a7a98062f5204743ce293005512ddb0 (patch)
tree4980819fc307190d28f8cc20f42111fe81e6f5a7
parente66742dcf0bf83e9d62f6d34024cf4869fa13fba (diff)
downloadurllib3-8fc94d7a0a7a98062f5204743ce293005512ddb0.tar.gz
Cleanup new RecentlyUsedContainer.
-rw-r--r--urllib3/_collections.py74
-rw-r--r--urllib3/connectionpool.py8
2 files changed, 41 insertions, 41 deletions
diff --git a/urllib3/_collections.py b/urllib3/_collections.py
index e027b906..a2512edf 100644
--- a/urllib3/_collections.py
+++ b/urllib3/_collections.py
@@ -3,92 +3,92 @@
#
# This module is part of urllib3 and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-from __future__ import with_statement
-import threading
from collections import MutableMapping
+from threading import Lock
-try:
- # available on 2.7 and up
+try: # Python 2.7+
from collections import OrderedDict
- # hush pyflakes
- OrderedDict
except ImportError:
from .packages.ordered_dict import OrderedDict
+
__all__ = ['RecentlyUsedContainer']
+
+_Empty = object()
+
+
class RecentlyUsedContainer(MutableMapping):
"""
Provides a dict-like that 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:
+ Callback which will get called wwhenever an element is evicted from
+ the container.
"""
- # this is an object no one else knows about, sort of a hyper-None
- # cf. the implementation of OrderedDict
- __marker = object()
+ ContainerType = OrderedDict
def __init__(self, maxsize=10, dispose_func=None):
- """Constructor.
-
- Args:
- maxsize - int, maximum number of elements to retain
- dispose_func - callback taking a single argument, called to destroy
- elements that are being evicted or released
- """
self._maxsize = maxsize
self.dispose_func = dispose_func
# OrderedDict is not inherently threadsafe, so protect it with a lock
- self._mapping = OrderedDict()
- self._lock = threading.Lock()
+ self._container = self.ContainerType()
+ self._lock = Lock()
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._mapping.values())
- self._mapping.clear()
+ values = list(self._container.values())
+ self._container.clear()
if self.dispose_func:
for value in values:
self.dispose_func(value)
def __getitem__(self, key):
+ # Re-insert the item, moving it to the end of the eviction line.
with self._lock:
- # remove and re-add the item, moving it to the end of the eviction line
- # throw the KeyError back to calling code if it's not present:
- item = self._mapping.pop(key)
- self._mapping[key] = item
+ item = self._container.pop(key)
+ self._container[key] = item
return item
def __setitem__(self, key, item):
- evicted_entry = self.__marker
+ evicted_entry = _Empty
with self._lock:
- # possibly evict the existing value of 'key'
- evicted_entry = self._mapping.get(key, self.__marker)
- self._mapping[key] = item
- # if we didn't evict an existing value, we might have to evict the LRU value
- if len(self._mapping) > self._maxsize:
- # pop from the beginning of the dict
- _key, evicted_entry = self._mapping.popitem(last=False)
-
- if self.dispose_func and evicted_entry is not self.__marker:
+ # Possibly evict the existing value of 'key'
+ evicted_entry = self._container.get(key, _Empty)
+ self._container[key] = item
+
+ # 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_entry = self._container.popitem(last=False)
+
+ if self.dispose_func and evicted_entry is not _Empty:
self.dispose_func(evicted_entry)
def __delitem__(self, key):
with self._lock:
- entry = self._mapping.pop(key)
+ entry = self._container.pop(key)
+
if self.dispose_func:
self.dispose_func(entry)
def __len__(self):
with self._lock:
- return len(self._mapping)
+ return len(self._container)
def __iter__(self):
raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.')
def keys(self):
with self._lock:
- return self._mapping.keys()
+ return self._container.keys()
diff --git a/urllib3/connectionpool.py b/urllib3/connectionpool.py
index 851d960a..05947aed 100644
--- a/urllib3/connectionpool.py
+++ b/urllib3/connectionpool.py
@@ -10,25 +10,25 @@ import threading
from socket import timeout as SocketTimeout
-try: # Python 3
+try: # Python 3
from http.client import HTTPConnection, HTTPException
from http.client import HTTP_PORT, HTTPS_PORT
except ImportError:
from httplib import HTTPConnection, HTTPException
from httplib import HTTP_PORT, HTTPS_PORT
-try: # Python 3
+try: # Python 3
from queue import LifoQueue, Empty, Full
except ImportError:
from Queue import LifoQueue, Empty, Full
-try: # Compiled with SSL?
+try: # Compiled with SSL?
HTTPSConnection = object
BaseSSLError = None
ssl = None
- try: # Python 3
+ try: # Python 3
from http.client import HTTPSConnection
except ImportError:
from httplib import HTTPSConnection