ietfparse/algorithms.py
def rewrite_url(input_url, **kwargs):
    """
    Create a new URL from `input_url` with modifications applied.

    :param str input_url: the URL to modify

    :keyword str fragment: if specified, this keyword sets the
        fragment portion of the URL.  A value of :data:`None`
        will remove the fragment portion of the URL.
    :keyword str host: if specified, this keyword sets the host
        portion of the network location.  A value of :data:`None`
        will remove the network location portion of the URL.
    :keyword str password: if specified, this keyword sets the
        password portion of the URL.  A value of :data:`None` will
        remove the password from the URL.
    :keyword str path: if specified, this keyword sets the path
        portion of the URL.  A value of :data:`None` will remove
        the path from the URL.
    :keyword int port: if specified, this keyword sets the port
        portion of the network location.  A value of :data:`None`
        will remove the port from the URL.
    :keyword query: if specified, this keyword sets the query portion
        of the URL.  See the comments for a description of this
        parameter.
    :keyword str scheme: if specified, this keyword sets the scheme
        portion of the URL.  A value of :data:`None` will remove
        the scheme.  Note that this will make the URL relative and
        may have unintended consequences.
    :keyword str user: if specified, this keyword sets the user
        portion of the URL.  A value of :data:`None` will remove
        the user and password portions.

    :keyword bool enable_long_host: if this keyword is specified
        and it is :data:`True`, then the host name length restriction
        from :rfc:`3986#section-3.2.2` is relaxed.
    :keyword bool encode_with_idna: if this keyword is specified
        and it is :data:`True`, then the ``host`` parameter will be
        encoded using IDN.  If this value is provided as :data:`False`,
        then the percent-encoding scheme is used instead.  If this
        parameter is omitted or included with a different value, then
        the ``host`` parameter is processed using :data:`IDNA_SCHEMES`.

    :return: the modified URL
    :raises ValueError: when a keyword parameter is given an invalid
        value

    If the `host` parameter is specified and not :data:`None`, then
    it will be processed as an Internationalized Domain Name (IDN)
    if the scheme appears in :data:`IDNA_SCHEMES`.  Otherwise, it
    will be encoded as UTF-8 and percent encoded.

    The handling of the `query` parameter requires some additional
    explanation.  You can specify a query value in three different
    ways - as a *mapping*, as a *sequence* of pairs, or as a *string*.
    This flexibility makes it possible to meet the wide range of
    finicky use cases.

    *If the query parameter is a mapping*, then the key + value pairs
    are *sorted by the key* before they are encoded.  Use this method
    whenever possible.

    *If the query parameter is a sequence of pairs*, then each pair
    is encoded *in the given order*.  Use this method if you require
    that parameter order is controlled.

    *If the query parameter is a string*, then it is *used as-is*.
    This form SHOULD BE AVOIDED since it can easily result in broken
    URLs since *no URL escaping is performed*.  This is the obvious
    pass through case that is almost always present.

    """
    scheme, netloc, path, query, fragment = parse.urlsplit(input_url)

    if 'scheme' in kwargs:
        scheme = kwargs['scheme']

    ident, host_n_port = parse.splituser(netloc)

    user, password = parse.splitpasswd(ident) if ident else (None, None)
    if 'user' in kwargs:
        user = kwargs['user']
    elif user is not None:
        user = parse.unquote_to_bytes(user).decode('utf-8')
    if 'password' in kwargs:
        password = kwargs['password']
    elif password is not None:
        password = parse.unquote_to_bytes(password).decode('utf-8')
    ident = _create_url_identifier(user, password)

    host, port = parse.splitnport(host_n_port, defport=None)
    if 'host' in kwargs:
        host = kwargs['host']
        if host is not None:
            host = _normalize_host(
                host,
                enable_long_host=kwargs.get('enable_long_host', False),
                encode_with_idna=kwargs.get('encode_with_idna', None),
                scheme=scheme,
            )

    if 'port' in kwargs:
        port = kwargs['port']
        if port is not None:
            port = int(kwargs['port'])
            if port < 0:
                raise ValueError('port is required to be non-negative')

    if host is None or host == '':
        host_n_port = None
    elif port is None:
        host_n_port = host
    else:
        host_n_port = '{0}:{1}'.format(host, port)

    if 'path' in kwargs:
        path = kwargs['path']
        if path is None:
            path = '/'
        else:
            path = parse.quote(path.encode('utf-8'), safe=PATH_SAFE_CHARS)

    netloc = '{0}@{1}'.format(ident, host_n_port) if ident else host_n_port

    if 'query' in kwargs:
        new_query = kwargs['query']
        if new_query is None:
            query = None
        else:
            params = []
            try:
                for param in sorted(new_query.keys()):
                    params.append((param, new_query[param]))
            except AttributeError:  # arg is None or not a dict
                pass

            if not params:  # maybe a sequence of tuples?
                try:
                    params = [(param, value) for param, value in new_query]
                except ValueError:  # guess not...
                    pass

            if params:
                query = parse.urlencode(params)
            else:
                query = new_query

    if 'fragment' in kwargs:
        fragment = kwargs['fragment']
        if fragment is not None:
            fragment = parse.quote(fragment.encode('utf-8'),
                                   safe=FRAGMENT_SAFE_CHARS)

    # The following is necessary to get around some interesting special
    # case code in urllib.parse._coerce_args in Python 3.4.  Setting
    # scheme to None causes urlunsplit to assume that all non-``None``
    # parameters with be byte strings....
    if scheme is None:
        scheme = ''

    return parse.urlunsplit((scheme, netloc, path, query, fragment))
def rewrite_url(input_url, **kwargs):
    scheme, netloc, path, query, fragment = parse.urlsplit(input_url)

    if 'scheme' in kwargs:
        scheme = kwargs['scheme']

    ident, host_n_port = parse.splituser(netloc)

    user, password = parse.splitpasswd(ident) if ident else (None, None)
    if 'user' in kwargs:
        user = kwargs['user']
    elif user is not None:
        user = parse.unquote_to_bytes(user).decode('utf-8')
    if 'password' in kwargs:
        password = kwargs['password']
    elif password is not None:
        password = parse.unquote_to_bytes(password).decode('utf-8')
    ident = _create_url_identifier(user, password)

    host, port = parse.splitnport(host_n_port, defport=None)
    if 'host' in kwargs:
        host = kwargs['host']
        if host is not None:
            host = _normalize_host(
                host,
                enable_long_host=kwargs.get('enable_long_host', False),
                encode_with_idna=kwargs.get('encode_with_idna', None),
                scheme=scheme,
            )

    if 'port' in kwargs:
        port = kwargs['port']
        if port is not None:
            port = int(kwargs['port'])
            if port < 0:
                raise ValueError('port is required to be non-negative')

    if host is None or host == '':
        host_n_port = None
    elif port is None:
        host_n_port = host
    else:
        host_n_port = '{0}:{1}'.format(host, port)

    if 'path' in kwargs:
        path = kwargs['path']
        if path is None:
            path = '/'
        else:
            path = parse.quote(path.encode('utf-8'), safe=PATH_SAFE_CHARS)

    netloc = '{0}@{1}'.format(ident, host_n_port) if ident else host_n_port

    if 'query' in kwargs:
        new_query = kwargs['query']
        if new_query is None:
            query = None
        else:
            params = []
            try:
                for param in sorted(new_query.keys()):
                    params.append((param, new_query[param]))
            except AttributeError:  # arg is None or not a dict
                pass

            if not params:  # maybe a sequence of tuples?
                try:
                    params = [(param, value) for param, value in new_query]
                except ValueError:  # guess not...
                    pass

            if params:
                query = parse.urlencode(params)
            else:
                query = new_query

    if 'fragment' in kwargs:
        fragment = kwargs['fragment']
        if fragment is not None:
            fragment = parse.quote(fragment.encode('utf-8'),
                                   safe=FRAGMENT_SAFE_CHARS)

    # The following is necessary to get around some interesting special
    # case code in urllib.parse._coerce_args in Python 3.4.  Setting
    # scheme to None causes urlunsplit to assume that all non-``None``
    # parameters with be byte strings....
    if scheme is None:
        scheme = ''

    return parse.urlunsplit((scheme, netloc, path, query, fragment))
def rewrite_url ( input_url , * * kwargs ) : scheme , netloc , path , query , fragment = parse . urlsplit ( input_url ) if 'scheme' in kwargs : scheme = kwargs [ 'scheme' ] ident , host_n_port = parse . splituser ( netloc ) user , password = parse . splitpasswd ( ident ) if ident else ( None , None ) if 'user' in kwargs : user = kwargs [ 'user' ] elif user is not None : user = parse . unquote_to_bytes ( user ) . decode ( 'utf-8' ) if 'password' in kwargs : password = kwargs [ 'password' ] elif password is not None : password = parse . unquote_to_bytes ( password ) . decode ( 'utf-8' ) ident = _create_url_identifier ( user , password ) host , port = parse . splitnport ( host_n_port , defport = None ) if 'host' in kwargs : host = kwargs [ 'host' ] if host is not None : host = _normalize_host ( host , enable_long_host = kwargs . get ( 'enable_long_host' , False ) , encode_with_idna = kwargs . get ( 'encode_with_idna' , None ) , scheme = scheme , ) if 'port' in kwargs : port = kwargs [ 'port' ] if port is not None : port = int ( kwargs [ 'port' ] ) if port < 0 : raise ValueError ( 'port is required to be non-negative' ) if host is None or host == '' : host_n_port = None elif port is None : host_n_port = host else : host_n_port = '{0}:{1}' . format ( host , port ) if 'path' in kwargs : path = kwargs [ 'path' ] if path is None : path = '/' else : path = parse . quote ( path . encode ( 'utf-8' ) , safe = PATH_SAFE_CHARS ) netloc = '{0}@{1}' . format ( ident , host_n_port ) if ident else host_n_port if 'query' in kwargs : new_query = kwargs [ 'query' ] if new_query is None : query = None else : params = [ ] try : for param in sorted ( new_query . keys ( ) ) : params . append ( ( param , new_query [ param ] ) ) except AttributeError : # arg is None or not a dict pass if not params : # maybe a sequence of tuples? try : params = [ ( param , value ) for param , value in new_query ] except ValueError : # guess not... pass if params : query = parse . urlencode ( params ) else : query = new_query if 'fragment' in kwargs : fragment = kwargs [ 'fragment' ] if fragment is not None : fragment = parse . quote ( fragment . encode ( 'utf-8' ) , safe = FRAGMENT_SAFE_CHARS ) # The following is necessary to get around some interesting special # case code in urllib.parse._coerce_args in Python 3.4.  Setting # scheme to None causes urlunsplit to assume that all non-``None`` # parameters with be byte strings.... if scheme is None : scheme = '' return parse . urlunsplit ( ( scheme , netloc , path , query , fragment ) )
Create a new URL from `input_url` with modifications applied.

    :param str input_url: the URL to modify

    :keyword str fragment: if specified, this keyword sets the
        fragment portion of the URL.  A value of :data:`None`
        will remove the fragment portion of the URL.
    :keyword str host: if specified, this keyword sets the host
        portion of the network location.  A value of :data:`None`
        will remove the network location portion of the URL.
    :keyword str password: if specified, this keyword sets the
        password portion of the URL.  A value of :data:`None` will
        remove the password from the URL.
    :keyword str path: if specified, this keyword sets the path
        portion of the URL.  A value of :data:`None` will remove
        the path from the URL.
    :keyword int port: if specified, this keyword sets the port
        portion of the network location.  A value of :data:`None`
        will remove the port from the URL.
    :keyword query: if specified, this keyword sets the query portion
        of the URL.  See the comments for a description of this
        parameter.
    :keyword str scheme: if specified, this keyword sets the scheme
        portion of the URL.  A value of :data:`None` will remove
        the scheme.  Note that this will make the URL relative and
        may have unintended consequences.
    :keyword str user: if specified, this keyword sets the user
        portion of the URL.  A value of :data:`None` will remove
        the user and password portions.

    :keyword bool enable_long_host: if this keyword is specified
        and it is :data:`True`, then the host name length restriction
        from :rfc:`3986#section-3.2.2` is relaxed.
    :keyword bool encode_with_idna: if this keyword is specified
        and it is :data:`True`, then the ``host`` parameter will be
        encoded using IDN.  If this value is provided as :data:`False`,
        then the percent-encoding scheme is used instead.  If this
        parameter is omitted or included with a different value, then
        the ``host`` parameter is processed using :data:`IDNA_SCHEMES`.

    :return: the modified URL
    :raises ValueError: when a keyword parameter is given an invalid
        value

    If the `host` parameter is specified and not :data:`None`, then
    it will be processed as an Internationalized Domain Name (IDN)
    if the scheme appears in :data:`IDNA_SCHEMES`.  Otherwise, it
    will be encoded as UTF-8 and percent encoded.

    The handling of the `query` parameter requires some additional
    explanation.  You can specify a query value in three different
    ways - as a *mapping*, as a *sequence* of pairs, or as a *string*.
    This flexibility makes it possible to meet the wide range of
    finicky use cases.

    *If the query parameter is a mapping*, then the key + value pairs
    are *sorted by the key* before they are encoded.  Use this method
    whenever possible.

    *If the query parameter is a sequence of pairs*, then each pair
    is encoded *in the given order*.  Use this method if you require
    that parameter order is controlled.

    *If the query parameter is a string*, then it is *used as-is*.
    This form SHOULD BE AVOIDED since it can easily result in broken
    URLs since *no URL escaping is performed*.  This is the obvious
    pass through case that is almost always present.
Create a new URL from input_url with modifications applied .