|
1 | | -""" |
2 | | -This implementation of CaseInsensitiveDict is taken from the python requests library. |
| 1 | +# author: Drew Botwinick, Botwinick Innovations |
| 2 | +# license: 3-clause BSD |
3 | 3 |
|
4 | | -Although some modifications were made, they were generally trivial. Given the ubiquitous |
5 | | -nature of requests, it would've been reasonable to just depend on the upstream code, but |
6 | | -it seemed inappropriate to risk upstream changes breaking code with changes across versions. |
7 | | -This seemed extremely relevant because the previous version of this code that was used in |
8 | | -a few places was from an older implementation that used upper-cased keys instead of |
9 | | -lower-cased keys. This type of change could break augmenting code. Therefore, it made |
10 | | -sense to reproduce it here to prevent version-related breaking changes. |
| 4 | +# this is a stub to provide backwards compatibility while transitioning code |
11 | 5 |
|
12 | | -The original license and copyright are: |
13 | | -
|
14 | | -(c) 2017 by Kenneth Reitz. |
15 | | -License: Apache 2.0 |
16 | | -
|
17 | | -""" |
18 | | - |
19 | | -from collections import OrderedDict |
20 | | - |
21 | | -try: |
22 | | - from collections import Mapping, MutableMapping |
23 | | -except ImportError: |
24 | | - from collections.abc import Mapping, MutableMapping |
25 | | - |
26 | | - |
27 | | -class CaseInsensitiveDict(MutableMapping): |
28 | | - """A case-insensitive ``dict``-like object. |
29 | | -
|
30 | | - Implements all methods and operations of |
31 | | - ``MutableMapping`` as well as dict's ``copy``. Also |
32 | | - provides ``lower_items``. |
33 | | -
|
34 | | - All keys are expected to be strings. The structure remembers the |
35 | | - case of the last key to be set, and ``iter(instance)``, |
36 | | - ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` |
37 | | - will contain case-sensitive keys. However, querying and contains |
38 | | - testing is case insensitive:: |
39 | | -
|
40 | | - cid = CaseInsensitiveDict() |
41 | | - cid['Accept'] = 'application/json' |
42 | | - cid['aCCEPT'] == 'application/json' # True |
43 | | - list(cid) == ['Accept'] # True |
44 | | -
|
45 | | - For example, ``headers['content-encoding']`` will return the |
46 | | - value of a ``'Content-Encoding'`` response header, regardless |
47 | | - of how the header name was originally stored. |
48 | | -
|
49 | | - If the constructor, ``.update``, or equality comparison |
50 | | - operations are given keys that have equal ``.lower()``s, the |
51 | | - behavior is undefined. |
52 | | - """ |
53 | | - |
54 | | - def __init__(self, data=None, **kwargs): |
55 | | - self._store = OrderedDict() |
56 | | - if data is None: |
57 | | - data = {} |
58 | | - self.update(data, **kwargs) |
59 | | - |
60 | | - def __setitem__(self, key, value): |
61 | | - # Use the lowercased key for lookups, but store the actual key alongside the value. |
62 | | - self._store[key.lower()] = (key, value) |
63 | | - |
64 | | - def __getitem__(self, key): |
65 | | - return self._store[key.lower()][1] |
66 | | - |
67 | | - def __delitem__(self, key): |
68 | | - del self._store[key.lower()] |
69 | | - |
70 | | - def __iter__(self): |
71 | | - return (cased_key for cased_key, mapped_value in self._store.values()) |
72 | | - |
73 | | - def __len__(self): |
74 | | - return len(self._store) |
75 | | - |
76 | | - def lower_items(self): |
77 | | - """Like iteritems(), but with all lowercase keys.""" |
78 | | - return ((lower_key, key_val[1]) for (lower_key, key_val) in self._store.items()) |
79 | | - |
80 | | - def get_item(self, key, default_key=None, default_value=None): |
81 | | - """ |
82 | | - Alternative version of get(key, default) for a case-insensitive dict. This always return a (key, value) tuple. |
83 | | - The key will be returned in its original cased form. This can be useful when filtering user input to lookup |
84 | | - data. The user provided key may not match the case of the backing dict data. This allows retrieval of the |
85 | | - "authoritative" key and associated value. |
86 | | -
|
87 | | - :param key: key of item to retrieve |
88 | | - :param default_key: default key to respond with if key not in dict |
89 | | - :param default_value: default value to respond with if key not in dict |
90 | | - :return: (key, value) tuple |
91 | | - """ |
92 | | - kl = key.lower() |
93 | | - return self._store[kl] if kl in self._store else (default_key, default_value) |
94 | | - |
95 | | - def __eq__(self, other): |
96 | | - if isinstance(other, Mapping): |
97 | | - other = CaseInsensitiveDict(other) |
98 | | - else: |
99 | | - return NotImplemented |
100 | | - # Compare insensitively |
101 | | - return dict(self.lower_items()) == dict(other.lower_items()) |
102 | | - |
103 | | - # Copy is required |
104 | | - def copy(self): |
105 | | - return CaseInsensitiveDict(self._store.values()) |
106 | | - |
107 | | - def __repr__(self): |
108 | | - return str(dict(self.items())) |
| 6 | +# noinspection PyUnresolvedReferences |
| 7 | +from .legacy.cid import CaseInsensitiveDict |
0 commit comments