File: test_evented_set.py

package info (click to toggle)
psygnal 0.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 752 kB
  • sloc: python: 9,252; makefile: 8
file content (169 lines) | stat: -rw-r--r-- 4,439 bytes parent folder | download | duplicates (2)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from copy import copy
from unittest.mock import Mock, call

import pytest

from psygnal.containers import EventedOrderedSet, EventedSet, OrderedSet


@pytest.fixture
def regular_set():
    return set(range(5))


@pytest.fixture(params=[EventedSet, EventedOrderedSet])
def test_set(request, regular_set):
    return request.param(regular_set)


@pytest.mark.parametrize(
    "meth",
    [
        # METHOD, ARGS, EXPECTED EVENTS
        # primary interface
        ("add", 2, []),
        ("add", 10, [call((10,), ())]),
        ("discard", 2, [call((), (2,))]),
        ("remove", 2, [call((), (2,))]),
        ("discard", 10, []),
        # parity with set
        ("update", {3, 4, 5, 6}, [call((5, 6), ())]),
        ("difference_update", {3, 4, 5, 6}, [call((), (3, 4))]),
        ("intersection_update", {3, 4, 5, 6}, [call((), (0, 1, 2))]),
        ("symmetric_difference_update", {3, 4, 5, 6}, [call((5, 6), (3, 4))]),
    ],
    ids=lambda x: x[0],
)
def test_set_interface_parity(test_set: EventedSet, regular_set: set, meth):
    method_name, arg, expected = meth
    mock = Mock()

    test_set.events.items_changed.connect(mock)

    test_set_method = getattr(test_set, method_name)
    assert tuple(test_set) == tuple(regular_set)

    regular_set_method = getattr(regular_set, method_name)
    assert test_set_method(arg) == regular_set_method(arg)
    assert tuple(test_set) == tuple(regular_set)

    mock.assert_has_calls(expected)
    assert type(test_set).__name__ in repr(test_set)


def test_set_pop(test_set: EventedSet):
    mock = Mock()
    test_set.events.items_changed.connect(mock)

    npops = len(test_set)
    while test_set:
        test_set.pop()

    assert mock.call_count == npops

    with pytest.raises(KeyError):
        test_set.pop()
    with pytest.raises(KeyError):
        test_set.remove(34)


def test_set_clear(test_set: EventedSet):
    mock = Mock()
    test_set.events.items_changed.connect(mock)
    mock.assert_not_called()
    test_set.clear()
    mock.assert_called_once_with((), (0, 1, 2, 3, 4))


@pytest.mark.parametrize(
    "meth",
    [
        ("difference", {3, 4, 5, 6}),
        ("intersection", {3, 4, 5, 6}),
        ("issubset", {3, 4}),
        ("issubset", {3, 4, 5, 6}),
        ("issubset", {1, 2, 3, 4, 5, 6}),
        ("issuperset", {3, 4}),
        ("issuperset", {3, 4, 5, 6}),
        ("issuperset", {1, 2, 3, 4, 5, 6}),
        ("symmetric_difference", {3, 4, 5, 6}),
        ("union", {3, 4, 5, 6}),
    ],
)
def test_set_new_objects(test_set: EventedSet, regular_set: set, meth):
    method_name, arg = meth
    test_set_method = getattr(test_set, method_name)
    assert tuple(test_set) == tuple(regular_set)

    mock = Mock()
    test_set.events.items_changed.connect(mock)
    regular_set_method = getattr(regular_set, method_name)
    result = test_set_method(arg)
    assert result == regular_set_method(arg)
    assert isinstance(result, (EventedSet, EventedOrderedSet, bool))
    assert result is not test_set

    mock.assert_not_called()


def test_ordering():
    tup = (24, 16, 8, 4, 5, 6)
    s_tup = set(tup)
    os_tup = OrderedSet(tup)

    assert tuple(s_tup) != tup
    assert repr(s_tup) == "{4, 5, 6, 8, 16, 24}"

    assert tuple(os_tup) == tup
    assert repr(os_tup) == "OrderedSet((24, 16, 8, 4, 5, 6))"
    os_tup.discard(8)
    os_tup.add(8)
    assert tuple(os_tup) == (24, 16, 4, 5, 6, 8)


def test_copy(test_set):
    from copy import copy

    assert test_set.copy() == copy(test_set)
    assert test_set is not copy(test_set)
    assert isinstance(copy(test_set), type(test_set))


def test_repr(test_set):
    if isinstance(test_set, EventedOrderedSet):
        assert repr(test_set) == "EventedOrderedSet((0, 1, 2, 3, 4))"
    else:
        assert repr(test_set) == "EventedSet({0, 1, 2, 3, 4})"


def test_copy_no_sync():
    s1 = EventedSet([1, 2, 3])
    s2 = copy(s1)
    s1.add(4)
    assert len(s2) == 3


def test_set_emission_order():
    s = EventedSet()

    def callback1():
        if 1 not in s:
            s.add(1)

    def callback2():
        if 5 not in s:
            s.update(range(5, 10))

    s.events.items_changed.connect(callback1)
    s.events.items_changed.connect(callback2)
    mock = Mock()
    s.events.items_changed.connect(mock)

    s.add(11)
    mock.assert_has_calls(
        [
            call((11,), ()),
            call((1,), ()),
            call((5, 6, 7, 8, 9), ()),
        ]
    )