
º|j¹u  ã               @   s2  d  Z  d d l Z d d l Z d d l Z d d l m Z d d l m Z d d l m	 Z	 d d l
 m Z m Z m Z m Z m Z d d l m Z m Z m Z m Z d d	 l m Z m Z m Z d d
 l m Z m Z d d l m Z d d l m Z m  Z  m! Z! d d l" m# Z# m$ Z$ m% Z% m& Z& d d l' m( Z( d d l) m* Z* d d l m+ Z+ m, Z, m- Z- m. Z. m/ Z/ m0 Z0 d d l1 m2 Z2 d d l m3 Z3 e j4 d k rÏy e j5 Z6 Wn e7 k
 rËe j8 Z6 Yn Xn	 e j Z6 e d d „ Z9 e d d „ Z: Gd d „  d e; ƒ Z< Gd d „  d e< ƒ Z= d d „  Z> d S)z•
requests.sessions
~~~~~~~~~~~~~~~~~

This module provides a Session object to manage and persist settings across
requests (cookies, auth, proxies).
é    N)Ú	timedelta)ÚOrderedDicté   )Ú_basic_auth_str)Ú	cookielibÚis_py3ÚurljoinÚurlparseÚMapping)Úcookiejar_from_dictÚextract_cookies_to_jarÚRequestsCookieJarÚmerge_cookies)ÚRequestÚPreparedRequestÚDEFAULT_REDIRECT_LIMIT)Údefault_hooksÚdispatch_hook)Úto_native_string)Úto_key_val_listÚdefault_headersÚDEFAULT_PORTS)ÚTooManyRedirectsÚInvalidSchemaÚChunkedEncodingErrorÚContentDecodingError)ÚCaseInsensitiveDict)ÚHTTPAdapter)Úrequote_uriÚget_environ_proxiesÚget_netrc_authÚshould_bypass_proxiesÚget_auth_from_urlÚrewind_body)Úcodes)ÚREDIRECT_STATIÚwin32c             C   sœ   | d k r |  S|  d k r  | St  | t ƒ o; t  |  t ƒ sB |  S| t | ƒ ƒ } | j t |  ƒ ƒ d d „  | j ƒ  Dƒ } x | D] } | | =q‡ W| S)zèDetermines appropriate setting for a given request, taking into account
    the explicit setting on that request, and the setting in the session. If a
    setting is a dictionary, they will be merged together using `dict_class`
    Nc             S   s(   g  |  ] \ } } | d  k r | ‘ q S)N© )Ú.0ÚkÚvr'   r'   ú5/tmp/pip-build-1hwfuv5s/requests/requests/sessions.pyú
<listcomp>J   s   	 z!merge_setting.<locals>.<listcomp>)Ú
isinstancer
   r   ÚupdateÚitems)Úrequest_settingÚsession_settingÚ
dict_classÚmerged_settingÚ	none_keysÚkeyr'   r'   r+   Úmerge_setting2   s    r6   c             C   sZ   | d k s! | j  d ƒ g  k r% |  S|  d k sF |  j  d ƒ g  k rJ | St |  | | ƒ S)z©Properly merges both requests and session hooks.

    This is necessary because when request_hooks == {'response': []}, the
    merge breaks Session hooks entirely.
    NÚresponse)Úgetr6   )Úrequest_hooksÚsession_hooksr2   r'   r'   r+   Úmerge_hooksQ   s
    !!r;   c               @   sj   e  Z d  Z d d „  Z d d „  Z d d d d d d d d	 „ Z d
 d „  Z d d „  Z d d „  Z d S)ÚSessionRedirectMixinc             C   s<   | j  r8 | j d } t r+ | j d ƒ } t | d ƒ Sd S)z7Receives a Response. Returns a redirect URI or ``None``ÚlocationÚlatin1Úutf8N)Úis_redirectÚheadersr   Úencoder   )ÚselfÚrespr=   r'   r'   r+   Úget_redirect_targetb   s    	z(SessionRedirectMixin.get_redirect_targetc             C   sà   t  | ƒ } t  | ƒ } | j | j k r. d S| j d k rn | j d k rn | j d k rn | j d	 k rn d S| j | j k } | j | j k } t j | j d ƒ d f } | rÖ | j | k rÖ | j | k rÖ d S| pß | S)
zFDecide whether Authorization header should be removed when redirectingTÚhttpéP   NÚhttpsé»  F)rG   N)rI   N)r	   ÚhostnameÚschemeÚportr   r8   )rC   Zold_urlÚnew_urlZ
old_parsedZ
new_parsedZchanged_portZchanged_schemeÚdefault_portr'   r'   r+   Úshould_strip_authw   s    z&SessionRedirectMixin.should_strip_authFNTc	             k   s,  g  }
 |  j  | ƒ } t | j ƒ j } xþ| r'| j ƒ  } |
 j | ƒ |
 d d … | _ y | j Wn. t t	 t
 f k
 r— | j j d d ƒ Yn Xt | j ƒ |  j k rÎ t d j |  j ƒ d | ƒ‚ | j ƒ  | j d ƒ rt | j ƒ } d j t | j ƒ | g ƒ } t | ƒ } | j d	 k rJ| rJ| j d
 | ƒ } n | j r\| j } | j ƒ  } | j sŒt | j t | ƒ ƒ } n t | ƒ } t | ƒ | _ |  j | | ƒ | j t j t j f k rd } x! | D] } | j  j! | d ƒ qßWd | _" | j  } | j! d d ƒ t# | j$ | | j ƒ t% | j$ |  j& ƒ | j' | j$ ƒ |  j( | | ƒ } |  j) | | ƒ | j* d k	 o�d | k p�d | k } | r°t+ | ƒ | } | rÄ| Vq* |  j, | d | d | d | d | d | d d |	 �} t# |  j& | | j ƒ |  j  | ƒ } | Vq* Wd S)zBReceives a Response. Returns a generator of Responses or Requests.r   NÚdecode_contentFzExceeded {} redirects.r7   z//ú:Ú ÚfragmentúContent-LengthúContent-TypeúTransfer-EncodingÚCookieÚstreamÚtimeoutÚverifyÚcertÚproxiesÚallow_redirects)rT   rU   rV   )-rE   r	   ÚurlrS   ÚcopyÚappendÚhistoryÚcontentr   r   ÚRuntimeErrorÚrawÚreadÚlenÚmax_redirectsr   ÚformatÚcloseÚ
startswithÚjoinr   rK   Ú_replaceÚgeturlÚnetlocr   r   Úrebuild_methodÚstatus_coder$   Útemporary_redirectÚpermanent_redirectrA   ÚpopÚbodyr   Ú_cookiesr   ÚcookiesÚprepare_cookiesÚrebuild_proxiesÚrebuild_authÚ_body_positionr#   Úsend)rC   rD   ÚreqrX   rY   rZ   r[   r\   Úyield_requestsÚadapter_kwargsÚhistr^   Zprevious_fragmentÚprepared_requestÚparsed_rurlÚparsedÚpurged_headersÚheaderrA   Ú
rewindabler'   r'   r+   Úresolve_redirects�   sv    	
					
	z&SessionRedirectMixin.resolve_redirectsc             C   su   | j  } | j } d | k r= |  j | j j | ƒ r= | d =|  j rR t | ƒ n d } | d k	 rq | j | ƒ d S)zéWhen being redirected we may want to strip authentication from the
        request to avoid leaking credentials. This method intelligently removes
        and reapplies authentication where possible to avoid credential loss.
        ÚAuthorizationN)rA   r^   rO   ÚrequestÚ	trust_envr    Úprepare_auth)rC   r€   r7   rA   r^   Únew_authr'   r'   r+   ry   þ   s    		$z!SessionRedirectMixin.rebuild_authc             C   s*  | d k	 r | n i  } | j  } | j } t | ƒ j } | j ƒ  } | j d ƒ } t | d | ƒ} |  j r¹ | r¹ t | d | ƒ}	 |	 j | |	 j d ƒ ƒ }
 |
 r¹ | j	 | |
 ƒ d | k rÌ | d =y t
 | | ƒ \ } } Wn t k
 rd \ } } Yn X| r&| r&t | | ƒ | d <| S)a°  This method re-evaluates the proxy configuration by considering the
        environment variables. If we are redirected to a URL covered by
        NO_PROXY, we strip the proxy configuration. Otherwise, we set missing
        proxy keys for this URL (in case they were stripped by a previous
        redirect).

        This method also replaces the Proxy-Authorization header where
        necessary.

        :rtype: dict
        NÚno_proxyÚallzProxy-Authorization)NN)rA   r^   r	   rK   r_   r8   r!   r‰   r   Ú
setdefaultr"   ÚKeyErrorr   )rC   r€   r\   rA   r^   rK   Únew_proxiesrŒ   Zbypass_proxyÚenviron_proxiesÚproxyÚusernameÚpasswordr'   r'   r+   rx     s*    		z$SessionRedirectMixin.rebuild_proxiesc             C   s‚   | j  } | j t j k r- | d k r- d } | j t j k rQ | d k rQ d } | j t j k ru | d k ru d } | | _  d S)z‚When being redirected we may want to change the method of the request
        based on certain specs or browser behavior.
        ÚHEADÚGETÚPOSTN)Úmethodrp   r$   Ú	see_otherÚfoundÚmoved)rC   r€   r7   r˜   r'   r'   r+   ro   :  s    	z#SessionRedirectMixin.rebuild_method)	Ú__name__Ú
__module__Ú__qualname__rE   rO   r†   ry   rx   ro   r'   r'   r'   r+   r<   `   s   m)r<   c               @   sZ  e  Z d  Z d Z d d d d d d d d	 d
 d d d g Z d d „  Z d d „  Z d d „  Z d d „  Z d d d d d d d d d d d d d d d d „ Z	 d d „  Z
 d d „  Z d d „  Z d d d  d! „ Z d d" d# „ Z d d$ d% „ Z d& d' „  Z d( d) „  Z d* d+ „  Z d, d- „  Z d. d/ „  Z d0 d1 „  Z d2 d3 „  Z d4 d5 „  Z d S)6ÚSessiona€  A Requests session.

    Provides cookie persistence, connection-pooling, and configuration.

    Basic Usage::

      >>> import requests
      >>> s = requests.Session()
      >>> s.get('https://httpbin.org/get')
      <Response [200]>

    Or as a context manager::

      >>> with requests.Session() as s:
      ...     s.get('https://httpbin.org/get')
      <Response [200]>
    rA   rv   Úauthr\   ÚhooksÚparamsrZ   r[   ÚadaptersrX   r‰   rg   c             C   s¥   t  ƒ  |  _ d  |  _ i  |  _ t ƒ  |  _ i  |  _ d |  _ d |  _ d  |  _	 t
 |  _ d |  _ t i  ƒ |  _ t ƒ  |  _ |  j d t ƒ  ƒ |  j d t ƒ  ƒ d  S)NFTzhttps://zhttp://)r   rA   r    r\   r   r¡   r¢   rX   rZ   r[   r   rg   r‰   r   rv   r   r£   Úmountr   )rC   r'   r'   r+   Ú__init__j  s    				
				zSession.__init__c             C   s   |  S)Nr'   )rC   r'   r'   r+   Ú	__enter__¨  s    zSession.__enter__c             G   s   |  j  ƒ  d  S)N)ri   )rC   Úargsr'   r'   r+   Ú__exit__«  s    zSession.__exit__c             C   s$  | j  p i  } t | t j ƒ s- t | ƒ } t t t ƒ  |  j  ƒ | ƒ } | j } |  j r} | r} |  j r} t	 | j
 ƒ } t ƒ  } | j d | j j ƒ  d | j
 d | j d | j d | j d t | j |  j d t ƒd t | j |  j ƒ d	 t | |  j ƒ d
 | d t | j |  j ƒ ƒ 
| S)a‹  Constructs a :class:`PreparedRequest <PreparedRequest>` for
        transmission and returns it. The :class:`PreparedRequest` has settings
        merged from the :class:`Request <Request>` instance and those of the
        :class:`Session`.

        :param request: :class:`Request` instance to prepare with this
            session's settings.
        :rtype: requests.PreparedRequest
        r˜   r^   ÚfilesÚdataÚjsonrA   r2   r¢   r    rv   r¡   )rv   r-   r   Ú	CookieJarr   r   r   r    r‰   r    r^   r   Úpreparer˜   Úupperr©   rª   r«   r6   rA   r   r¢   r;   r¡   )rC   rˆ   rv   Úmerged_cookiesr    Úpr'   r'   r+   Úprepare_request®  s*    
							zSession.prepare_requestNTc             C   sÅ   t  d | j ƒ  d | d | d | d | p- i  d | d | p? i  d | d	 | d
 | ƒ 
} |  j | ƒ } | po i  } |  j | j | | | | ƒ } d |	 d |
 i } | j | ƒ |  j | | � } | S)ax	  Constructs a :class:`Request <Request>`, prepares it and sends it.
        Returns :class:`Response <Response>` object.

        :param method: method for the new :class:`Request` object.
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary or bytes to be sent in the query
            string for the :class:`Request`.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) json to send in the body of the
            :class:`Request`.
        :param headers: (optional) Dictionary of HTTP Headers to send with the
            :class:`Request`.
        :param cookies: (optional) Dict or CookieJar object to send with the
            :class:`Request`.
        :param files: (optional) Dictionary of ``'filename': file-like-objects``
            for multipart encoding upload.
        :param auth: (optional) Auth tuple or callable to enable
            Basic/Digest/Custom HTTP Auth.
        :param timeout: (optional) How long to wait for the server to send
            data before giving up, as a float, or a :ref:`(connect timeout,
            read timeout) <timeouts>` tuple.
        :type timeout: float or tuple
        :param allow_redirects: (optional) Set to True by default.
        :type allow_redirects: bool
        :param proxies: (optional) Dictionary mapping protocol or protocol and
            hostname to the URL of the proxy.
        :param stream: (optional) whether to immediately download the response
            content. Defaults to ``False``.
        :param verify: (optional) Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use. Defaults to ``True``. When set to
            ``False``, requests will accept any TLS certificate presented by
            the server, and will ignore hostname mismatches and/or expired
            certificates, which will make your application vulnerable to
            man-in-the-middle (MitM) attacks. Setting verify to ``False`` 
            may be useful during local development or testing.
        :param cert: (optional) if String, path to ssl client cert file (.pem).
            If Tuple, ('cert', 'key') pair.
        :rtype: requests.Response
        r˜   r^   rA   r©   rª   r«   r¢   r    rv   r¡   rY   r]   )r   r®   r±   Úmerge_environment_settingsr^   r.   r{   )rC   r˜   r^   r¢   rª   rA   rv   r©   r    rY   r]   r\   r¡   rX   rZ   r[   r«   r|   ÚprepÚsettingsÚsend_kwargsrD   r'   r'   r+   rˆ   Ö  s(    .	zSession.requestc             K   s#   | j  d d ƒ |  j d | | � S)zåSends a GET request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        r]   Tr–   )rŽ   rˆ   )rC   r^   Úkwargsr'   r'   r+   r8   "  s    zSession.getc             K   s#   | j  d d ƒ |  j d | | � S)zéSends a OPTIONS request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        r]   TÚOPTIONS)rŽ   rˆ   )rC   r^   r¶   r'   r'   r+   Úoptions-  s    zSession.optionsc             K   s#   | j  d d ƒ |  j d | | � S)zæSends a HEAD request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        r]   Fr•   )rŽ   rˆ   )rC   r^   r¶   r'   r'   r+   Úhead8  s    zSession.headc             K   s   |  j  d | d | d | | �S)aÈ  Sends a POST request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) json to send in the body of the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        r—   rª   r«   )rˆ   )rC   r^   rª   r«   r¶   r'   r'   r+   ÚpostC  s    zSession.postc             K   s   |  j  d | d | | �S)au  Sends a PUT request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        ÚPUTrª   )rˆ   )rC   r^   rª   r¶   r'   r'   r+   ÚputP  s    
zSession.putc             K   s   |  j  d | d | | �S)aw  Sends a PATCH request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        ÚPATCHrª   )rˆ   )rC   r^   rª   r¶   r'   r'   r+   Úpatch\  s    
zSession.patchc             K   s   |  j  d | | � S)zèSends a DELETE request. Returns :class:`Response` object.

        :param url: URL for the new :class:`Request` object.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :rtype: requests.Response
        ÚDELETE)rˆ   )rC   r^   r¶   r'   r'   r+   Údeleteh  s    zSession.deletec             K   s÷  | j  d |  j ƒ | j  d |  j ƒ | j  d |  j ƒ | j  d |  j ƒ t | t ƒ rg t d ƒ ‚ | j d d ƒ } | j	 d ƒ } | j
 } |  j d | j ƒ } t ƒ  } | j | | � } t ƒ  | }	 t d	 |	 ƒ | _ t d
 | | | � } | j r+x* | j D] }
 t |  j |
 j |
 j ƒ qWt |  j | | j ƒ | rr|  j | | | � } d d „  | Dƒ } n g  } | r£| j d | ƒ | j ƒ  } | | _ | sæy( t |  j | | d d | �ƒ | _ Wn t k
 råYn X| só| j | S)zISend a given PreparedRequest.

        :rtype: requests.Response
        rX   rZ   r[   r\   z#You can only send PreparedRequests.r]   Tr^   Úsecondsr7   c             S   s   g  |  ] } | ‘ q Sr'   r'   )r(   rD   r'   r'   r+   r,   ¥  s   	 z Session.send.<locals>.<listcomp>r   r}   )rŽ   rX   rZ   r[   r\   r-   r   Ú
ValueErrorrs   r8   r¡   Úget_adapterr^   Úpreferred_clockr{   r   Úelapsedr   ra   r   rv   rˆ   rd   r†   ÚinsertÚnextZ_nextÚStopIterationrb   )rC   rˆ   r¶   r]   rX   r¡   ÚadapterÚstartÚrrÅ   rD   Úgenra   r'   r'   r+   r{   r  sF    				(zSession.sendc       
      C   s	  |  j  r¥ | d k	 r$ | j d ƒ n d } t | d | ƒ} x* | j ƒ  D] \ } }	 | j | |	 ƒ qI W| d k s� | d k r¥ t j j d ƒ p¢ t j j d ƒ } t | |  j ƒ } t | |  j	 ƒ } t | |  j
 ƒ } t | |  j ƒ } d | d | d | d	 | i S)
z^
        Check the environment and merge it with some settings.

        :rtype: dict
        NrŒ   TÚREQUESTS_CA_BUNDLEÚCURL_CA_BUNDLErZ   r\   rX   r[   )r‰   r8   r   r/   rŽ   ÚosÚenvironr6   r\   rX   rZ   r[   )
rC   r^   r\   rX   rZ   r[   rŒ   Úenv_proxiesr)   r*   r'   r'   r+   r²   ½  s    	!z"Session.merge_environment_settingsc             C   sX   x< |  j  j ƒ  D]+ \ } } | j ƒ  j | j ƒ  ƒ r | Sq Wt d j | ƒ ƒ ‚ d S)z~
        Returns the appropriate connection adapter for the given URL.

        :rtype: requests.adapters.BaseAdapter
        z*No connection adapters were found for {!r}N)r£   r/   Úlowerrj   r   rh   )rC   r^   ÚprefixrÉ   r'   r'   r+   rÃ   Ú  s    zSession.get_adapterc             C   s(   x! |  j  j ƒ  D] } | j ƒ  q Wd S)z+Closes all adapters and as such the sessionN)r£   Úvaluesri   )rC   r*   r'   r'   r+   ri   è  s    zSession.closec                sW   | |  j  ˆ  <‡  f d d †  |  j  Dƒ } x' | D] } |  j  j | ƒ |  j  | <q0 Wd S)zwRegisters a connection adapter to a prefix.

        Adapters are sorted in descending order by prefix length.
        c                s.   g  |  ]$ } t  | ƒ t  ˆ  ƒ k  r | ‘ q Sr'   )rf   )r(   r)   )rÓ   r'   r+   r,   ó  s   	 z!Session.mount.<locals>.<listcomp>N)r£   rs   )rC   rÓ   rÉ   Úkeys_to_mover5   r'   )rÓ   r+   r¤   í  s    zSession.mountc                s    ‡  f d d †  ˆ  j  Dƒ } | S)Nc                s%   i  |  ] } t  ˆ  | d  ƒ | “ q S)N)Úgetattr)r(   Úattr)rC   r'   r+   ú
<dictcomp>ù  s   	 z(Session.__getstate__.<locals>.<dictcomp>)Ú	__attrs__)rC   Ústater'   )rC   r+   Ú__getstate__ø  s    zSession.__getstate__c             C   s1   x* | j  ƒ  D] \ } } t |  | | ƒ q Wd  S)N)r/   Úsetattr)rC   rÚ   r×   Úvaluer'   r'   r+   Ú__setstate__ü  s    zSession.__setstate__)rœ   r�   rž   Ú__doc__rÙ   r¥   r¦   r¨   r±   rˆ   r8   r¸   r¹   rº   r¼   r¾   rÀ   r{   r²   rÃ   ri   r¤   rÛ   rÞ   r'   r'   r'   r+   rŸ   Q  s2   	>)I
KrŸ   c               C   s   t  ƒ  S)aZ  
    Returns a :class:`Session` for context-management.

    .. deprecated:: 1.0.0

        This method has been deprecated since version 1.0.0 and is only kept for
        backwards compatibility. New code should use :class:`~requests.sessions.Session`
        to create a session. This may be removed at a future date.

    :rtype: Session
    )rŸ   r'   r'   r'   r+   Úsession  s    rà   )?rß   rÏ   ÚsysÚtimeÚdatetimer   Úcollectionsr   r    r   Úcompatr   r   r   r	   r
   rv   r   r   r   r   Úmodelsr   r   r   r¡   r   r   Ú_internal_utilsr   Úutilsr   r   r   Ú
exceptionsr   r   r   r   Ú
structuresr   r£   r   r   r   r    r!   r"   r#   Ústatus_codesr$   r%   ÚplatformÚperf_counterrÄ   ÚAttributeErrorÚclockr6   r;   Úobjectr<   rŸ   rà   r'   r'   r'   r+   Ú<module>	   s<   ("".	ñÿ ±