# Path: src/werkzeug/_internal.py
# def _check_str_tuple(value: t.Tuple[t.AnyStr, ...]) -> None:
#     """Ensure tuple items are all strings or all bytes."""
#     if not value:
#         return
# 
#     item_type = str if isinstance(value[0], str) else bytes
# 
#     if any(not isinstance(item, item_type) for item in value):
#         raise TypeError(f"Cannot mix str and bytes arguments (got {value!r})")
# 
# Path: src/werkzeug/_internal.py
# def _decode_idna(domain: t.Union[str, bytes]) -> str:
#     # If the input is a string try to encode it to ascii to do the idna
#     # decoding. If that fails because of a unicode error, then we
#     # already have a decoded idna domain.
#     if isinstance(domain, str):
#         try:
#             domain = domain.encode("ascii")
#         except UnicodeError:
#             return domain  # type: ignore
# 
#     # Decode each part separately. If a part fails, try to decode it
#     # with ascii and silently ignore errors. This makes sense because
#     # the idna codec does not have error handling.
#     def decode_part(part: bytes) -> str:
#         try:
#             return part.decode("idna")
#         except UnicodeError:
#             return part.decode("ascii", "ignore")
# 
#     return ".".join(decode_part(p) for p in domain.split(b"."))
# 
# Path: src/werkzeug/_internal.py
# def _encode_idna(domain: str) -> bytes:
#     # If we're given bytes, make sure they fit into ASCII
#     if isinstance(domain, bytes):
#         domain.decode("ascii")
#         return domain
# 
#     # Otherwise check if it's already ascii, then return
#     try:
#         return domain.encode("ascii")
#     except UnicodeError:
#         pass
# 
#     # Otherwise encode each part separately
#     return b".".join(p.encode("idna") for p in domain.split("."))
# 
# Path: src/werkzeug/_internal.py
# @typing.overload
# def _make_encode_wrapper(reference: str) -> t.Callable[[str], str]:
#     ...
# 
# Path: src/werkzeug/_internal.py
# @typing.overload
# def _to_str(  # type: ignore
#     x: None,
#     charset: t.Optional[str] = ...,
#     errors: str = ...,
#     allow_none_charset: bool = ...,
# ) -> None:
#     ...


import codecs
import os
import re
import typing as t
            import ntpath
            import posixpath
from ._internal import _check_str_tuple
from ._internal import _decode_idna
from ._internal import _encode_idna
from ._internal import _make_encode_wrapper
from ._internal import _to_str
    from . import datastructures as ds
    from .datastructures import iter_multi_items
        from .datastructures import MultiDict  # noqa: F811
    from .wsgi import make_chunk_iter
        from .datastructures import MultiDict  # noqa: F811
    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
    """
    if isinstance(iri, tuple):
        iri = url_unparse(iri)

    if safe_conversion:
        # If we're not sure if it's safe to convert the URL, and it only
        # contains ASCII characters, return it unconverted.
        try:
            native_iri = _to_str(iri)
            ascii_iri = native_iri.encode("ascii")

            # Only return if it doesn't have whitespace. (Why?)
            if len(ascii_iri.split()) == 1:
                return native_iri
        except UnicodeError:
            pass


# Path: src/werkzeug/_internal.py
# def _check_str_tuple(value: t.Tuple[t.AnyStr, ...]) -> None:
#     """Ensure tuple items are all strings or all bytes."""
#     if not value:
#         return
# 
#     item_type = str if isinstance(value[0], str) else bytes
# 
#     if any(not isinstance(item, item_type) for item in value):
#         raise TypeError(f"Cannot mix str and bytes arguments (got {value!r})")
# 
# Path: src/werkzeug/_internal.py
# def _decode_idna(domain: t.Union[str, bytes]) -> str:
#     # If the input is a string try to encode it to ascii to do the idna
#     # decoding. If that fails because of a unicode error, then we
#     # already have a decoded idna domain.
#     if isinstance(domain, str):
#         try:
#             domain = domain.encode("ascii")
#         except UnicodeError:
#             return domain  # type: ignore
# 
#     # Decode each part separately. If a part fails, try to decode it
#     # with ascii and silently ignore errors. This makes sense because
#     # the idna codec does not have error handling.
#     def decode_part(part: bytes) -> str:
#         try:
#             return part.decode("idna")
#         except UnicodeError:
#             return part.decode("ascii", "ignore")
# 
#     return ".".join(decode_part(p) for p in domain.split(b"."))
# 
# Path: src/werkzeug/_internal.py
# def _encode_idna(domain: str) -> bytes:
#     # If we're given bytes, make sure they fit into ASCII
#     if isinstance(domain, bytes):
#         domain.decode("ascii")
#         return domain
# 
#     # Otherwise check if it's already ascii, then return
#     try:
#         return domain.encode("ascii")
#     except UnicodeError:
#         pass
# 
#     # Otherwise encode each part separately
#     return b".".join(p.encode("idna") for p in domain.split("."))
# 
# Path: src/werkzeug/_internal.py
# @typing.overload
# def _make_encode_wrapper(reference: str) -> t.Callable[[str], str]:
#     ...
# 
# Path: src/werkzeug/_internal.py
# @typing.overload
# def _to_str(  # type: ignore
#     x: None,
#     charset: t.Optional[str] = ...,
#     errors: str = ...,
#     allow_none_charset: bool = ...,
# ) -> None:
#     ...


# Path: src/werkzeug/urls.py
import codecs
import os
import re
import typing as t
            import ntpath
            import posixpath
from ._internal import _check_str_tuple
from ._internal import _decode_idna
from ._internal import _encode_idna
from ._internal import _make_encode_wrapper
from ._internal import _to_str
    from . import datastructures as ds
    from .datastructures import iter_multi_items
        from .datastructures import MultiDict  # noqa: F811
    from .wsgi import make_chunk_iter
        from .datastructures import MultiDict  # noqa: F811

    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
    """
    if isinstance(iri, tuple):
        iri = url_unparse(iri)

    if safe_conversion:
        # If we're not sure if it's safe to convert the URL, and it only
        # contains ASCII characters, return it unconverted.
        try:
            native_iri = _to_str(iri)
            ascii_iri = native_iri.encode("ascii")

            # Only return if it doesn't have whitespace. (Why?)
            if len(ascii_iri.split()) == 1:
                return native_iri
        except UnicodeError:
            pass


    iri = url_parse(_to_str(iri, charset, errors))