Source code for woob.tools.url
# Copyright(C) 2022 Budget Insight
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
# flake8: compatible
from __future__ import annotations
from typing import Dict
from urllib.parse import parse_qsl, urlencode, urlparse
from woob.tools.misc import NO_DEFAULT, NoDefaultType
__all__ = [
'get_url_fragment_param', 'get_url_fragment_params',
'get_url_param', 'get_url_params', 'get_url_with_params',
]
[docs]def get_url_param(
url: str, name: str, *,
default: str | NoDefaultType | None = NO_DEFAULT,
) -> str | None:
"""Get a specific query parameter from an URL.
:param url: The URL to get the parameter from.
:param name: The name of the query parameter to get.
:param default: The default value, as a string or None.
Should not be set if the function should raise an exception
in cases where no value could be obtained using this URL
and name.
"""
parsed_url = urlparse(url)
params = dict(parse_qsl(parsed_url.query, keep_blank_values=True))
if name not in params:
if default is NO_DEFAULT:
raise ValueError(
f'URL {url!r} has no query parameter named {name!r}.',
)
return default
return params[name]
[docs]def get_url_fragment_param(
url: str, name: str, *,
default: str | NoDefaultType | None = NO_DEFAULT,
) -> str | None:
"""Get a specific fragment parameter from an URL.
Note that this function is only for cases where the fragment is encoded
the same way as a query string, e.g. 'https://example.org/#a=b&c=d'.
:param url: The URL to get the fragment parameter from.
:param name: The name of the fragment parameter to get.
:param default: The default value, as a string or None.
Should not be set if the function should raise an exception
in cases where no value could be obtained using this URL
and name.
"""
parsed_url = urlparse(url)
params = dict(parse_qsl(parsed_url.fragment, keep_blank_values=True))
if name not in params:
if default is NO_DEFAULT:
raise ValueError(
f'URL {url!r} has no fragment parameter named {name!r}.',
)
return default
return params[name]
[docs]def get_url_params(url: str) -> Dict[str, str]:
"""Get query parameters from an URL.
:param url: The URL to get the parameters from.
"""
parsed_url = urlparse(url)
return dict(parse_qsl(parsed_url.query, keep_blank_values=True))
[docs]def get_url_fragment_params(url: str) -> Dict[str, str]:
"""Get fragment parameters from an URL.
Note that this function is only for cases where the fragment is encoded
the same way as a query string, e.g. 'https://example.org/#a=b&c=d'.
:param url: The URL to get the parameters from.
"""
parsed_url = urlparse(url)
return dict(parse_qsl(parsed_url.fragment, keep_blank_values=True))
[docs]def get_url_with_params(url: str, **kwargs: str | None) -> str:
"""Get an URL with additional or without some query parameters.
:param url: The URL to modify.
"""
parsed_url = urlparse(url)
params = dict(parse_qsl(parsed_url.query, keep_blank_values=True))
for key, value in kwargs.items():
if value is None:
if key in params:
del params[key]
else:
params[key] = str(value)
return parsed_url._replace(
query=urlencode(params, doseq=True),
).geturl()