Rewrite CaseInsensitiveDict to work correctly/sanely
authorColin Dunklau <colin.dunklau@gmail.com>
Tue, 30 Apr 2013 19:52:27 +0000 (14:52 -0500)
committerColin Dunklau <colin.dunklau@gmail.com>
Tue, 30 Apr 2013 19:52:27 +0000 (14:52 -0500)
commitf7596c75dce4e87ab83bdf74e8f120a4b1a5ff03
treecfb256c7700542f9dd723769f66e6e87033b2c5a
parentab36f3cc6f91f1e4903a3f4b31501cb7fefe4555
Rewrite CaseInsensitiveDict to work correctly/sanely

Fixes #649 and #1329 by making Session.headers a CaseInsensitiveDict,
and fixing the implementation of CID. Credit for the brilliant idea
to map `lowercased_key -> (cased_key, mapped_value)` goes to
@gazpachoking, thanks a bunch.

Changes from original implementation of CaseInsensitiveDict:

1.  CID is rewritten as a subclass of `collections.MutableMapping`.
2.  CID remembers the case of the last-set key, but `__setitem__`
    and `__delitem__` will handle keys without respect to case.
3.  CID returns the key case as remembered for the `keys`, `items`,
    and `__iter__` methods.
4.  Query operations (`__getitem__` and `__contains__`) are done in
    a case-insensitive manner: `cid['foo']` and `cid['FOO']` will
    return the same value.
5.  The constructor as well as `update` and `__eq__` have undefined
    behavior when given multiple keys that have the same `lower()`.
6.  The new method `lower_items` is like `iteritems`, but keys are
    all lowercased.
7.  CID raises `KeyError` for `__getitem__` as normal dicts do. The
    old implementation returned
6.  The `__repr__` now makes it obvious that it's not a normal dict.

See PR #1333 for the discussions that lead up to this implementation
AUTHORS.rst
requests/structures.py
requests/utils.py
test_requests.py