2 # -*- coding: utf-8 -*-
4 """Tests for Requests."""
6 from __future__ import division
14 from requests.auth import HTTPDigestAuth
15 from requests.adapters import HTTPAdapter
16 from requests.compat import str, cookielib, getproxies, urljoin, urlparse
17 from requests.cookies import cookiejar_from_dict
18 from requests.exceptions import InvalidURL, MissingSchema
19 from requests.structures import CaseInsensitiveDict
26 HTTPBIN = os.environ.get('HTTPBIN_URL', 'http://httpbin.org/')
27 # Issue #1483: Make sure the URL always has a trailing slash
28 HTTPBIN = HTTPBIN.rstrip('/') + '/'
32 """Returns url for HTTPBIN resource."""
33 return urljoin(HTTPBIN, '/'.join(suffix))
36 class RequestsTestCase(unittest.TestCase):
38 _multiprocess_can_split_ = True
41 """Create simple data set with headers."""
48 def test_entry_points(self):
51 requests.session().get
52 requests.session().head
59 def test_invalid_url(self):
60 self.assertRaises(MissingSchema, requests.get, 'hiwpefhipowhefopw')
61 self.assertRaises(InvalidURL, requests.get, 'http://')
63 def test_basic_building(self):
64 req = requests.Request()
65 req.url = 'http://kennethreitz.org/'
66 req.data = {'life': '42'}
69 assert pr.url == req.url
70 assert pr.body == 'life=42'
72 def test_no_content_length(self):
73 get_req = requests.Request('GET', httpbin('get')).prepare()
74 self.assertTrue('Content-Length' not in get_req.headers)
75 head_req = requests.Request('HEAD', httpbin('head')).prepare()
76 self.assertTrue('Content-Length' not in head_req.headers)
78 def test_path_is_not_double_encoded(self):
79 request = requests.Request('GET', "http://0.0.0.0/get/test case").prepare()
81 self.assertEqual(request.path_url, "/get/test%20case")
83 def test_params_are_added_before_fragment(self):
84 request = requests.Request('GET',
85 "http://example.com/path#fragment", params={"a": "b"}).prepare()
86 self.assertEqual(request.url,
87 "http://example.com/path?a=b#fragment")
88 request = requests.Request('GET',
89 "http://example.com/path?key=value#fragment", params={"a": "b"}).prepare()
90 self.assertEqual(request.url,
91 "http://example.com/path?key=value&a=b#fragment")
93 def test_mixed_case_scheme_acceptable(self):
94 s = requests.Session()
95 s.proxies = getproxies()
96 parts = urlparse(httpbin('get'))
97 schemes = ['http://', 'HTTP://', 'hTTp://', 'HttP://',
98 'https://', 'HTTPS://', 'hTTps://', 'HttPs://']
99 for scheme in schemes:
100 url = scheme + parts.netloc + parts.path
101 r = requests.Request('GET', url)
102 r = s.send(r.prepare())
103 self.assertEqual(r.status_code, 200,
104 "failed for scheme %s" % scheme)
106 def test_HTTP_200_OK_GET_ALTERNATIVE(self):
107 r = requests.Request('GET', httpbin('get'))
108 s = requests.Session()
109 s.proxies = getproxies()
111 r = s.send(r.prepare())
113 self.assertEqual(r.status_code, 200)
115 def test_HTTP_302_ALLOW_REDIRECT_GET(self):
116 r = requests.get(httpbin('redirect', '1'))
117 self.assertEqual(r.status_code, 200)
119 # def test_HTTP_302_ALLOW_REDIRECT_POST(self):
120 # r = requests.post(httpbin('status', '302'), data={'some': 'data'})
121 # self.assertEqual(r.status_code, 200)
123 def test_HTTP_200_OK_GET_WITH_PARAMS(self):
124 heads = {'User-agent': 'Mozilla/5.0'}
126 r = requests.get(httpbin('user-agent'), headers=heads)
128 self.assertTrue(heads['User-agent'] in r.text)
129 self.assertEqual(r.status_code, 200)
131 def test_HTTP_200_OK_GET_WITH_MIXED_PARAMS(self):
132 heads = {'User-agent': 'Mozilla/5.0'}
134 r = requests.get(httpbin('get') + '?test=true', params={'q': 'test'}, headers=heads)
135 self.assertEqual(r.status_code, 200)
137 def test_set_cookie_on_301(self):
138 s = requests.session()
139 url = httpbin('cookies/set?foo=bar')
141 self.assertTrue(s.cookies['foo'] == 'bar')
143 def test_cookie_sent_on_redirect(self):
144 s = requests.session()
145 s.get(httpbin('cookies/set?foo=bar'))
146 r = s.get(httpbin('redirect/1')) # redirects to httpbin('get')
147 self.assertTrue("Cookie" in r.json()["headers"])
149 def test_cookie_removed_on_expire(self):
150 s = requests.session()
151 s.get(httpbin('cookies/set?foo=bar'))
152 self.assertTrue(s.cookies['foo'] == 'bar')
154 httpbin('response-headers'),
157 'foo=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT'
160 assert 'foo' not in s.cookies
162 def test_cookie_quote_wrapped(self):
163 s = requests.session()
164 s.get(httpbin('cookies/set?foo="bar:baz"'))
165 self.assertTrue(s.cookies['foo'] == '"bar:baz"')
167 def test_request_cookie_overrides_session_cookie(self):
168 s = requests.session()
169 s.cookies['foo'] = 'bar'
170 r = s.get(httpbin('cookies'), cookies={'foo': 'baz'})
171 assert r.json()['cookies']['foo'] == 'baz'
172 # Session cookie should not be modified
173 assert s.cookies['foo'] == 'bar'
175 def test_generic_cookiejar_works(self):
176 cj = cookielib.CookieJar()
177 cookiejar_from_dict({'foo': 'bar'}, cj)
178 s = requests.session()
180 r = s.get(httpbin('cookies'))
181 # Make sure the cookie was sent
182 assert r.json()['cookies']['foo'] == 'bar'
183 # Make sure the session cj is still the custom one
184 assert s.cookies is cj
186 def test_requests_in_history_are_not_overridden(self):
187 resp = requests.get(httpbin('redirect/3'))
188 urls = [r.url for r in resp.history]
189 req_urls = [r.request.url for r in resp.history]
190 self.assertEquals(urls, req_urls)
192 def test_user_agent_transfers(self):
195 'User-agent': 'Mozilla/5.0 (github.com/kennethreitz/requests)'
198 r = requests.get(httpbin('user-agent'), headers=heads)
199 self.assertTrue(heads['User-agent'] in r.text)
202 'user-agent': 'Mozilla/5.0 (github.com/kennethreitz/requests)'
205 r = requests.get(httpbin('user-agent'), headers=heads)
206 self.assertTrue(heads['user-agent'] in r.text)
208 def test_HTTP_200_OK_HEAD(self):
209 r = requests.head(httpbin('get'))
210 self.assertEqual(r.status_code, 200)
212 def test_HTTP_200_OK_PUT(self):
213 r = requests.put(httpbin('put'))
214 self.assertEqual(r.status_code, 200)
216 def test_BASICAUTH_TUPLE_HTTP_200_OK_GET(self):
217 auth = ('user', 'pass')
218 url = httpbin('basic-auth', 'user', 'pass')
220 r = requests.get(url, auth=auth)
221 self.assertEqual(r.status_code, 200)
223 r = requests.get(url)
224 self.assertEqual(r.status_code, 401)
226 s = requests.session()
229 self.assertEqual(r.status_code, 200)
231 def test_basicauth_with_netrc(self):
232 auth = ('user', 'pass')
233 wrong_auth = ('wronguser', 'wrongpass')
234 url = httpbin('basic-auth', 'user', 'pass')
236 def get_netrc_auth_mock(url):
238 requests.sessions.get_netrc_auth = get_netrc_auth_mock
240 # Should use netrc and work.
241 r = requests.get(url)
242 self.assertEqual(r.status_code, 200)
244 # Given auth should override and fail.
245 r = requests.get(url, auth=wrong_auth)
246 self.assertEqual(r.status_code, 401)
248 s = requests.session()
250 # Should use netrc and work.
252 self.assertEqual(r.status_code, 200)
254 # Given auth should override and fail.
257 self.assertEqual(r.status_code, 401)
259 def test_DIGEST_HTTP_200_OK_GET(self):
261 auth = HTTPDigestAuth('user', 'pass')
262 url = httpbin('digest-auth', 'auth', 'user', 'pass')
264 r = requests.get(url, auth=auth)
265 self.assertEqual(r.status_code, 200)
267 r = requests.get(url)
268 self.assertEqual(r.status_code, 401)
270 s = requests.session()
271 s.auth = HTTPDigestAuth('user', 'pass')
273 self.assertEqual(r.status_code, 200)
275 def test_DIGEST_AUTH_RETURNS_COOKIE(self):
276 url = httpbin('digest-auth', 'auth', 'user', 'pass')
277 auth = HTTPDigestAuth('user', 'pass')
278 r = requests.get(url)
279 assert r.cookies['fake'] == 'fake_value'
281 r = requests.get(url, auth=auth)
282 assert r.status_code == 200
284 def test_DIGEST_AUTH_SETS_SESSION_COOKIES(self):
285 url = httpbin('digest-auth', 'auth', 'user', 'pass')
286 auth = HTTPDigestAuth('user', 'pass')
287 s = requests.Session()
288 s.get(url, auth=auth)
289 assert s.cookies['fake'] == 'fake_value'
291 def test_DIGEST_STREAM(self):
293 auth = HTTPDigestAuth('user', 'pass')
294 url = httpbin('digest-auth', 'auth', 'user', 'pass')
296 r = requests.get(url, auth=auth, stream=True)
297 self.assertNotEqual(r.raw.read(), b'')
299 r = requests.get(url, auth=auth, stream=False)
300 self.assertEqual(r.raw.read(), b'')
303 def test_DIGESTAUTH_WRONG_HTTP_401_GET(self):
305 auth = HTTPDigestAuth('user', 'wrongpass')
306 url = httpbin('digest-auth', 'auth', 'user', 'pass')
308 r = requests.get(url, auth=auth)
309 self.assertEqual(r.status_code, 401)
311 r = requests.get(url)
312 self.assertEqual(r.status_code, 401)
314 s = requests.session()
317 self.assertEqual(r.status_code, 401)
319 def test_POSTBIN_GET_POST_FILES(self):
321 url = httpbin('post')
322 post1 = requests.post(url).raise_for_status()
324 post1 = requests.post(url, data={'some': 'data'})
325 self.assertEqual(post1.status_code, 200)
327 with open('requirements.txt') as f:
328 post2 = requests.post(url, files={'some': f})
329 self.assertEqual(post2.status_code, 200)
331 post4 = requests.post(url, data='[{"some": "json"}]')
332 self.assertEqual(post4.status_code, 200)
335 requests.post(url, files=['bad file data'])
339 def test_POSTBIN_GET_POST_FILES_WITH_DATA(self):
341 url = httpbin('post')
342 post1 = requests.post(url).raise_for_status()
344 post1 = requests.post(url, data={'some': 'data'})
345 self.assertEqual(post1.status_code, 200)
347 with open('requirements.txt') as f:
348 post2 = requests.post(url, data={'some': 'data'}, files={'some': f})
349 self.assertEqual(post2.status_code, 200)
351 post4 = requests.post(url, data='[{"some": "json"}]')
352 self.assertEqual(post4.status_code, 200)
355 requests.post(url, files=['bad file data'])
359 def test_conflicting_post_params(self):
360 url = httpbin('post')
361 with open('requirements.txt') as f:
362 pytest.raises(ValueError, "requests.post(url, data='[{\"some\": \"data\"}]', files={'some': f})")
363 pytest.raises(ValueError, "requests.post(url, data=u'[{\"some\": \"data\"}]', files={'some': f})")
365 def test_request_ok_set(self):
366 r = requests.get(httpbin('status', '404'))
367 self.assertEqual(r.ok, False)
369 def test_status_raising(self):
370 r = requests.get(httpbin('status', '404'))
371 self.assertRaises(requests.exceptions.HTTPError, r.raise_for_status)
373 r = requests.get(httpbin('status', '500'))
374 self.assertFalse(r.ok)
376 def test_decompress_gzip(self):
377 r = requests.get(httpbin('gzip'))
378 r.content.decode('ascii')
380 def test_unicode_get(self):
381 url = httpbin('/get')
382 requests.get(url, params={'foo': 'føø'})
383 requests.get(url, params={'føø': 'føø'})
384 requests.get(url, params={'føø': 'føø'})
385 requests.get(url, params={'foo': 'foo'})
386 requests.get(httpbin('ø'), params={'foo': 'foo'})
388 def test_unicode_header_name(self):
389 requests.put(httpbin('put'), headers={str('Content-Type'): 'application/octet-stream'}, data='\xff') # compat.str is unicode.
391 def test_urlencoded_get_query_multivalued_param(self):
393 r = requests.get(httpbin('get'), params=dict(test=['foo', 'baz']))
394 self.assertEqual(r.status_code, 200)
395 self.assertEqual(r.url, httpbin('get?test=foo&test=baz'))
397 def test_different_encodings_dont_break_post(self):
398 r = requests.post(httpbin('post'),
399 data={'stuff': json.dumps({'a': 123})},
400 params={'blah': 'asdf1234'},
401 files={'file': ('test_requests.py', open(__file__, 'rb'))})
402 self.assertEqual(r.status_code, 200)
404 def test_unicode_multipart_post(self):
405 r = requests.post(httpbin('post'),
406 data={'stuff': u'ëlïxr'},
407 files={'file': ('test_requests.py', open(__file__, 'rb'))})
408 self.assertEqual(r.status_code, 200)
410 r = requests.post(httpbin('post'),
411 data={'stuff': u'ëlïxr'.encode('utf-8')},
412 files={'file': ('test_requests.py', open(__file__, 'rb'))})
413 self.assertEqual(r.status_code, 200)
415 r = requests.post(httpbin('post'),
416 data={'stuff': 'elixr'},
417 files={'file': ('test_requests.py', open(__file__, 'rb'))})
418 self.assertEqual(r.status_code, 200)
420 r = requests.post(httpbin('post'),
421 data={'stuff': 'elixr'.encode('utf-8')},
422 files={'file': ('test_requests.py', open(__file__, 'rb'))})
423 self.assertEqual(r.status_code, 200)
425 def test_unicode_multipart_post_fieldnames(self):
426 filename = os.path.splitext(__file__)[0] + '.py'
427 r = requests.Request(method='POST',
429 data={'stuff'.encode('utf-8'): 'elixr'},
430 files={'file': ('test_requests.py',
431 open(filename, 'rb'))})
433 self.assertTrue(b'name="stuff"' in prep.body)
434 self.assertFalse(b'name="b\'stuff\'"' in prep.body)
436 def test_custom_content_type(self):
437 r = requests.post(httpbin('post'),
438 data={'stuff': json.dumps({'a': 123})},
439 files={'file1': ('test_requests.py', open(__file__, 'rb')),
440 'file2': ('test_requests', open(__file__, 'rb'),
441 'text/py-content-type')})
442 self.assertEqual(r.status_code, 200)
443 self.assertTrue(b"text/py-content-type" in r.request.body)
445 def test_hook_receives_request_arguments(self):
446 def hook(resp, **kwargs):
447 assert resp is not None
450 requests.Request('GET', HTTPBIN, hooks={'response': hook})
452 def test_prepared_request_hook(self):
453 def hook(resp, **kwargs):
454 resp.hook_working = True
457 req = requests.Request('GET', HTTPBIN, hooks={'response': hook})
460 s = requests.Session()
461 s.proxies = getproxies()
464 self.assertTrue(hasattr(resp, 'hook_working'))
466 def test_prepared_from_session(self):
467 class DummyAuth(requests.auth.AuthBase):
468 def __call__(self, r):
469 r.headers['Dummy-Auth-Test'] = 'dummy-auth-test-ok'
472 req = requests.Request('GET', httpbin('headers'))
473 self.assertEqual(req.auth, None)
475 s = requests.Session()
478 prep = s.prepare_request(req)
481 self.assertTrue(resp.json()['headers']['Dummy-Auth-Test'], 'dummy-auth-test-ok')
483 def test_links(self):
484 r = requests.Response()
486 'cache-control': 'public, max-age=60, s-maxage=60',
487 'connection': 'keep-alive',
488 'content-encoding': 'gzip',
489 'content-type': 'application/json; charset=utf-8',
490 'date': 'Sat, 26 Jan 2013 16:47:56 GMT',
491 'etag': '"6ff6a73c0e446c1f61614769e3ceb778"',
492 'last-modified': 'Sat, 26 Jan 2013 16:22:39 GMT',
493 'link': ('<https://api.github.com/users/kennethreitz/repos?'
494 'page=2&per_page=10>; rel="next", <https://api.github.'
495 'com/users/kennethreitz/repos?page=7&per_page=10>; '
497 'server': 'GitHub.com',
500 'x-content-type-options': 'nosniff',
501 'x-github-media-type': 'github.beta',
502 'x-ratelimit-limit': '60',
503 'x-ratelimit-remaining': '57'
505 self.assertEqual(r.links['next']['rel'], 'next')
507 def test_cookie_parameters(self):
512 rest = {'HttpOnly': True}
514 jar = requests.cookies.RequestsCookieJar()
515 jar.set(key, value, secure=secure, domain=domain, rest=rest)
517 self.assertEqual(len(jar), 1)
518 self.assertTrue('some_cookie' in jar)
520 cookie = list(jar)[0]
521 self.assertEqual(cookie.secure, secure)
522 self.assertEqual(cookie.domain, domain)
523 self.assertEqual(cookie._rest['HttpOnly'], rest['HttpOnly'])
525 def test_time_elapsed_blank(self):
526 r = requests.get(httpbin('get'))
528 total_seconds = ((td.microseconds + (td.seconds + td.days * 24 * 3600)
530 self.assertTrue(total_seconds > 0.0)
532 def test_response_is_iterable(self):
533 r = requests.Response()
534 io = StringIO.StringIO('abc')
537 def read_mock(amt, decode_content=None):
539 setattr(io, 'read', read_mock)
541 self.assertTrue(next(iter(r)))
544 def test_get_auth_from_url(self):
545 url = 'http://user:pass@complex.url.com/path?query=yes'
546 self.assertEqual(('user', 'pass'),
547 requests.utils.get_auth_from_url(url))
549 def test_cannot_send_unprepared_requests(self):
550 r = requests.Request(url=HTTPBIN)
551 self.assertRaises(ValueError, requests.Session().send, r)
553 def test_http_error(self):
554 error = requests.exceptions.HTTPError()
555 self.assertEqual(error.response, None)
556 response = requests.Response()
557 error = requests.exceptions.HTTPError(response=response)
558 self.assertEqual(error.response, response)
559 error = requests.exceptions.HTTPError('message', response=response)
560 self.assertEqual(str(error), 'message')
561 self.assertEqual(error.response, response)
563 def test_session_pickling(self):
564 r = requests.Request('GET', httpbin('get'))
565 s = requests.Session()
567 s = pickle.loads(pickle.dumps(s))
568 s.proxies = getproxies()
570 r = s.send(r.prepare())
571 self.assertEqual(r.status_code, 200)
573 def test_fixes_1329(self):
575 Ensure that header updates are done case-insensitively.
577 s = requests.Session()
578 s.headers.update({'ACCEPT': 'BOGUS'})
579 s.headers.update({'accept': 'application/json'})
580 r = s.get(httpbin('get'))
581 headers = r.request.headers
595 def test_uppercase_scheme_redirect(self):
596 parts = urlparse(httpbin('html'))
597 url = "HTTP://" + parts.netloc + parts.path
598 r = requests.get(httpbin('redirect-to'), params={'url': url})
599 self.assertEqual(r.status_code, 200)
600 self.assertEqual(r.url.lower(), url.lower())
602 def test_transport_adapter_ordering(self):
603 s = requests.Session()
604 order = ['https://', 'http://']
605 self.assertEqual(order, list(s.adapters))
606 s.mount('http://git', HTTPAdapter())
607 s.mount('http://github', HTTPAdapter())
608 s.mount('http://github.com', HTTPAdapter())
609 s.mount('http://github.com/about/', HTTPAdapter())
611 'http://github.com/about/',
618 self.assertEqual(order, list(s.adapters))
619 s.mount('http://gittip', HTTPAdapter())
620 s.mount('http://gittip.com', HTTPAdapter())
621 s.mount('http://gittip.com/about/', HTTPAdapter())
623 'http://github.com/about/',
624 'http://gittip.com/about/',
633 self.assertEqual(order, list(s.adapters))
634 s2 = requests.Session()
635 s2.adapters = {'http://': HTTPAdapter()}
636 s2.mount('https://', HTTPAdapter())
637 self.assertTrue('http://' in s2.adapters)
638 self.assertTrue('https://' in s2.adapters)
640 def test_header_remove_is_case_insensitive(self):
642 s = requests.Session()
643 s.headers['foo'] = 'bar'
644 r = s.get(httpbin('get'), headers={'FOO': None})
645 assert 'foo' not in r.request.headers
647 def test_params_are_merged_case_sensitive(self):
648 s = requests.Session()
649 s.params['foo'] = 'bar'
650 r = s.get(httpbin('get'), params={'FOO': 'bar'})
651 assert r.json()['args'] == {'foo': 'bar', 'FOO': 'bar'}
654 def test_long_authinfo_in_url(self):
655 url = 'http://{0}:{1}@{2}:9000/path?query#frag'.format(
656 'E8A3BE87-9E3F-4620-8858-95478E385B5B',
657 'EA770032-DA4D-4D84-8CE9-29C6D910BF1E',
658 'exactly-------------sixty-----------three------------characters',
660 r = requests.Request('GET', url).prepare()
661 self.assertEqual(r.url, url)
663 def test_header_keys_are_native(self):
664 headers = {u'unicode': 'blah', 'byte'.encode('ascii'): 'blah'}
665 r = requests.Request('GET', httpbin('get'), headers=headers)
668 # This is testing that they are builtin strings. A bit weird, but there
670 self.assertTrue('unicode' in p.headers.keys())
671 self.assertTrue('byte' in p.headers.keys())
673 def test_can_send_nonstring_objects_with_files(self):
676 r = requests.Request('POST', httpbin('post'), data=data, files=files)
679 self.assertTrue('multipart/form-data' in p.headers['Content-Type'])
682 class TestContentEncodingDetection(unittest.TestCase):
685 encodings = requests.utils.get_encodings_from_content('')
686 self.assertEqual(len(encodings), 0)
688 def test_html_charset(self):
689 """HTML5 meta charset attribute"""
690 content = '<meta charset="UTF-8">'
691 encodings = requests.utils.get_encodings_from_content(content)
692 self.assertEqual(len(encodings), 1)
693 self.assertEqual(encodings[0], 'UTF-8')
695 def test_html4_pragma(self):
696 """HTML4 pragma directive"""
697 content = '<meta http-equiv="Content-type" content="text/html;charset=UTF-8">'
698 encodings = requests.utils.get_encodings_from_content(content)
699 self.assertEqual(len(encodings), 1)
700 self.assertEqual(encodings[0], 'UTF-8')
702 def test_xhtml_pragma(self):
703 """XHTML 1.x served with text/html MIME type"""
704 content = '<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />'
705 encodings = requests.utils.get_encodings_from_content(content)
706 self.assertEqual(len(encodings), 1)
707 self.assertEqual(encodings[0], 'UTF-8')
710 """XHTML 1.x served as XML"""
711 content = '<?xml version="1.0" encoding="UTF-8"?>'
712 encodings = requests.utils.get_encodings_from_content(content)
713 self.assertEqual(len(encodings), 1)
714 self.assertEqual(encodings[0], 'UTF-8')
716 def test_precedence(self):
718 <?xml version="1.0" encoding="XML"?>
719 <meta charset="HTML5">
720 <meta http-equiv="Content-type" content="text/html;charset=HTML4" />
722 encodings = requests.utils.get_encodings_from_content(content)
723 self.assertEqual(encodings, ['HTML5', 'HTML4', 'XML'])
726 class TestCaseInsensitiveDict(unittest.TestCase):
728 def test_mapping_init(self):
729 cid = CaseInsensitiveDict({'Foo': 'foo','BAr': 'bar'})
730 self.assertEqual(len(cid), 2)
731 self.assertTrue('foo' in cid)
732 self.assertTrue('bar' in cid)
734 def test_iterable_init(self):
735 cid = CaseInsensitiveDict([('Foo', 'foo'), ('BAr', 'bar')])
736 self.assertEqual(len(cid), 2)
737 self.assertTrue('foo' in cid)
738 self.assertTrue('bar' in cid)
740 def test_kwargs_init(self):
741 cid = CaseInsensitiveDict(FOO='foo', BAr='bar')
742 self.assertEqual(len(cid), 2)
743 self.assertTrue('foo' in cid)
744 self.assertTrue('bar' in cid)
746 def test_docstring_example(self):
747 cid = CaseInsensitiveDict()
748 cid['Accept'] = 'application/json'
749 self.assertEqual(cid['aCCEPT'], 'application/json')
750 self.assertEqual(list(cid), ['Accept'])
753 cid = CaseInsensitiveDict({'a': 'a', 'b': 'b'})
755 self.assertEqual(len(cid), 2)
757 def test_getitem(self):
758 cid = CaseInsensitiveDict({'Spam': 'blueval'})
759 self.assertEqual(cid['spam'], 'blueval')
760 self.assertEqual(cid['SPAM'], 'blueval')
762 def test_fixes_649(self):
763 """__setitem__ should behave case-insensitively."""
764 cid = CaseInsensitiveDict()
765 cid['spam'] = 'oneval'
766 cid['Spam'] = 'twoval'
767 cid['sPAM'] = 'redval'
768 cid['SPAM'] = 'blueval'
769 self.assertEqual(cid['spam'], 'blueval')
770 self.assertEqual(cid['SPAM'], 'blueval')
771 self.assertEqual(list(cid.keys()), ['SPAM'])
773 def test_delitem(self):
774 cid = CaseInsensitiveDict()
775 cid['Spam'] = 'someval'
777 self.assertFalse('spam' in cid)
778 self.assertEqual(len(cid), 0)
780 def test_contains(self):
781 cid = CaseInsensitiveDict()
782 cid['Spam'] = 'someval'
783 self.assertTrue('Spam' in cid)
784 self.assertTrue('spam' in cid)
785 self.assertTrue('SPAM' in cid)
786 self.assertTrue('sPam' in cid)
787 self.assertFalse('notspam' in cid)
790 cid = CaseInsensitiveDict()
791 cid['spam'] = 'oneval'
792 cid['SPAM'] = 'blueval'
793 self.assertEqual(cid.get('spam'), 'blueval')
794 self.assertEqual(cid.get('SPAM'), 'blueval')
795 self.assertEqual(cid.get('sPam'), 'blueval')
796 self.assertEqual(cid.get('notspam', 'default'), 'default')
798 def test_update(self):
799 cid = CaseInsensitiveDict()
800 cid['spam'] = 'blueval'
801 cid.update({'sPam': 'notblueval'})
802 self.assertEqual(cid['spam'], 'notblueval')
803 cid = CaseInsensitiveDict({'Foo': 'foo','BAr': 'bar'})
804 cid.update({'fOO': 'anotherfoo', 'bAR': 'anotherbar'})
805 self.assertEqual(len(cid), 2)
806 self.assertEqual(cid['foo'], 'anotherfoo')
807 self.assertEqual(cid['bar'], 'anotherbar')
809 def test_update_retains_unchanged(self):
810 cid = CaseInsensitiveDict({'foo': 'foo', 'bar': 'bar'})
811 cid.update({'foo': 'newfoo'})
812 self.assertEquals(cid['bar'], 'bar')
815 cid = CaseInsensitiveDict({'Spam': 'spam', 'Eggs': 'eggs'})
816 keys = frozenset(['Spam', 'Eggs'])
817 self.assertEqual(frozenset(iter(cid)), keys)
819 def test_equality(self):
820 cid = CaseInsensitiveDict({'SPAM': 'blueval', 'Eggs': 'redval'})
821 othercid = CaseInsensitiveDict({'spam': 'blueval', 'eggs': 'redval'})
822 self.assertEqual(cid, othercid)
824 self.assertNotEqual(cid, othercid)
825 self.assertEqual(cid, {'spam': 'blueval', 'eggs': 'redval'})
827 def test_setdefault(self):
828 cid = CaseInsensitiveDict({'Spam': 'blueval'})
830 cid.setdefault('spam', 'notblueval'),
834 cid.setdefault('notspam', 'notblueval'),
838 def test_lower_items(self):
839 cid = CaseInsensitiveDict({
840 'Accept': 'application/json',
841 'user-Agent': 'requests',
843 keyset = frozenset(lowerkey for lowerkey, v in cid.lower_items())
844 lowerkeyset = frozenset(['accept', 'user-agent'])
845 self.assertEqual(keyset, lowerkeyset)
847 def test_preserve_key_case(self):
848 cid = CaseInsensitiveDict({
849 'Accept': 'application/json',
850 'user-Agent': 'requests',
852 keyset = frozenset(['Accept', 'user-Agent'])
853 self.assertEqual(frozenset(i[0] for i in cid.items()), keyset)
854 self.assertEqual(frozenset(cid.keys()), keyset)
855 self.assertEqual(frozenset(cid), keyset)
857 def test_preserve_last_key_case(self):
858 cid = CaseInsensitiveDict({
859 'Accept': 'application/json',
860 'user-Agent': 'requests',
862 cid.update({'ACCEPT': 'application/json'})
863 cid['USER-AGENT'] = 'requests'
864 keyset = frozenset(['ACCEPT', 'USER-AGENT'])
865 self.assertEqual(frozenset(i[0] for i in cid.items()), keyset)
866 self.assertEqual(frozenset(cid.keys()), keyset)
867 self.assertEqual(frozenset(cid), keyset)
870 if __name__ == '__main__':