~anitanayak/charms/trusty/ibm-mq/ibm-mq-trusty

« back to all changes in this revision

Viewing changes to .tox/py35/lib/python3.5/site-packages/pip/_vendor/requests/models.py

  • Committer: Anita Nayak
  • Date: 2016-10-24 07:10:08 UTC
  • Revision ID: anitanayak@in.ibm.com-20161024071008-tqk3cefak6nc1c69
checking in after fixing lint errors

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
"""
 
4
requests.models
 
5
~~~~~~~~~~~~~~~
 
6
 
 
7
This module contains the primary objects that power Requests.
 
8
"""
 
9
 
 
10
import collections
 
11
import datetime
 
12
 
 
13
from io import BytesIO, UnsupportedOperation
 
14
from .hooks import default_hooks
 
15
from .structures import CaseInsensitiveDict
 
16
 
 
17
from .auth import HTTPBasicAuth
 
18
from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar
 
19
from .packages.urllib3.fields import RequestField
 
20
from .packages.urllib3.filepost import encode_multipart_formdata
 
21
from .packages.urllib3.util import parse_url
 
22
from .packages.urllib3.exceptions import (
 
23
    DecodeError, ReadTimeoutError, ProtocolError, LocationParseError)
 
24
from .exceptions import (
 
25
    HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError,
 
26
    ContentDecodingError, ConnectionError, StreamConsumedError)
 
27
from .utils import (
 
28
    guess_filename, get_auth_from_url, requote_uri,
 
29
    stream_decode_response_unicode, to_key_val_list, parse_header_links,
 
30
    iter_slices, guess_json_utf, super_len, to_native_string)
 
31
from .compat import (
 
32
    cookielib, urlunparse, urlsplit, urlencode, str, bytes, StringIO,
 
33
    is_py2, chardet, builtin_str, basestring)
 
34
from .compat import json as complexjson
 
35
from .status_codes import codes
 
36
 
 
37
#: The set of HTTP status codes that indicate an automatically
 
38
#: processable redirect.
 
39
REDIRECT_STATI = (
 
40
    codes.moved,              # 301
 
41
    codes.found,              # 302
 
42
    codes.other,              # 303
 
43
    codes.temporary_redirect, # 307
 
44
    codes.permanent_redirect, # 308
 
45
)
 
46
 
 
47
DEFAULT_REDIRECT_LIMIT = 30
 
48
CONTENT_CHUNK_SIZE = 10 * 1024
 
49
ITER_CHUNK_SIZE = 512
 
50
 
 
51
 
 
52
class RequestEncodingMixin(object):
 
53
    @property
 
54
    def path_url(self):
 
55
        """Build the path URL to use."""
 
56
 
 
57
        url = []
 
58
 
 
59
        p = urlsplit(self.url)
 
60
 
 
61
        path = p.path
 
62
        if not path:
 
63
            path = '/'
 
64
 
 
65
        url.append(path)
 
66
 
 
67
        query = p.query
 
68
        if query:
 
69
            url.append('?')
 
70
            url.append(query)
 
71
 
 
72
        return ''.join(url)
 
73
 
 
74
    @staticmethod
 
75
    def _encode_params(data):
 
76
        """Encode parameters in a piece of data.
 
77
 
 
78
        Will successfully encode parameters when passed as a dict or a list of
 
79
        2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
 
80
        if parameters are supplied as a dict.
 
81
        """
 
82
 
 
83
        if isinstance(data, (str, bytes)):
 
84
            return data
 
85
        elif hasattr(data, 'read'):
 
86
            return data
 
87
        elif hasattr(data, '__iter__'):
 
88
            result = []
 
89
            for k, vs in to_key_val_list(data):
 
90
                if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
 
91
                    vs = [vs]
 
92
                for v in vs:
 
93
                    if v is not None:
 
94
                        result.append(
 
95
                            (k.encode('utf-8') if isinstance(k, str) else k,
 
96
                             v.encode('utf-8') if isinstance(v, str) else v))
 
97
            return urlencode(result, doseq=True)
 
98
        else:
 
99
            return data
 
100
 
 
101
    @staticmethod
 
102
    def _encode_files(files, data):
 
103
        """Build the body for a multipart/form-data request.
 
104
 
 
105
        Will successfully encode files when passed as a dict or a list of
 
106
        tuples. Order is retained if data is a list of tuples but arbitrary
 
107
        if parameters are supplied as a dict.
 
108
        The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype)
 
109
        or 4-tuples (filename, fileobj, contentype, custom_headers).
 
110
 
 
111
        """
 
112
        if (not files):
 
113
            raise ValueError("Files must be provided.")
 
114
        elif isinstance(data, basestring):
 
115
            raise ValueError("Data must not be a string.")
 
116
 
 
117
        new_fields = []
 
118
        fields = to_key_val_list(data or {})
 
119
        files = to_key_val_list(files or {})
 
120
 
 
121
        for field, val in fields:
 
122
            if isinstance(val, basestring) or not hasattr(val, '__iter__'):
 
123
                val = [val]
 
124
            for v in val:
 
125
                if v is not None:
 
126
                    # Don't call str() on bytestrings: in Py3 it all goes wrong.
 
127
                    if not isinstance(v, bytes):
 
128
                        v = str(v)
 
129
 
 
130
                    new_fields.append(
 
131
                        (field.decode('utf-8') if isinstance(field, bytes) else field,
 
132
                         v.encode('utf-8') if isinstance(v, str) else v))
 
133
 
 
134
        for (k, v) in files:
 
135
            # support for explicit filename
 
136
            ft = None
 
137
            fh = None
 
138
            if isinstance(v, (tuple, list)):
 
139
                if len(v) == 2:
 
140
                    fn, fp = v
 
141
                elif len(v) == 3:
 
142
                    fn, fp, ft = v
 
143
                else:
 
144
                    fn, fp, ft, fh = v
 
145
            else:
 
146
                fn = guess_filename(v) or k
 
147
                fp = v
 
148
 
 
149
            if isinstance(fp, (str, bytes, bytearray)):
 
150
                fdata = fp
 
151
            else:
 
152
                fdata = fp.read()
 
153
 
 
154
            rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
 
155
            rf.make_multipart(content_type=ft)
 
156
            new_fields.append(rf)
 
157
 
 
158
        body, content_type = encode_multipart_formdata(new_fields)
 
159
 
 
160
        return body, content_type
 
161
 
 
162
 
 
163
class RequestHooksMixin(object):
 
164
    def register_hook(self, event, hook):
 
165
        """Properly register a hook."""
 
166
 
 
167
        if event not in self.hooks:
 
168
            raise ValueError('Unsupported event specified, with event name "%s"' % (event))
 
169
 
 
170
        if isinstance(hook, collections.Callable):
 
171
            self.hooks[event].append(hook)
 
172
        elif hasattr(hook, '__iter__'):
 
173
            self.hooks[event].extend(h for h in hook if isinstance(h, collections.Callable))
 
174
 
 
175
    def deregister_hook(self, event, hook):
 
176
        """Deregister a previously registered hook.
 
177
        Returns True if the hook existed, False if not.
 
178
        """
 
179
 
 
180
        try:
 
181
            self.hooks[event].remove(hook)
 
182
            return True
 
183
        except ValueError:
 
184
            return False
 
185
 
 
186
 
 
187
class Request(RequestHooksMixin):
 
188
    """A user-created :class:`Request <Request>` object.
 
189
 
 
190
    Used to prepare a :class:`PreparedRequest <PreparedRequest>`, which is sent to the server.
 
191
 
 
192
    :param method: HTTP method to use.
 
193
    :param url: URL to send.
 
194
    :param headers: dictionary of headers to send.
 
195
    :param files: dictionary of {filename: fileobject} files to multipart upload.
 
196
    :param data: the body to attach to the request. If a dictionary is provided, form-encoding will take place.
 
197
    :param json: json for the body to attach to the request (if files or data is not specified).
 
198
    :param params: dictionary of URL parameters to append to the URL.
 
199
    :param auth: Auth handler or (user, pass) tuple.
 
200
    :param cookies: dictionary or CookieJar of cookies to attach to this request.
 
201
    :param hooks: dictionary of callback hooks, for internal usage.
 
202
 
 
203
    Usage::
 
204
 
 
205
      >>> import requests
 
206
      >>> req = requests.Request('GET', 'http://httpbin.org/get')
 
207
      >>> req.prepare()
 
208
      <PreparedRequest [GET]>
 
209
 
 
210
    """
 
211
    def __init__(self, method=None, url=None, headers=None, files=None,
 
212
        data=None, params=None, auth=None, cookies=None, hooks=None, json=None):
 
213
 
 
214
        # Default empty dicts for dict params.
 
215
        data = [] if data is None else data
 
216
        files = [] if files is None else files
 
217
        headers = {} if headers is None else headers
 
218
        params = {} if params is None else params
 
219
        hooks = {} if hooks is None else hooks
 
220
 
 
221
        self.hooks = default_hooks()
 
222
        for (k, v) in list(hooks.items()):
 
223
            self.register_hook(event=k, hook=v)
 
224
 
 
225
        self.method = method
 
226
        self.url = url
 
227
        self.headers = headers
 
228
        self.files = files
 
229
        self.data = data
 
230
        self.json = json
 
231
        self.params = params
 
232
        self.auth = auth
 
233
        self.cookies = cookies
 
234
 
 
235
    def __repr__(self):
 
236
        return '<Request [%s]>' % (self.method)
 
237
 
 
238
    def prepare(self):
 
239
        """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it."""
 
240
        p = PreparedRequest()
 
241
        p.prepare(
 
242
            method=self.method,
 
243
            url=self.url,
 
244
            headers=self.headers,
 
245
            files=self.files,
 
246
            data=self.data,
 
247
            json=self.json,
 
248
            params=self.params,
 
249
            auth=self.auth,
 
250
            cookies=self.cookies,
 
251
            hooks=self.hooks,
 
252
        )
 
253
        return p
 
254
 
 
255
 
 
256
class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
 
257
    """The fully mutable :class:`PreparedRequest <PreparedRequest>` object,
 
258
    containing the exact bytes that will be sent to the server.
 
259
 
 
260
    Generated from either a :class:`Request <Request>` object or manually.
 
261
 
 
262
    Usage::
 
263
 
 
264
      >>> import requests
 
265
      >>> req = requests.Request('GET', 'http://httpbin.org/get')
 
266
      >>> r = req.prepare()
 
267
      <PreparedRequest [GET]>
 
268
 
 
269
      >>> s = requests.Session()
 
270
      >>> s.send(r)
 
271
      <Response [200]>
 
272
 
 
273
    """
 
274
 
 
275
    def __init__(self):
 
276
        #: HTTP verb to send to the server.
 
277
        self.method = None
 
278
        #: HTTP URL to send the request to.
 
279
        self.url = None
 
280
        #: dictionary of HTTP headers.
 
281
        self.headers = None
 
282
        # The `CookieJar` used to create the Cookie header will be stored here
 
283
        # after prepare_cookies is called
 
284
        self._cookies = None
 
285
        #: request body to send to the server.
 
286
        self.body = None
 
287
        #: dictionary of callback hooks, for internal usage.
 
288
        self.hooks = default_hooks()
 
289
 
 
290
    def prepare(self, method=None, url=None, headers=None, files=None,
 
291
        data=None, params=None, auth=None, cookies=None, hooks=None, json=None):
 
292
        """Prepares the entire request with the given parameters."""
 
293
 
 
294
        self.prepare_method(method)
 
295
        self.prepare_url(url, params)
 
296
        self.prepare_headers(headers)
 
297
        self.prepare_cookies(cookies)
 
298
        self.prepare_body(data, files, json)
 
299
        self.prepare_auth(auth, url)
 
300
 
 
301
        # Note that prepare_auth must be last to enable authentication schemes
 
302
        # such as OAuth to work on a fully prepared request.
 
303
 
 
304
        # This MUST go after prepare_auth. Authenticators could add a hook
 
305
        self.prepare_hooks(hooks)
 
306
 
 
307
    def __repr__(self):
 
308
        return '<PreparedRequest [%s]>' % (self.method)
 
309
 
 
310
    def copy(self):
 
311
        p = PreparedRequest()
 
312
        p.method = self.method
 
313
        p.url = self.url
 
314
        p.headers = self.headers.copy() if self.headers is not None else None
 
315
        p._cookies = _copy_cookie_jar(self._cookies)
 
316
        p.body = self.body
 
317
        p.hooks = self.hooks
 
318
        return p
 
319
 
 
320
    def prepare_method(self, method):
 
321
        """Prepares the given HTTP method."""
 
322
        self.method = method
 
323
        if self.method is not None:
 
324
            self.method = to_native_string(self.method.upper())
 
325
 
 
326
    def prepare_url(self, url, params):
 
327
        """Prepares the given HTTP URL."""
 
328
        #: Accept objects that have string representations.
 
329
        #: We're unable to blindly call unicode/str functions
 
330
        #: as this will include the bytestring indicator (b'')
 
331
        #: on python 3.x.
 
332
        #: https://github.com/kennethreitz/requests/pull/2238
 
333
        if isinstance(url, bytes):
 
334
            url = url.decode('utf8')
 
335
        else:
 
336
            url = unicode(url) if is_py2 else str(url)
 
337
 
 
338
        # Don't do any URL preparation for non-HTTP schemes like `mailto`,
 
339
        # `data` etc to work around exceptions from `url_parse`, which
 
340
        # handles RFC 3986 only.
 
341
        if ':' in url and not url.lower().startswith('http'):
 
342
            self.url = url
 
343
            return
 
344
 
 
345
        # Support for unicode domain names and paths.
 
346
        try:
 
347
            scheme, auth, host, port, path, query, fragment = parse_url(url)
 
348
        except LocationParseError as e:
 
349
            raise InvalidURL(*e.args)
 
350
 
 
351
        if not scheme:
 
352
            error = ("Invalid URL {0!r}: No schema supplied. Perhaps you meant http://{0}?")
 
353
            error = error.format(to_native_string(url, 'utf8'))
 
354
 
 
355
            raise MissingSchema(error)
 
356
 
 
357
        if not host:
 
358
            raise InvalidURL("Invalid URL %r: No host supplied" % url)
 
359
 
 
360
        # Only want to apply IDNA to the hostname
 
361
        try:
 
362
            host = host.encode('idna').decode('utf-8')
 
363
        except UnicodeError:
 
364
            raise InvalidURL('URL has an invalid label.')
 
365
 
 
366
        # Carefully reconstruct the network location
 
367
        netloc = auth or ''
 
368
        if netloc:
 
369
            netloc += '@'
 
370
        netloc += host
 
371
        if port:
 
372
            netloc += ':' + str(port)
 
373
 
 
374
        # Bare domains aren't valid URLs.
 
375
        if not path:
 
376
            path = '/'
 
377
 
 
378
        if is_py2:
 
379
            if isinstance(scheme, str):
 
380
                scheme = scheme.encode('utf-8')
 
381
            if isinstance(netloc, str):
 
382
                netloc = netloc.encode('utf-8')
 
383
            if isinstance(path, str):
 
384
                path = path.encode('utf-8')
 
385
            if isinstance(query, str):
 
386
                query = query.encode('utf-8')
 
387
            if isinstance(fragment, str):
 
388
                fragment = fragment.encode('utf-8')
 
389
 
 
390
        if isinstance(params, (str, bytes)):
 
391
            params = to_native_string(params)
 
392
 
 
393
        enc_params = self._encode_params(params)
 
394
        if enc_params:
 
395
            if query:
 
396
                query = '%s&%s' % (query, enc_params)
 
397
            else:
 
398
                query = enc_params
 
399
 
 
400
        url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment]))
 
401
        self.url = url
 
402
 
 
403
    def prepare_headers(self, headers):
 
404
        """Prepares the given HTTP headers."""
 
405
 
 
406
        if headers:
 
407
            self.headers = CaseInsensitiveDict((to_native_string(name), value) for name, value in headers.items())
 
408
        else:
 
409
            self.headers = CaseInsensitiveDict()
 
410
 
 
411
    def prepare_body(self, data, files, json=None):
 
412
        """Prepares the given HTTP body data."""
 
413
 
 
414
        # Check if file, fo, generator, iterator.
 
415
        # If not, run through normal process.
 
416
 
 
417
        # Nottin' on you.
 
418
        body = None
 
419
        content_type = None
 
420
        length = None
 
421
 
 
422
        if not data and json is not None:
 
423
            content_type = 'application/json'
 
424
            body = complexjson.dumps(json)
 
425
 
 
426
        is_stream = all([
 
427
            hasattr(data, '__iter__'),
 
428
            not isinstance(data, (basestring, list, tuple, dict))
 
429
        ])
 
430
 
 
431
        try:
 
432
            length = super_len(data)
 
433
        except (TypeError, AttributeError, UnsupportedOperation):
 
434
            length = None
 
435
 
 
436
        if is_stream:
 
437
            body = data
 
438
 
 
439
            if files:
 
440
                raise NotImplementedError('Streamed bodies and files are mutually exclusive.')
 
441
 
 
442
            if length:
 
443
                self.headers['Content-Length'] = builtin_str(length)
 
444
            else:
 
445
                self.headers['Transfer-Encoding'] = 'chunked'
 
446
        else:
 
447
            # Multi-part file uploads.
 
448
            if files:
 
449
                (body, content_type) = self._encode_files(files, data)
 
450
            else:
 
451
                if data:
 
452
                    body = self._encode_params(data)
 
453
                    if isinstance(data, basestring) or hasattr(data, 'read'):
 
454
                        content_type = None
 
455
                    else:
 
456
                        content_type = 'application/x-www-form-urlencoded'
 
457
 
 
458
            self.prepare_content_length(body)
 
459
 
 
460
            # Add content-type if it wasn't explicitly provided.
 
461
            if content_type and ('content-type' not in self.headers):
 
462
                self.headers['Content-Type'] = content_type
 
463
 
 
464
        self.body = body
 
465
 
 
466
    def prepare_content_length(self, body):
 
467
        if hasattr(body, 'seek') and hasattr(body, 'tell'):
 
468
            curr_pos = body.tell()
 
469
            body.seek(0, 2)
 
470
            end_pos = body.tell()
 
471
            self.headers['Content-Length'] = builtin_str(max(0, end_pos - curr_pos))
 
472
            body.seek(curr_pos, 0)
 
473
        elif body is not None:
 
474
            l = super_len(body)
 
475
            if l:
 
476
                self.headers['Content-Length'] = builtin_str(l)
 
477
        elif (self.method not in ('GET', 'HEAD')) and (self.headers.get('Content-Length') is None):
 
478
            self.headers['Content-Length'] = '0'
 
479
 
 
480
    def prepare_auth(self, auth, url=''):
 
481
        """Prepares the given HTTP auth data."""
 
482
 
 
483
        # If no Auth is explicitly provided, extract it from the URL first.
 
484
        if auth is None:
 
485
            url_auth = get_auth_from_url(self.url)
 
486
            auth = url_auth if any(url_auth) else None
 
487
 
 
488
        if auth:
 
489
            if isinstance(auth, tuple) and len(auth) == 2:
 
490
                # special-case basic HTTP auth
 
491
                auth = HTTPBasicAuth(*auth)
 
492
 
 
493
            # Allow auth to make its changes.
 
494
            r = auth(self)
 
495
 
 
496
            # Update self to reflect the auth changes.
 
497
            self.__dict__.update(r.__dict__)
 
498
 
 
499
            # Recompute Content-Length
 
500
            self.prepare_content_length(self.body)
 
501
 
 
502
    def prepare_cookies(self, cookies):
 
503
        """Prepares the given HTTP cookie data.
 
504
 
 
505
        This function eventually generates a ``Cookie`` header from the
 
506
        given cookies using cookielib. Due to cookielib's design, the header
 
507
        will not be regenerated if it already exists, meaning this function
 
508
        can only be called once for the life of the
 
509
        :class:`PreparedRequest <PreparedRequest>` object. Any subsequent calls
 
510
        to ``prepare_cookies`` will have no actual effect, unless the "Cookie"
 
511
        header is removed beforehand."""
 
512
 
 
513
        if isinstance(cookies, cookielib.CookieJar):
 
514
            self._cookies = cookies
 
515
        else:
 
516
            self._cookies = cookiejar_from_dict(cookies)
 
517
 
 
518
        cookie_header = get_cookie_header(self._cookies, self)
 
519
        if cookie_header is not None:
 
520
            self.headers['Cookie'] = cookie_header
 
521
 
 
522
    def prepare_hooks(self, hooks):
 
523
        """Prepares the given hooks."""
 
524
        # hooks can be passed as None to the prepare method and to this
 
525
        # method. To prevent iterating over None, simply use an empty list
 
526
        # if hooks is False-y
 
527
        hooks = hooks or []
 
528
        for event in hooks:
 
529
            self.register_hook(event, hooks[event])
 
530
 
 
531
 
 
532
class Response(object):
 
533
    """The :class:`Response <Response>` object, which contains a
 
534
    server's response to an HTTP request.
 
535
    """
 
536
 
 
537
    __attrs__ = [
 
538
        '_content', 'status_code', 'headers', 'url', 'history',
 
539
        'encoding', 'reason', 'cookies', 'elapsed', 'request'
 
540
    ]
 
541
 
 
542
    def __init__(self):
 
543
        super(Response, self).__init__()
 
544
 
 
545
        self._content = False
 
546
        self._content_consumed = False
 
547
 
 
548
        #: Integer Code of responded HTTP Status, e.g. 404 or 200.
 
549
        self.status_code = None
 
550
 
 
551
        #: Case-insensitive Dictionary of Response Headers.
 
552
        #: For example, ``headers['content-encoding']`` will return the
 
553
        #: value of a ``'Content-Encoding'`` response header.
 
554
        self.headers = CaseInsensitiveDict()
 
555
 
 
556
        #: File-like object representation of response (for advanced usage).
 
557
        #: Use of ``raw`` requires that ``stream=True`` be set on the request.
 
558
        # This requirement does not apply for use internally to Requests.
 
559
        self.raw = None
 
560
 
 
561
        #: Final URL location of Response.
 
562
        self.url = None
 
563
 
 
564
        #: Encoding to decode with when accessing r.text.
 
565
        self.encoding = None
 
566
 
 
567
        #: A list of :class:`Response <Response>` objects from
 
568
        #: the history of the Request. Any redirect responses will end
 
569
        #: up here. The list is sorted from the oldest to the most recent request.
 
570
        self.history = []
 
571
 
 
572
        #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK".
 
573
        self.reason = None
 
574
 
 
575
        #: A CookieJar of Cookies the server sent back.
 
576
        self.cookies = cookiejar_from_dict({})
 
577
 
 
578
        #: The amount of time elapsed between sending the request
 
579
        #: and the arrival of the response (as a timedelta).
 
580
        #: This property specifically measures the time taken between sending
 
581
        #: the first byte of the request and finishing parsing the headers. It
 
582
        #: is therefore unaffected by consuming the response content or the
 
583
        #: value of the ``stream`` keyword argument.
 
584
        self.elapsed = datetime.timedelta(0)
 
585
 
 
586
        #: The :class:`PreparedRequest <PreparedRequest>` object to which this
 
587
        #: is a response.
 
588
        self.request = None
 
589
 
 
590
    def __getstate__(self):
 
591
        # Consume everything; accessing the content attribute makes
 
592
        # sure the content has been fully read.
 
593
        if not self._content_consumed:
 
594
            self.content
 
595
 
 
596
        return dict(
 
597
            (attr, getattr(self, attr, None))
 
598
            for attr in self.__attrs__
 
599
        )
 
600
 
 
601
    def __setstate__(self, state):
 
602
        for name, value in state.items():
 
603
            setattr(self, name, value)
 
604
 
 
605
        # pickled objects do not have .raw
 
606
        setattr(self, '_content_consumed', True)
 
607
        setattr(self, 'raw', None)
 
608
 
 
609
    def __repr__(self):
 
610
        return '<Response [%s]>' % (self.status_code)
 
611
 
 
612
    def __bool__(self):
 
613
        """Returns true if :attr:`status_code` is 'OK'."""
 
614
        return self.ok
 
615
 
 
616
    def __nonzero__(self):
 
617
        """Returns true if :attr:`status_code` is 'OK'."""
 
618
        return self.ok
 
619
 
 
620
    def __iter__(self):
 
621
        """Allows you to use a response as an iterator."""
 
622
        return self.iter_content(128)
 
623
 
 
624
    @property
 
625
    def ok(self):
 
626
        try:
 
627
            self.raise_for_status()
 
628
        except HTTPError:
 
629
            return False
 
630
        return True
 
631
 
 
632
    @property
 
633
    def is_redirect(self):
 
634
        """True if this Response is a well-formed HTTP redirect that could have
 
635
        been processed automatically (by :meth:`Session.resolve_redirects`).
 
636
        """
 
637
        return ('location' in self.headers and self.status_code in REDIRECT_STATI)
 
638
 
 
639
    @property
 
640
    def is_permanent_redirect(self):
 
641
        """True if this Response one of the permanent versions of redirect"""
 
642
        return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect))
 
643
 
 
644
    @property
 
645
    def apparent_encoding(self):
 
646
        """The apparent encoding, provided by the chardet library"""
 
647
        return chardet.detect(self.content)['encoding']
 
648
 
 
649
    def iter_content(self, chunk_size=1, decode_unicode=False):
 
650
        """Iterates over the response data.  When stream=True is set on the
 
651
        request, this avoids reading the content at once into memory for
 
652
        large responses.  The chunk size is the number of bytes it should
 
653
        read into memory.  This is not necessarily the length of each item
 
654
        returned as decoding can take place.
 
655
 
 
656
        If decode_unicode is True, content will be decoded using the best
 
657
        available encoding based on the response.
 
658
        """
 
659
 
 
660
        def generate():
 
661
            # Special case for urllib3.
 
662
            if hasattr(self.raw, 'stream'):
 
663
                try:
 
664
                    for chunk in self.raw.stream(chunk_size, decode_content=True):
 
665
                        yield chunk
 
666
                except ProtocolError as e:
 
667
                    raise ChunkedEncodingError(e)
 
668
                except DecodeError as e:
 
669
                    raise ContentDecodingError(e)
 
670
                except ReadTimeoutError as e:
 
671
                    raise ConnectionError(e)
 
672
            else:
 
673
                # Standard file-like object.
 
674
                while True:
 
675
                    chunk = self.raw.read(chunk_size)
 
676
                    if not chunk:
 
677
                        break
 
678
                    yield chunk
 
679
 
 
680
            self._content_consumed = True
 
681
 
 
682
        if self._content_consumed and isinstance(self._content, bool):
 
683
            raise StreamConsumedError()
 
684
        # simulate reading small chunks of the content
 
685
        reused_chunks = iter_slices(self._content, chunk_size)
 
686
 
 
687
        stream_chunks = generate()
 
688
 
 
689
        chunks = reused_chunks if self._content_consumed else stream_chunks
 
690
 
 
691
        if decode_unicode:
 
692
            chunks = stream_decode_response_unicode(chunks, self)
 
693
 
 
694
        return chunks
 
695
 
 
696
    def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None, delimiter=None):
 
697
        """Iterates over the response data, one line at a time.  When
 
698
        stream=True is set on the request, this avoids reading the
 
699
        content at once into memory for large responses.
 
700
 
 
701
        .. note:: This method is not reentrant safe.
 
702
        """
 
703
 
 
704
        pending = None
 
705
 
 
706
        for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode):
 
707
 
 
708
            if pending is not None:
 
709
                chunk = pending + chunk
 
710
 
 
711
            if delimiter:
 
712
                lines = chunk.split(delimiter)
 
713
            else:
 
714
                lines = chunk.splitlines()
 
715
 
 
716
            if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]:
 
717
                pending = lines.pop()
 
718
            else:
 
719
                pending = None
 
720
 
 
721
            for line in lines:
 
722
                yield line
 
723
 
 
724
        if pending is not None:
 
725
            yield pending
 
726
 
 
727
    @property
 
728
    def content(self):
 
729
        """Content of the response, in bytes."""
 
730
 
 
731
        if self._content is False:
 
732
            # Read the contents.
 
733
            try:
 
734
                if self._content_consumed:
 
735
                    raise RuntimeError(
 
736
                        'The content for this response was already consumed')
 
737
 
 
738
                if self.status_code == 0:
 
739
                    self._content = None
 
740
                else:
 
741
                    self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
 
742
 
 
743
            except AttributeError:
 
744
                self._content = None
 
745
 
 
746
        self._content_consumed = True
 
747
        # don't need to release the connection; that's been handled by urllib3
 
748
        # since we exhausted the data.
 
749
        return self._content
 
750
 
 
751
    @property
 
752
    def text(self):
 
753
        """Content of the response, in unicode.
 
754
 
 
755
        If Response.encoding is None, encoding will be guessed using
 
756
        ``chardet``.
 
757
 
 
758
        The encoding of the response content is determined based solely on HTTP
 
759
        headers, following RFC 2616 to the letter. If you can take advantage of
 
760
        non-HTTP knowledge to make a better guess at the encoding, you should
 
761
        set ``r.encoding`` appropriately before accessing this property.
 
762
        """
 
763
 
 
764
        # Try charset from content-type
 
765
        content = None
 
766
        encoding = self.encoding
 
767
 
 
768
        if not self.content:
 
769
            return str('')
 
770
 
 
771
        # Fallback to auto-detected encoding.
 
772
        if self.encoding is None:
 
773
            encoding = self.apparent_encoding
 
774
 
 
775
        # Decode unicode from given encoding.
 
776
        try:
 
777
            content = str(self.content, encoding, errors='replace')
 
778
        except (LookupError, TypeError):
 
779
            # A LookupError is raised if the encoding was not found which could
 
780
            # indicate a misspelling or similar mistake.
 
781
            #
 
782
            # A TypeError can be raised if encoding is None
 
783
            #
 
784
            # So we try blindly encoding.
 
785
            content = str(self.content, errors='replace')
 
786
 
 
787
        return content
 
788
 
 
789
    def json(self, **kwargs):
 
790
        """Returns the json-encoded content of a response, if any.
 
791
 
 
792
        :param \*\*kwargs: Optional arguments that ``json.loads`` takes.
 
793
        """
 
794
 
 
795
        if not self.encoding and len(self.content) > 3:
 
796
            # No encoding set. JSON RFC 4627 section 3 states we should expect
 
797
            # UTF-8, -16 or -32. Detect which one to use; If the detection or
 
798
            # decoding fails, fall back to `self.text` (using chardet to make
 
799
            # a best guess).
 
800
            encoding = guess_json_utf(self.content)
 
801
            if encoding is not None:
 
802
                try:
 
803
                    return complexjson.loads(
 
804
                        self.content.decode(encoding), **kwargs
 
805
                    )
 
806
                except UnicodeDecodeError:
 
807
                    # Wrong UTF codec detected; usually because it's not UTF-8
 
808
                    # but some other 8-bit codec.  This is an RFC violation,
 
809
                    # and the server didn't bother to tell us what codec *was*
 
810
                    # used.
 
811
                    pass
 
812
        return complexjson.loads(self.text, **kwargs)
 
813
 
 
814
    @property
 
815
    def links(self):
 
816
        """Returns the parsed header links of the response, if any."""
 
817
 
 
818
        header = self.headers.get('link')
 
819
 
 
820
        # l = MultiDict()
 
821
        l = {}
 
822
 
 
823
        if header:
 
824
            links = parse_header_links(header)
 
825
 
 
826
            for link in links:
 
827
                key = link.get('rel') or link.get('url')
 
828
                l[key] = link
 
829
 
 
830
        return l
 
831
 
 
832
    def raise_for_status(self):
 
833
        """Raises stored :class:`HTTPError`, if one occurred."""
 
834
 
 
835
        http_error_msg = ''
 
836
 
 
837
        if 400 <= self.status_code < 500:
 
838
            http_error_msg = '%s Client Error: %s for url: %s' % (self.status_code, self.reason, self.url)
 
839
 
 
840
        elif 500 <= self.status_code < 600:
 
841
            http_error_msg = '%s Server Error: %s for url: %s' % (self.status_code, self.reason, self.url)
 
842
 
 
843
        if http_error_msg:
 
844
            raise HTTPError(http_error_msg, response=self)
 
845
 
 
846
    def close(self):
 
847
        """Releases the connection back to the pool. Once this method has been
 
848
        called the underlying ``raw`` object must not be accessed again.
 
849
 
 
850
        *Note: Should not normally need to be called explicitly.*
 
851
        """
 
852
        if not self._content_consumed:
 
853
            return self.raw.close()
 
854
 
 
855
        return self.raw.release_conn()