U
    \                 -   @   s`  d Z ddlZddlZddlZddlZddlmZ zddlmZ W n ek
rX   dZY nX zddl	m
Z
 W n  ek
r   ddlm
Z
 Y nX ddlmZmZmZ edkrddlZG dd dejZejjjZejjjZd	d
 Zejd dkZedZze W n ek
r   eZY nX edZ dddZ!e!d Z"Z#e$dZ%e&dZ'e&dZ(e&dZ)e*dd ej+D Z,e&dZ-e$dZ.e$dZ/e.e/B Z0e%e/B e1dB Z2e0e2 Z3e2e1dB Z4e0e4 Z5e4e1d Z6e0e6 Z7e%e4B e1dB Z8e0e8 Z9e%e8e1d B Z:e0e: Z;e%e:e1d B Z<e0e< Z=dd!d"Z>d#d$ Z?e?e2Z@e>e3ZAe?e4ZBe?e6ZCe>e5ZDe?e<ZEe>e=ZFe?e:ZGe>e;ZHe?e8ZIe>e9ZJe?e%ZKe*d%d e,L D ZMe$d&ZNdd(d)ZOdd*d+ZPdd,d-ZQdd.d/ZRdd0d1ZSdd2d3ZTdd4d5ZUdd6d7ZVd8d9d:d;dd<d=d>d?d@dAdBdBdCdDdEdFdGdHddIdJdKdLdMdNdOdPdQdRdSdTdUdVdTddWdXdYdZd[d?d@dd\,ZWe1d]d^d_d`dadbdcdddedfdgdhdigZXddjdkZYddldmZZG dndo doe[Z\dpdq Z]drds Z^e$ d fdtduZ_dvdw Z`ddxdyZaddzd{Zbdd|d}Zcdd~dZddddZedddZfd dd d e,fddZgdd Zhdd Zidd ZjG dd dekZlelZmG dd dekZndddZodS )a  Hyperlink provides Pythonic URL parsing, construction, and rendering.

Usage is straightforward::

   >>> from hyperlink import URL
   >>> url = URL.from_text(u'http://github.com/mahmoud/hyperlink?utm_source=docs')
   >>> url.host
   u'github.com'
   >>> secure_url = url.replace(scheme=u'https')
   >>> secure_url.get('utm_source')[0]
   u'docs'

As seen here, the API revolves around the lightweight and immutable
:class:`URL` type, documented below.
    N)	normalize)	inet_pton)Mapping)encodedecode	IDNAErrorc                   @   s@   e Zd Zdejfdejfdejd fdejd fdejfgZdS )		_sockaddr	sa_familyZ__pad1	ipv4_addr   	ipv6_addr   Z__pad2N)	__name__
__module____qualname__ctypesZc_shortZc_ushortZc_byteZc_ulongZ_fields_ r   r   0/usr/lib/python3/dist-packages/hyperlink/_url.pyr   )   s   r   c                 C   s   t  }|d}| |_tt|}t|| d t|t|dkrTt	t
 | tjkrlt|jdS | tjkrt|jdS t	dd S )Nasciir   r   r   zunknown address family)r   r   r	   r   Zc_intZsizeofWSAStringToAddressAZbyrefsocketerrorZFormatErrorAF_INETZ	string_atr
   AF_INET6r   )Zaddress_familyZ	ip_stringZaddrZ	addr_sizer   r   r   r   3   s    
 

r       _MISSINGc                    s   G  fdddt }| S )a  Creates and returns a new **instance** of a new class, suitable for
    usage as a "sentinel", a kind of singleton often used to indicate
    a value is missing when ``None`` is a valid input.

    Args:
        name (str): Name of the Sentinel
        var_name (str): Set this name to the name of the variable in
            its respective module enable pickleability.

    >>> make_sentinel(var_name='_MISSING')
    _MISSING

    The most common use cases here in boltons are as default values
    for optional function arguments, partly because of its
    less-confusing appearance in automatically generated
    documentation. Sentinels also function well as placeholders in queues
    and linked lists.

    .. note::

      By design, additional calls to ``make_sentinel`` with the same
      values will not produce equivalent objects.

      >>> make_sentinel('TEST') == make_sentinel('TEST')
      False
      >>> type(make_sentinel('TEST')) == type(make_sentinel('TEST'))
      False

    c                       s:   e Zd Z fddZdd Zr*dd Zdd ZeZd	S )
zmake_sentinel.<locals>.Sentinelc                    s    | _ | _d S Nnamevar_nameselfr   r   r   __init__l   s    z(make_sentinel.<locals>.Sentinel.__init__c                 S   s   | j r| j S d| jj| jf S )Nz%s(%r))r    	__class__r   r   r!   r   r   r   __repr__p   s    z(make_sentinel.<locals>.Sentinel.__repr__c                 S   s   | j S r   )r    r!   r   r   r   
__reduce__u   s    z*make_sentinel.<locals>.Sentinel.__reduce__c                 S   s   dS )NFr   r!   r   r   r   __nonzero__x   s    z+make_sentinel.<locals>.Sentinel.__nonzero__N)r   r   r   r#   r%   r&   r'   __bool__r   r   r   r   Sentinelk   s   r)   )object)r   r    r)   r   r   r   make_sentinelM   s    r+   _UNSETzB~-._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzz^((?P<scheme>[^:/?#]+):)?((?P<_netloc_sep>//)(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$z^[a-zA-Z0-9+-.]*$z^(?:(?P<userinfo>[^@/?#]*)@)?(?P<host>(?:\[(?P<ipv6_host>[^[\]/?#]*)\])|(?P<plain_host>[^:/?#[\]]*)|(?P<bad_host>.*?))?(?::(?P<port>.*))?$c                 C   s>   g | ]6}t jD ]*}|| d tt|| ddfqqS )r   r   charmap)string	hexdigitsr   unichrint).0abr   r   r   
<listcomp>   s     r5   z([ -]+)z:/?#[]@z!$&'()*+,;=%z:@:z/?z&+=Fc                 C   sd   t t}|st| tdgB } | D ]<}dt|d}| }|| ||kr"|| q"|S )Nr6   z{0:02X}r   )dict_HEX_CHAR_MAPsetformatordr   lowerpop)delimsZallow_percentretZdelimZ_hexordZ_hexord_lowerr   r   r   _make_decode_map   s    
rB   c                 C   s\   i }t tdtdD ]@\}}t|}|| kr@| ||< ||< qd| ||< ||< q|S )N   z%{0:02X})ziprangechrr<   )Z
safe_charsrA   ivcr   r   r   _make_quote_map   s    rJ   c                 C   s(   g | ] \}}| d dtkr||fqS )r   replace)r   _UNRESERVED_CHARSr2   krH   r   r   r   r5      s
    
)r   r   Tc                 C   s<   |r(t d| d}ddd |D S ddd | D S )zA very comprehensive percent encoding for encoding all
    delimiters. Used for arguments to DecodedURL, where a % means a
    percent sign, and not the character used by URLs for escaping
    bytes.
    NFCutf8r   c                 S   s   g | ]}t | qS r   )_UNRESERVED_QUOTE_MAPr2   r4   r   r   r   r5      s     z$_encode_reserved.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )rL   rR   r2   tr   r   r   r5      s   r   r   jointextmaximalZbytestrr   r   r   _encode_reserved   s    
r[   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )z.Percent-encode a single segment of a URL path.rP   rQ   r   c                 S   s   g | ]}t | qS r   )_PATH_PART_QUOTE_MAPrS   r   r   r   r5      s     z%_encode_path_part.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_PATH_DELIMSr\   rT   r   r   r   r5      s   rV   rX   r   r   r   _encode_path_part   s    
r^   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )z]Percent-encode the first segment of a URL path for a URL without a
    scheme specified.
    rP   rQ   r   c                 S   s   g | ]}t | qS r   )_SCHEMELESS_PATH_PART_QUOTE_MAPrS   r   r   r   r5      s     z0_encode_schemeless_path_part.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_SCHEMELESS_PATH_DELIMSr_   rT   r   r   r   r5      s    
rV   rX   r   r   r   _encode_schemeless_path_part   s    
ra   c                    s|   | s|rdS | S |rd|  } g }|r8 fdd| D }n.t | d g}| fdd| dd D  |rtd	|S t|S )
aL  
    Percent-encode a tuple of path parts into a complete path.

    Setting *maximal* to False percent-encodes only the reserved
    characters that are syntactically necessary for serialization,
    preserving any IRI-style textual data.

    Leaving *maximal* set to its default True percent-encodes
    everything required to convert a portion of an IRI to a portion of
    a URI.

    RFC 3986 3.3:

       If a URI contains an authority component, then the path component
       must either be empty or begin with a slash ("/") character.  If a URI
       does not contain an authority component, then the path cannot begin
       with two slash characters ("//").  In addition, a URI reference
       (Section 4.1) may be a relative-path reference, in which case the
       first path segment cannot contain a colon (":") character.
    r   rO   c                    s    g | ]}|rt | d n|qS rZ   r^   r2   partrc   r   r   r5     s    z&_encode_path_parts.<locals>.<listcomp>r   c                    s    g | ]}|rt | d n|qS rb   rd   re   rc   r   r   r5   "  s       N/)ra   extendrW   tuple)Z
text_partsrooted
has_schemehas_authorityjoinedrZ   Zencoded_partsr   rc   r   _encode_path_parts   s     


ro   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )<
    Percent-encode a single query string key or value.
    rP   rQ   r   c                 S   s   g | ]}t | qS r   )_QUERY_KEY_QUOTE_MAPrS   r   r   r   r5   /  s     z%_encode_query_key.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_QUERY_KEY_DELIMSrq   rT   r   r   r   r5   0  s   rV   rX   r   r   r   _encode_query_key)  s    
rs   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )rp   rP   rQ   r   c                 S   s   g | ]}t | qS r   )_QUERY_VALUE_QUOTE_MAPrS   r   r   r   r5   :  s     z'_encode_query_value.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_QUERY_VALUE_DELIMSrt   rT   r   r   r   r5   ;  s    
rV   rX   r   r   r   _encode_query_value4  s    
rv   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )zyQuote the fragment part of the URL. Fragments don't have
    subdelimiters, so the whole URL fragment can be passed.
    rP   rQ   r   c                 S   s   g | ]}t | qS r   )_FRAGMENT_QUOTE_MAPrS   r   r   r   r5   E  s     z)_encode_fragment_part.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_FRAGMENT_DELIMSrw   rT   r   r   r   r5   F  s   rV   rX   r   r   r   _encode_fragment_part?  s    
ry   c                 C   s<   |r(t d| d}ddd |D S ddd | D S )zXQuote special characters in either the username or password
    section of the URL.
    rP   rQ   r   c                 S   s   g | ]}t | qS r   )_USERINFO_PART_QUOTE_MAPrS   r   r   r   r5   P  s     z)_encode_userinfo_part.<locals>.<listcomp>c                 S   s    g | ]}|t krt| n|qS r   )_USERINFO_DELIMSrz   rT   r   r   r   r5   Q  s   rV   rX   r   r   r   _encode_userinfo_partJ  s    
r|   i  i$  iD
  5      i$  F   P   i     iw     i)  i  i|  i  i'  i  o   w   i3  n   i  i  ii  i*  iB  i     i     ij     i  i     ),ZacapZafpr9   ZdnsfileZftpZgitZgopherhttpZhttpsZimapZippZippsZircZircsZldapZldapsZmmsZmsrpZmsrpsZmtqpZnfsZnntpZnntpsr?   ZprosperoZredisZrsyncZrtspZrtspsZrtspuZsftpZsmbZsnmpZsshZsteamZsvnZtelnetZventriloZvncZwaisZwsZwssZxmppZurnZaboutZbitcoinZblobdataZgeoZmagnetZmailtoZnewsZpkcs11ZsipZsipsZtelc              	   C   s   |   } |dk	rDzt|}W n& ttfk
rB   td|f Y nX |dkrV|t| < n4|dkr~|dk	rrtd| t|  ntd| dS )a  Registers new scheme information, resulting in correct port and
    slash behavior from the URL object. There are dozens of standard
    schemes preregistered, so this function is mostly meant for
    proprietary internal customizations or stopgaps on missing
    standards information. If a scheme seems to be missing, please
    `file an issue`_!

    Args:
        text (unicode): Text representing the scheme.
           (the 'http' in 'http://hatnote.com')
        uses_netloc (bool): Does the scheme support specifying a
           network host? For instance, "http" does, "mailto" does
           not. Defaults to True.
        default_port (int): The default port, if any, for netloc-using
           schemes.

    .. _file an issue: https://github.com/mahmoud/hyperlink/issues

    Nz-default_port expected integer or None, not %rTFz>unexpected default port while specifying non-netloc scheme: %rz"uses_netloc expected bool, not: %r)r>   r1   
ValueError	TypeErrorSCHEME_PORT_MAPNO_NETLOC_SCHEMESadd)rY   uses_netlocZdefault_portr   r   r   register_schemem  s$    
r   c                 C   sB   | sdS |   } | tkrdS | tkr(dS | dd tkr>dS |S )aA  Whether or not a URL uses :code:`:` or :code:`://` to separate the
    scheme from the rest of the URL depends on the scheme's own
    standard definition. There is no way to infer this behavior
    from other parts of the URL. A scheme either supports network
    locations or it does not.

    The URL type's approach to this is to check for explicitly
    registered schemes, with common schemes like HTTP
    preregistered. This is the same approach taken by
    :mod:`urlparse`.

    URL adds two additional heuristics if the scheme as a whole is
    not registered. First, it attempts to check the subpart of the
    scheme after the last ``+`` character. This adds intuitive
    behavior for schemes like ``git+ssh``. Second, if a URL with
    an unrecognized scheme is loaded, it will maintain the
    separator it sees.
    FT+)r>   r   r   split)schemedefaultr   r   r   scheme_uses_netloc  s    r   c                   @   s   e Zd ZdZdS )URLParseErrorzException inheriting from :exc:`ValueError`, raised when failing to
    parse a URL. Mostly raised on invalid ports and IPv6 addresses.
    N)r   r   r   __doc__r   r   r   r   r     s   r   c                 C   s   | t kr|S | S d S r   )r,   )Zargumentr   r   r   r   	_optional  s    r   c                 G   s<   |st dt||s8tdddd |D | |f |S )z
    Check that the given *value* is one of the given *types*, or raise an
    exception describing the problem using *name*.
    z1expected one or more types, maybe use _textcheck?expected %s for %s, got %rz or c                 S   s   g | ]
}|j qS r   )r   rT   r   r   r   r5     s     z_typecheck.<locals>.<listcomp>)r   
isinstancer   rW   )r   valuetypesr   r   r   
_typecheck  s    
 r   c                 C   sx   t |tsH|r|d kr|S tr"dnd}|r2|d n|}td|| |f |rtt|t|@ rttdd|| |f |S )Nunicodestrz or NoneTyper   z4one or more reserved delimiters %s present in %s: %rr   )r   r   PY2r   r;   r   rW   )r   r   r@   nullableZstr_nameZexpr   r   r   
_textcheck  s    
r   c                 C   s   t | tr|  } t| S )z
    Iterate over the (key, value) pairs in ``iterable``.

    This handles dictionaries sensibly, and falls back to assuming the
    iterable yields (key, value) pairs. This behaviour is similar to
    what Python's ``dict()`` constructor does.
    )r   r   itemsiter)iterabler   r   r   
iter_pairs  s    
r   c                 C   s   t | ||tdS Nnormalize_caseencode_stray_percents_decode_map)_percent_decode_UNRESERVED_DECODE_MAPrY   r   r   r   r   r   _decode_unreserved  s    r   c                 C   s   t | ||tdS r   )r   _USERINFO_DECODE_MAPr   r   r   r   _decode_userinfo_part  s    r   c                 C   s   t | ||tdS )z
    >>> _decode_path_part(u'%61%77%2f%7a')
    u'aw%2fz'
    >>> _decode_path_part(u'%61%77%2f%7a', normalize_case=True)
    u'aw%2Fz'
    r   )r   _PATH_DECODE_MAPr   r   r   r   _decode_path_part  s    r   c                 C   s   t | ||tdS r   )r   _QUERY_KEY_DECODE_MAPr   r   r   r   _decode_query_key  s    r   c                 C   s   t | ||tdS r   )r   _QUERY_VALUE_DECODE_MAPr   r   r   r   _decode_query_value
  s    r   c                 C   s   t | ||tdS r   )r   _FRAGMENT_DECODE_MAPr   r   r   r   _decode_fragment_part  s    r   utf-8c              	   C   sN  z|  |dkrdn|}W n tk
r2   |  Y S X |d}t|dkrN| S |d g}|j}	|dd D ]}
|
dd |
dd  }}z|	||  |	| W qj tk
 r   |tk}|s|s|	d n|	d |r|r|	|  |	| n|	|
 Y qjX qjd	|}|dkr|S z|	|W S  t
k
rH   |r@ |  Y S X dS )
a.  Convert percent-encoded text characters to their normal,
    human-readable equivalents.

    All characters in the input text must be encodable by
    *subencoding*. All special characters underlying the values in the
    percent-encoding must be decodable as *subencoding*. If a
    non-*subencoding*-valid string is passed, the original text is
    returned with no changes applied.

    Only called by field-tailored variants, e.g.,
    :func:`_decode_path_part`, as every percent-encodable part of the
    URL has characters which should not be percent decoded.

    >>> _percent_decode(u'abc%20def')
    u'abc def'

    Args:
       text (unicode): Text with percent-encoding present.
       normalize_case (bool): Whether undecoded percent segments, such
          as encoded delimiters, should be uppercased, per RFC 3986
          Section 2.1. See :func:`_decode_path_part` for an example.
       subencoding (unicode): The name of the encoding underlying the
          percent-encoding. Pass `False` to get back raw bytes.
       raise_subencoding_exc (bool): Whether an error in decoding the bytes
          underlying the percent-decoding should be raised.

    Returns:
       unicode: The percent-decoded version of *text*, decoded by
         *subencoding*, unless `subencoding=False` which returns bytes.

    Fr      %rg   r   Nr   s   %25    )r   UnicodeEncodeErrorr   lenappendKeyErrorr:   upperrW   r   UnicodeDecodeError)rY   r   Zsubencodingraise_subencoding_excr   r   Zquoted_bytesbitsresr   itemZhexpairrestZpair_is_hexZunquoted_bytesr   r   r   r     s@    "






r   c                 C   s^   | sdS z|  d}W n tk
r.   | }Y n,X zt|dd}W n tk
rX   | }Y nX |S )u  Decode a host from ASCII-encodable text to IDNA-decoded text. If
    the host text is not ASCII, it is returned unchanged, as it is
    presumed that it is already IDNA-decoded.

    Some technical details: _decode_host is built on top of the "idna"
    package, which has some quirks:

    Capital letters are not valid IDNA2008. The idna package will
    raise an exception like this on capital letters:

    > idna.core.InvalidCodepoint: Codepoint U+004B at position 1 ... not allowed

    However, if a segment of a host (i.e., something in
    url.host.split('.')) is already ASCII, idna doesn't perform its
    usual checks. In fact, for capital letters it automatically
    lowercases them.

    This check and some other functionality can be bypassed by passing
    uts46=True to idna.encode/decode. This allows a more permissive and
    convenient interface. So far it seems like the balanced approach.

    Example output (from idna==2.6):

    >> idna.encode(u'mahmöud.io')
    'xn--mahmud-zxa.io'
    >> idna.encode(u'Mahmöud.io')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 355, in encode
        result.append(alabel(label))
      File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 276, in alabel
        check_label(label)
      File "/home/mahmoud/virtualenvs/hyperlink/local/lib/python2.7/site-packages/idna/core.py", line 253, in check_label
        raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label)))
    idna.core.InvalidCodepoint: Codepoint U+004D at position 1 of u'Mahmöud' not allowed
    >> idna.encode(u'Mahmoud.io')
    'Mahmoud.io'

    # Similar behavior for decodes below
    >> idna.decode(u'Mahmoud.io')
    u'mahmoud.io
    >> idna.decode(u'Méhmoud.io', uts46=True)
    u'méhmoud.io'
    r   r   TZuts46)r   r   idna_decoder   )hostZ
host_bytes	host_textr   r   r   _decode_hoste  s    -

r   c                 C   sb   g }| D ].}|dkrq|dkr,|r6|   q|| qt| dd dgdgfkr^|d |S )a  Normalize the URL path by resolving segments of '.' and '..'. For
    more details, see `RFC 3986 section 5.2.4, Remove Dot Segments`_.

    Args:
       path (list): path segments in string form

    Returns:
       list: a new list of path segments with the '.' and '..' elements
          removed and resolved.

    .. _RFC 3986 section 5.2.4, Remove Dot Segments: https://tools.ietf.org/html/rfc3986#section-5.2.4
    .z..r   Nr   )r?   r   list)pathZsegsZsegr   r   r   _resolve_dot_segments  s    

r   c              
   C   s   | sdS d| krvzt tj|  W nF tjk
rT } ztd| |f W 5 d}~X Y n" tk
rf   Y nX tj}|| fS zt tj|  W n tjtfk
r   d}Y nX tj}|| fS )a7  Parse the host into a tuple of ``(family, host)``, where family
    is the appropriate :mod:`socket` module constant when the host is
    an IP address. Family is ``None`` when the host is not an IP.

    Will raise :class:`URLParseError` on invalid IPv6 constants.

    Returns:
      tuple: family (socket constant or None), host (string)

    >>> parse_host('googlewebsite.com') == (None, 'googlewebsite.com')
    True
    >>> parse_host('::1') == (socket.AF_INET6, '::1')
    True
    >>> parse_host('192.168.1.1') == (socket.AF_INET, '192.168.1.1')
    True
    )Nr   r7   zinvalid IPv6 host: %r (%r)N)r   r   r   r   r   r   r   )r   ZseZfamilyr   r   r   
parse_host  s"     
r   c                	   @   s  e Zd ZdZdMddZdNdd	Zed
d Zedd Zedd Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd ZdOddZd d! Zd"d# Zd$d% Zed&d' Zeeeeeeeeef	d(d)Zed*d+ ZdPd-d.Zd/d0 Zd1d2 ZdQd3d4Zd5d6 Zd7d8 ZdRd9d:Z d;d< Z!d=d> Z"e#rLe"Z$e Z%ne"Z&e Z$eZ'eZ(ed?d@ Z)dSdAdBZ*dCdD Z+dTdEdFZ,dUdGdHZ-dIdJ Z.edfdKdLZ/dS )VURLa	  From blogs to billboards, URLs are so common, that it's easy to
    overlook their complexity and power. With hyperlink's
    :class:`URL` type, working with URLs doesn't have to be hard.

    URLs are made of many parts. Most of these parts are officially
    named in `RFC 3986`_ and this diagram may prove handy in identifying
    them::

       foo://user:pass@example.com:8042/over/there?name=ferret#nose
       \_/   \_______/ \_________/ \__/\_________/ \_________/ \__/
        |        |          |        |      |           |        |
      scheme  userinfo     host     port   path       query   fragment

    While :meth:`~URL.from_text` is used for parsing whole URLs, the
    :class:`URL` constructor builds a URL from the individual
    components, like so::

        >>> from hyperlink import URL
        >>> url = URL(scheme=u'https', host=u'example.com', path=[u'hello', u'world'])
        >>> print(url.to_text())
        https://example.com/hello/world

    The constructor runs basic type checks. All strings are expected
    to be decoded (:class:`unicode` in Python 2). All arguments are
    optional, defaulting to appropriately empty values. A full list of
    constructor arguments is below.

    Args:
       scheme (unicode): The text name of the scheme.
       host (unicode): The host portion of the network location
       port (int): The port part of the network location. If
          ``None`` or no port is passed, the port will default to
          the default port of the scheme, if it is known. See the
          ``SCHEME_PORT_MAP`` and :func:`register_default_port`
          for more info.
       path (tuple): A tuple of strings representing the
          slash-separated parts of the path.
       query (tuple): The query parameters, as a dictionary or
          as an iterable of key-value pairs.
       fragment (unicode): The fragment part of the URL.
       rooted (bool): Whether or not the path begins with a slash.
       userinfo (unicode): The username or colon-separated
          username:password pair.
       uses_netloc (bool): Indicates whether two slashes appear
          between the scheme and the host (``http://eg.com`` vs
          ``mailto:e@g.com``). Set automatically based on scheme.

    All of these parts are also exposed as read-only attributes of
    URL instances, along with several useful methods.

    .. _RFC 3986: https://tools.ietf.org/html/rfc3986
    .. _RFC 3987: https://tools.ietf.org/html/rfc3987
    Nr   r   c
                 C   sD  |d k	r|d krd}|d kr&t |}|r6|r6|s6d}|d krBd}|d krNd}|d kr^t|}td|| _| jrt| jstd| j| jj	f t
td|d\}
| _t|trtd|f td	d
 |D | _tdd
 t|D | _td|| _td|tt| _td|t| _td|d| _t| j|	}	td|	tt| _d S )Nr   rO   r   r   zginvalid scheme: %r. Only alphanumeric, "+", "-", and "." allowed. Did you meant to call %s.from_text()?r   z/?#@z+expected iterable of text for path, not: %rc                 s   s   | ]}t d |dV  qdS )path segmentz/?#Nr   r2   segmentr   r   r   	<genexpr>A  s   zURL.__init__.<locals>.<genexpr>c                 s   s.   | ]&\}}t d |dt d|dddfV  qdS )zquery parameter namez&=#zquery parameter valuez&#T)r   Nr   rM   r   r   r   r   C  s   
fragmentportrk   userinfor   )r   getboolr   _scheme
_SCHEME_REmatchr   r$   r   r   _hostr   r   r   rj   _pathr   _query	_fragmentr   r1   NoneType_port_rooted	_userinfor   _uses_netloc)r"   r   r   r   queryr   r   rk   r   r   _r   r   r   r#     sP    



  zURL.__init__Fc                 C   s2   z| j W S  tk
r*   t| |d| _ Y nX | j S Nlazy)Z_decoded_urlAttributeError
DecodedURL)r"   r   r   r   r   get_decoded_urlR  s
    zURL.get_decoded_urlc                 C   s   | j S )aM  The scheme is a string, and the first part of an absolute URL, the
        part before the first colon, and the part which defines the
        semantics of the rest of the URL. Examples include "http",
        "https", "ssh", "file", "mailto", and many others. See
        :func:`~hyperlink.register_scheme()` for more info.
        )r   r!   r   r   r   r   Y  s    z
URL.schemec                 C   s   | j S )a  The host is a string, and the second standard part of an absolute
        URL. When present, a valid host must be a domain name, or an
        IP (v4 or v6). It occurs before the first slash, or the second
        colon, if a :attr:`~hyperlink.URL.port` is provided.
        )r   r!   r   r   r   r   c  s    zURL.hostc                 C   s   | j S )a  The port is an integer that is commonly used in connecting to the
        :attr:`host`, and almost never appears without it.

        When not present in the original URL, this attribute defaults
        to the scheme's default port. If the scheme's default port is
        not known, and the port is not provided, this attribute will
        be set to None.

        >>> URL.from_text(u'http://example.com/pa/th').port
        80
        >>> URL.from_text(u'foo://example.com/pa/th').port
        >>> URL.from_text(u'foo://example.com:8042/pa/th').port
        8042

        .. note::

           Per the standard, when the port is the same as the schemes
           default port, it will be omitted in the text URL.

        )r   r!   r   r   r   r   l  s    zURL.portc                 C   s   | j S )zA tuple of strings, created by splitting the slash-separated
        hierarchical path. Started by the first slash after the host,
        terminated by a "?", which indicates the start of the
        :attr:`~hyperlink.URL.query` string.
        )r   r!   r   r   r   r     s    zURL.pathc                 C   s   | j S )a  Tuple of pairs, created by splitting the ampersand-separated
        mapping of keys and optional values representing
        non-hierarchical data used to identify the resource. Keys are
        always strings. Values are strings when present, or None when
        missing.

        For more operations on the mapping, see
        :meth:`~hyperlink.URL.get()`, :meth:`~hyperlink.URL.add()`,
        :meth:`~hyperlink.URL.set()`, and
        :meth:`~hyperlink.URL.delete()`.
        )r   r!   r   r   r   r     s    z	URL.queryc                 C   s   | j S )a  A string, the last part of the URL, indicated by the first "#"
        after the :attr:`~hyperlink.URL.path` or
        :attr:`~hyperlink.URL.query`. Enables indirect identification
        of a secondary resource, like an anchor within an HTML page.

        )r   r!   r   r   r   r     s    zURL.fragmentc                 C   s   | j S )ax  Whether or not the path starts with a forward slash (``/``).

        This is taken from the terminology in the BNF grammar,
        specifically the "path-rootless", rule, since "absolute path"
        and "absolute URI" are somewhat ambiguous. :attr:`path` does
        not contain the implicit prefixed ``"/"`` since that is
        somewhat awkward to work with.

        )r   r!   r   r   r   rk     s    z
URL.rootedc                 C   s   | j S )zVThe colon-separated string forming the username-password
        combination.
        )r   r!   r   r   r   r     s    zURL.userinfoc                 C   s   | j S )z	
        )r   r!   r   r   r   r     s    zURL.uses_netlocc                 C   s   | j dd S )zF
        The user portion of :attr:`~hyperlink.URL.userinfo`.
        r7   r   )r   r   r!   r   r   r   user  s    zURL.userc                 K   s   | d|}|r td|  | j}d|kr>d| d g}n| jg}| jt| jkrh|t	| j g }| j
r| j
}|sd|kr|d|dd  }|| |d| d|S )	aV  Compute and return the appropriate host/port/userinfo combination.

        >>> url = URL.from_text(u'http://user:pass@localhost:8080/a/b?x=y')
        >>> url.authority()
        u'user:@localhost:8080'
        >>> url.authority(with_password=True)
        u'user:pass@localhost:8080'

        Args:
           with_password (bool): Whether the return value of this
              method include the password in the URL, if it is
              set. Defaults to False.

        Returns:
           str: The authority (network location and user information) portion
              of the URL.
        includeSecretsz$got unexpected keyword arguments: %rr7   []Nrg   @)r?   r   keysr   r   r   r   r   r   r   r   indexrW   )r"   with_passwordkwr   Zhostport	authorityr   r   r   r   r     s"    
zURL.authorityc                 C   s\   t || jstS dD ]}t| |t||kr dS q| j|jksT| jtkrX|jtkrXdS dS )N)r   r   r   r   r   r   r   FT)r   r$   NotImplementedgetattrr   _ROOT_PATHS)r"   otherattrr   r   r   __eq__  s    z
URL.__eq__c                 C   s   t || jstS | | S r   r   r$   r   r  r"   r  r   r   r   __ne__  s    z
URL.__ne__c                 C   s0   t | j| j| j| j| j| j| j| j| j	| j
f
S r   hashr$   r   r   r   r   r   r   r   rk   r   r!   r   r   r   __hash__  s        zURL.__hash__c                 C   s   t | jo| jS )ao  Whether or not the URL is "absolute". Absolute URLs are complete
        enough to resolve to a network resource without being relative
        to a base URI.

        >>> URL.from_text(u'http://wikipedia.org/').absolute
        True
        >>> URL.from_text(u'?a=b&c=d').absolute
        False

        Absolute URLs must have both a scheme and a host set.
        )r   r   r   r!   r   r   r   absolute  s    zURL.absolutec
           
      C   sd   | j t|| jt|| jt|| jt|| jt|| jt|| jt|| jt|| j	t|	| j
d	S )ar  :class:`URL` objects are immutable, which means that attributes
        are designed to be set only once, at construction. Instead of
        modifying an existing URL, one simply creates a copy with the
        desired changes.

        If any of the following arguments is omitted, it defaults to
        the value on the current URL.

        Args:
           scheme (unicode): The text name of the scheme.
           host (unicode): The host portion of the network location
           port (int): The port part of the network location.
           path (tuple): A tuple of strings representing the
              slash-separated parts of the path.
           query (tuple): The query parameters, as a tuple of
              key-value pairs.
           query (tuple): The query parameters, as a dictionary or
              as an iterable of key-value pairs.
           fragment (unicode): The fragment part of the URL.
           rooted (bool): Whether or not the path begins with a slash.
           userinfo (unicode): The username or colon-separated
              username:password pair.
           uses_netloc (bool): Indicates whether two slashes appear
              between the scheme and the host (``http://eg.com`` vs
              ``mailto:e@g.com``)

        Returns:
           URL: a copy of the current :class:`URL`, with new values for
              parameters passed.

        	r   r   r   r   r   r   rk   r   r   )r$   r   r   r   r   r   r   r   rk   r   r   )
r"   r   r   r   r   r   r   rk   r   r   r   r   r   rK     s    "








zURL.replacec              
   C   s  t td|}z| }W n  tk
r<   td| Y nX |d pHd}t|}z| }W n$ tk
r   td||f Y nX |d rtd|d |f |d pd}|d	 p|d
 }|d }	|	dk	rzt|	}	W n2 tk
r   |	std| td|	 Y nX |d pd}
|d p*d}t	|d }|d rp|d 
d}|d sj|d d}nd}nd}t	|}|d rdd |d 
dD }nd}| |
|||||	|||	S )aM  Whereas the :class:`URL` constructor is useful for constructing
        URLs from parts, :meth:`~URL.from_text` supports parsing whole
        URLs from their string form::

           >>> URL.from_text(u'http://example.com')
           URL.from_text(u'http://example.com')
           >>> URL.from_text(u'?a=b&x=y')
           URL.from_text(u'?a=b&x=y')

        As you can see above, it's also used as the :func:`repr` of
        :class:`URL` objects. The natural counterpart to
        :func:`~URL.to_text()`. This method only accepts *text*, so be
        sure to decode those bytestrings.

        Args:
           text (unicode): A valid URL string.

        Returns:
           URL: The structured object version of the parsed string.

        .. note::

            Somewhat unexpectedly, URLs are a far more permissive
            format than most would assume. Many strings which don't
            look like URLs are still valid URLs. As a result, this
            method only raises :class:`URLParseError` on invalid port
            and IPv6 values in the host portion of the URL.

        rY   zcould not parse url: %rr   r   zinvalid authority %r in url: %rZbad_hostzinvalid host %r in url: %rr   Z	ipv6_hostZ
plain_hostr   Nzport must not be empty: %rz!expected integer for port, not %rr   r   Z_netloc_sepr   rh   r   TFr   r   c                 s   s*   | ]"}d |kr| d dn|dfV  qdS )r8   rg   N)r   )r2   Zqer   r   r   r     s   z URL.from_text.<locals>.<genexpr>&)_URL_REr   r   	groupdictr   r   _AUTHORITY_REr1   r   r   r   r?   )clsrY   ZumZgsZau_textZau_mZau_gsr   r   r   r   r   r   r   rk   r   r   r   r   	from_text@  s`    






  zURL.from_textTc           	         s   i }|r| j  |d< |r(| j |d< fdd |rd| jr\ fddt| jD |d< nd|d< |r fd	d| jD |d
< |r | j|d< |rd fdd| j	ddD |d< | j
f |S )aM  Return a new URL object with several standard normalizations
        applied:

        * Decode unreserved characters (`RFC 3986 2.3`_)
        * Uppercase remaining percent-encoded octets (`RFC 3986 2.1`_)
        * Convert scheme and host casing to lowercase (`RFC 3986 3.2.2`_)
        * Resolve any "." and ".." references in the path (`RFC 3986 6.2.2.3`_)
        * Ensure an ending slash on URLs with an empty path (`RFC 3986 6.2.3`_)
        * Encode any stray percent signs (`%`) in percent-encoded
          fields (path, query, fragment, userinfo) (`RFC 3986 2.4`_)

        All are applied by default, but normalizations can be disabled
        per-part by passing `False` for that part's corresponding
        name.

        Args:
           scheme (bool): Convert the scheme to lowercase
           host (bool): Convert the host to lowercase
           path (bool): Normalize the path (see above for details)
           query (bool): Normalize the query string
           fragment (bool): Normalize the fragment
           userinfo (bool): Normalize the userinfo
           percents (bool): Encode isolated percent signs
              for any percent-encoded fields which are being
              normalized (defaults to True).

        >>> url = URL.from_text(u'Http://example.COM/a/../b/./c%2f?%61%')
        >>> print(url.normalize().to_text())
        http://example.com/b/c%2F?a%25

        .. _RFC 3986 3.2.2: https://tools.ietf.org/html/rfc3986#section-3.2.2
        .. _RFC 3986 2.3: https://tools.ietf.org/html/rfc3986#section-2.3
        .. _RFC 3986 2.1: https://tools.ietf.org/html/rfc3986#section-2.1
        .. _RFC 3986 6.2.2.3: https://tools.ietf.org/html/rfc3986#section-6.2.2.3
        .. _RFC 3986 6.2.3: https://tools.ietf.org/html/rfc3986#section-6.2.3
        .. _RFC 3986 2.4: https://tools.ietf.org/html/rfc3986#section-2.4

        r   r   c                    s   t | d dS )NT)r   r   )r   )target)percentsr   r   
_dec_unres  s    z!URL.normalize.<locals>._dec_unresc                    s   g | ]} |qS r   r   r2   pr  r   r   r5     s     z!URL.normalize.<locals>.<listcomp>r   rO   c                    s(   g | ] \}} ||r |n|fqS r   r   rM   r  r   r   r5     s   r   r   r7   c                    s   g | ]} |qS r   r   r  r  r   r   r5     s   rg   r   )r   r>   r   r   r   r   r   rW   r   r   rK   )	r"   r   r   r   r   r   r   r  r   r   )r  r  r   r     s*    (

zURL.normalizec                 G   sZ   |s| S dd |D }t |ddd}| jd| jrB| jd dkrBdnd | }| j|dS )	a  Make a new :class:`URL` where the given path segments are a child
        of this URL, preserving other parts of the URL, including the
        query string and fragment.

        For example::

            >>> url = URL.from_text(u'http://localhost/a/b?x=y')
            >>> child_url = url.child(u"c", u"d")
            >>> child_url.to_text()
            u'http://localhost/a/b/c/d?x=y'

        Args:
           segments (unicode): Additional parts to be joined and added to
              the path, like :func:`os.path.join`. Special characters
              in segments will be percent encoded.

        Returns:
           URL: A copy of the current URL with the extra path segments.

        c                 S   s   g | ]}t d |qS )r   r   r2   sr   r   r   r5     s     zURL.child.<locals>.<listcomp>F)rn   rZ   Nr   r   r   )ro   r   rK   )r"   segmentsnew_segsnew_pathr   r   r   child  s    z	URL.childc                 C   s.   t d| | jdd t|f }| j|dS )ar  Make a new :class:`URL` with a single path segment that is a
        sibling of this URL path.

        Args:
           segment (unicode): A single path segment.

        Returns:
           URL: A copy of the current URL with the last path segment
              replaced by *segment*. Special characters such as
              ``/?#`` will be percent encoded.

        r   Nr   r  )r   r   r^   rK   )r"   r   r  r   r   r   sibling  s    
zURL.siblingc                 C   s   |r4t |tr|}ntd| t|}|jr8|S n| }|j}|jrZ|jsZtd|f n:|jrh|j	}n,|j	r| j	dd |j	 }n| j	}|s| j}| j
|jp| j|jp| j|jp| jt|||jdS )a9  Resolve the given URL relative to this URL.

        The resulting URI should match what a web browser would
        generate if you visited the current URL and clicked on *href*.

           >>> url = URL.from_text(u'http://blog.hatnote.com/')
           >>> url.click(u'/post/155074058790').to_text()
           u'http://blog.hatnote.com/post/155074058790'
           >>> url = URL.from_text(u'http://localhost/a/b/c/')
           >>> url.click(u'../d/./e').to_text()
           u'http://localhost/a/b/d/e'

        Args:
            href (unicode): A string representing a clicked URL.

        Return:
            URL: A copy of the current URL with navigation logic applied.

        For more information, see `RFC 3986 section 5`_.

        .. _RFC 3986 section 5: https://tools.ietf.org/html/rfc3986#section-5
        zrelative URLz#absolute URI with rootless path: %rNr   )r   r   r   r   r   r   )r   r   r   r  r  r   r   rk   NotImplementedErrorr   rK   r   r   r   r   )r"   hrefZclickedr   r   r   r   r   click  s6    




z	URL.clickc              	   C   s   d dd | jddD }t| jt| jdddd}| jsD| jnt| jdd	d	}| j
|||td
d | jD t| jdddS )u<  Make a new :class:`URL` instance with all non-ASCII characters
        appropriately percent-encoded. This is useful to do in preparation
        for sending a :class:`URL` over a network protocol.

        For example::

            >>> URL.from_text(u'https://ايران.com/foo⇧bar/').to_uri()
            URL.from_text(u'https://xn--mgba3a4fra.com/foo%E2%87%A7bar/')

        Returns:
            URL: A new instance with its path segments, query parameters, and
            hostname encoded, so that they are all in the standard
            US-ASCII range.
        r7   c                 S   s   g | ]}t |qS r   )r|   r  r   r   r   r5   L  s     zURL.to_uri.<locals>.<listcomp>rg   FT)rl   rk   rn   rZ   r   r   c                 S   s4   g | ],\}}t |d d|dk	r*t|d dndfqS )Trc   N)rs   rv   rM   r   r   r   r5   U  s   
rc   r   r   r   r   r   )rW   r   r   ro   r   r   r   r   idna_encoder   rK   rj   r   ry   r   )r"   new_userinfor  Znew_hostr   r   r   to_uri=  s$    
   z
URL.to_uric                 C   sZ   d dd | jddD }t| j}| j||dd | jD dd | jD t| j	dS )u  Make a new :class:`URL` instance with all but a few reserved
        characters decoded into human-readable format.

        Percent-encoded Unicode and IDNA-encoded hostnames are
        decoded, like so::

            >>> url = URL.from_text(u'https://xn--mgba3a4fra.example.com/foo%E2%87%A7bar/')
            >>> print(url.to_iri().to_text())
            https://ايران.example.com/foo⇧bar/

        .. note::

            As a general Python issue, "narrow" (UCS-2) builds of
            Python may not be able to fully decode certain URLs, and
            the in those cases, this method will return a best-effort,
            partially-decoded, URL which is still valid. This issue
            does not affect any Python builds 3.4+.

        Returns:
            URL: A new instance with its path segments, query parameters, and
            hostname decoded for display purposes.
        r7   c                 S   s   g | ]}t |qS r   )r   r  r   r   r   r5   s  s     zURL.to_iri.<locals>.<listcomp>rg   c                 S   s   g | ]}t |qS r   )r   r   r   r   r   r5   y  s   c                 S   s,   g | ]$\}}t ||d k	r"t|nd fqS r   )r   r   rM   r   r   r   r5   {  s   
r$  )
rW   r   r   r   r   rK   r   r   r   r   )r"   r&  r   r   r   r   to_iri\  s    

z
URL.to_iric              
   C   sR  | j }| |}t| j| jt|t|dd}g }| jD ]H\}}|dkr\|t|dd q8|d	t|ddt
|ddf q8d	|}| j}	g }
|
j}|r|| |d |r|d || n"|r|dd	 dkr| jr|d |r|r|r|dd
 dkr|d || |r2|d || |	rH|d ||	 d	|
S )a  Render this URL to its textual representation.

        By default, the URL text will *not* include a password, if one
        is set. RFC 3986 considers using URLs to represent such
        sensitive information as deprecated. Quoting from RFC 3986,
        `section 3.2.1`:

            "Applications should not render as clear text any data after the
            first colon (":") character found within a userinfo subcomponent
            unless the data after the colon is the empty string (indicating no
            password)."

        Args:
            with_password (bool): Whether or not to include the
               password in the URL text. Defaults to False.

        Returns:
            str: The serialized textual representation of this URL,
            such as ``u"http://example.com/some/path?some=query"``.

        The natural counterpart to :class:`URL.from_text()`.

        .. _section 3.2.1: https://tools.ietf.org/html/rfc3986#section-3.2.1
        F)rk   rl   rm   rZ   Nrc   r8   r  r7   z//r   rg   rh   ?#r   )r   r   ro   r   rk   r   r   r   rs   rW   rv   r   r   )r"   r   r   r   r   Zquery_partsrN   rH   Zquery_stringr   partsZ_addr   r   r   to_text  sL    




zURL.to_textc                 C   s   d| j j|  f S )zConvert this URL to an representation that shows all of its
        constituent parts, as well as being a valid argument to
        :func:`eval`.
        z%s.from_text(%r))r$   r   r,  r!   r   r   r   r%     s    zURL.__repr__c                 C   s   |    dS )z
        Allows for direct usage of URL objects with libraries like
        requests, which automatically stringify URL parameters. See
        issue #49.
        r   )r'  r,  r   r!   r   r   r   	_to_bytes  s    zURL._to_bytesc                 C   s
   |  |S r   r  )r  r  r   r   r   fromText  s    zURL.fromTextc                 C   s   | j |dS N)r   r,  r"   r   r   r   r   asText  s    z
URL.asTextc                 C   s\   zt | }W n, tk
r:   t| jt| j  }Y nX tt	|t	ddddg }|S Nr/  asURIasIRIr3  
r*   __dir__r   dirr$   r   __dict__r   sortedr;   r"   rA   r   r   r   r8    s    zURL.__dir__c                 C   s   | j | j||ff dS )a  Make a new :class:`URL` instance with a given query argument,
        *name*, added to it with the value *value*, like so::

            >>> URL.from_text(u'https://example.com/?x=y').add(u'x')
            URL.from_text(u'https://example.com/?x=y&x')
            >>> URL.from_text(u'https://example.com/?x=y').add(u'x', u'z')
            URL.from_text(u'https://example.com/?x=y&x=z')

        Args:
            name (unicode): The name of the query parameter to add. The
                part before the ``=``.
            value (unicode): The value of the query parameter to add. The
                part after the ``=``. Defaults to ``None``, meaning no
                value.

        Returns:
            URL: A new :class:`URL` instance with the parameter added.
        r   rK   r   r"   r   r   r   r   r   r     s    zURL.addc                    sP    fdd| j D }t fddt| j D d} |fg|||< | j|dS )a/  Make a new :class:`URL` instance with the query parameter *name*
        set to *value*. All existing occurences, if any are replaced
        by the single name-value pair.

            >>> URL.from_text(u'https://example.com/?x=y').set(u'x')
            URL.from_text(u'https://example.com/?x')
            >>> URL.from_text(u'https://example.com/?x=y').set(u'x', u'z')
            URL.from_text(u'https://example.com/?x=z')

        Args:
            name (unicode): The name of the query parameter to set. The
                part before the ``=``.
            value (unicode): The value of the query parameter to set. The
                part after the ``=``. Defaults to ``None``, meaning no
                value.

        Returns:
            URL: A new :class:`URL` instance with the parameter set.
        c                    s    g | ]\}}| kr||fqS r   r   rM   r   r   r   r5     s      zURL.set.<locals>.<listcomp>c                 3   s"   | ]\}\}}| kr|V  qd S r   r   r2   rG   rN   rH   r@  r   r   r     s    
zURL.set.<locals>.<genexpr>r   r=  r   next	enumeraterK   )r"   r   r   qidxr   r@  r   r;     s    zURL.setc                    s    fdd| j D S )a0  Get a list of values for the given query parameter, *name*::

            >>> url = URL.from_text(u'?x=1&x=2')
            >>> url.get('x')
            [u'1', u'2']
            >>> url.get('y')
            []

        If the given *name* is not set, an empty list is returned. A
        list is always returned, and this method raises no exceptions.

        Args:
            name (unicode): The name of the query parameter to get.

        Returns:
            list: A list of all the values associated with the key, in
                string form.

        c                    s   g | ]\}} |kr|qS r   r   )r2   keyr   r@  r   r   r5   2  s      zURL.get.<locals>.<listcomp>r=  r"   r   r   r@  r   r     s    zURL.getc                    s   |dkr>t kr& fdd| jD }q fdd| jD }nRg d }}| jD ]@\}}| krt ksn|kr||k r|d7 }qN|||f qN| j|dS )a  Make a new :class:`URL` instance with occurrences of the query
        parameter *name* removed, or, if *value* is set, parameters
        matching *name* and *value*. No exception is raised if the
        parameter is not already set.

        Args:
            name (unicode): The name of the query parameter to remove.
            value (unicode): Optional value to additionally filter
               on. Setting this removes query parameters which match
               both name and value.
            limit (int): Optional maximum number of parameters to remove.

        Returns:
            URL: A new :class:`URL` instance with the parameter removed.
        Nc                    s    g | ]\}}| kr||fqS r   r   rM   r@  r   r   r5   F  s      zURL.remove.<locals>.<listcomp>c                    s(   g | ] \}}| kr|ks||fqS r   r   rM   r   r   r   r   r5   H  s       r   rg   r=  r,   r   r   rK   r"   r   r   limitZnqZremoved_countrN   rH   r   rI  r   remove4  s    
 
z
URL.remove)	NNr   r   r   NNr   N)F)F)TTTTTTT)r   )F)F)N)N)0r   r   r   r   r#   r   propertyr   r   r   r   r   r   rk   r   r   r   r   r  r  r
  r  r,   rK   classmethodr  r   r  r   r#  r'  r(  r,  r%   r-  r   __str__Z__unicode__	__bytes__r5  r6  r/  r3  r8  r   r;   r   rM  r   r   r   r   r     s   6        
3

	




	




&
   
.
Q      
@
<%
A



r   c                	   @   s  e Zd ZdZdIddZedJddZedd Zd	d
 Z	dd Z
dd ZdKddZdd Zdd Zdd Zedd Zedd Zedd Zedd Zed d! Zed"d# Zed$d% Zed&d' Zed(d) Zed*d+ Zed,d- Zeeeeeeeeef	d.d/Zd0d1 ZdLd3d4ZdMd5d6Zed2fd7d8Z d9d: Z!d;d< Z"d=d> Z#d?d@ Z$dAdB Z%e
Z&eZ'edNdCdDZ(dOdEdFZ)dGdH Z*d2S )Pr   ap  DecodedURL is a type meant to act as a higher-level interface to
    the URL. It is the `unicode` to URL's `bytes`. `DecodedURL` has
    almost exactly the same API as `URL`, but everything going in and
    out is in its maximally decoded state. All percent decoding is
    handled automatically.

    Where applicable, a UTF-8 encoding is presumed. Be advised that
    some interactions can raise :exc:`UnicodeEncodeErrors` and
    :exc:`UnicodeDecodeErrors`, just like when working with
    bytestrings. Examples of such interactions include handling query
    strings encoding binary data, and paths containing segments with
    special characters encoded with codecs other than UTF-8.

    Args:
       url (URL): A :class:`URL` object to wrap.
       lazy (bool): Set to True to avoid pre-decode all parts of the
           URL to check for validity. Defaults to False.

    Fc                 C   s&   || _ |s"| j| j| j| j| jf d S r   )_urlr   r   r   r   r   )r"   urlr   r   r   r   r#   l  s    zDecodedURL.__init__c                 C   s   t |}| ||dS )a          Make a `DecodedURL` instance from any text string containing a URL.

        Args:
          text (unicode): Text containing the URL
          lazy (bool): Whether to pre-decode all parts of the URL to
              check for validity. Defaults to True.
        r   )r   r  )r  rY   r   rR  r   r   r   r  t  s    

zDecodedURL.from_textc                 C   s   | j S )zeAccess the underlying :class:`URL` object, which has any special
        characters encoded.
        )rR  r!   r   r   r   encoded_url  s    zDecodedURL.encoded_urlc                 O   s   | j j||S )z/Passthrough to :meth:`~hyperlink.URL.to_text()`)rR  r,  r"   r3   r   r   r   r   r,    s    zDecodedURL.to_textc                 O   s   | j j||S )z.Passthrough to :meth:`~hyperlink.URL.to_uri()`)rR  r'  rU  r   r   r   r'    s    zDecodedURL.to_uric                 O   s   | j j||S )z.Passthrough to :meth:`~hyperlink.URL.to_iri()`)rR  r(  rU  r   r   r   r(    s    zDecodedURL.to_irir   c                 C   s$   t |tr|j}| | jj|dS )zMReturn a new DecodedURL wrapping the result of :meth:`~hyperlink.URL.click()`)r"  )r   r   rR  r$   r#  )r"   r"  r   r   r   r#    s    
zDecodedURL.clickc                 C   s   |  | jt|S )zAutomatically encode any reserved characters in *segment* and
        return a new `DecodedURL` wrapping the result of
        :meth:`~hyperlink.URL.sibling()`
        )r$   rR  r   r[   )r"   r   r   r   r   r     s    zDecodedURL.siblingc                 G   s(   |s| S dd |D }|  | jj| S )zAutomatically encode any reserved characters in *segments* and
        return a new `DecodedURL` wrapping the result of
        :meth:`~hyperlink.URL.child()`.
        c                 S   s   g | ]}t |qS r   r[   r  r   r   r   r5     s     z$DecodedURL.child.<locals>.<listcomp>)r$   rR  r  )r"   r  r  r   r   r   r    s    zDecodedURL.childc                 O   s   |  | jj||S )zSReturn a new `DecodedURL` wrapping the result of :meth:`~hyperlink.URL.normalize()`)r$   rR  r   rU  r   r   r   r     s    zDecodedURL.normalizec                 C   s   | j jS r   )rR  r  r!   r   r   r   r    s    zDecodedURL.absolutec                 C   s   | j jS r   )rR  r   r!   r   r   r   r     s    zDecodedURL.schemec                 C   s   t | jjS r   )r   rR  r   r!   r   r   r   r     s    zDecodedURL.hostc                 C   s   | j jS r   )rR  r   r!   r   r   r   r     s    zDecodedURL.portc                 C   s   | j jS r   )rR  rk   r!   r   r   r   rk     s    zDecodedURL.rootedc                 C   s<   z| j W S  tk
r   Y nX tdd | jjD | _ | j S )Nc                 S   s   g | ]}t |d dqS Tr   r   r  r   r   r   r5     s   z#DecodedURL.path.<locals>.<listcomp>)r   r   rj   rR  r   r!   r   r   r   r     s    
zDecodedURL.pathc                 C   s@   z| j W S  tk
r   Y nX dd | jjD }t|| _ | j S )Nc                 S   s&   g | ]\}}t d d ||fD qS )c                 s   s&   | ]}|d k	rt |ddnd V  qd S NTrX  rY  r2   xr   r   r   r     s   z.DecodedURL.query.<locals>.<listcomp>.<genexpr>)rj   rM   r   r   r   r5     s   z$DecodedURL.query.<locals>.<listcomp>)r   r   rR  r   rj   )r"   Z_qr   r   r   r     s    
zDecodedURL.queryc                 C   s:   z| j W S  tk
r   Y nX | jj}t|dd| _ | j S rZ  )r   r   rR  r   r   )r"   Zfragr   r   r   r     s    zDecodedURL.fragmentc                 C   sD   z| j W S  tk
r   Y nX tdd | jjddD | _ | j S )Nc                 S   s   g | ]}t |d dqS rW  rY  r  r   r   r   r5     s   z'DecodedURL.userinfo.<locals>.<listcomp>r7   rg   )r   r   rj   rR  r   r   r!   r   r   r   r     s    
zDecodedURL.userinfoc                 C   s
   | j d S )Nr   )r   r!   r   r   r   r     s    zDecodedURL.userc                 C   s   | j jS r   )rR  r   r!   r   r   r   r     s    zDecodedURL.uses_netlocc
                 C   s   |t k	rdd |D }|t k	r0dd t|D }|t k	rdt|dkrPtd| ddd |D }| jj|||||||||	d	}
| j|
d	S )
a  While the signature is the same, this `replace()` differs a little
        from URL.replace. For instance, it accepts userinfo as a
        tuple, not as a string, handling the case of having a username
        containing a `:`. As with the rest of the methods on
        DecodedURL, if you pass a reserved character, it will be
        automatically encoded instead of an error being raised.

        c                 S   s   g | ]}t |qS r   rV  r  r   r   r   r5     s     z&DecodedURL.replace.<locals>.<listcomp>c                 S   s"   g | ]\}}d d ||fD qS )c                 S   s    g | ]}|d k	rt |nd qS r   rV  r[  r   r   r   r5     s   
z1DecodedURL.replace.<locals>.<listcomp>.<listcomp>r   rM   r   r   r   r5     s   r   zFuserinfo expected sequence of ["user"] or ["user", "password"], got %rr7   c                 S   s   g | ]}t |qS r   rV  r  r   r   r   r5     s     r  )rS  )r,   r   r   r   rW   rR  rK   r$   )r"   r   r   r   r   r   r   rk   r   r   Znew_urlr   r   r   rK     s.    	zDecodedURL.replacec                    s    fdd| j D S )z?Get the value of all query parameters whose name matches *name*c                    s   g | ]\}} |kr|qS r   r   rM   r@  r   r   r5     s      z"DecodedURL.get.<locals>.<listcomp>r=  rH  r   r@  r   r     s    zDecodedURL.getNc                 C   s   | j | j||ff dS )zJReturn a new DecodedURL with the query parameter *name* and *value* added.r=  r>  r?  r   r   r   r     s    zDecodedURL.addc                    sR   | j } fdd|D }t fddt|D d} |fg|||< | j|dS )zBReturn a new DecodedURL with query parameter *name* set to *value*c                    s    g | ]\}}| kr||fqS r   r   rM   r@  r   r   r5   #  s      z"DecodedURL.set.<locals>.<listcomp>c                 3   s"   | ]\}\}}| kr|V  qd S r   r   rA  r@  r   r   r   $  s    
  z!DecodedURL.set.<locals>.<genexpr>r   r=  rB  )r"   r   r   r   rE  rF  r   r@  r   r;      s
    zDecodedURL.setc                    s   |dkr>t kr& fdd| jD }q fdd| jD }nRg d }}| jD ]@\}}| krt ksn|kr||k r|d7 }qN|||f qN| j|dS )zReturn a new DecodedURL with query parameter *name* removed.

        Optionally also filter for *value*, as well as cap the number
        of parameters removed with *limit*.
        Nc                    s    g | ]\}}| kr||fqS r   r   rM   r@  r   r   r5   0  s      z%DecodedURL.remove.<locals>.<listcomp>c                    s(   g | ] \}}| kr|ks||fqS r   r   rM   rI  r   r   r5   2  s       r   rg   r=  rJ  rK  r   rI  r   rM  (  s    
 
zDecodedURL.removec                 C   s   | j j}d|| jf S )Nz
%s(url=%r))r$   r   rR  )r"   Zcnr   r   r   r%   =  s    zDecodedURL.__repr__c                 C   s
   t | jS r   )r   rR  r!   r   r   r   rP  A  s    zDecodedURL.__str__c                 C   s(   t || jstS |   |  kS r   )r   r$   r   r   r'  r  r   r   r   r  F  s    zDecodedURL.__eq__c                 C   s   t || jstS | | S r   r  r  r   r   r   r  K  s    zDecodedURL.__ne__c                 C   s0   t | j| j| j| j| j| j| j| j| j	| j
f
S r   r  r!   r   r   r   r
  P  s        zDecodedURL.__hash__c                 C   s   | j ||dS r   r.  )r  r  r   r   r   r   r/  Y  s    zDecodedURL.fromTextc                 C   s   | j |dS r0  r1  r2  r   r   r   r3  ]  s    zDecodedURL.asTextc                 C   s\   zt | }W n, tk
r:   t| jt| j  }Y nX tt	|t	ddddg }|S r4  r7  r<  r   r   r   r8  `  s    zDecodedURL.__dir__)F)F)r   )N)N)F)F)+r   r   r   r   r#   rO  r  rN  rT  r,  r'  r(  r#  r   r  r   r  r   r   r   rk   r   r   r   r   r   r   r,   rK   r   r   r;   rM  r%   rP  r  r  r
  r5  r6  r/  r3  r8  r   r   r   r   r   X  sr   









	

	
	

   
"


r   c                 C   s"   t | }|s|S t||d}|S )a  Automatically turn text into a structured URL object.

    Args:

       decoded (bool): Whether or not to return a :class:`DecodedURL`,
          which automatically handles all
          encoding/decoding/quoting/unquoting for all the various
          accessors of parts of the URL, or an :class:`EncodedURL`,
          which has the same API, but requires handling of special
          characters for different parts of the URL.

       lazy (bool): In the case of `decoded=True`, this controls
          whether the URL is decoded immediately or as accessed. The
          default, `lazy=False`, checks all encoded parts of the URL
          for decodability.
    r   )
EncodedURLr  r   )rS  Zdecodedr   Zenc_urlZdec_urlr   r   r   parsel  s
    
r^  )r   N)F)T)T)T)FTTTT)T)T)T)T)TN)N)FF)FF)FF)FF)FF)FF)TF)pr   resysr.   r   unicodedatar   r   ImportErrorZcollections.abcr   collectionsZidnar   r%  r   r   r   r   Z	Structurer   ZwindllZws2_32r   ZWSAAddressToStringAversion_infor   typer   r0   	NameErrorrF   r   r+   Z_unspecifiedr,   	frozensetrL   compiler  r   r  r9   r/   r:   Z	_ASCII_REZ_GEN_DELIMSZ_SUB_DELIMSZ_ALL_DELIMSr;   Z_USERINFO_SAFEr{   Z
_PATH_SAFEr]   Z_SCHEMELESS_PATH_SAFEr`   Z_FRAGMENT_SAFErx   Z_QUERY_VALUE_SAFEru   Z_QUERY_KEY_SAFErr   rB   rJ   rz   r   r\   r_   r   rq   r   rt   r   rw   r   rR   r   r   r  r[   r^   ra   ro   rs   rv   ry   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*   r   r]  r   r^  r   r   r   r   <module>   sH  




3






	
      
)



                                   
)






 
O?&      s  