Support CookieJar, references #281

This is my update of dhagrow's branch. It makes the backing store for cookies be a `CookieJar`, and adds compatibility with passed-in `CookieJar` subclasses like `LWPCookieJar`.

The default `CookieJar` implementation is compatible with existing code that expects `response.cookies` to be a dict.

This branch is complete to the best of my knowledge, but I haven't tested it against Python 3.x, since the current `develop` branch is broken against 3.x. I thought about trying to fix it but this change is confusing enough already :-)

I would appreciate suggestions for additional tests :-)

```
Traceback (most recent call last):
  File "./test_requests_https.py", line 10, in <module>
    import requests
  File "/home/shivaram/workspace/requests/requests/__init__.py", line 25, in <module>
    from . import utils
  File "/home/shivaram/workspace/requests/requests/utils.py", line 476, in <module>
    _unreserved_hextochr = dict((binascii.b2a_hex(c), c) for c in _unreserved_set)
  File "/home/shivaram/workspace/requests/requests/utils.py", line 476, in <genexpr>
    _unreserved_hextochr = dict((binascii.b2a_hex(c), c) for c in _unreserved_set)
TypeError: 'str' does not support the buffer interface
```


Right now, in `develop` and in this branch, it looks like if you pass in extra cookies via the `cookies` kwarg, they get stuck to the session:

https://gist.github.com/2488388

Is this correct / expected?


Python 3 definitely needs to be supported :)


This looks fantastic, btw. Going to dive in shortly.


Looks great to me as well.


Looks like I was wrong, it works properly on redirects. Here is my test for reference.

``` python

# get a cookie for tinyurl.com ONLY
r1 = session.request(url='http://tinyurl.com/preview.php?disable=1', method='GET')
# we have the cookie
assert 'preview' in r1.cookies

# get cookies on another domain
r2 = session.request(url='http://httpbin.org/cookies', method='GET')
# the cookie is not there
assert 'preview' not in r2.text

# this redirects to another domain, httpbin.org
# cookies of the first domain should NOT be sent to the next one
r3 = session.request(url='http://tinyurl.com/7zp3jnr', method='GET')
assert r3.url == 'http://httpbin.org/cookies'
assert 'preview' not in r3.text
```

This was my biggest issue with the current implementation, I had to disable the redirection handling entirely because there was no way to intervene between redirects (I still think that part is broken though, hooks would be nice).

I also tested it against some weird Set-Cookie: combinations, and it seems to work. The secure flag works too.


This pull request [fails](http://travis-ci.org/kennethreitz/requests/builds/1184171) (merged 0faf1c6c into a744edd0).


@travisbot that's the same traceback I get from `develop` under Python 3.2.


@slingamn I'll update the repo to pass today :)


This pull request [fails](http://travis-ci.org/kennethreitz/requests/builds/1209718) (merged cc6b1ce3 into a744edd0).


would it be possible for you to remove the commits that are included that aren't by you?


The ones by dhagrow? Any particular reason? Most of the code is originally his, and in particular c04bf801a339 is an atomic bug fix.


Oh, I think what happened is that `develop` was rebased and force-pushed:

```
From git://github.com/kennethreitz/requests
 + a744edd...a189c23 develop    -> parent/develop  (forced update)
```

so now commits that were force-removed from `develop` are showing up as part of this pull request.

I'll rebase the commits from me and dhagrow on top of the current `develop` and archive the current version of this branch in my fork.


Actually, wait. It looks like that force-push removed some stuff that might actually be relevant, e.g., #563 and #564. Did you intend to force those out of `develop`?


It wasn't force pushed, it was removed and republished with the bad commits removed. I should have taken the time to revert properly, but I couldn't find the offending commit easily and was an impatient mood ;(

I may create a new pull request with only your actual changes included.


No problem; if a189c238cc2 is the correct version of develop, then I'll rebase on that myself. Coming up.


Oh, heh, I left something out. I'll update again.


This pull request [fails](http://travis-ci.org/kennethreitz/requests/builds/1222636) (merged 722338f6 into a189c238).


Only fails on 3.x now :)


This pull request [fails](http://travis-ci.org/kennethreitz/requests/builds/1222656) (merged 7af97b69 into a189c238).


Oh, cool, an actual failure! I'll get that fixed.


Actually, `develop` is still broken for me under Python 3:

```
======================================================================
ERROR: test_HTTP_200_OK_GET_WITH_PARAMS (__main__.RequestsTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test_requests.py", line 100, in test_HTTP_200_OK_GET_WITH_PARAMS
    assert heads['User-agent'] in r.text
TypeError: argument of type 'NoneType' is not iterable

======================================================================
ERROR: test_nonurlencoded_post_data (__main__.RequestsTestSuite)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test_requests.py", line 421, in test_nonurlencoded_post_data
    rbody = json.loads(r.text)
  File "/usr/lib64/python3.2/json/__init__.py", line 307, in loads
    return _default_decoder.decode(s)
  File "/usr/lib64/python3.2/json/decoder.py", line 351, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer
```


Looks like you need the `chardet` dependency installed.


This pull request [passes](http://travis-ci.org/kennethreitz/requests/builds/1223031) (merged 11a3eaec into a189c238).


\o/


Any thoughts on the expected behavior question?

https://github.com/kennethreitz/requests/pull/565#issuecomment-5327172


Wow, this is a really fantastic implementation. Thanks for the fantastic work!


Extremely fantastic work.


https://gist.github.com/2488388#gistcomment-294773


Thanks! The core implementation is all @dhagrow's, I just rearranged stuff and made the tests green :-)


@dhagrow and @slingamn  are my heroes.

:sparkles: :cake: :sparkles: