# Path: natsort/compat/fastnumbers.py
# def is_supported_fastnumbers(fastnumbers_version: str) -> bool:
# 
# Path: natsort/compat/locale.py
# def get_strxfrm() -> TrxfmFunc:
#     return cast(TrxfmFunc, icu.Collator.createInstance(get_icu_locale()).getSortKey)
# 
# Path: natsort/ns_enum.py
# class ns(enum.IntEnum):  # noqa: N801
#     FLOAT = F = 1 << next(_counter)
#     SIGNED = S = 1 << next(_counter)
#     NOEXP = N = 1 << next(_counter)
#     PATH = P = 1 << next(_counter)
#     LOCALEALPHA = LA = 1 << next(_counter)
#     LOCALENUM = LN = 1 << next(_counter)
#     IGNORECASE = IC = 1 << next(_counter)
#     LOWERCASEFIRST = LF = 1 << next(_counter)
#     GROUPLETTERS = G = 1 << next(_counter)
#     UNGROUPLETTERS = CAPITALFIRST = C = UG = 1 << next(_counter)
#     NANLAST = NL = 1 << next(_counter)
#     COMPATIBILITYNORMALIZE = CN = 1 << next(_counter)
#     NUMAFTER = NA = 1 << next(_counter)
#     DEFAULT = 0
#     INT = I = 0  # noqa: E741
#     UNSIGNED = U = 0
#     REAL = R = FLOAT | SIGNED
#     LOCALE = L = LOCALEALPHA | LOCALENUM
# NS_DUMB = 1 << 31
# 
# Path: natsort/utils.py
# def groupletters(x: str, _low: StrToStr = lower_function) -> str:
#     """
#     Double all characters, making doubled letters lowercase.
# 
#     Parameters
#     ----------
#     x : str
# 
#     Returns
#     -------
#     str
# 
#     Examples
#     --------
# 
#         >>> groupletters("Apple")
#         'aAppppllee'
# 
#     """
#     return "".join(ichain.from_iterable((_low(y), y) for y in x))
# 
# def string_component_transform_factory(alg: NSType) -> StrTransformer:
#     """
#     Create a function to either transform a string or convert to a number.
# 
#     Parameters
#     ----------
#     alg : ns enum
#         Indicate how to format the *str*.
# 
#     Returns
#     -------
#     func : callable
#         A function to be used as the *component_transform* argument to
#         *parse_string_factory*.
# 
#     See Also
#     --------
#     parse_string_factory
# 
#     """
#     # Shortcuts.
#     use_locale = alg & ns.LOCALEALPHA
#     dumb = alg & NS_DUMB
#     group_letters = (alg & ns.GROUPLETTERS) or (use_locale and dumb)
#     nan_val = float("+inf") if alg & ns.NANLAST else float("-inf")
# 
#     # Build the chain of functions to execute in order.
#     func_chain: List[Callable[[str], StrOrBytes]] = []
#     if group_letters:
#         func_chain.append(groupletters)
#     if use_locale:
#         func_chain.append(get_strxfrm())
# 
#     # Return the correct chained functions.
#     kwargs: Dict[str, Union[float, Callable[[str], StrOrBytes]]]
#     kwargs = {"key": chain_functions(func_chain)} if func_chain else {}
#     if alg & ns.FLOAT:
#         # noinspection PyTypeChecker
#         kwargs["nan"] = nan_val
#         return cast(Callable[[str], StrOrBytes], partial(fast_float, **kwargs))
#     else:
#         return cast(Callable[[str], StrOrBytes], partial(fast_int, **kwargs))


from functools import partial
from typing import Any, Callable, FrozenSet, Union
from hypothesis import example, given
from hypothesis.strategies import floats, integers, text
from natsort.compat.fastnumbers import fast_float, fast_int
from natsort.compat.locale import get_strxfrm
from natsort.ns_enum import NSType, NS_DUMB, ns
from natsort.utils import groupletters, string_component_transform_factory
import pytest
# There are some unicode values that are known failures with the builtin locale
# library on BSD systems that has nothing to do with natsort (a ValueError is
# raised by strxfrm). Let's filter them out.
try:
    bad_uni_chars = frozenset(chr(x) for x in range(0x10FEFD, 0x10FFFF + 1))
except ValueError:
    # Narrow unicode build... no worries.
    bad_uni_chars = frozenset()


def no_bad_uni_chars(x: str, _bad_chars: FrozenSet[str] = bad_uni_chars) -> bool:
    """Ensure text does not contain bad unicode characters"""
    return not any(y in _bad_chars for y in x)


def no_null(x: str) -> bool:
    """Ensure text does not contain a null character."""
    return "\0" not in x


@pytest.mark.parametrize(
    "alg, example_func",
    [
        (ns.INT, fast_int),
        (ns.DEFAULT, fast_int),
        (ns.FLOAT, partial(fast_float, nan=float("-inf"))),
        (ns.FLOAT | ns.NANLAST, partial(fast_float, nan=float("+inf"))),
        (ns.GROUPLETTERS, partial(fast_int, key=groupletters)),
        (ns.LOCALE, partial(fast_int, key=lambda x: get_strxfrm()(x))),
        (

# Path: natsort/compat/fastnumbers.py
# def is_supported_fastnumbers(fastnumbers_version: str) -> bool:
# 
# Path: natsort/compat/locale.py
# def get_strxfrm() -> TrxfmFunc:
#     return cast(TrxfmFunc, icu.Collator.createInstance(get_icu_locale()).getSortKey)
# 
# Path: natsort/ns_enum.py
# class ns(enum.IntEnum):  # noqa: N801
#     FLOAT = F = 1 << next(_counter)
#     SIGNED = S = 1 << next(_counter)
#     NOEXP = N = 1 << next(_counter)
#     PATH = P = 1 << next(_counter)
#     LOCALEALPHA = LA = 1 << next(_counter)
#     LOCALENUM = LN = 1 << next(_counter)
#     IGNORECASE = IC = 1 << next(_counter)
#     LOWERCASEFIRST = LF = 1 << next(_counter)
#     GROUPLETTERS = G = 1 << next(_counter)
#     UNGROUPLETTERS = CAPITALFIRST = C = UG = 1 << next(_counter)
#     NANLAST = NL = 1 << next(_counter)
#     COMPATIBILITYNORMALIZE = CN = 1 << next(_counter)
#     NUMAFTER = NA = 1 << next(_counter)
#     DEFAULT = 0
#     INT = I = 0  # noqa: E741
#     UNSIGNED = U = 0
#     REAL = R = FLOAT | SIGNED
#     LOCALE = L = LOCALEALPHA | LOCALENUM
# NS_DUMB = 1 << 31
# 
# Path: natsort/utils.py
# def groupletters(x: str, _low: StrToStr = lower_function) -> str:
#     """
#     Double all characters, making doubled letters lowercase.
# 
#     Parameters
#     ----------
#     x : str
# 
#     Returns
#     -------
#     str
# 
#     Examples
#     --------
# 
#         >>> groupletters("Apple")
#         'aAppppllee'
# 
#     """
#     return "".join(ichain.from_iterable((_low(y), y) for y in x))
# 
# def string_component_transform_factory(alg: NSType) -> StrTransformer:
#     """
#     Create a function to either transform a string or convert to a number.
# 
#     Parameters
#     ----------
#     alg : ns enum
#         Indicate how to format the *str*.
# 
#     Returns
#     -------
#     func : callable
#         A function to be used as the *component_transform* argument to
#         *parse_string_factory*.
# 
#     See Also
#     --------
#     parse_string_factory
# 
#     """
#     # Shortcuts.
#     use_locale = alg & ns.LOCALEALPHA
#     dumb = alg & NS_DUMB
#     group_letters = (alg & ns.GROUPLETTERS) or (use_locale and dumb)
#     nan_val = float("+inf") if alg & ns.NANLAST else float("-inf")
# 
#     # Build the chain of functions to execute in order.
#     func_chain: List[Callable[[str], StrOrBytes]] = []
#     if group_letters:
#         func_chain.append(groupletters)
#     if use_locale:
#         func_chain.append(get_strxfrm())
# 
#     # Return the correct chained functions.
#     kwargs: Dict[str, Union[float, Callable[[str], StrOrBytes]]]
#     kwargs = {"key": chain_functions(func_chain)} if func_chain else {}
#     if alg & ns.FLOAT:
#         # noinspection PyTypeChecker
#         kwargs["nan"] = nan_val
#         return cast(Callable[[str], StrOrBytes], partial(fast_float, **kwargs))
#     else:
#         return cast(Callable[[str], StrOrBytes], partial(fast_int, **kwargs))


# Path: tests/test_string_component_transform_factory.py
from functools import partial
from typing import Any, Callable, FrozenSet, Union
from hypothesis import example, given
from hypothesis.strategies import floats, integers, text
from natsort.compat.fastnumbers import fast_float, fast_int
from natsort.compat.locale import get_strxfrm
from natsort.ns_enum import NSType, NS_DUMB, ns
from natsort.utils import groupletters, string_component_transform_factory
import pytest

# There are some unicode values that are known failures with the builtin locale
# library on BSD systems that has nothing to do with natsort (a ValueError is
# raised by strxfrm). Let's filter them out.
try:
    bad_uni_chars = frozenset(chr(x) for x in range(0x10FEFD, 0x10FFFF + 1))
except ValueError:
    # Narrow unicode build... no worries.
    bad_uni_chars = frozenset()


def no_bad_uni_chars(x: str, _bad_chars: FrozenSet[str] = bad_uni_chars) -> bool:
    """Ensure text does not contain bad unicode characters"""
    return not any(y in _bad_chars for y in x)


def no_null(x: str) -> bool:
    """Ensure text does not contain a null character."""
    return "\0" not in x


@pytest.mark.parametrize(
    "alg, example_func",
    [
        (ns.INT, fast_int),
        (ns.DEFAULT, fast_int),
        (ns.FLOAT, partial(fast_float, nan=float("-inf"))),
        (ns.FLOAT | ns.NANLAST, partial(fast_float, nan=float("+inf"))),
        (ns.GROUPLETTERS, partial(fast_int, key=groupletters)),
        (ns.LOCALE, partial(fast_int, key=lambda x: get_strxfrm()(x))),
        (

            ns.GROUPLETTERS | ns.LOCALE,