B
    Ǉb              
   @   s8  U d Z ddl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
 ddlmZ ejrtdd	lmZ ed
ZeedZdZdd eD Zdd edD ZG dd dejZG dd deZG dd deZG dd deZe eiZejej e! eje"e!f f e#d< dlej$e%e"f ej$e%e"f e"dddZ&ej$ej'e%e%f ej(ej)e%e%f  f e%e*ej+ej,ej)e%e%f gej-f  ej.e% dd d!Z/dme%e%e%d"d#d$Z0dne%ej+e% e*ed&d'd(Z1doe%e%ej$e%e"f ej$e%e"f ej,e"ge%f d,d-d.Z2e2 Z3e2d/d0d1Z4e"e%d2d3d4Z5dpej$e%e"f e%e%ej$e%e"f ej$e%e"f e%d5d6d7Z6dqe%e%e%e%e%d8d9d:Z7ej)e%e%e%e%e%f e%d;d<d=Z8drej$e%e"f e%e%e%e%d?d@dAZ9dsej$e%e"f e%e%e%dBdCdDZ:dte%e%e%dEdFdGZ;d<dHd edID Z=e>ej)e%e!f dJdKdLZ?e@dMe? duej$e%ej)e%e%e%e%e%f f e%e%e%dNdOdPZAdQZBdvej$e%ej)e%e%e%e%e%f f e%e%e*e%dSdTdUZCdwejDe%e*e%e%ej+ejEdW  dXdYdZd[ZFdxejGe" e%e*e%e"ej+ejEdW  ej+e! dXd]d^d_ZHej(ejD e%e*e%ej.ej)e%e%f  d`dadbZIdyej$ej'e%e%f ej(ej)e%e%f  f e%e*ej+ej,ej)e%e%f gej-f  e%e%dcdddeZJdzej$ej'e%e%f ej(ej)e%e%f  f ej+ejGe%  e%e*ej+ej,ej)e%e%f gej-f  e%ddfdgdhZKd{ej$e%ej)e%e%e%e%e%f f ej$e%ej)e%e%e%e%e%f f e*e%didjdkZLdS )|zFunctions for working with URLs.

Contains implementations of functions from :mod:`urllib.parse` that
handle bytes and strings.
    N   )_check_str_tuple)_decode_idna)_encode_idna)_make_encode_wrapper)_to_str)datastructuresz^[a-zA-Z0-9+-.]+$sK   abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~$!'()*+,;0123456789ABCDEFabcdefc             C   s8   i | ]0}t D ]&}t| | d | | dqqS )   ascii)
_hexdigitsintencode).0ab r   a/var/www/downstreamdata.science/rtclock/rtclock-venv/lib/python3.7/site-packages/werkzeug/urls.py
<dictcomp>#   s   r   c             C   s   g | ]}d |d dqS )%02Xr   )r   )r   charr   r   r   
<listcomp>(   s    r      c               @   s6   e Zd ZU eed< eed< eed< eed< eed< dS )	_URLTupleschemenetlocpathqueryfragmentN)__name__
__module____qualname__str__annotations__r   r   r   r   r   +   s
   
r   c               @   s  e Zd ZU dZdZeed< eed< eed< eed< eddd	Zej	d d
ddZ
eeje dddZeeje dddZeeje dddZeeje dddZeeje dddZeeje dddZeeje dddZeeje dddZej	ej	dddd Zej	ej	d dd!d"Zedd#d$Zedd%d&Zedd'd(Zd dd)d*Zd dd+d,Zd7eje ejeje eje f d.d/d0Zejeje ef dd1d2Zejeje eje f dd3d4Z ejeje eje f dd5d6Z!d-S )8BaseURLz7Superclass of :py:class:`URL` and :py:class:`BytesURL`.r   _at_colon	_lbracket	_rbracket)returnc             C   s   |   S )N)to_url)selfr   r   r   __str__<   s    zBaseURL.__str__)kwargsr*   c             K   s   | j f |S )zReturn an URL with the same values, except for those parameters
        given new values by whichever keyword arguments are specified.)_replace)r,   r.   r   r   r   replace?   s    zBaseURL.replacec             C   s   |   d S )zThe host part of the URL if available, otherwise `None`.  The
        host is either the hostname or the IP address mentioned in the
        URL.  It will not contain the port.
        r   )_split_host)r,   r   r   r   hostD   s    zBaseURL.hostc             C   sR   | j }|dk	rFt|trFyt|}W n  tk
rD   |dd}Y nX t|ddS )a   Works exactly like :attr:`host` but will return a result that
        is restricted to ASCII.  If it finds a netloc that is not ASCII
        it will attempt to idna decode it.  This is useful for socket
        operations when the URL might include internationalized characters.
        Nr   ignore)r2   
isinstancer#   r   UnicodeErrorr   r   )r,   rvr   r   r   
ascii_hostL   s    zBaseURL.ascii_hostc          	   C   sR   y4t t|  d }d|  kr*dkr2n n|S W n ttfk
rL   Y nX dS )z}The port in the URL as an integer if it was present, `None`
        otherwise.  This does not fill in default ports.
        r   r   i  N)r   r   r1   
ValueError	TypeError)r,   r6   r   r   r   port[   s    zBaseURL.portc             C   s   |   d S )zSThe authentication part in the URL if available, `None`
        otherwise.
        r   )_split_netloc)r,   r   r   r   authh   s    zBaseURL.authc             C   s    |   d }|dk	rt|S dS )zThe username if it was part of the URL, `None` otherwise.
        This undergoes URL decoding and will always be a string.
        r   N)_split_auth_url_unquote_legacy)r,   r6   r   r   r   usernameo   s    zBaseURL.usernamec             C   s   |   d S )zThe username if it was part of the URL, `None` otherwise.
        Unlike :attr:`username` this one is not being decoded.
        r   )r=   )r,   r   r   r   raw_usernamey   s    zBaseURL.raw_usernamec             C   s    |   d }|dk	rt|S dS )zThe password if it was part of the URL, `None` otherwise.
        This undergoes URL decoding and will always be a string.
        r   N)r=   r>   )r,   r6   r   r   r   password   s    zBaseURL.passwordc             C   s   |   d S )zThe password if it was part of the URL, `None` otherwise.
        Unlike :attr:`password` this one is not being decoded.
        r   )r=   )r,   r   r   r   raw_password   s    zBaseURL.raw_passwordzds.MultiDict[str, str])argsr.   r*   c             O   s   t | jf||S )zDecodes the query part of the URL.  Ths is a shortcut for
        calling :func:`url_decode` on the query argument.  The arguments and
        keyword arguments are forwarded to :func:`url_decode` unchanged.
        )
url_decoder   )r,   rC   r.   r   r   r   decode_query   s    zBaseURL.decode_queryc             O   s   t t| f||S )zJoins this URL with another one.  This is just a convenience
        function for calling into :meth:`url_join` and then parsing the
        return value again.
        )	url_parseurl_join)r,   rC   r.   r   r   r   join   s    zBaseURL.joinc             C   s   t | S )zReturns a URL string or bytes depending on the type of the
        information stored.  This is just a convenience function
        for calling :meth:`url_unparse` for this URL.
        )url_unparse)r,   r   r   r   r+      s    zBaseURL.to_urlc          
   C   s   | j pd}d|krd| d}| j}|dk	r:| d| }dtdt| jpLddddt| jp^ddddg}|r| d	| }|S )
z6Encodes the netloc part to an ASCII safe URL as bytes. :[]Nzutf-8strictz/:%@)r7   r:   rH   filter	url_quoter@   rB   )r,   r6   r:   r<   r   r   r   encode_netloc   s    
zBaseURL.encode_netlocc             C   s   t | jp
d}d|kr"d| d}| j}|dk	r>| d| }dtdt| jpPddt| jp^ddg}|r|| d| }|S )z&Decodes the netloc part into a string.rJ   rK   rL   rM   Nz/:%@rO   )r   r2   r:   rH   rP   r>   r@   rB   )r,   r6   r:   r<   r   r   r   decode_netloc   s    zBaseURL.decode_netlocc             C   s   t t| S )a*  Returns a :class:`BytesURL` tuple that holds a URI.  This will
        encode all the information in the URL properly to ASCII using the
        rules a web browser would follow.

        It's usually more interesting to directly call :meth:`iri_to_uri` which
        will return a string.
        )rF   
iri_to_uri)r,   r   r   r   to_uri_tuple   s    zBaseURL.to_uri_tuplec             C   s   t t| S )aS  Returns a :class:`URL` tuple that holds a IRI.  This will try
        to decode as much information as possible in the URL without
        losing information similar to how a web browser does it for the
        URL bar.

        It's usually more interesting to directly call :meth:`uri_to_iri` which
        will return a string.
        )rF   
uri_to_iri)r,   r   r   r   to_iri_tuple   s    	zBaseURL.to_iri_tupleN)
pathformatr*   c             C   s:  | j dkrdS t| j}| jp d}|dkr>tjdkr:d}nd}|dkr|dd dkr|dd	  r|d	d
 dkr|dd	  d|d
d  }|dd
 dk}ddl}||}|r|dkr|	d
dd}t|d	kr|\}}n|d }d}n,|dkrddl}||}ntd||dkr2d}||fS )a@  Returns a tuple with the location of the file in the form
        ``(server, location)``.  If the netloc is empty in the URL or
        points to localhost, it's represented as ``None``.

        The `pathformat` by default is autodetection but needs to be set
        when working with URLs of a specific system.  The supported values
        are ``'windows'`` when working with Windows or DOS paths and
        ``'posix'`` when working with posix paths.

        If the URL does not point to a local file, the server and location
        are both represented as ``None``.

        :param pathformat: The expected format of the path component.
                           Currently ``'windows'`` and ``'posix'`` are
                           supported.  Defaults to ``None`` which is
                           autodetect.
        file)NNNntwindowsposixr   /      z|:rK   )z\\\z///r   \rJ   zInvalid path format )z	127.0.0.1z::1	localhost)r   url_unquoter   r   osnameisalphantpathnormpathlstripsplitlen	posixpathr9   )r,   rX   r   r2   Zwindows_sharerf   partsrk   r   r   r   get_file_location   s6    



0



zBaseURL.get_file_locationc             C   s2   | j | jkr(| j| j \}}}||fS d | jfS )N)r&   r   	partition)r,   r<   _r   r   r   r   r;   $  s    zBaseURL._split_netlocc             C   s@   |   d }|sdS | j|kr&|d fS || j\}}}||fS )Nr   )NN)r;   r'   rn   )r,   r<   r?   ro   rA   r   r   r   r=   *  s    
zBaseURL._split_authc             C   s   |   d }|sdS || jsL| j|krD|| j\}}}||fS |d fS || j}|dk rh|d fS |d| }||d d  }|| jr||dd  fS |d fS )Nr   )NNr   )r;   
startswithr(   r'   rn   findr)   )r,   r6   r2   ro   r:   idxrestr   r   r   r1   4  s     
zBaseURL._split_host)N)"r    r!   r"   __doc__	__slots__r#   r$   r-   tAnyr0   propertyOptionalr2   r7   r   r:   r<   r?   r@   rA   rB   rE   rH   r+   rR   rS   rU   rW   Tuplerm   r;   r=   r1   r   r   r   r   r%   3   sH   
		

$<$
r%   c               @   s8   e Zd ZdZdZdZdZdZdZde	e	d	d
ddZ
dS )URLzRepresents a parsed URL.  This behaves like a regular tuple but
    also has some extra attributes that give further insight into the
    URL.
    r   rO   rK   rL   rM   utf-8r0   BytesURL)charseterrorsr*   c          	   C   s:   t | jd|  | j||| j||| j||S )zEncodes the URL to a tuple made out of bytes.  The charset is
        only being used for the path, query and fragment.
        r   )r}   r   r   rR   r   r   r   )r,   r~   r   r   r   r   r   V  s    
z
URL.encodeN)r|   r0   )r    r!   r"   rt   ru   r&   r'   r(   r)   r#   r   r   r   r   r   r{   J  s   r{   c               @   sT   e Zd ZdZdZdZdZdZdZe	ddd	Z
edd
dZde	e	ddddZdS )r}   z!Represents a parsed URL in bytes.r      @   :   [   ])r*   c             C   s   |   ddS )Nzutf-8r0   )r+   decode)r,   r   r   r   r-   l  s    zBytesURL.__str__c             C   s   | j S )z&Returns the netloc unchanged as bytes.)r   )r,   r   r   r   rR   o  s    zBytesURL.encode_netlocutf-8r0   r{   )r~   r   r*   c          	   C   s:   t | jd|  | j||| j||| j||S )zDecodes the URL to a tuple made out of strings.  The charset is
        only being used for the path, query and fragment.
        r   )r{   r   r   rS   r   r   r   )r,   r~   r   r   r   r   r   s  s    
zBytesURL.decodeN)r   r0   )r    r!   r"   rt   ru   r&   r'   r(   r)   r#   r-   bytesrR   r   r   r   r   r   r}   c  s   r}   _unquote_mapsrJ   )stringunsafer*   c                s   t | tr| d} t  tr( d tt  t| d}tt|d}yt  }W n2 t	k
r    fddt
 D  }t < Y nX xV|D ]N}|d d }||kr|||  ||dd   q|d || qW t|S )Nzutf-8   %    c                s   i | ]\}}| kr||qS r   r   )r   hr   )r   r   r   r     s   z%_unquote_to_bytes.<locals>.<dictcomp>r^   %   )r4   r#   r   	frozenset	bytearrayiterri   nextr   KeyError
_hextobyteitemsappendextendr   )r   r   groupsresultZhex_to_bytegroupcoder   )r   r   _unquote_to_bytes  s(    






r   )objr~   sortkeyr*   c       
      c   s   ddl m} || }|r$t||d}xn|D ]f\}}|d kr<q*t|tsVt||}n|}t|tstt||}	n|}	t| dt|	 V  q*W d S )Nr   )iter_multi_items)r   =)r   r   sortedr4   r   r#   r   _fast_url_quote_plus)
r   r~   r   r   r   iterableZkey_strZ	value_str	key_bytesZvalue_bytesr   r   r   _url_encode_impl  s    

r   )valuer   r*   c             C   s4   yt | dd|dS  tk
r.   t | d|dS X d S )Nzutf-8rN   )r~   r   r   latin1)r~   r   )rb   r5   )r   r   r   r   r   r>     s    r>   T)urlr   allow_fragmentsr*   c                s  t |  t| t}|dkr" d} d } }}|  d}|dkrtt| d| ddr| |d d }|rt fdd	|D r| d|  | }} | dd
  dkrJt	| }	x. dD ]"}
| |
d
}|dkrt
|	|}	qW | d
|	 | |	d  }}  d|kr& d|ksB d|krJ d|krJtd|rr d| krr|  dd\} } d| kr|  dd\} }|rtnt}|||| ||S )a  Parses a URL from a string into a :class:`URL` tuple.  If the URL
    is lacking a scheme it can be provided as second argument. Otherwise,
    it is ignored.  Optionally fragments can be stripped from the URL
    by setting `allow_fragments` to `False`.

    The inverse of this function is :func:`url_unparse`.

    :param url: the URL to parse.
    :param scheme: the default schema to use if the URL is schemaless.
    :param allow_fragments: if set to `False` a fragment will be removed
                            from the URL.
    NrJ   rK   r   r0   )r   r   c             3   s   | ]}| d kV  qdS )
0123456789Nr   )r   c)sr   r   	<genexpr>  s    zurl_parse.<locals>.<genexpr>r^   z//z/?#rL   rM   zInvalid IPv6 URL#?)r   r4   r#   rq   
_scheme_rematchr   anylowerrj   minr8   ri   r{   r}   )r   r   r   Zis_text_basedr   r   r   irs   delimr   wdelimZresult_typer   )r   r   rF     s4    
"rF   utf-8rN   /:)r~   r   safer   r*   c                sv   t  tr | | t |tr,|| |}tt tB tt|   fddtdD ttdfdd}|S )a  Precompile the translation table for a URL encoding function.

    Unlike :func:`url_quote`, the generated function only takes the
    string to quote.

    :param charset: The charset to encode the result with.
    :param errors: How to handle encoding errors.
    :param safe: An optional sequence of safe characters to never encode.
    :param unsafe: An optional sequence of unsafe characters to always encode.
    c                s(   g | ] }| krt |n
d |dqS )r   r   )chr)r   r   )r   r   r   r     s    z(_make_fast_url_quote.<locals>.<listcomp>r   )r   r*   c                s   d  fdd| D S )NrJ   c                s   g | ]} | qS r   r   )r   r   )tabler   r   r     s    z7_make_fast_url_quote.<locals>.quote.<locals>.<listcomp>)rH   )r   )r   r   r   quote  s    z#_make_fast_url_quote.<locals>.quote)r4   r#   r   r   r   _always_saferanger   )r~   r   r   r   r   r   )r   r   r   _make_fast_url_quote  s    

r    +)r   r   )r   r*   c             C   s   t | ddS )Nr   r   )_fast_quote_plusr0   )r   r   r   r   r     s    r   )r   r~   r   r   r   r*   c             C   s   t | tttfst| } t | tr.| ||} t |trD|||}t |trZ|||}tt|tB tt| }t }x2t| D ]&}||kr|| q|t	|  qW t|
|S )aD  URL encode a single string with a given encoding.

    :param s: the string to quote.
    :param charset: the charset to be used.
    :param safe: an optional sequence of safe characters.
    :param unsafe: an optional sequence of unsafe characters.

    .. versionadded:: 0.9.2
       The `unsafe` parameter was added.
    )r4   r#   r   r   r   r   r   r   r   
_bytetohexr   )r   r~   r   r   r   r6   r   r   r   r   rQ   #  s    


rQ   )r   r~   r   r   r*   c             C   s   t | |||d dddS )zURL encode a single string with the given encoding and convert
    whitespace to "+".

    :param s: The string to quote.
    :param charset: The charset to be used.
    :param safe: An optional sequence of safe characters.
    r   r   )rQ   r0   )r   r~   r   r   r   r   r   url_quote_plusF  s    
r   )
componentsr*   c             C   s   t |  | \}}}}}t|}|d}|s<|rz||drz|r`|dd |dkr`|d| }|d|pp|d | }n|r||7 }|r||d | }|r||d | }|r||d | }|S )	zThe reverse operation to :meth:`url_parse`.  This accepts arbitrary
    as well as :class:`URL` tuples and returns a URL as a string.

    :param components: the parsed URL as tuple which should be converted
                       into a URL string.
    rJ   r]   Nr   z//rK   r   r   )r   r   rp   )r   r   r   r   r   r   r   r   r   r   r   rI   S  s"    rI   r0   )r   r~   r   r   r*   c             C   s"   t | |}|dkr|S |||S )af  URL decode a single string with a given encoding.  If the charset
    is set to `None` no decoding is performed and raw bytes are
    returned.

    :param s: the string to unquote.
    :param charset: the charset of the query string.  If set to `None`
        no decoding will take place.
    :param errors: the error handling for the charset decoding.
    N)r   r   )r   r~   r   r   r6   r   r   r   rb   r  s    
rb   )r   r~   r   r*   c             C   s0   t | tr| dd} n| dd} t| ||S )a  URL decode a single string with the given `charset` and decode "+" to
    whitespace.

    Per default encoding errors are ignored.  If you want a different behavior
    you can set `errors` to ``'replace'`` or ``'strict'``.

    :param s: The string to unquote.
    :param charset: the charset of the query string.  If set to `None`
        no decoding will take place.
    :param errors: The error handling for the `charset` decoding.
    r   r      +    )r4   r#   r0   rb   )r   r~   r   r   r   r   url_unquote_plus  s    
r   )r   r~   r*   c             C   s   t | |ddd} | drP| dd  rP| dd dkrPd	| dd
  } t| }t|j|dd}t|j|dd}t|j	|dd}t
|j| |||fS )a  Sometimes you get an URL by a user that just isn't a real URL because
    it contains unsafe characters like ' ' and so on. This function can fix
    some of the problems in a similar way browsers handle data entered by the
    user:

    >>> url_fix('http://de.wikipedia.org/wiki/Elf (Begriffskl\xe4rung)')
    'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)'

    :param s: the string with the URL to fix.
    :param charset: The target charset for the URL if the url was given
        as a string.
    r0   r`   r]   zfile://      
   )z:/z|/zfile:///Nz
/%+$!*'(),)r   z:&%=+$!*'(),)r   r0   rp   re   rF   rQ   r   r   r   r   rI   r   rR   )r   r~   r   r   qsanchorr   r   r   url_fix  s    *r   c             C   s   g | ]}|t krt|qS r   )r   r   )r   r   r   r   r   r     s       )er*   c             C   s    t | j| j| j }|| jfS )zRUsed in :func:`uri_to_iri` after unquoting to re-quote any
    invalid bytes.
    )_fast_url_quoteobjectstartend)r   outr   r   r   _codec_error_url_quote  s    r   werkzeug.url_quote)urir~   r   r*   c             C   sh   t | trt| } tt| |} t| j||t}t| j||t}t| j	||t}t| j
|  |||fS )a  Convert a URI to an IRI. All valid UTF-8 characters are unquoted,
    leaving all reserved and invalid characters quoted. If the URL has
    a domain, it is decoded from Punycode.

    >>> uri_to_iri("http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF")
    'http://\u2603.net/p\xe5th?q=\xe8ry%DF'

    :param uri: The URI to convert.
    :param charset: The encoding to encode unquoted bytes with.
    :param errors: Error handler to use during ``bytes.encode``. By
        default, invalid bytes are left quoted.

    .. versionchanged:: 0.15
        All reserved and invalid characters remain quoted. Previously,
        only some reserved characters were preserved, and invalid bytes
        were replaced instead of left quoted.

    .. versionadded:: 0.6
    )r4   tuplerI   rF   r   rb   r   _to_iri_unsafer   r   r   rS   )r   r~   r   r   r   r   r   r   r   rV     s    
rV   z:/?#[]@!$&'()*+,;=%F)irir~   r   safe_conversionr*   c       	      C   s   t | trt| } |rVy*t| }|d}t| dkr>|S W n tk
rT   Y nX tt| ||} t	| j
||t}t	| j||t}t	| j||t}t| j|  |||fS )a  Convert an IRI to a URI. All non-ASCII and unsafe characters are
    quoted. If the URL has a domain, it is encoded to Punycode.

    >>> iri_to_uri('http://\u2603.net/p\xe5th?q=\xe8ry%DF')
    'http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF'

    :param iri: The IRI to convert.
    :param charset: The encoding of the IRI.
    :param errors: Error handler to use during ``bytes.encode``.
    :param safe_conversion: Return the URL unchanged if it only contains
        ASCII characters and no whitespace. See the explanation below.

    There is a general problem with IRI conversion with some protocols
    that are in violation of the URI specification. Consider the
    following two IRIs::

        magnet:?xt=uri:whatever
        itms-services://?action=download-manifest

    After parsing, we don't know if the scheme requires the ``//``,
    which is dropped if empty, but conveys different meanings in the
    final URL if it's present or not. In this case, you can use
    ``safe_conversion``, which will return the URL unchanged if it only
    contains ASCII characters and no whitespace. This can result in a
    URI with unquoted characters if it was not already quoted correctly,
    but preserves the URL's semantics. Werkzeug uses this for the
    ``Location`` header for redirects.

    .. versionchanged:: 0.15
        All reserved characters remain unquoted. Previously, only some
        reserved characters were left unquoted.

    .. versionchanged:: 0.9.6
       The ``safe_conversion`` parameter was added.

    .. versionadded:: 0.6
    r   r   )r4   r   rI   r   r   rj   ri   r5   rF   rQ   r   _to_uri_safer   r   r   rR   )	r   r~   r   r   Z
native_iriZ	ascii_irir   r   r   r   r   r   rT     s    +

rT   &zds.MultiDictzds.MultiDict[str, str])r   r~   include_emptyr   	separatorclsr*   c             C   sv   |dkrddl m} |}t| tr<t|ts<||p6d}n"t| tr^t|ts^||pZd}|t| ||||S )aw  Parse a query string and return it as a :class:`MultiDict`.

    :param s: The query string to parse.
    :param charset: Decode bytes to string with this charset. If not
        given, bytes are returned as-is.
    :param include_empty: Include keys with empty values in the dict.
    :param errors: Error handling behavior when decoding bytes.
    :param separator: Separator character between pairs.
    :param cls: Container to hold result instead of :class:`MultiDict`.

    .. versionchanged:: 2.0
        The ``decode_keys`` parameter is deprecated and will be removed
        in Werkzeug 2.1.

    .. versionchanged:: 0.5
        In previous versions ";" and "&" could be used for url decoding.
        Now only "&" is supported. If you want to use ";", a different
        ``separator`` can be provided.

    .. versionchanged:: 0.5
        The ``cls`` parameter was added.
    Nr   )	MultiDictr   )	r   r   r4   r#   r   r   r   _url_decode_implri   )r   r~   r   r   r   r   r   r   r   r   rD   3  s    rD      &)streamr~   r   r   r   r   limitr*   c             C   sF   ddl m} || ||}t||||}	|dkr>ddlm}
 |
}||	S )a_  Works like :func:`url_decode` but decodes a stream.  The behavior
    of stream and limit follows functions like
    :func:`~werkzeug.wsgi.make_line_iter`.  The generator of pairs is
    directly fed to the `cls` so you can consume the data while it's
    parsed.

    :param stream: a stream with the encoded querystring
    :param charset: the charset of the query string.  If set to `None`
        no decoding will take place.
    :param include_empty: Set to `False` if you don't want empty values to
                          appear in the dict.
    :param errors: the decoding error behavior.
    :param separator: the pair separator to be used, defaults to ``&``
    :param cls: an optional dict class to use.  If this is not specified
                       or `None` the default :class:`MultiDict` is used.
    :param limit: the content length of the URL data.  Not necessary if
                  a limited stream is provided.

    .. versionchanged:: 2.0
        The ``decode_keys`` and ``return_iterator`` parameters are
        deprecated and will be removed in Werkzeug 2.1.

    .. versionadded:: 0.8
    r   )make_chunk_iterN)r   )Zwsgir   r   r   r   )r   r~   r   r   r   r   r   r   	pair_iterdecoderr   r   r   r   url_decode_stream`  s    !r   )r   r~   r   r   r*   c       	      c   sn   xh| D ]`}|sqt |}|d}||kr:||d\}}n|s@q|}|d}t|||t|||fV  qW d S )Nr   r   rJ   )r   ri   r   )	r   r~   r   r   pairr   equalr   r   r   r   r   r     s    

r   )r   r~   r   r   r   r*   c             C   s   t |d}|t| |||S )a  URL encode a dict/`MultiDict`.  If a value is `None` it will not appear
    in the result string.  Per default only values are encoded into the target
    charset strings.

    :param obj: the object to encode into a query string.
    :param charset: the charset of the query string.
    :param sort: set to `True` if you want parameters to be sorted by `key`.
    :param separator: the separator to be used for the pairs.
    :param key: an optional function to be used for sorting.  For more details
                check out the :func:`sorted` documentation.

    .. versionchanged:: 2.0
        The ``encode_keys`` parameter is deprecated and will be removed
        in Werkzeug 2.1.

    .. versionchanged:: 0.5
        Added the ``sort``, ``key``, and ``separator`` parameters.
    r   )r   rH   r   )r   r~   r   r   r   r   r   r   
url_encode  s    
r   )r   r   r~   r   r   r   r*   c       	      C   sV   t |d}t| |||}|dkr$|S x,t|D ] \}}|rD|| || q.W dS )a  Like :meth:`url_encode` but writes the results to a stream
    object.  If the stream is `None` a generator over all encoded
    pairs is returned.

    :param obj: the object to encode into a query string.
    :param stream: a stream to write the encoded object into or `None` if
                   an iterator over the encoded pairs should be returned.  In
                   that case the separator argument is ignored.
    :param charset: the charset of the query string.
    :param sort: set to `True` if you want parameters to be sorted by `key`.
    :param separator: the separator to be used for the pairs.
    :param key: an optional function to be used for sorting.  For more details
                check out the :func:`sorted` documentation.

    .. versionchanged:: 2.0
        The ``encode_keys`` parameter is deprecated and will be removed
        in Werkzeug 2.1.

    .. versionadded:: 0.8
    r   N)r   r   	enumeratewrite)	r   r   r~   r   r   r   genrr   chunkr   r   r   url_encode_stream  s    

r   )baser   r   r*   c                s  t | trt| } t |tr$t|}t| |f t|  | s@|S |sH| S t| |d\}}}}}t|||\}}	}
}}||kr|S |	rt||	|
||fS |}	|
dd  dkr|
 d}n@|
s| d}|s|}n$| ddd |
 d }|d  dkr d|d<  fdd	|D }xvd}t|d }x^||k r||  d
kr||d   d d
fkr||d |d = P |d7 }qBW P q0W  d d
g}x|dd |kr|d= qW  d|}
t||	|
||fS )a	  Join a base URL and a possibly relative URL to form an absolute
    interpretation of the latter.

    :param base: the base URL for the join operation.
    :param url: the URL to join.
    :param allow_fragments: indicates whether fragments should be allowed.
    )r   Nr   r]   .rJ   c                s   g | ]}| d kr|qS )r   r   )r   segment)r   r   r   r     s    zurl_join.<locals>.<listcomp>z..r^   )	r4   r   rI   r   r   rF   ri   rj   rH   )r   r   r   bschemebnetlocbpathbquery	bfragmentr   r   r   r   r   segmentsr   nZunwanted_markerr   )r   r   rG     sT    

$0rG   )rJ   )rJ   )NT)r   rN   r   rJ   )r   rN   r   rJ   )r   rN   rJ   )r   r0   rJ   )r   r0   )r   )r   r   )r   rN   F)r   Tr0   r   N)r   Tr0   r   NN)r   FNr   )Nr   FNr   )T)Mrt   codecsrc   retypingrv   	_internalr   r   r   r   r   TYPE_CHECKINGrJ   r   Zdscompiler   r   r   r   r   r   r   r   
NamedTupler   r%   r{   r}   r   Dict	FrozenSetr   r   r$   Unionr#   r   MappingIterablerz   boolry   Callablerw   Iteratorr   r>   rF   r   r   r   r   rQ   r   rI   rb   r   r   rH   r   r5   r   register_errorrV   r   rT   AnyStrTyperD   IOr   r   r   r   rG   r   r   r   r   <module>   s   
  , & 2      *
 !  
 "  $?    (     ('   N    \#<