from re import Pattern
from typing import Final, TypeAlias, overload

always_safe: Final[str]
urlencoded: Final[set[str]]
INVALID_HEX_PATTERN: Final[Pattern[str]]

_ExplodedQueryString: TypeAlias = list[tuple[str, str]]

def url_encode(params: _ExplodedQueryString) -> str: ...
def url_decode(query: str) -> _ExplodedQueryString: ...
def add_params_to_qs(query: str, params: _ExplodedQueryString | dict[str, str]) -> str: ...
def add_params_to_uri(uri: str, params: _ExplodedQueryString, fragment: bool = False) -> str: ...
def quote(s: str, safe: bytes = b"/") -> str: ...
def unquote(s: str | bytes) -> str: ...
def quote_url(s: str) -> str: ...

@overload
def extract_params(raw: None) -> None: ...
@overload
def extract_params(raw: dict[str, str]) -> _ExplodedQueryString: ...
@overload
def extract_params(raw: _ExplodedQueryString | tuple[tuple[str, str], ...] | str) -> _ExplodedQueryString | None: ...

def is_valid_url(url: str, fragments_allowed: bool = True) -> bool: ...
