summaryrefslogtreecommitdiff
path: root/tests/test_parse_string_function.py
blob: 46347f185dec8f4c34c4e6426530b483e7eb3783 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# -*- coding: utf-8 -*-
"""These test the utils.py functions."""

import unicodedata

import pytest
from hypothesis import given
from hypothesis.strategies import floats, integers, lists, text
from natsort.compat.fastnumbers import fast_float
from natsort.ns_enum import NS_DUMB, ns
from natsort.utils import NumericalRegularExpressions as NumRegex
from natsort.utils import parse_string_factory


class CustomTuple(tuple):
    """Used to ensure what is given during testing is what is returned."""

    original = None


def input_transform(x):
    """Make uppercase."""
    try:
        return x.upper()
    except AttributeError:
        return x


def final_transform(x, original):
    """Make the input a CustomTuple."""
    t = CustomTuple(x)
    t.original = original
    return t


def parse_string_func_factory(alg):
    """A parse_string_factory result with sample arguments."""
    sep = ""
    return parse_string_factory(
        alg,
        sep,
        NumRegex.int_nosign().split,
        input_transform,
        fast_float,
        final_transform,
    )


@given(x=floats() | integers())
def test_parse_string_factory_raises_type_error_if_given_number(x):
    parse_string_func = parse_string_func_factory(ns.DEFAULT)
    with pytest.raises(TypeError):
        assert parse_string_func(x)


# noinspection PyCallingNonCallable
@pytest.mark.parametrize(
    "alg, orig_func",
    [
        (ns.DEFAULT, lambda x: x.upper()),
        (ns.LOCALE, lambda x: x.upper()),
        (ns.LOCALE | NS_DUMB, lambda x: x),  # This changes the "original" handling.
    ],
)
@given(
    x=lists(
        elements=floats(allow_nan=False) | text() | integers(), min_size=1, max_size=10
    )
)
@pytest.mark.usefixtures("with_locale_en_us")
def test_parse_string_factory_invariance(x, alg, orig_func):
    parse_string_func = parse_string_func_factory(alg)
    # parse_string_factory is the high-level combination of several dedicated
    # functions involved in splitting and manipulating a string. The details of
    # what those functions do is not relevant to testing parse_string_factory.
    # What is relevant is that the form of the output matches the invariant
    # that even elements are string and odd are numerical. That each component
    # function is doing what it should is tested elsewhere.
    value = "".join(map(str, x))  # Convert the input to a single string.
    result = parse_string_func(value)
    result_types = list(map(type, result))
    expected_types = [str if i % 2 == 0 else float for i in range(len(result))]
    assert result_types == expected_types

    # The result is in our CustomTuple.
    assert isinstance(result, CustomTuple)

    # Original should have gone through the "input_transform"
    # which is uppercase in these tests.
    assert result.original == orig_func(unicodedata.normalize("NFD", value))