Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: third_party/requests/models.py

Issue 25004007: Update 'requests' lib to v2.0. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/swarm_client
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 """ 3 """
4 requests.models 4 requests.models
5 ~~~~~~~~~~~~~~~ 5 ~~~~~~~~~~~~~~~
6 6
7 This module contains the primary objects that power Requests. 7 This module contains the primary objects that power Requests.
8 """ 8 """
9 9
10 import collections 10 import collections
11 import logging 11 import logging
12 import datetime 12 import datetime
13 13
14 from io import BytesIO 14 from io import BytesIO, UnsupportedOperation
15 from .hooks import default_hooks 15 from .hooks import default_hooks
16 from .structures import CaseInsensitiveDict 16 from .structures import CaseInsensitiveDict
17 17
18 from .auth import HTTPBasicAuth 18 from .auth import HTTPBasicAuth
19 from .cookies import cookiejar_from_dict, get_cookie_header 19 from .cookies import cookiejar_from_dict, get_cookie_header
20 from .packages.urllib3.filepost import encode_multipart_formdata 20 from .packages.urllib3.filepost import encode_multipart_formdata
21 from .packages.urllib3.util import parse_url 21 from .packages.urllib3.util import parse_url
22 from .exceptions import HTTPError, RequestException, MissingSchema, InvalidURL 22 from .exceptions import (
23 HTTPError, RequestException, MissingSchema, InvalidURL,
24 ChunkedEncodingError)
23 from .utils import ( 25 from .utils import (
24 guess_filename, get_auth_from_url, requote_uri, 26 guess_filename, get_auth_from_url, requote_uri,
25 stream_decode_response_unicode, to_key_val_list, parse_header_links, 27 stream_decode_response_unicode, to_key_val_list, parse_header_links,
26 iter_slices, guess_json_utf, super_len) 28 iter_slices, guess_json_utf, super_len, to_native_string)
27 from .compat import ( 29 from .compat import (
28 cookielib, urlparse, urlunparse, urlsplit, urlencode, str, bytes, StringIO, 30 cookielib, urlunparse, urlsplit, urlencode, str, bytes, StringIO,
29 is_py2, chardet, json, builtin_str, basestring) 31 is_py2, chardet, json, builtin_str, basestring, IncompleteRead)
30 32
31 CONTENT_CHUNK_SIZE = 10 * 1024 33 CONTENT_CHUNK_SIZE = 10 * 1024
32 ITER_CHUNK_SIZE = 512 34 ITER_CHUNK_SIZE = 512
33 35
34 log = logging.getLogger(__name__) 36 log = logging.getLogger(__name__)
35 37
36 38
37 class RequestEncodingMixin(object): 39 class RequestEncodingMixin(object):
38 @property 40 @property
39 def path_url(self): 41 def path_url(self):
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 87
86 @staticmethod 88 @staticmethod
87 def _encode_files(files, data): 89 def _encode_files(files, data):
88 """Build the body for a multipart/form-data request. 90 """Build the body for a multipart/form-data request.
89 91
90 Will successfully encode files when passed as a dict or a list of 92 Will successfully encode files when passed as a dict or a list of
91 2-tuples. Order is retained if data is a list of 2-tuples but abritrary 93 2-tuples. Order is retained if data is a list of 2-tuples but abritrary
92 if parameters are supplied as a dict. 94 if parameters are supplied as a dict.
93 95
94 """ 96 """
95 if (not files) or isinstance(data, str): 97 if (not files):
96 return None 98 raise ValueError("Files must be provided.")
99 elif isinstance(data, basestring):
100 raise ValueError("Data must not be a string.")
97 101
98 new_fields = [] 102 new_fields = []
99 fields = to_key_val_list(data or {}) 103 fields = to_key_val_list(data or {})
100 files = to_key_val_list(files or {}) 104 files = to_key_val_list(files or {})
101 105
102 for field, val in fields: 106 for field, val in fields:
103 if isinstance(val, basestring) or not hasattr(val, '__iter__'): 107 if isinstance(val, basestring) or not hasattr(val, '__iter__'):
104 val = [val] 108 val = [val]
105 for v in val: 109 for v in val:
106 if v is not None: 110 if v is not None:
111 # Don't call str() on bytestrings: in Py3 it all goes wrong.
112 if not isinstance(v, bytes):
113 v = str(v)
114
107 new_fields.append( 115 new_fields.append(
108 (field.decode('utf-8') if isinstance(field, bytes) else field, 116 (field.decode('utf-8') if isinstance(field, bytes) else field,
109 v.encode('utf-8') if isinstance(v, str) else v)) 117 v.encode('utf-8') if isinstance(v, str) else v))
110 118
111 for (k, v) in files: 119 for (k, v) in files:
112 # support for explicit filename 120 # support for explicit filename
113 ft = None 121 ft = None
114 if isinstance(v, (tuple, list)): 122 if isinstance(v, (tuple, list)):
115 if len(v) == 2: 123 if len(v) == 2:
116 fn, fp = v 124 fn, fp = v
(...skipping 15 matching lines...) Expand all
132 140
133 body, content_type = encode_multipart_formdata(new_fields) 141 body, content_type = encode_multipart_formdata(new_fields)
134 142
135 return body, content_type 143 return body, content_type
136 144
137 145
138 class RequestHooksMixin(object): 146 class RequestHooksMixin(object):
139 def register_hook(self, event, hook): 147 def register_hook(self, event, hook):
140 """Properly register a hook.""" 148 """Properly register a hook."""
141 149
150 if event not in self.hooks:
151 raise ValueError('Unsupported event specified, with event name "%s"' % (event))
152
142 if isinstance(hook, collections.Callable): 153 if isinstance(hook, collections.Callable):
143 self.hooks[event].append(hook) 154 self.hooks[event].append(hook)
144 elif hasattr(hook, '__iter__'): 155 elif hasattr(hook, '__iter__'):
145 self.hooks[event].extend(h for h in hook if isinstance(h, collection s.Callable)) 156 self.hooks[event].extend(h for h in hook if isinstance(h, collection s.Callable))
146 157
147 def deregister_hook(self, event, hook): 158 def deregister_hook(self, event, hook):
148 """Deregister a previously registered hook. 159 """Deregister a previously registered hook.
149 Returns True if the hook existed, False if not. 160 Returns True if the hook existed, False if not.
150 """ 161 """
151 162
(...skipping 25 matching lines...) Expand all
177 >>> req = requests.Request('GET', 'http://httpbin.org/get') 188 >>> req = requests.Request('GET', 'http://httpbin.org/get')
178 >>> req.prepare() 189 >>> req.prepare()
179 <PreparedRequest [GET]> 190 <PreparedRequest [GET]>
180 191
181 """ 192 """
182 def __init__(self, 193 def __init__(self,
183 method=None, 194 method=None,
184 url=None, 195 url=None,
185 headers=None, 196 headers=None,
186 files=None, 197 files=None,
187 data=dict(), 198 data=None,
188 params=dict(), 199 params=None,
189 auth=None, 200 auth=None,
190 cookies=None, 201 cookies=None,
191 hooks=None): 202 hooks=None):
192 203
193 # Default empty dicts for dict params. 204 # Default empty dicts for dict params.
194 data = [] if data is None else data 205 data = [] if data is None else data
195 files = [] if files is None else files 206 files = [] if files is None else files
196 headers = {} if headers is None else headers 207 headers = {} if headers is None else headers
197 params = {} if params is None else params 208 params = {} if params is None else params
198 hooks = {} if hooks is None else hooks 209 hooks = {} if hooks is None else hooks
199 210
200 self.hooks = default_hooks() 211 self.hooks = default_hooks()
201 for (k, v) in list(hooks.items()): 212 for (k, v) in list(hooks.items()):
202 self.register_hook(event=k, hook=v) 213 self.register_hook(event=k, hook=v)
203 214
204 self.method = method 215 self.method = method
205 self.url = url 216 self.url = url
206 self.headers = headers 217 self.headers = headers
207 self.files = files 218 self.files = files
208 self.data = data 219 self.data = data
209 self.params = params 220 self.params = params
210 self.auth = auth 221 self.auth = auth
211 self.cookies = cookies 222 self.cookies = cookies
212 self.hooks = hooks
213 223
214 def __repr__(self): 224 def __repr__(self):
215 return '<Request [%s]>' % (self.method) 225 return '<Request [%s]>' % (self.method)
216 226
217 def prepare(self): 227 def prepare(self):
218 """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmiss ion and returns it.""" 228 """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmiss ion and returns it."""
219 p = PreparedRequest() 229 p = PreparedRequest()
220 230 p.prepare(
221 p.prepare_method(self.method) 231 method=self.method,
222 p.prepare_url(self.url, self.params) 232 url=self.url,
223 p.prepare_headers(self.headers) 233 headers=self.headers,
224 p.prepare_cookies(self.cookies) 234 files=self.files,
225 p.prepare_body(self.data, self.files) 235 data=self.data,
226 p.prepare_auth(self.auth, self.url) 236 params=self.params,
227 # Note that prepare_auth must be last to enable authentication schemes 237 auth=self.auth,
228 # such as OAuth to work on a fully prepared request. 238 cookies=self.cookies,
229 239 hooks=self.hooks,
230 # This MUST go after prepare_auth. Authenticators could add a hook 240 )
231 p.prepare_hooks(self.hooks)
232
233 return p 241 return p
234 242
235 243
236 class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): 244 class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
237 """The fully mutable :class:`PreparedRequest <PreparedRequest>` object, 245 """The fully mutable :class:`PreparedRequest <PreparedRequest>` object,
238 containing the exact bytes that will be sent to the server. 246 containing the exact bytes that will be sent to the server.
239 247
240 Generated from either a :class:`Request <Request>` object or manually. 248 Generated from either a :class:`Request <Request>` object or manually.
241 249
242 Usage:: 250 Usage::
(...skipping 14 matching lines...) Expand all
257 self.method = None 265 self.method = None
258 #: HTTP URL to send the request to. 266 #: HTTP URL to send the request to.
259 self.url = None 267 self.url = None
260 #: dictionary of HTTP headers. 268 #: dictionary of HTTP headers.
261 self.headers = None 269 self.headers = None
262 #: request body to send to the server. 270 #: request body to send to the server.
263 self.body = None 271 self.body = None
264 #: dictionary of callback hooks, for internal usage. 272 #: dictionary of callback hooks, for internal usage.
265 self.hooks = default_hooks() 273 self.hooks = default_hooks()
266 274
275 def prepare(self, method=None, url=None, headers=None, files=None,
276 data=None, params=None, auth=None, cookies=None, hooks=None):
277 """Prepares the the entire request with the given parameters."""
278
279 self.prepare_method(method)
280 self.prepare_url(url, params)
281 self.prepare_headers(headers)
282 self.prepare_cookies(cookies)
283 self.prepare_body(data, files)
284 self.prepare_auth(auth, url)
285 # Note that prepare_auth must be last to enable authentication schemes
286 # such as OAuth to work on a fully prepared request.
287
288 # This MUST go after prepare_auth. Authenticators could add a hook
289 self.prepare_hooks(hooks)
290
267 def __repr__(self): 291 def __repr__(self):
268 return '<PreparedRequest [%s]>' % (self.method) 292 return '<PreparedRequest [%s]>' % (self.method)
269 293
294 def copy(self):
295 p = PreparedRequest()
296 p.method = self.method
297 p.url = self.url
298 p.headers = self.headers
299 p.body = self.body
300 p.hooks = self.hooks
301 return p
302
270 def prepare_method(self, method): 303 def prepare_method(self, method):
271 """Prepares the given HTTP method.""" 304 """Prepares the given HTTP method."""
272 self.method = method 305 self.method = method
273 if self.method is not None: 306 if self.method is not None:
274 self.method = self.method.upper() 307 self.method = self.method.upper()
275 308
276 def prepare_url(self, url, params): 309 def prepare_url(self, url, params):
277 """Prepares the given HTTP URL.""" 310 """Prepares the given HTTP URL."""
278 #: Accept objects that have string representations. 311 #: Accept objects that have string representations.
279 try: 312 try:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 else: 363 else:
331 query = enc_params 364 query = enc_params
332 365
333 url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragmen t])) 366 url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragmen t]))
334 self.url = url 367 self.url = url
335 368
336 def prepare_headers(self, headers): 369 def prepare_headers(self, headers):
337 """Prepares the given HTTP headers.""" 370 """Prepares the given HTTP headers."""
338 371
339 if headers: 372 if headers:
340 headers = dict((name.encode('ascii'), value) for name, value in head ers.items()) 373 self.headers = CaseInsensitiveDict((to_native_string(name), value) f or name, value in headers.items())
341 self.headers = CaseInsensitiveDict(headers)
342 else: 374 else:
343 self.headers = CaseInsensitiveDict() 375 self.headers = CaseInsensitiveDict()
344 376
345 def prepare_body(self, data, files): 377 def prepare_body(self, data, files):
346 """Prepares the given HTTP body data.""" 378 """Prepares the given HTTP body data."""
347 379
348 # Check if file, fo, generator, iterator. 380 # Check if file, fo, generator, iterator.
349 # If not, run through normal process. 381 # If not, run through normal process.
350 382
351 # Nottin' on you. 383 # Nottin' on you.
352 body = None 384 body = None
353 content_type = None 385 content_type = None
354 length = None 386 length = None
355 is_stream = False
356 387
357 is_stream = all([ 388 is_stream = all([
358 hasattr(data, '__iter__'), 389 hasattr(data, '__iter__'),
359 not isinstance(data, basestring), 390 not isinstance(data, basestring),
360 not isinstance(data, list), 391 not isinstance(data, list),
361 not isinstance(data, dict) 392 not isinstance(data, dict)
362 ]) 393 ])
363 394
364 try: 395 try:
365 length = super_len(data) 396 length = super_len(data)
366 except (TypeError, AttributeError): 397 except (TypeError, AttributeError, UnsupportedOperation):
367 length = False 398 length = None
368 399
369 if is_stream: 400 if is_stream:
370 body = data 401 body = data
371 402
372 if files: 403 if files:
373 raise NotImplementedError('Streamed bodies and files are mutuall y exclusive.') 404 raise NotImplementedError('Streamed bodies and files are mutuall y exclusive.')
374 405
375 if length: 406 if length is not None:
376 self.headers['Content-Length'] = str(length) 407 self.headers['Content-Length'] = str(length)
377 else: 408 else:
378 self.headers['Transfer-Encoding'] = 'chunked' 409 self.headers['Transfer-Encoding'] = 'chunked'
379 # Check if file, fo, generator, iterator.
380 # If not, run through normal process.
381
382 else: 410 else:
383 # Multi-part file uploads. 411 # Multi-part file uploads.
384 if files: 412 if files:
385 (body, content_type) = self._encode_files(files, data) 413 (body, content_type) = self._encode_files(files, data)
386 else: 414 else:
387 if data: 415 if data:
388 body = self._encode_params(data) 416 body = self._encode_params(data)
389 if isinstance(data, str) or isinstance(data, builtin_str) or hasattr(data, 'read'): 417 if isinstance(data, str) or isinstance(data, builtin_str) or hasattr(data, 'read'):
390 content_type = None 418 content_type = None
391 else: 419 else:
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 request, this avoids reading the content at once into memory for 558 request, this avoids reading the content at once into memory for
531 large responses. The chunk size is the number of bytes it should 559 large responses. The chunk size is the number of bytes it should
532 read into memory. This is not necessarily the length of each item 560 read into memory. This is not necessarily the length of each item
533 returned as decoding can take place. 561 returned as decoding can take place.
534 """ 562 """
535 if self._content_consumed: 563 if self._content_consumed:
536 # simulate reading small chunks of the content 564 # simulate reading small chunks of the content
537 return iter_slices(self._content, chunk_size) 565 return iter_slices(self._content, chunk_size)
538 566
539 def generate(): 567 def generate():
540 while 1: 568 try:
541 chunk = self.raw.read(chunk_size, decode_content=True) 569 # Special case for urllib3.
542 if not chunk: 570 try:
543 break 571 for chunk in self.raw.stream(chunk_size,
544 yield chunk 572 decode_content=True):
573 yield chunk
574 except IncompleteRead as e:
575 raise ChunkedEncodingError(e)
576 except AttributeError:
577 # Standard file-like object.
578 while 1:
579 chunk = self.raw.read(chunk_size)
580 if not chunk:
581 break
582 yield chunk
583
545 self._content_consumed = True 584 self._content_consumed = True
546 585
547 gen = generate() 586 gen = generate()
548 587
549 if decode_unicode: 588 if decode_unicode:
550 gen = stream_decode_response_unicode(gen, self) 589 gen = stream_decode_response_unicode(gen, self)
551 590
552 return gen 591 return gen
553 592
554 def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None): 593 def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None):
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 if 400 <= self.status_code < 500: 715 if 400 <= self.status_code < 500:
677 http_error_msg = '%s Client Error: %s' % (self.status_code, self.rea son) 716 http_error_msg = '%s Client Error: %s' % (self.status_code, self.rea son)
678 717
679 elif 500 <= self.status_code < 600: 718 elif 500 <= self.status_code < 600:
680 http_error_msg = '%s Server Error: %s' % (self.status_code, self.rea son) 719 http_error_msg = '%s Server Error: %s' % (self.status_code, self.rea son)
681 720
682 if http_error_msg: 721 if http_error_msg:
683 raise HTTPError(http_error_msg, response=self) 722 raise HTTPError(http_error_msg, response=self)
684 723
685 def close(self): 724 def close(self):
725 """Closes the underlying file descriptor and releases the connection
726 back to the pool.
727
728 *Note: Should not normally need to be called explicitly.*
729 """
686 return self.raw.release_conn() 730 return self.raw.release_conn()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698