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 |