OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 |
| 3 """ |
| 4 requests.structures |
| 5 ~~~~~~~~~~~~~~~~~~~ |
| 6 |
| 7 Data structures that power Requests. |
| 8 |
| 9 """ |
| 10 |
| 11 import os |
| 12 import collections |
| 13 from itertools import islice |
| 14 |
| 15 |
| 16 class IteratorProxy(object): |
| 17 """docstring for IteratorProxy""" |
| 18 def __init__(self, i): |
| 19 self.i = i |
| 20 # self.i = chain.from_iterable(i) |
| 21 |
| 22 def __iter__(self): |
| 23 return self.i |
| 24 |
| 25 def __len__(self): |
| 26 if hasattr(self.i, '__len__'): |
| 27 return len(self.i) |
| 28 if hasattr(self.i, 'len'): |
| 29 return self.i.len |
| 30 if hasattr(self.i, 'fileno'): |
| 31 return os.fstat(self.i.fileno()).st_size |
| 32 |
| 33 def read(self, n): |
| 34 return "".join(islice(self.i, None, n)) |
| 35 |
| 36 |
| 37 class CaseInsensitiveDict(collections.MutableMapping): |
| 38 """ |
| 39 A case-insensitive ``dict``-like object. |
| 40 |
| 41 Implements all methods and operations of |
| 42 ``collections.MutableMapping`` as well as dict's ``copy``. Also |
| 43 provides ``lower_items``. |
| 44 |
| 45 All keys are expected to be strings. The structure remembers the |
| 46 case of the last key to be set, and ``iter(instance)``, |
| 47 ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` |
| 48 will contain case-sensitive keys. However, querying and contains |
| 49 testing is case insensitive: |
| 50 |
| 51 cid = CaseInsensitiveDict() |
| 52 cid['Accept'] = 'application/json' |
| 53 cid['aCCEPT'] == 'application/json' # True |
| 54 list(cid) == ['Accept'] # True |
| 55 |
| 56 For example, ``headers['content-encoding']`` will return the |
| 57 value of a ``'Content-Encoding'`` response header, regardless |
| 58 of how the header name was originally stored. |
| 59 |
| 60 If the constructor, ``.update``, or equality comparison |
| 61 operations are given keys that have equal ``.lower()``s, the |
| 62 behavior is undefined. |
| 63 |
| 64 """ |
| 65 def __init__(self, data=None, **kwargs): |
| 66 self._store = dict() |
| 67 if data is None: |
| 68 data = {} |
| 69 self.update(data, **kwargs) |
| 70 |
| 71 def __setitem__(self, key, value): |
| 72 # Use the lowercased key for lookups, but store the actual |
| 73 # key alongside the value. |
| 74 self._store[key.lower()] = (key, value) |
| 75 |
| 76 def __getitem__(self, key): |
| 77 return self._store[key.lower()][1] |
| 78 |
| 79 def __delitem__(self, key): |
| 80 del self._store[key.lower()] |
| 81 |
| 82 def __iter__(self): |
| 83 return (casedkey for casedkey, mappedvalue in self._store.values()) |
| 84 |
| 85 def __len__(self): |
| 86 return len(self._store) |
| 87 |
| 88 def lower_items(self): |
| 89 """Like iteritems(), but with all lowercase keys.""" |
| 90 return ( |
| 91 (lowerkey, keyval[1]) |
| 92 for (lowerkey, keyval) |
| 93 in self._store.items() |
| 94 ) |
| 95 |
| 96 def __eq__(self, other): |
| 97 if isinstance(other, collections.Mapping): |
| 98 other = CaseInsensitiveDict(other) |
| 99 else: |
| 100 return NotImplemented |
| 101 # Compare insensitively |
| 102 return dict(self.lower_items()) == dict(other.lower_items()) |
| 103 |
| 104 # Copy is required |
| 105 def copy(self): |
| 106 return CaseInsensitiveDict(self._store.values()) |
| 107 |
| 108 def __repr__(self): |
| 109 return '%s(%r)' % (self.__class__.__name__, dict(self.items())) |
| 110 |
| 111 |
| 112 class LookupDict(dict): |
| 113 """Dictionary lookup object.""" |
| 114 |
| 115 def __init__(self, name=None): |
| 116 self.name = name |
| 117 super(LookupDict, self).__init__() |
| 118 |
| 119 def __repr__(self): |
| 120 return '<lookup \'%s\'>' % (self.name) |
| 121 |
| 122 def __getitem__(self, key): |
| 123 # We allow fall-through here, so values default to None |
| 124 |
| 125 return self.__dict__.get(key, None) |
| 126 |
| 127 def get(self, key, default=None): |
| 128 return self.__dict__.get(key, default) |
OLD | NEW |