requests models this module contains the primary objects that power requests import encoding now to avoid implicit import later implicit import within threads may cause lookuperror when standard library is in a zip such as in embedded python see https github compsfrequestsissues3578 the set of http status codes that indicate an automatically processable redirect build the path url to use url p urlsplitself url path p path if not path path url appendpath query p query if query url append url appendquery return joinurl staticmethod def encodeparamsdata if isinstancedata str bytes return data elif hasattrdata read return data elif hasattrdata iter result for k vs in tokeyvallistdata if isinstancevs basestring or not hasattrvs iter vs vs for v in vs if v is not none result append k encodeutf8 if isinstancek str else k v encodeutf8 if isinstancev str else v return urlencoderesult doseqtrue else return data staticmethod def encodefilesfiles data if not files raise valueerrorfiles must be provided elif isinstancedata basestring raise valueerrordata must not be a string newfields fields tokeyvallistdata or files tokeyvallistfiles or for field val in fields if isinstanceval basestring or not hasattrval iter val val for v in val if v is not none don t call str on bytestrings in py3 it all goes wrong if not isinstancev bytes v strv newfields append field decodeutf8 if isinstancefield bytes else field v encodeutf8 if isinstancev str else v for k v in files support for explicit filename ft none fh none if isinstancev tuple list if lenv 2 fn fp v elif lenv 3 fn fp ft v else fn fp ft fh v else fn guessfilenamev or k fp v if isinstancefp str bytes bytearray fdata fp elif hasattrfp read fdata fp read elif fp is none continue else fdata fp rf requestfieldnamek datafdata filenamefn headersfh rf makemultipartcontenttypeft newfields appendrf body contenttype encodemultipartformdatanewfields return body contenttype class requesthooksmixin def registerhookself event hook deregister a previously registered hook returns true if the hook existed false if not a usercreated class request request object used to prepare a class preparedrequest preparedrequest which is sent to the server param method http method to use param url url to send param headers dictionary of headers to send param files dictionary of filename fileobject files to multipart upload param data the body to attach to the request if a dictionary or list of tuples key value is provided formencoding will take place param json json for the body to attach to the request if files or data is not specified param params url parameters to append to the url if a dictionary or list of tuples key value is provided formencoding will take place param auth auth handler or user pass tuple param cookies dictionary or cookiejar of cookies to attach to this request param hooks dictionary of callback hooks for internal usage usage import requests req requests request get https httpbin orgget req prepare preparedrequest get default empty dicts for dict params constructs a class preparedrequest preparedrequest for transmission and returns it p preparedrequest p prepare methodself method urlself url headersself headers filesself files dataself data jsonself json paramsself params authself auth cookiesself cookies hooksself hooks return p class preparedrequestrequestencodingmixin requesthooksmixin def initself http verb to send to the server self method none http url to send the request to self url none dictionary of http headers self headers none the cookiejar used to create the cookie header will be stored here after preparecookies is called self cookies none request body to send to the server self body none dictionary of callback hooks for internal usage self hooks defaulthooks integer denoting starting position of a readable filelike body self bodyposition none def prepare self methodnone urlnone headersnone filesnone datanone paramsnone authnone cookiesnone hooksnone jsonnone note that prepareauth must be last to enable authentication schemes such as oauth to work on a fully prepared request this must go after prepareauth authenticators could add a hook prepares the given http method self method method if self method is not none self method tonativestringself method upper staticmethod def getidnaencodedhosthost import idna try host idna encodehost uts46true decodeutf8 except idna idnaerror raise unicodeerror return host def prepareurlself url params accept objects that have string representations we re unable to blindly call unicodestr functions as this will include the bytestring indicator b on python 3 x https github compsfrequestspull2238 remove leading whitespaces from url don t do any url preparation for nonhttp schemes like mailto data etc to work around exceptions from urlparse which handles rfc 3986 only support for unicode domain names and paths in general we want to try idna encoding the hostname if the string contains nonascii characters this allows users to automatically get the correct idna behaviour for strings containing only ascii characters we need to also verify it doesn t start with a wildcard before allowing the unencoded hostname carefully reconstruct the network location bare domains aren t valid urls prepares the given http headers self headers caseinsensitivedict if headers for header in headers items raise exception on invalid header value checkheadervalidityheader name value header self headerstonativestringname value def preparebodyself data files jsonnone check if file fo generator iterator if not run through normal process nottin on you urllib3 requires a byteslike body python 2 s json dumps provides this natively but python 3 gives a unicode string record the current file position before reading this will allow us to rewind a file in the event of a redirect this differentiates from none allowing us to catch a failed tell later when trying to rewind the body multipart file uploads add contenttype if it wasn t explicitly provided prepare contentlength header based on request method and body if body is not none length superlenbody if length if length exists set it otherwise we fallback to transferencoding chunked self headerscontentlength builtinstrlength elif self method not in get head and self headers getcontentlength is none set contentlength to 0 for methods that can have a body but don t provide one i e not get or head self headerscontentlength 0 def prepareauthself auth url if no auth is explicitly provided extract it from the url first specialcase basic http auth allow auth to make its changes update self to reflect the auth changes recompute contentlength prepares the given http cookie data this function eventually generates a cookie header from the given cookies using cookielib due to cookielib s design the header will not be regenerated if it already exists meaning this function can only be called once for the life of the class preparedrequest preparedrequest object any subsequent calls to preparecookies will have no actual effect unless the cookie header is removed beforehand prepares the given hooks hooks can be passed as none to the prepare method and to this method to prevent iterating over none simply use an empty list if hooks is falsey hooks hooks or for event in hooks self registerhookevent hooksevent class response attrs content statuscode headers url history encoding reason cookies elapsed request def initself self content false self contentconsumed false self next none integer code of responded http status e g 404 or 200 self statuscode none caseinsensitive dictionary of response headers for example headers contentencoding will return the value of a contentencoding response header self headers caseinsensitivedict filelike object representation of response for advanced usage use of raw requires that streamtrue be set on the request this requirement does not apply for use internally to requests self raw none final url location of response self url none encoding to decode with when accessing r text self encoding none a list of class response response objects from the history of the request any redirect responses will end up here the list is sorted from the oldest to the most recent request self history textual reason of responded http status e g not found or ok self reason none a cookiejar of cookies the server sent back self cookies cookiejarfromdict the amount of time elapsed between sending the request and the arrival of the response as a timedelta this property specifically measures the time taken between sending the first byte of the request and finishing parsing the headers it is therefore unaffected by consuming the response content or the value of the stream keyword argument self elapsed datetime timedelta0 the class preparedrequest preparedrequest object to which this is a response self request none def enterself return self def exitself args self close def getstateself consume everything accessing the content attribute makes sure the content has been fully read if not self contentconsumed self content return attr getattrself attr none for attr in self attrs def setstateself state for name value in state items setattrself name value pickled objects do not have raw setattrself contentconsumed true setattrself raw none def reprself return fresponse self statuscode def boolself return self ok def nonzeroself return self ok def iterself returns true if attr statuscode is less than 400 false if not this attribute checks if the status code of the response is between 400 and 600 to see if there was a client error or a server error if the status code is between 200 and 400 this will return true this is not a check to see if the response code is 200 ok true if this response is a wellformed http redirect that could have been processed automatically by meth session resolveredirects true if this response one of the permanent versions of redirect return location in self headers and self statuscode in codes movedpermanently codes permanentredirect property def nextself the apparent encoding provided by the charsetnormalizer or chardet libraries return chardet detectself contentencoding def itercontentself chunksize1 decodeunicodefalse def generate special case for urllib3 if hasattrself raw stream try yield from self raw streamchunksize decodecontenttrue except protocolerror as e raise chunkedencodingerrore except decodeerror as e raise contentdecodingerrore except readtimeouterror as e raise connectionerrore except sslerror as e raise requestssslerrore else standard filelike object while true chunk self raw readchunksize if not chunk break yield chunk self contentconsumed true if self contentconsumed and isinstanceself content bool raise streamconsumederror elif chunksize is not none and not isinstancechunksize int raise typeerror fchunksize must be an int it is instead a typechunksize simulate reading small chunks of the content reusedchunks iterslicesself content chunksize streamchunks generate chunks reusedchunks if self contentconsumed else streamchunks if decodeunicode chunks streamdecoderesponseunicodechunks self return chunks def iterlines self chunksizeiterchunksize decodeunicodefalse delimiternone pending none for chunk in self itercontent chunksizechunksize decodeunicodedecodeunicode if pending is not none chunk pending chunk if delimiter lines chunk splitdelimiter else lines chunk splitlines if lines and lines1 and chunk and lines11 chunk1 pending lines pop else pending none yield from lines if pending is not none yield pending property def contentself read the contents don t need to release the connection that s been handled by urllib3 since we exhausted the data content of the response in unicode if response encoding is none encoding will be guessed using charsetnormalizer or chardet the encoding of the response content is determined based solely on http headers following rfc 2616 to the letter if you can take advantage of nonhttp knowledge to make a better guess at the encoding you should set r encoding appropriately before accessing this property try charset from contenttype fallback to autodetected encoding decode unicode from given encoding a lookuperror is raised if the encoding was not found which could indicate a misspelling or similar mistake a typeerror can be raised if encoding is none so we try blindly encoding if not self encoding and self content and lenself content 3 no encoding set json rfc 4627 section 3 states we should expect utf8 16 or 32 detect which one to use if the detection or decoding fails fall back to self text using charsetnormalizer to make a best guess encoding guessjsonutfself content if encoding is not none try return complexjson loadsself content decodeencoding kwargs except unicodedecodeerror wrong utf codec detected usually because it s not utf8 but some other 8bit codec this is an rfc violation and the server didn t bother to tell us what codec was used pass except jsondecodeerror as e raise requestsjsondecodeerrore msg e doc e pos try return complexjson loadsself text kwargs except jsondecodeerror as e catch jsonrelated errors and raise as requests jsondecodeerror this aliases json jsondecodeerror and simplejson jsondecodeerror raise requestsjsondecodeerrore msg e doc e pos property def linksself raises class httperror if one occurred httperrormsg if isinstanceself reason bytes we attempt to decode utf8 first because some servers choose to localize their reason strings if the string isn t utf8 we fall back to iso88591 for all other encodings see pr 3538 try reason self reason decodeutf8 except unicodedecodeerror reason self reason decodeiso88591 else reason self reason if 400 self statuscode 500 httperrormsg fself statuscode client error reason for url self url elif 500 self statuscode 600 httperrormsg fself statuscode server error reason for url self url if httperrormsg raise httperrorhttperrormsg responseself def closeself if not self contentconsumed self raw close releaseconn getattrself raw releaseconn none if releaseconn is not none releaseconn import encoding now to avoid implicit import later implicit import within threads may cause lookuperror when standard library is in a zip such as in embedded python see https github com psf requests issues 3578 noqa f401 the set of http status codes that indicate an automatically processable redirect 301 302 303 307 308 build the path url to use encode parameters in a piece of data will successfully encode parameters when passed as a dict or a list of 2 tuples order is retained if data is a list of 2 tuples but arbitrary if parameters are supplied as a dict build the body for a multipart form data request will successfully encode files when passed as a dict or a list of tuples order is retained if data is a list of tuples but arbitrary if parameters are supplied as a dict the tuples may be 2 tuples filename fileobj 3 tuples filename fileobj contentype or 4 tuples filename fileobj contentype custom_headers don t call str on bytestrings in py3 it all goes wrong support for explicit filename properly register a hook deregister a previously registered hook returns true if the hook existed false if not a user created class request request object used to prepare a class preparedrequest preparedrequest which is sent to the server param method http method to use param url url to send param headers dictionary of headers to send param files dictionary of filename fileobject files to multipart upload param data the body to attach to the request if a dictionary or list of tuples key value is provided form encoding will take place param json json for the body to attach to the request if files or data is not specified param params url parameters to append to the url if a dictionary or list of tuples key value is provided form encoding will take place param auth auth handler or user pass tuple param cookies dictionary or cookiejar of cookies to attach to this request param hooks dictionary of callback hooks for internal usage usage import requests req requests request get https httpbin org get req prepare preparedrequest get default empty dicts for dict params constructs a class preparedrequest preparedrequest for transmission and returns it the fully mutable class preparedrequest preparedrequest object containing the exact bytes that will be sent to the server instances are generated from a class request request object and should not be instantiated manually doing so may produce undesirable effects usage import requests req requests request get https httpbin org get r req prepare r preparedrequest get s requests session s send r response 200 http verb to send to the server http url to send the request to dictionary of http headers the cookiejar used to create the cookie header will be stored here after prepare_cookies is called request body to send to the server dictionary of callback hooks for internal usage integer denoting starting position of a readable file like body prepares the entire request with the given parameters note that prepare_auth must be last to enable authentication schemes such as oauth to work on a fully prepared request this must go after prepare_auth authenticators could add a hook prepares the given http method prepares the given http url accept objects that have string representations we re unable to blindly call unicode str functions as this will include the bytestring indicator b on python 3 x https github com psf requests pull 2238 remove leading whitespaces from url don t do any url preparation for non http schemes like mailto data etc to work around exceptions from url_parse which handles rfc 3986 only support for unicode domain names and paths in general we want to try idna encoding the hostname if the string contains non ascii characters this allows users to automatically get the correct idna behaviour for strings containing only ascii characters we need to also verify it doesn t start with a wildcard before allowing the unencoded hostname carefully reconstruct the network location bare domains aren t valid urls prepares the given http headers raise exception on invalid header value prepares the given http body data check if file fo generator iterator if not run through normal process nottin on you urllib3 requires a bytes like body python 2 s json dumps provides this natively but python 3 gives a unicode string record the current file position before reading this will allow us to rewind a file in the event of a redirect this differentiates from none allowing us to catch a failed tell later when trying to rewind the body multi part file uploads add content type if it wasn t explicitly provided prepare content length header based on request method and body if length exists set it otherwise we fallback to transfer encoding chunked set content length to 0 for methods that can have a body but don t provide one i e not get or head prepares the given http auth data if no auth is explicitly provided extract it from the url first special case basic http auth allow auth to make its changes update self to reflect the auth changes recompute content length prepares the given http cookie data this function eventually generates a cookie header from the given cookies using cookielib due to cookielib s design the header will not be regenerated if it already exists meaning this function can only be called once for the life of the class preparedrequest preparedrequest object any subsequent calls to prepare_cookies will have no actual effect unless the cookie header is removed beforehand prepares the given hooks hooks can be passed as none to the prepare method and to this method to prevent iterating over none simply use an empty list if hooks is false y the class response response object which contains a server s response to an http request integer code of responded http status e g 404 or 200 case insensitive dictionary of response headers for example headers content encoding will return the value of a content encoding response header file like object representation of response for advanced usage use of raw requires that stream true be set on the request this requirement does not apply for use internally to requests final url location of response encoding to decode with when accessing r text a list of class response response objects from the history of the request any redirect responses will end up here the list is sorted from the oldest to the most recent request textual reason of responded http status e g not found or ok a cookiejar of cookies the server sent back the amount of time elapsed between sending the request and the arrival of the response as a timedelta this property specifically measures the time taken between sending the first byte of the request and finishing parsing the headers it is therefore unaffected by consuming the response content or the value of the stream keyword argument the class preparedrequest preparedrequest object to which this is a response consume everything accessing the content attribute makes sure the content has been fully read pickled objects do not have raw returns true if attr status_code is less than 400 this attribute checks if the status code of the response is between 400 and 600 to see if there was a client error or a server error if the status code is between 200 and 400 this will return true this is not a check to see if the response code is 200 ok returns true if attr status_code is less than 400 this attribute checks if the status code of the response is between 400 and 600 to see if there was a client error or a server error if the status code is between 200 and 400 this will return true this is not a check to see if the response code is 200 ok allows you to use a response as an iterator returns true if attr status_code is less than 400 false if not this attribute checks if the status code of the response is between 400 and 600 to see if there was a client error or a server error if the status code is between 200 and 400 this will return true this is not a check to see if the response code is 200 ok true if this response is a well formed http redirect that could have been processed automatically by meth session resolve_redirects true if this response one of the permanent versions of redirect returns a preparedrequest for the next request in a redirect chain if there is one the apparent encoding provided by the charset_normalizer or chardet libraries iterates over the response data when stream true is set on the request this avoids reading the content at once into memory for large responses the chunk size is the number of bytes it should read into memory this is not necessarily the length of each item returned as decoding can take place chunk_size must be of type int or none a value of none will function differently depending on the value of stream stream true will read data as it arrives in whatever size the chunks are received if stream false data is returned as a single chunk if decode_unicode is true content will be decoded using the best available encoding based on the response special case for urllib3 standard file like object simulate reading small chunks of the content iterates over the response data one line at a time when stream true is set on the request this avoids reading the content at once into memory for large responses note this method is not reentrant safe content of the response in bytes read the contents don t need to release the connection that s been handled by urllib3 since we exhausted the data content of the response in unicode if response encoding is none encoding will be guessed using charset_normalizer or chardet the encoding of the response content is determined based solely on http headers following rfc 2616 to the letter if you can take advantage of non http knowledge to make a better guess at the encoding you should set r encoding appropriately before accessing this property try charset from content type fallback to auto detected encoding decode unicode from given encoding a lookuperror is raised if the encoding was not found which could indicate a misspelling or similar mistake a typeerror can be raised if encoding is none so we try blindly encoding returns the json encoded content of a response if any param kwargs optional arguments that json loads takes raises requests exceptions jsondecodeerror if the response body does not contain valid json no encoding set json rfc 4627 section 3 states we should expect utf 8 16 or 32 detect which one to use if the detection or decoding fails fall back to self text using charset_normalizer to make a best guess wrong utf codec detected usually because it s not utf 8 but some other 8 bit codec this is an rfc violation and the server didn t bother to tell us what codec was used catch json related errors and raise as requests jsondecodeerror this aliases json jsondecodeerror and simplejson jsondecodeerror returns the parsed header links of the response if any raises class httperror if one occurred we attempt to decode utf 8 first because some servers choose to localize their reason strings if the string isn t utf 8 we fall back to iso 8859 1 for all other encodings see pr 3538 releases the connection back to the pool once this method has been called the underlying raw object must not be accessed again note should not normally need to be called explicitly
import datetime




import encodings.idna  
from io import UnsupportedOperation

from urllib3.exceptions import (
    DecodeError,
    LocationParseError,
    ProtocolError,
    ReadTimeoutError,
    SSLError,
)
from urllib3.fields import RequestField
from urllib3.filepost import encode_multipart_formdata
from urllib3.util import parse_url

from ._internal_utils import to_native_string, unicode_is_ascii
from .auth import HTTPBasicAuth
from .compat import (
    Callable,
    JSONDecodeError,
    Mapping,
    basestring,
    builtin_str,
    chardet,
    cookielib,
)
from .compat import json as complexjson
from .compat import urlencode, urlsplit, urlunparse
from .cookies import _copy_cookie_jar, cookiejar_from_dict, get_cookie_header
from .exceptions import (
    ChunkedEncodingError,
    ConnectionError,
    ContentDecodingError,
    HTTPError,
    InvalidJSONError,
    InvalidURL,
)
from .exceptions import JSONDecodeError as RequestsJSONDecodeError
from .exceptions import MissingSchema
from .exceptions import SSLError as RequestsSSLError
from .exceptions import StreamConsumedError
from .hooks import default_hooks
from .status_codes import codes
from .structures import CaseInsensitiveDict
from .utils import (
    check_header_validity,
    get_auth_from_url,
    guess_filename,
    guess_json_utf,
    iter_slices,
    parse_header_links,
    requote_uri,
    stream_decode_response_unicode,
    super_len,
    to_key_val_list,
)



REDIRECT_STATI = (
    codes.moved,  
    codes.found,  
    codes.other,  
    codes.temporary_redirect,  
    codes.permanent_redirect,  
)

DEFAULT_REDIRECT_LIMIT = 30
CONTENT_CHUNK_SIZE = 10 * 1024
ITER_CHUNK_SIZE = 512


class RequestEncodingMixin:
    @property
    def path_url(self):
        

        url = []

        p = urlsplit(self.url)

        path = p.path
        if not path:
            path = "/"

        url.append(path)

        query = p.query
        if query:
            url.append("?")
            url.append(query)

        return "".join(url)

    @staticmethod
    def _encode_params(data):
        

        if isinstance(data, (str, bytes)):
            return data
        elif hasattr(data, "read"):
            return data
        elif hasattr(data, "__iter__"):
            result = []
            for k, vs in to_key_val_list(data):
                if isinstance(vs, basestring) or not hasattr(vs, "__iter__"):
                    vs = [vs]
                for v in vs:
                    if v is not None:
                        result.append(
                            (
                                k.encode("utf-8") if isinstance(k, str) else k,
                                v.encode("utf-8") if isinstance(v, str) else v,
                            )
                        )
            return urlencode(result, doseq=True)
        else:
            return data

    @staticmethod
    def _encode_files(files, data):
        
        if not files:
            raise ValueError("Files must be provided.")
        elif isinstance(data, basestring):
            raise ValueError("Data must not be a string.")

        new_fields = []
        fields = to_key_val_list(data or {})
        files = to_key_val_list(files or {})

        for field, val in fields:
            if isinstance(val, basestring) or not hasattr(val, "__iter__"):
                val = [val]
            for v in val:
                if v is not None:
                    
                    if not isinstance(v, bytes):
                        v = str(v)

                    new_fields.append(
                        (
                            field.decode("utf-8")
                            if isinstance(field, bytes)
                            else field,
                            v.encode("utf-8") if isinstance(v, str) else v,
                        )
                    )

        for k, v in files:
            
            ft = None
            fh = None
            if isinstance(v, (tuple, list)):
                if len(v) == 2:
                    fn, fp = v
                elif len(v) == 3:
                    fn, fp, ft = v
                else:
                    fn, fp, ft, fh = v
            else:
                fn = guess_filename(v) or k
                fp = v

            if isinstance(fp, (str, bytes, bytearray)):
                fdata = fp
            elif hasattr(fp, "read"):
                fdata = fp.read()
            elif fp is None:
                continue
            else:
                fdata = fp

            rf = RequestField(name=k, data=fdata, filename=fn, headers=fh)
            rf.make_multipart(content_type=ft)
            new_fields.append(rf)

        body, content_type = encode_multipart_formdata(new_fields)

        return body, content_type


class RequestHooksMixin:
    def register_hook(self, event, hook):
        

        if event not in self.hooks:
            raise ValueError(f'Unsupported event specified, with event name "{event}"')

        if isinstance(hook, Callable):
            self.hooks[event].append(hook)
        elif hasattr(hook, "__iter__"):
            self.hooks[event].extend(h for h in hook if isinstance(h, Callable))

    def deregister_hook(self, event, hook):
        

        try:
            self.hooks[event].remove(hook)
            return True
        except ValueError:
            return False


class Request(RequestHooksMixin):
    

    def __init__(
        self,
        method=None,
        url=None,
        headers=None,
        files=None,
        data=None,
        params=None,
        auth=None,
        cookies=None,
        hooks=None,
        json=None,
    ):
        
        data = [] if data is None else data
        files = [] if files is None else files
        headers = {} if headers is None else headers
        params = {} if params is None else params
        hooks = {} if hooks is None else hooks

        self.hooks = default_hooks()
        for k, v in list(hooks.items()):
            self.register_hook(event=k, hook=v)

        self.method = method
        self.url = url
        self.headers = headers
        self.files = files
        self.data = data
        self.json = json
        self.params = params
        self.auth = auth
        self.cookies = cookies

    def __repr__(self):
        return f"<Request [{self.method}]>"

    def prepare(self):
        
        p = PreparedRequest()
        p.prepare(
            method=self.method,
            url=self.url,
            headers=self.headers,
            files=self.files,
            data=self.data,
            json=self.json,
            params=self.params,
            auth=self.auth,
            cookies=self.cookies,
            hooks=self.hooks,
        )
        return p


class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
    

    def __init__(self):
        
        self.method = None
        
        self.url = None
        
        self.headers = None
        
        
        self._cookies = None
        
        self.body = None
        
        self.hooks = default_hooks()
        
        self._body_position = None

    def prepare(
        self,
        method=None,
        url=None,
        headers=None,
        files=None,
        data=None,
        params=None,
        auth=None,
        cookies=None,
        hooks=None,
        json=None,
    ):
        

        self.prepare_method(method)
        self.prepare_url(url, params)
        self.prepare_headers(headers)
        self.prepare_cookies(cookies)
        self.prepare_body(data, files, json)
        self.prepare_auth(auth, url)

        
        

        
        self.prepare_hooks(hooks)

    def __repr__(self):
        return f"<PreparedRequest [{self.method}]>"

    def copy(self):
        p = PreparedRequest()
        p.method = self.method
        p.url = self.url
        p.headers = self.headers.copy() if self.headers is not None else None
        p._cookies = _copy_cookie_jar(self._cookies)
        p.body = self.body
        p.hooks = self.hooks
        p._body_position = self._body_position
        return p

    def prepare_method(self, method):
        
        self.method = method
        if self.method is not None:
            self.method = to_native_string(self.method.upper())

    @staticmethod
    def _get_idna_encoded_host(host):
        import idna

        try:
            host = idna.encode(host, uts46=True).decode("utf-8")
        except idna.IDNAError:
            raise UnicodeError
        return host

    def prepare_url(self, url, params):
        
        
        
        
        
        
        if isinstance(url, bytes):
            url = url.decode("utf8")
        else:
            url = str(url)

        
        url = url.lstrip()

        
        
        
        if ":" in url and not url.lower().startswith("http"):
            self.url = url
            return

        
        try:
            scheme, auth, host, port, path, query, fragment = parse_url(url)
        except LocationParseError as e:
            raise InvalidURL(*e.args)

        if not scheme:
            raise MissingSchema(
                f"Invalid URL {url!r}: No scheme supplied. "
                f"Perhaps you meant https://{url}?"
            )

        if not host:
            raise InvalidURL(f"Invalid URL {url!r}: No host supplied")

        
        
        
        
        if not unicode_is_ascii(host):
            try:
                host = self._get_idna_encoded_host(host)
            except UnicodeError:
                raise InvalidURL("URL has an invalid label.")
        elif host.startswith(("*", ".")):
            raise InvalidURL("URL has an invalid label.")

        
        netloc = auth or ""
        if netloc:
            netloc += "@"
        netloc += host
        if port:
            netloc += f":{port}"

        
        if not path:
            path = "/"

        if isinstance(params, (str, bytes)):
            params = to_native_string(params)

        enc_params = self._encode_params(params)
        if enc_params:
            if query:
                query = f"{query}&{enc_params}"
            else:
                query = enc_params

        url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment]))
        self.url = url

    def prepare_headers(self, headers):
        

        self.headers = CaseInsensitiveDict()
        if headers:
            for header in headers.items():
                
                check_header_validity(header)
                name, value = header
                self.headers[to_native_string(name)] = value

    def prepare_body(self, data, files, json=None):
        

        
        

        
        body = None
        content_type = None

        if not data and json is not None:
            
            
            content_type = "application/json"

            try:
                body = complexjson.dumps(json, allow_nan=False)
            except ValueError as ve:
                raise InvalidJSONError(ve, request=self)

            if not isinstance(body, bytes):
                body = body.encode("utf-8")

        is_stream = all(
            [
                hasattr(data, "__iter__"),
                not isinstance(data, (basestring, list, tuple, Mapping)),
            ]
        )

        if is_stream:
            try:
                length = super_len(data)
            except (TypeError, AttributeError, UnsupportedOperation):
                length = None

            body = data

            if getattr(body, "tell", None) is not None:
                
                
                
                try:
                    self._body_position = body.tell()
                except OSError:
                    
                    
                    self._body_position = object()

            if files:
                raise NotImplementedError(
                    "Streamed bodies and files are mutually exclusive."
                )

            if length:
                self.headers["Content-Length"] = builtin_str(length)
            else:
                self.headers["Transfer-Encoding"] = "chunked"
        else:
            
            if files:
                (body, content_type) = self._encode_files(files, data)
            else:
                if data:
                    body = self._encode_params(data)
                    if isinstance(data, basestring) or hasattr(data, "read"):
                        content_type = None
                    else:
                        content_type = "application/x-www-form-urlencoded"

            self.prepare_content_length(body)

            
            if content_type and ("content-type" not in self.headers):
                self.headers["Content-Type"] = content_type

        self.body = body

    def prepare_content_length(self, body):
        
        if body is not None:
            length = super_len(body)
            if length:
                
                
                self.headers["Content-Length"] = builtin_str(length)
        elif (
            self.method not in ("GET", "HEAD")
            and self.headers.get("Content-Length") is None
        ):
            
            
            self.headers["Content-Length"] = "0"

    def prepare_auth(self, auth, url=""):
        

        
        if auth is None:
            url_auth = get_auth_from_url(self.url)
            auth = url_auth if any(url_auth) else None

        if auth:
            if isinstance(auth, tuple) and len(auth) == 2:
                
                auth = HTTPBasicAuth(*auth)

            
            r = auth(self)

            
            self.__dict__.update(r.__dict__)

            
            self.prepare_content_length(self.body)

    def prepare_cookies(self, cookies):
        
        if isinstance(cookies, cookielib.CookieJar):
            self._cookies = cookies
        else:
            self._cookies = cookiejar_from_dict(cookies)

        cookie_header = get_cookie_header(self._cookies, self)
        if cookie_header is not None:
            self.headers["Cookie"] = cookie_header

    def prepare_hooks(self, hooks):
        
        
        
        
        hooks = hooks or []
        for event in hooks:
            self.register_hook(event, hooks[event])


class Response:
    

    __attrs__ = [
        "_content",
        "status_code",
        "headers",
        "url",
        "history",
        "encoding",
        "reason",
        "cookies",
        "elapsed",
        "request",
    ]

    def __init__(self):
        self._content = False
        self._content_consumed = False
        self._next = None

        
        self.status_code = None

        
        
        
        self.headers = CaseInsensitiveDict()

        
        
        
        self.raw = None

        
        self.url = None

        
        self.encoding = None

        
        
        
        self.history = []

        
        self.reason = None

        
        self.cookies = cookiejar_from_dict({})

        
        
        
        
        
        
        self.elapsed = datetime.timedelta(0)

        
        
        self.request = None

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def __getstate__(self):
        
        
        if not self._content_consumed:
            self.content

        return {attr: getattr(self, attr, None) for attr in self.__attrs__}

    def __setstate__(self, state):
        for name, value in state.items():
            setattr(self, name, value)

        
        setattr(self, "_content_consumed", True)
        setattr(self, "raw", None)

    def __repr__(self):
        return f"<Response [{self.status_code}]>"

    def __bool__(self):
        
        return self.ok

    def __nonzero__(self):
        
        return self.ok

    def __iter__(self):
        
        return self.iter_content(128)

    @property
    def ok(self):
        
        try:
            self.raise_for_status()
        except HTTPError:
            return False
        return True

    @property
    def is_redirect(self):
        
        return "location" in self.headers and self.status_code in REDIRECT_STATI

    @property
    def is_permanent_redirect(self):
        
        return "location" in self.headers and self.status_code in (
            codes.moved_permanently,
            codes.permanent_redirect,
        )

    @property
    def next(self):
        
        return self._next

    @property
    def apparent_encoding(self):
        
        return chardet.detect(self.content)["encoding"]

    def iter_content(self, chunk_size=1, decode_unicode=False):
        

        def generate():
            
            if hasattr(self.raw, "stream"):
                try:
                    yield from self.raw.stream(chunk_size, decode_content=True)
                except ProtocolError as e:
                    raise ChunkedEncodingError(e)
                except DecodeError as e:
                    raise ContentDecodingError(e)
                except ReadTimeoutError as e:
                    raise ConnectionError(e)
                except SSLError as e:
                    raise RequestsSSLError(e)
            else:
                
                while True:
                    chunk = self.raw.read(chunk_size)
                    if not chunk:
                        break
                    yield chunk

            self._content_consumed = True

        if self._content_consumed and isinstance(self._content, bool):
            raise StreamConsumedError()
        elif chunk_size is not None and not isinstance(chunk_size, int):
            raise TypeError(
                f"chunk_size must be an int, it is instead a {type(chunk_size)}."
            )
        
        reused_chunks = iter_slices(self._content, chunk_size)

        stream_chunks = generate()

        chunks = reused_chunks if self._content_consumed else stream_chunks

        if decode_unicode:
            chunks = stream_decode_response_unicode(chunks, self)

        return chunks

    def iter_lines(
        self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=False, delimiter=None
    ):
        

        pending = None

        for chunk in self.iter_content(
            chunk_size=chunk_size, decode_unicode=decode_unicode
        ):
            if pending is not None:
                chunk = pending + chunk

            if delimiter:
                lines = chunk.split(delimiter)
            else:
                lines = chunk.splitlines()

            if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]:
                pending = lines.pop()
            else:
                pending = None

            yield from lines

        if pending is not None:
            yield pending

    @property
    def content(self):
        

        if self._content is False:
            
            if self._content_consumed:
                raise RuntimeError("The content for this response was already consumed")

            if self.status_code == 0 or self.raw is None:
                self._content = None
            else:
                self._content = b"".join(self.iter_content(CONTENT_CHUNK_SIZE)) or b""

        self._content_consumed = True
        
        
        return self._content

    @property
    def text(self):
        

        
        content = None
        encoding = self.encoding

        if not self.content:
            return ""

        
        if self.encoding is None:
            encoding = self.apparent_encoding

        
        try:
            content = str(self.content, encoding, errors="replace")
        except (LookupError, TypeError):
            
            
            
            
            
            
            content = str(self.content, errors="replace")

        return content

    def json(self, **kwargs):
        r

        if not self.encoding and self.content and len(self.content) > 3:
            
            
            
            
            encoding = guess_json_utf(self.content)
            if encoding is not None:
                try:
                    return complexjson.loads(self.content.decode(encoding), **kwargs)
                except UnicodeDecodeError:
                    
                    
                    
                    
                    pass
                except JSONDecodeError as e:
                    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

        try:
            return complexjson.loads(self.text, **kwargs)
        except JSONDecodeError as e:
            
            
            raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

    @property
    def links(self):
        

        header = self.headers.get("link")

        resolved_links = {}

        if header:
            links = parse_header_links(header)

            for link in links:
                key = link.get("rel") or link.get("url")
                resolved_links[key] = link

        return resolved_links

    def raise_for_status(self):
        

        http_error_msg = ""
        if isinstance(self.reason, bytes):
            
            
            
            
            try:
                reason = self.reason.decode("utf-8")
            except UnicodeDecodeError:
                reason = self.reason.decode("iso-8859-1")
        else:
            reason = self.reason

        if 400 <= self.status_code < 500:
            http_error_msg = (
                f"{self.status_code} Client Error: {reason} for url: {self.url}"
            )

        elif 500 <= self.status_code < 600:
            http_error_msg = (
                f"{self.status_code} Server Error: {reason} for url: {self.url}"
            )

        if http_error_msg:
            raise HTTPError(http_error_msg, response=self)

    def close(self):
        
        if not self._content_consumed:
            self.raw.close()

        release_conn = getattr(self.raw, "release_conn", None)
        if release_conn is not None:
            release_conn()