summaryrefslogtreecommitdiffstats
path: root/tests/test_filter.py
blob: f7184c286f2c5f950d61202d7ff950e48f8ea297 (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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from __future__ import annotations

import pytest

from prompt_toolkit.filters import Always, Condition, Filter, Never, to_filter
from prompt_toolkit.filters.base import _AndList, _OrList


def test_never():
    assert not Never()()


def test_always():
    assert Always()()


def test_invert():
    assert not (~Always())()
    assert ~Never()()

    c = ~Condition(lambda: False)
    assert c()


def test_or():
    for a in (True, False):
        for b in (True, False):
            c1 = Condition(lambda: a)
            c2 = Condition(lambda: b)
            c3 = c1 | c2

            assert isinstance(c3, Filter)
            assert c3() == a or b


def test_and():
    for a in (True, False):
        for b in (True, False):
            c1 = Condition(lambda: a)
            c2 = Condition(lambda: b)
            c3 = c1 & c2

            assert isinstance(c3, Filter)
            assert c3() == (a and b)


def test_nested_and():
    for a in (True, False):
        for b in (True, False):
            for c in (True, False):
                c1 = Condition(lambda: a)
                c2 = Condition(lambda: b)
                c3 = Condition(lambda: c)
                c4 = (c1 & c2) & c3

                assert isinstance(c4, Filter)
                assert c4() == (a and b and c)


def test_nested_or():
    for a in (True, False):
        for b in (True, False):
            for c in (True, False):
                c1 = Condition(lambda: a)
                c2 = Condition(lambda: b)
                c3 = Condition(lambda: c)
                c4 = (c1 | c2) | c3

                assert isinstance(c4, Filter)
                assert c4() == (a or b or c)


def test_to_filter():
    f1 = to_filter(True)
    f2 = to_filter(False)
    f3 = to_filter(Condition(lambda: True))
    f4 = to_filter(Condition(lambda: False))

    assert isinstance(f1, Filter)
    assert isinstance(f2, Filter)
    assert isinstance(f3, Filter)
    assert isinstance(f4, Filter)
    assert f1()
    assert not f2()
    assert f3()
    assert not f4()

    with pytest.raises(TypeError):
        to_filter(4)


def test_filter_cache_regression_1():
    # See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1729

    cond = Condition(lambda: True)

    # The use of a `WeakValueDictionary` caused this following expression to
    # fail. The problem is that the nested `(a & a)` expression gets garbage
    # collected between the two statements and is removed from our cache.
    x = (cond & cond) & cond
    y = (cond & cond) & cond
    assert x == y


def test_filter_cache_regression_2():
    cond1 = Condition(lambda: True)
    cond2 = Condition(lambda: True)
    cond3 = Condition(lambda: True)

    x = (cond1 & cond2) & cond3
    y = (cond1 & cond2) & cond3
    assert x == y


def test_filter_remove_duplicates():
    cond1 = Condition(lambda: True)
    cond2 = Condition(lambda: True)

    # When a condition is appended to itself using an `&` or `|` operator, it
    # should not be present twice. Having it twice in the `_AndList` or
    # `_OrList` will make them more expensive to evaluate.

    assert isinstance(cond1 & cond1, Condition)
    assert isinstance(cond1 & cond1 & cond1, Condition)
    assert isinstance(cond1 & cond1 & cond2, _AndList)
    assert len((cond1 & cond1 & cond2).filters) == 2

    assert isinstance(cond1 | cond1, Condition)
    assert isinstance(cond1 | cond1 | cond1, Condition)
    assert isinstance(cond1 | cond1 | cond2, _OrList)
    assert len((cond1 | cond1 | cond2).filters) == 2