3 �Pf�A�@sddlmZddlZddlZddlZddlmZddlmZm Z ddlm Z ddl m Z m Z mZddlmZdd lmZdd lmZdd lmZd d dgZeje�Zd4Zd5Zejd-e�Zd.d/�Zej ee�ej ee�d0�Z!ee d0�Z"Gd1d �d e�Z#Gd2d �d e#�Z$d3d�Z%dS)6�)�absolute_importN�)�RecentlyUsedContainer)�HTTPConnectionPool�HTTPSConnectionPool)�port_by_scheme)�LocationValueError� MaxRetryError�ProxySchemeUnknown)�urljoin)�RequestMethods)� parse_url)�Retry� PoolManager� ProxyManager�proxy_from_url�key_file� cert_file� cert_reqs�ca_certs� ssl_version� ca_cert_dir� ssl_context� key_scheme�key_host�key_port� key_timeout� key_retries� key_strict� key_block�key_source_address� key_key_file� key_cert_file� key_cert_reqs� key_ca_certs�key_ssl_version�key_ca_cert_dir�key_ssl_context� key_maxsize� key_headers� key__proxy�key__proxy_headers�key_socket_options�key__socks_options�key_assert_hostname�key_assert_fingerprint�PoolKeycCs�|j�}|dj�|d<|dj�|d<x4d D],}||kr.||dk r.t||j��||<q.W|jd�}|dk r|t|�|d<x&t|j��D]}|j|�|d|<q�Wx|j D]}||kr�d||<q�W|f|�S) a� Create a pool key out of a request context dictionary. According to RFC 3986, both the scheme and host are case-insensitive. Therefore, this function normalizes both before constructing the pool key for an HTTPS request. If you wish to change this behaviour, provide alternate callables to ``key_fn_by_scheme``. :param key_class: The class to use when constructing the key. This should be a namedtuple with the ``scheme`` and ``host`` keys at a minimum. :type key_class: namedtuple :param request_context: A dictionary-like object that contain the context for a request. :type request_context: dict :return: A namedtuple that can be used as a connection pool key. :rtype: PoolKey �scheme�host�headers�_proxy_headers�_socks_optionsNZsocket_optionsZkey_)r3r4r5) �copy�lower� frozenset�items�get�tuple�list�keys�pop�_fields)Z key_class�request_context�context�keyZ socket_optsZfield�rC�!/usr/lib/python3.6/poolmanager.py�_default_key_normalizer9s     rE)�http�httpsc@sxeZdZdZdZddd�Zdd�Zdd �Zdd d �Zd d �Z ddd�Z dd�Z ddd�Z d dd�Z dd�Zd!dd�ZdS)"ra$ Allows for arbitrary requests while transparently keeping track of necessary connection pools for you. :param num_pools: Number of connection pools to cache before discarding the least recently used pool. :param headers: Headers to include with all requests, unless other headers are given explicitly. :param \**connection_pool_kw: Additional parameters are used to create fresh :class:`urllib3.connectionpool.ConnectionPool` instances. Example:: >>> manager = PoolManager(num_pools=2) >>> r = manager.request('GET', 'http://google.com/') >>> r = manager.request('GET', 'http://google.com/mail') >>> r = manager.request('GET', 'http://yahoo.com/') >>> len(manager.pools) 2 N� cKs8tj||�||_t|dd�d�|_t|_tj�|_dS)NcSs|j�S)N)�close)�prCrCrD��sz&PoolManager.__init__..)Z dispose_func)r �__init__�connection_pool_kwr�pools�pool_classes_by_scheme�key_fn_by_schemer6)�self� num_poolsr3rMrCrCrDrL�s  zPoolManager.__init__cCs|S)NrC)rQrCrCrD� __enter__�szPoolManager.__enter__cCs |j�dS)NF)�clear)rQ�exc_typeZexc_valZexc_tbrCrCrD�__exit__�szPoolManager.__exit__cCsf|j|}|dkr|jj�}xdD]}|j|d�q"W|dkrXxtD]}|j|d�qDW|||f|�S)a� Create a new :class:`ConnectionPool` based on host, port, scheme, and any additional pool keyword arguments. If ``request_context`` is provided, it is provided as keyword arguments to the pool class used. This method is used to actually create the connection pools handed out by :meth:`connection_from_url` and companion methods. It is intended to be overridden for customization. Nr1r2�portrF)r1r2rW)rOrMr6r>� SSL_KEYWORDS)rQr1r2rWr@Zpool_clsrB�kwrCrCrD� _new_pool�s    zPoolManager._new_poolcCs|jj�dS)z� Empty our store of pools and direct them all to close. This will not affect in-flight connections, but they will not be re-used after completion. N)rNrT)rQrCrCrDrT�szPoolManager.clearrFcCsT|s td��|j|�}|pd|d<|s:tj|dj�d�}||d<||d<|j|�S)a� Get a :class:`ConnectionPool` based on the host, port, and scheme. If ``port`` isn't given, it will be derived from the ``scheme`` using ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is provided, it is merged with the instance's ``connection_pool_kw`` variable and used to create the new connection pool, if one is needed. zNo host specified.rFr1�PrWr2)r�_merge_pool_kwargsrr:r7�connection_from_context)rQr2rWr1� pool_kwargsr@rCrCrD�connection_from_host�s   z PoolManager.connection_from_hostcCs,|dj�}|j|}||�}|j||d�S)z� Get a :class:`ConnectionPool` based on the request context. ``request_context`` must at least contain the ``scheme`` key and its value must be a key in ``key_fn_by_scheme`` instance variable. r1)r@)r7rP�connection_from_pool_key)rQr@r1Zpool_key_constructor�pool_keyrCrCrDr]�s  z#PoolManager.connection_from_contextc Cs`|jj�N|jj|�}|r|S|d}|d}|d}|j||||d�}||j|<WdQRX|S)z� Get a :class:`ConnectionPool` based on the provided pool key. ``pool_key`` should be a namedtuple that only contains immutable objects. At a minimum it must have the ``scheme``, ``host``, and ``port`` fields. r1r2rW)r@N)rN�lockr:rZ)rQrar@Zpoolr1r2rWrCrCrDr`�s  z$PoolManager.connection_from_pool_keycCs t|�}|j|j|j|j|d�S)a� Similar to :func:`urllib3.connectionpool.connection_from_url`. If ``pool_kwargs`` is not provided and a new pool needs to be constructed, ``self.connection_pool_kw`` is used to initialize the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` is provided, it is used instead. Note that if a new pool does not need to be created for the request, the provided ``pool_kwargs`` are not used. )rWr1r^)r r_r2rWr1)rQ�urlr^�urCrCrD�connection_from_url s zPoolManager.connection_from_urlc CsZ|jj�}|rVxF|j�D]:\}}|dkrJy ||=WqRtk rFYqRXq|||<qW|S)a Merge a dictionary of override values for self.connection_pool_kw. This does not modify self.connection_pool_kw and returns a new dict. Any keys in the override dictionary with a value of ``None`` are removed from the merged dictionary. N)rMr6r9�KeyError)rQ�overrideZbase_pool_kwargsrB�valuerCrCrDr\s   zPoolManager._merge_pool_kwargsTc Ksdt|�}|j|j|j|jd�}d|d<d|d<d|krD|jj�|d<|jdk rj|jdkrj|j||f|�}n|j||j f|�}|o�|j �}|s�|St ||�}|j dkr�d }|j d �} t| t�s�tj| |d �} | jo�|j|� �r�x| jD]} |dj| d�q�Wy| j||||d �} Wn tk �r4| j�r0�|SX| |d <||d<tjd ||�|j||f|�S)a] Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` with custom cross-host redirect logic and only sends the request-uri portion of the ``url``. The given ``url`` parameter must be absolute, such that an appropriate :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. )rWr1FZassert_same_host�redirectr3NrFi/ZGET�retries)ri)�responseZ_poolzRedirecting %s -> %s)r r_r2rWr1r3r6�proxy�urlopenZ request_uriZget_redirect_locationr Zstatusr:� isinstancerZfrom_intZremove_headers_on_redirectZ is_same_hostr>Z incrementr Zraise_on_redirect�log�info) rQ�methodrcrirYrdZconnrkZredirect_locationrj�headerrCrCrDrm-s@       zPoolManager.urlopen)rHN)N)NrFN)N)N)T)�__name__� __module__� __qualname__�__doc__rlrLrSrVrZrTr_r]r`rer\rmrCrCrCrDrys     csHeZdZdZd�fdd� Zd�fdd� Zdd d �Zd�fd d � Z�ZS)raw Behaves just like :class:`PoolManager`, but sends all requests through the defined proxy, using the CONNECT method for HTTPS URLs. :param proxy_url: The URL of the proxy to be used. :param proxy_headers: A dictionary contaning headers that will be sent to the proxy. In case of HTTP they are being sent with each request, while in the HTTPS/CONNECT case they are sent only once. Could be used for proxy authentication. Example: >>> proxy = urllib3.ProxyManager('http://localhost:3128/') >>> r1 = proxy.request('GET', 'http://google.com/') >>> r2 = proxy.request('GET', 'http://httpbin.org/') >>> len(proxy.pools) 1 >>> r3 = proxy.request('GET', 'https://httpbin.org/') >>> r4 = proxy.request('GET', 'https://twitter.com/') >>> len(proxy.pools) 3 rHNc s�t|t�rd|j|j|jf}t|�}|jsFtj|jd�}|j|d�}|jdkrZt |j��||_ |pfi|_ |j |d<|j |d<t t |�j||f|�dS) Nz %s://%s:%ir[)rWrFrG�_proxyr4)rFrG)rnrr1r2rWr rr:�_replacer rl� proxy_headers�superrrL)rQ� proxy_urlrRr3ryrMrlrW)� __class__rCrDrL�s          zProxyManager.__init__rFcsD|dkr tt|�j||||d�Stt|�j|jj|jj|jj|d�S)NrG)r^)rzrr_rlr2rWr1)rQr2rWr1r^)r|rCrDr_�s   z!ProxyManager.connection_from_hostcCs0ddi}t|�j}|r||d<|r,|j|�|S)z� Sets headers needed by proxies: specifically, the Accept and Host headers. Only sets headers not provided by the user. ZAcceptz*/*ZHost)r �netloc�update)rQrcr3Zheaders_r}rCrCrD�_set_proxy_headers�s  zProxyManager._set_proxy_headersTc sNt|�}|jdkr0|jd|j�}|j||�|d<tt|�j||fd|i|��S)z@Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute.rFr3ri)r r1r:r3rrzrrm)rQrqrcrirYrdr3)r|rCrDrm�s  zProxyManager.urlopen)rHNN)NrFN)N)T) rsrtrurvrLr_rrm� __classcell__rCrC)r|rDris  cKstfd|i|��S)Nr{)r)rcrYrCrCrDr�s)rrrrrrr)rrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/)&Z __future__r� collections� functoolsZlogging� _collectionsrZconnectionpoolrrr� exceptionsrr r Zpackages.six.moves.urllib.parser Zrequestr Zutil.urlr Z util.retryr�__all__Z getLoggerrsrorXZ _key_fields� namedtupler0rE�partialrPrOrrrrCrCrCrD�s`          6 qW