2 # -*- coding: utf-8 -*-
4 """Tests for Requests."""
6 from __future__ import division
13 from requests.auth import HTTPDigestAuth
14 from requests.adapters import HTTPAdapter
15 from requests.compat import str, cookielib, getproxies, urljoin, urlparse
16 from requests.cookies import cookiejar_from_dict
17 from requests.exceptions import InvalidURL, MissingSchema
18 from requests.structures import CaseInsensitiveDict
25 HTTPBIN = os.environ.get('HTTPBIN_URL', 'http://httpbin.org/')
26 # Issue #1483: Make sure the URL always has a trailing slash
27 HTTPBIN = HTTPBIN.rstrip('/') + '/'
31 """Returns url for HTTPBIN resource."""
32 return urljoin(HTTPBIN, '/'.join(suffix))
35 class RequestsTestCase(unittest.TestCase):
37 _multiprocess_can_split_ = True
40 """Create simple data set with headers."""
47 def test_entry_points(self):
50 requests.session().get
51 requests.session().head
58 def test_invalid_url(self):
59 self.assertRaises(MissingSchema, requests.get, 'hiwpefhipowhefopw')
60 self.assertRaises(InvalidURL, requests.get, 'http://')
62 def test_basic_building(self):
63 req = requests.Request()
64 req.url = 'http://kennethreitz.org/'
65 req.data = {'life': '42'}
68 assert pr.url == req.url
69 assert pr.body == 'life=42'
71 def test_no_content_length(self):
72 get_req = requests.Request('GET', httpbin('get')).prepare()
73 self.assertTrue('Content-Length' not in get_req.headers)
74 head_req = requests.Request('HEAD', httpbin('head')).prepare()
75 self.assertTrue('Content-Length' not in head_req.headers)
77 def test_path_is_not_double_encoded(self):
78 request = requests.Request('GET', "http://0.0.0.0/get/test case").prepare()
80 self.assertEqual(request.path_url, "/get/test%20case")
82 def test_params_are_added_before_fragment(self):
83 request = requests.Request('GET',
84 "http://example.com/path#fragment", params={"a": "b"}).prepare()
85 self.assertEqual(request.url,
86 "http://example.com/path?a=b#fragment")
87 request = requests.Request('GET',
88 "http://example.com/path?key=value#fragment", params={"a": "b"}).prepare()
89 self.assertEqual(request.url,
90 "http://example.com/path?key=value&a=b#fragment")
92 def test_mixed_case_scheme_acceptable(self):
93 s = requests.Session()
94 s.proxies = getproxies()
95 parts = urlparse(httpbin('get'))
96 schemes = ['http://', 'HTTP://', 'hTTp://', 'HttP://',
97 'https://', 'HTTPS://', 'hTTps://', 'HttPs://']
98 for scheme in schemes:
99 url = scheme + parts.netloc + parts.path
100 r = requests.Request('GET', url)
101 r = s.send(r.prepare())
102 self.assertEqual(r.status_code, 200,
103 "failed for scheme %s" % scheme)
105 def test_HTTP_200_OK_GET_ALTERNATIVE(self):
106 r = requests.Request('GET', httpbin('get'))
107 s = requests.Session()
108 s.proxies = getproxies()
110 r = s.send(r.prepare())
112 self.assertEqual(r.status_code, 200)
114 def test_HTTP_302_ALLOW_REDIRECT_GET(self):
115 r = requests.get(httpbin('redirect', '1'))
116 self.assertEqual(r.status_code, 200)
118 # def test_HTTP_302_ALLOW_REDIRECT_POST(self):
119 # r = requests.post(httpbin('status', '302'), data={'some': 'data'})
120 # self.assertEqual(r.status_code, 200)
122 def test_HTTP_200_OK_GET_WITH_PARAMS(self):
123 heads = {'User-agent': 'Mozilla/5.0'}
125 r = requests.get(httpbin('user-agent'), headers=heads)
127 self.assertTrue(heads['User-agent'] in r.text)
128 self.assertEqual(r.status_code, 200)
130 def test_HTTP_200_OK_GET_WITH_MIXED_PARAMS(self):
131 heads = {'User-agent': 'Mozilla/5.0'}
133 r = requests.get(httpbin('get') + '?test=true', params={'q': 'test'}, headers=heads)
134 self.assertEqual(r.status_code, 200)
136 def test_set_cookie_on_301(self):
137 s = requests.session()
138 url = httpbin('cookies/set?foo=bar')
140 self.assertTrue(s.cookies['foo'] == 'bar')
142 def test_cookie_sent_on_redirect(self):
143 s = requests.session()
144 s.get(httpbin('cookies/set?foo=bar'))
145 r = s.get(httpbin('redirect/1')) # redirects to httpbin('get')
146 self.assertTrue("Cookie" in r.json()["headers"])
148 def test_cookie_removed_on_expire(self):
149 s = requests.session()
150 s.get(httpbin('cookies/set?foo=bar'))
151 self.assertTrue(s.cookies['foo'] == 'bar')
153 httpbin('response-headers'),
156 'foo=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT'
159 assert 'foo' not in s.cookies
161 def test_cookie_quote_wrapped(self):
162 s = requests.session()
163 s.get(httpbin('cookies/set?foo="bar:baz"'))
164 self.assertTrue(s.cookies['foo'] == '"bar:baz"')
166 def test_request_cookie_overrides_session_cookie(self):
167 s = requests.session()
168 s.cookies['foo'] = 'bar'
169 r = s.get(httpbin('cookies'), cookies={'foo': 'baz'})
170 assert r.json()['cookies']['foo'] == 'baz'
171 # Session cookie should not be modified
172 assert s.cookies['foo'] == 'bar'
174 def test_generic_cookiejar_works(self):
175 cj = cookielib.CookieJar()
176 cookiejar_from_dict({'foo': 'bar'}, cj)
177 s = requests.session()
179 r = s.get(httpbin('cookies'))
180 # Make sure the cookie was sent
181 assert r.json()['cookies']['foo'] == 'bar'
182 # Make sure the session cj is still the custom one
183 assert s.cookies is cj
185 def test_requests_in_history_are_not_overridden(self):
186 resp = requests.get(httpbin('redirect/3'))
187 urls = [r.url for r in resp.history]
188 req_urls = [r.request.url for r in resp.history]
189 self.assertEquals(urls, req_urls)
191 def test_user_agent_transfers(self):
194 'User-agent': 'Mozilla/5.0 (github.com/kennethreitz/requests)'
197 r = requests.get(httpbin('user-agent'), headers=heads)
198 self.assertTrue(heads['User-agent'] in r.text)
201 'user-agent': 'Mozilla/5.0 (github.com/kennethreitz/requests)'
204 r = requests.get(httpbin('user-agent'), headers=heads)
205 self.assertTrue(heads['user-agent'] in r.text)
207 def test_HTTP_200_OK_HEAD(self):
208 r = requests.head(httpbin('get'))
209 self.assertEqual(r.status_code, 200)
211 def test_HTTP_200_OK_PUT(self):
212 r = requests.put(httpbin('put'))
213 self.assertEqual(r.status_code, 200)
215 def test_BASICAUTH_TUPLE_HTTP_200_OK_GET(self):
216 auth = ('user', 'pass')
217 url = httpbin('basic-auth', 'user', 'pass')
219 r = requests.get(url, auth=auth)
220 self.assertEqual(r.status_code, 200)
222 r = requests.get(url)
223 self.assertEqual(r.status_code, 401)
225 s = requests.session()
228 self.assertEqual(r.status_code, 200)
230 def test_basicauth_with_netrc(self):
231 auth = ('user', 'pass')
232 wrong_auth = ('wronguser', 'wrongpass')
233 url = httpbin('basic-auth', 'user', 'pass')
235 def get_netrc_auth_mock(url):
237 requests.sessions.get_netrc_auth = get_netrc_auth_mock
239 # Should use netrc and work.
240 r = requests.get(url)
241 self.assertEqual(r.status_code, 200)
243 # Given auth should override and fail.
244 r = requests.get(url, auth=wrong_auth)
245 self.assertEqual(r.status_code, 401)
247 s = requests.session()
249 # Should use netrc and work.
251 self.assertEqual(r.status_code, 200)
253 # Given auth should override and fail.
256 self.assertEqual(r.status_code, 401)
258 def test_DIGEST_HTTP_200_OK_GET(self):
260 auth = HTTPDigestAuth('user', 'pass')
261 url = httpbin('digest-auth', 'auth', 'user', 'pass')
263 r = requests.get(url, auth=auth)
264 self.assertEqual(r.status_code, 200)
266 r = requests.get(url)
267 self.assertEqual(r.status_code, 401)
269 s = requests.session()
270 s.auth = HTTPDigestAuth('user', 'pass')
272 self.assertEqual(r.status_code, 200)
274 def test_DIGEST_AUTH_RETURNS_COOKIE(self):
275 url = httpbin('digest-auth', 'auth', 'user', 'pass')
276 auth = HTTPDigestAuth('user', 'pass')
277 r = requests.get(url)
278 assert r.cookies['fake'] == 'fake_value'
280 r = requests.get(url, auth=auth)
281 assert r.status_code == 200
283 def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self):
284 url = httpbin('digest-auth', 'auth', 'user', 'pass')
285 auth = HTTPDigestAuth('user', 'pass')
286 s = requests.Session()
287 s.get(url, auth=auth)
288 assert s.cookies['fake'] == 'fake_value'
290 def test_DIGEST_STREAM(self):
292 auth = HTTPDigestAuth('user', 'pass')
293 url = httpbin('digest-auth', 'auth', 'user', 'pass')
295 r = requests.get(url, auth=auth, stream=True)
296 self.assertNotEqual(r.raw.read(), b'')
298 r = requests.get(url, auth=auth, stream=False)
299 self.assertEqual(r.raw.read(), b'')
302 def test_DIGESTAUTH_WRONG_HTTP_401_GET(self):
304 auth = HTTPDigestAuth('user', 'wrongpass')
305 url = httpbin('digest-auth', 'auth', 'user', 'pass')
307 r = requests.get(url, auth=auth)
308 self.assertEqual(r.status_code, 401)
310 r = requests.get(url)
311 self.assertEqual(r.status_code, 401)
313 s = requests.session()
316 self.assertEqual(r.status_code, 401)
318 def test_POSTBIN_GET_POST_FILES(self):
320 url = httpbin('post')
321 post1 = requests.post(url).raise_for_status()
323 post1 = requests.post(url, data={'some': 'data'})
324 self.assertEqual(post1.status_code, 200)
326 with open('requirements.txt') as f:
327 post2 = requests.post(url, files={'some': f})
328 self.assertEqual(post2.status_code, 200)
330 post4 = requests.post(url, data='[{"some": "json"}]')
331 self.assertEqual(post4.status_code, 200)
334 requests.post(url, files=['bad file data'])
338 def test_POSTBIN_GET_POST_FILES_WITH_DATA(self):
340 url = httpbin('post')
341 post1 = requests.post(url).raise_for_status()
343 post1 = requests.post(url, data={'some': 'data'})
344 self.assertEqual(post1.status_code, 200)
346 with open('requirements.txt') as f:
347 post2 = requests.post(url, data={'some': 'data'}, files={'some': f})
348 self.assertEqual(post2.status_code, 200)
350 post4 = requests.post(url, data='[{"some": "json"}]')
351 self.assertEqual(post4.status_code, 200)
354 requests.post(url, files=['bad file data'])
358 def test_request_ok_set(self):
359 r = requests.get(httpbin('status', '404'))
360 self.assertEqual(r.ok, False)
362 def test_status_raising(self):
363 r = requests.get(httpbin('status', '404'))
364 self.assertRaises(requests.exceptions.HTTPError, r.raise_for_status)
366 r = requests.get(httpbin('status', '500'))
367 self.assertFalse(r.ok)
369 def test_decompress_gzip(self):
370 r = requests.get(httpbin('gzip'))
371 r.content.decode('ascii')
373 def test_unicode_get(self):
374 url = httpbin('/get')
375 requests.get(url, params={'foo': 'føø'})
376 requests.get(url, params={'føø': 'føø'})
377 requests.get(url, params={'føø': 'føø'})
378 requests.get(url, params={'foo': 'foo'})
379 requests.get(httpbin('ø'), params={'foo': 'foo'})
381 def test_unicode_header_name(self):
382 requests.put(httpbin('put'), headers={str('Content-Type'): 'application/octet-stream'}, data='\xff') # compat.str is unicode.
384 def test_urlencoded_get_query_multivalued_param(self):
386 r = requests.get(httpbin('get'), params=dict(test=['foo', 'baz']))
387 self.assertEqual(r.status_code, 200)
388 self.assertEqual(r.url, httpbin('get?test=foo&test=baz'))
390 def test_different_encodings_dont_break_post(self):
391 r = requests.post(httpbin('post'),
392 data={'stuff': json.dumps({'a': 123})},
393 params={'blah': 'asdf1234'},
394 files={'file': ('test_requests.py', open(__file__, 'rb'))})
395 self.assertEqual(r.status_code, 200)
397 def test_unicode_multipart_post(self):
398 r = requests.post(httpbin('post'),
399 data={'stuff': u'ëlïxr'},
400 files={'file': ('test_requests.py', open(__file__, 'rb'))})
401 self.assertEqual(r.status_code, 200)
403 r = requests.post(httpbin('post'),
404 data={'stuff': u'ëlïxr'.encode('utf-8')},
405 files={'file': ('test_requests.py', open(__file__, 'rb'))})
406 self.assertEqual(r.status_code, 200)
408 r = requests.post(httpbin('post'),
409 data={'stuff': 'elixr'},
410 files={'file': ('test_requests.py', open(__file__, 'rb'))})
411 self.assertEqual(r.status_code, 200)
413 r = requests.post(httpbin('post'),
414 data={'stuff': 'elixr'.encode('utf-8')},
415 files={'file': ('test_requests.py', open(__file__, 'rb'))})
416 self.assertEqual(r.status_code, 200)
418 def test_unicode_multipart_post_fieldnames(self):
419 filename = os.path.splitext(__file__)[0] + '.py'
420 r = requests.Request(method='POST',
422 data={'stuff'.encode('utf-8'): 'elixr'},
423 files={'file': ('test_requests.py',
424 open(filename, 'rb'))})
426 self.assertTrue(b'name="stuff"' in prep.body)
427 self.assertFalse(b'name="b\'stuff\'"' in prep.body)
429 def test_custom_content_type(self):
430 r = requests.post(httpbin('post'),
431 data={'stuff': json.dumps({'a': 123})},
432 files={'file1': ('test_requests.py', open(__file__, 'rb')),
433 'file2': ('test_requests', open(__file__, 'rb'),
434 'text/py-content-type')})
435 self.assertEqual(r.status_code, 200)
436 self.assertTrue(b"text/py-content-type" in r.request.body)
438 def test_hook_receives_request_arguments(self):
439 def hook(resp, **kwargs):
440 assert resp is not None
443 requests.Request('GET', HTTPBIN, hooks={'response': hook})
445 def test_prepared_request_hook(self):
446 def hook(resp, **kwargs):
447 resp.hook_working = True
450 req = requests.Request('GET', HTTPBIN, hooks={'response': hook})
453 s = requests.Session()
454 s.proxies = getproxies()
457 self.assertTrue(hasattr(resp, 'hook_working'))
459 def test_prepared_from_session(self):
460 class DummyAuth(requests.auth.AuthBase):
461 def __call__(self, r):
462 r.headers['Dummy-Auth-Test'] = 'dummy-auth-test-ok'
465 req = requests.Request('GET', httpbin('headers'))
466 self.assertEqual(req.auth, None)
468 s = requests.Session()
471 prep = s.prepare_request(req)
474 self.assertTrue(resp.json()['headers']['Dummy-Auth-Test'], 'dummy-auth-test-ok')
476 def test_links(self):
477 r = requests.Response()
479 'cache-control': 'public, max-age=60, s-maxage=60',
480 'connection': 'keep-alive',
481 'content-encoding': 'gzip',
482 'content-type': 'application/json; charset=utf-8',
483 'date': 'Sat, 26 Jan 2013 16:47:56 GMT',
484 'etag': '"6ff6a73c0e446c1f61614769e3ceb778"',
485 'last-modified': 'Sat, 26 Jan 2013 16:22:39 GMT',
486 'link': ('<https://api.github.com/users/kennethreitz/repos?'
487 'page=2&per_page=10>; rel="next", <https://api.github.'
488 'com/users/kennethreitz/repos?page=7&per_page=10>; '
490 'server': 'GitHub.com',
493 'x-content-type-options': 'nosniff',
494 'x-github-media-type': 'github.beta',
495 'x-ratelimit-limit': '60',
496 'x-ratelimit-remaining': '57'
498 self.assertEqual(r.links['next']['rel'], 'next')
500 def test_cookie_parameters(self):
505 rest = {'HttpOnly': True}
507 jar = requests.cookies.RequestsCookieJar()
508 jar.set(key, value, secure=secure, domain=domain, rest=rest)
510 self.assertEqual(len(jar), 1)
511 self.assertTrue('some_cookie' in jar)
513 cookie = list(jar)[0]
514 self.assertEqual(cookie.secure, secure)
515 self.assertEqual(cookie.domain, domain)
516 self.assertEqual(cookie._rest['HttpOnly'], rest['HttpOnly'])
518 def test_time_elapsed_blank(self):
519 r = requests.get(httpbin('get'))
521 total_seconds = ((td.microseconds + (td.seconds + td.days * 24 * 3600)
523 self.assertTrue(total_seconds > 0.0)
525 def test_response_is_iterable(self):
526 r = requests.Response()
527 io = StringIO.StringIO('abc')
530 def read_mock(amt, decode_content=None):
532 setattr(io, 'read', read_mock)
534 self.assertTrue(next(iter(r)))
537 def test_get_auth_from_url(self):
538 url = 'http://user:pass@complex.url.com/path?query=yes'
539 self.assertEqual(('user', 'pass'),
540 requests.utils.get_auth_from_url(url))
542 def test_cannot_send_unprepared_requests(self):
543 r = requests.Request(url=HTTPBIN)
544 self.assertRaises(ValueError, requests.Session().send, r)
546 def test_http_error(self):
547 error = requests.exceptions.HTTPError()
548 self.assertEqual(error.response, None)
549 response = requests.Response()
550 error = requests.exceptions.HTTPError(response=response)
551 self.assertEqual(error.response, response)
552 error = requests.exceptions.HTTPError('message', response=response)
553 self.assertEqual(str(error), 'message')
554 self.assertEqual(error.response, response)
556 def test_session_pickling(self):
557 r = requests.Request('GET', httpbin('get'))
558 s = requests.Session()
560 s = pickle.loads(pickle.dumps(s))
561 s.proxies = getproxies()
563 r = s.send(r.prepare())
564 self.assertEqual(r.status_code, 200)
566 def test_fixes_1329(self):
568 Ensure that header updates are done case-insensitively.
570 s = requests.Session()
571 s.headers.update({'ACCEPT': 'BOGUS'})
572 s.headers.update({'accept': 'application/json'})
573 r = s.get(httpbin('get'))
574 headers = r.request.headers
588 def test_uppercase_scheme_redirect(self):
589 parts = urlparse(httpbin('html'))
590 url = "HTTP://" + parts.netloc + parts.path
591 r = requests.get(httpbin('redirect-to'), params={'url': url})
592 self.assertEqual(r.status_code, 200)
593 self.assertEqual(r.url.lower(), url.lower())
595 def test_transport_adapter_ordering(self):
596 s = requests.Session()
597 order = ['https://', 'http://']
598 self.assertEqual(order, list(s.adapters))
599 s.mount('http://git', HTTPAdapter())
600 s.mount('http://github', HTTPAdapter())
601 s.mount('http://github.com', HTTPAdapter())
602 s.mount('http://github.com/about/', HTTPAdapter())
604 'http://github.com/about/',
611 self.assertEqual(order, list(s.adapters))
612 s.mount('http://gittip', HTTPAdapter())
613 s.mount('http://gittip.com', HTTPAdapter())
614 s.mount('http://gittip.com/about/', HTTPAdapter())
616 'http://github.com/about/',
617 'http://gittip.com/about/',
626 self.assertEqual(order, list(s.adapters))
627 s2 = requests.Session()
628 s2.adapters = {'http://': HTTPAdapter()}
629 s2.mount('https://', HTTPAdapter())
630 self.assertTrue('http://' in s2.adapters)
631 self.assertTrue('https://' in s2.adapters)
633 def test_header_remove_is_case_insensitive(self):
635 s = requests.Session()
636 s.headers['foo'] = 'bar'
637 r = s.get(httpbin('get'), headers={'FOO': None})
638 assert 'foo' not in r.request.headers
640 def test_params_are_merged_case_sensitive(self):
641 s = requests.Session()
642 s.params['foo'] = 'bar'
643 r = s.get(httpbin('get'), params={'FOO': 'bar'})
644 assert r.json()['args'] == {'foo': 'bar', 'FOO': 'bar'}
647 def test_long_authinfo_in_url(self):
648 url = 'http://{0}:{1}@{2}:9000/path?query#frag'.format(
649 'E8A3BE87-9E3F-4620-8858-95478E385B5B',
650 'EA770032-DA4D-4D84-8CE9-29C6D910BF1E',
651 'exactly-------------sixty-----------three------------characters',
653 r = requests.Request('GET', url).prepare()
654 self.assertEqual(r.url, url)
656 def test_header_keys_are_native(self):
657 headers = {u'unicode': 'blah', 'byte'.encode('ascii'): 'blah'}
658 r = requests.Request('GET', httpbin('get'), headers=headers)
661 # This is testing that they are builtin strings. A bit weird, but there
663 self.assertTrue('unicode' in p.headers.keys())
664 self.assertTrue('byte' in p.headers.keys())
666 def test_can_send_nonstring_objects_with_files(self):
669 r = requests.Request('POST', httpbin('post'), data=data, files=files)
672 self.assertTrue('multipart/form-data' in p.headers['Content-Type'])
675 class TestCaseInsensitiveDict(unittest.TestCase):
677 def test_mapping_init(self):
678 cid = CaseInsensitiveDict({'Foo': 'foo','BAr': 'bar'})
679 self.assertEqual(len(cid), 2)
680 self.assertTrue('foo' in cid)
681 self.assertTrue('bar' in cid)
683 def test_iterable_init(self):
684 cid = CaseInsensitiveDict([('Foo', 'foo'), ('BAr', 'bar')])
685 self.assertEqual(len(cid), 2)
686 self.assertTrue('foo' in cid)
687 self.assertTrue('bar' in cid)
689 def test_kwargs_init(self):
690 cid = CaseInsensitiveDict(FOO='foo', BAr='bar')
691 self.assertEqual(len(cid), 2)
692 self.assertTrue('foo' in cid)
693 self.assertTrue('bar' in cid)
695 def test_docstring_example(self):
696 cid = CaseInsensitiveDict()
697 cid['Accept'] = 'application/json'
698 self.assertEqual(cid['aCCEPT'], 'application/json')
699 self.assertEqual(list(cid), ['Accept'])
702 cid = CaseInsensitiveDict({'a': 'a', 'b': 'b'})
704 self.assertEqual(len(cid), 2)
706 def test_getitem(self):
707 cid = CaseInsensitiveDict({'Spam': 'blueval'})
708 self.assertEqual(cid['spam'], 'blueval')
709 self.assertEqual(cid['SPAM'], 'blueval')
711 def test_fixes_649(self):
712 """__setitem__ should behave case-insensitively."""
713 cid = CaseInsensitiveDict()
714 cid['spam'] = 'oneval'
715 cid['Spam'] = 'twoval'
716 cid['sPAM'] = 'redval'
717 cid['SPAM'] = 'blueval'
718 self.assertEqual(cid['spam'], 'blueval')
719 self.assertEqual(cid['SPAM'], 'blueval')
720 self.assertEqual(list(cid.keys()), ['SPAM'])
722 def test_delitem(self):
723 cid = CaseInsensitiveDict()
724 cid['Spam'] = 'someval'
726 self.assertFalse('spam' in cid)
727 self.assertEqual(len(cid), 0)
729 def test_contains(self):
730 cid = CaseInsensitiveDict()
731 cid['Spam'] = 'someval'
732 self.assertTrue('Spam' in cid)
733 self.assertTrue('spam' in cid)
734 self.assertTrue('SPAM' in cid)
735 self.assertTrue('sPam' in cid)
736 self.assertFalse('notspam' in cid)
739 cid = CaseInsensitiveDict()
740 cid['spam'] = 'oneval'
741 cid['SPAM'] = 'blueval'
742 self.assertEqual(cid.get('spam'), 'blueval')
743 self.assertEqual(cid.get('SPAM'), 'blueval')
744 self.assertEqual(cid.get('sPam'), 'blueval')
745 self.assertEqual(cid.get('notspam', 'default'), 'default')
747 def test_update(self):
748 cid = CaseInsensitiveDict()
749 cid['spam'] = 'blueval'
750 cid.update({'sPam': 'notblueval'})
751 self.assertEqual(cid['spam'], 'notblueval')
752 cid = CaseInsensitiveDict({'Foo': 'foo','BAr': 'bar'})
753 cid.update({'fOO': 'anotherfoo', 'bAR': 'anotherbar'})
754 self.assertEqual(len(cid), 2)
755 self.assertEqual(cid['foo'], 'anotherfoo')
756 self.assertEqual(cid['bar'], 'anotherbar')
758 def test_update_retains_unchanged(self):
759 cid = CaseInsensitiveDict({'foo': 'foo', 'bar': 'bar'})
760 cid.update({'foo': 'newfoo'})
761 self.assertEquals(cid['bar'], 'bar')
764 cid = CaseInsensitiveDict({'Spam': 'spam', 'Eggs': 'eggs'})
765 keys = frozenset(['Spam', 'Eggs'])
766 self.assertEqual(frozenset(iter(cid)), keys)
768 def test_equality(self):
769 cid = CaseInsensitiveDict({'SPAM': 'blueval', 'Eggs': 'redval'})
770 othercid = CaseInsensitiveDict({'spam': 'blueval', 'eggs': 'redval'})
771 self.assertEqual(cid, othercid)
773 self.assertNotEqual(cid, othercid)
774 self.assertEqual(cid, {'spam': 'blueval', 'eggs': 'redval'})
776 def test_setdefault(self):
777 cid = CaseInsensitiveDict({'Spam': 'blueval'})
779 cid.setdefault('spam', 'notblueval'),
783 cid.setdefault('notspam', 'notblueval'),
787 def test_lower_items(self):
788 cid = CaseInsensitiveDict({
789 'Accept': 'application/json',
790 'user-Agent': 'requests',
792 keyset = frozenset(lowerkey for lowerkey, v in cid.lower_items())
793 lowerkeyset = frozenset(['accept', 'user-agent'])
794 self.assertEqual(keyset, lowerkeyset)
796 def test_preserve_key_case(self):
797 cid = CaseInsensitiveDict({
798 'Accept': 'application/json',
799 'user-Agent': 'requests',
801 keyset = frozenset(['Accept', 'user-Agent'])
802 self.assertEqual(frozenset(i[0] for i in cid.items()), keyset)
803 self.assertEqual(frozenset(cid.keys()), keyset)
804 self.assertEqual(frozenset(cid), keyset)
806 def test_preserve_last_key_case(self):
807 cid = CaseInsensitiveDict({
808 'Accept': 'application/json',
809 'user-Agent': 'requests',
811 cid.update({'ACCEPT': 'application/json'})
812 cid['USER-AGENT'] = 'requests'
813 keyset = frozenset(['ACCEPT', 'USER-AGENT'])
814 self.assertEqual(frozenset(i[0] for i in cid.items()), keyset)
815 self.assertEqual(frozenset(cid.keys()), keyset)
816 self.assertEqual(frozenset(cid), keyset)
819 if __name__ == '__main__':