File: test_set_behaviors.py

package info (click to toggle)
python-atom 0.12.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,616 kB
  • sloc: cpp: 9,040; python: 6,249; makefile: 123
file content (203 lines) | stat: -rw-r--r-- 5,600 bytes parent folder | download
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# --------------------------------------------------------------------------------------
# Copyright (c) 2013-2025, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
# --------------------------------------------------------------------------------------
"""Test the set behaviors

no_op_handler: do nothing on setting
slot_handler: standard one tested through other tests (post_set, ...)
constant_handler: prevent to set a value
read_only_handler: allow a single set
event_handler: not tested here (see test_observe.py)
signal_handler: siganls are not settable
delegate_handler: not tested here (see test_delegate.py)
property_handler: not tested here (see test_property.py)
call_object_object_value_handler: use a custom function
call_object_object_name_value_handler: use a custom function
object_method_value_handler: use an object method
object_method_name_value_handler: use an object method
member_method_object_value_handler: method defined on a Member subclass

"""

import pytest

from atom.api import Atom, Constant, Int, ReadOnly, SetAttr, Signal


@pytest.mark.parametrize(
    "member, mode", [(Signal(), "Signal"), (Constant(1), "Constant")]
)
def test_unsettable(member, mode):
    """Test that unsettable members do raise the proper error."""

    class Unsettable(Atom):
        m = member

    u = Unsettable()
    assert u.get_member("m").setattr_mode[0] == getattr(SetAttr, mode)
    with pytest.raises(TypeError) as excinfo:
        u.m = 1
    assert mode.lower() in excinfo.exconly()


@pytest.mark.parametrize("member, mode", [(Int(), "Slot"), (ReadOnly(), "ReadOnly")])
def test_wrong_index_value(member, mode):
    """Test handling wrong index

    This should never happen save if the user manipulate the index.

    """

    class Unsettable(Atom):
        m = member

    Unsettable.m.set_index(100)
    u = Unsettable()
    assert u.get_member("m").setattr_mode[0] == getattr(SetAttr, mode)
    with pytest.raises(AttributeError) as excinfo:
        u.m = 1
    assert "'m'" in excinfo.exconly()


def test_read_only_behavior():
    """Test the behavior of read only member."""

    class ReadOnlyTest(Atom):
        r = ReadOnly()

    rt = ReadOnlyTest()
    rt.r = 1
    assert rt.r == 1
    with pytest.raises(TypeError) as excinfo:
        rt.r = 2
    assert "read only" in excinfo.exconly()


def test_no_op():
    """Test the no-op behavior."""

    class Unsettable(Atom):
        m = Constant("1")
        m.set_setattr_mode(SetAttr.NoOp, None)

    u = Unsettable()
    u.m = None
    assert u.m == "1"


def co_ov_factory():
    """Factory for the CallObject_ObjectValue behavior."""

    def custom_set(obj, value):
        obj.get_member("mi").set_slot(obj, value % 2)

    class SetTest(Atom):
        mi = Int()
        mi.set_setattr_mode(SetAttr.CallObject_ObjectValue, custom_set)

    return SetTest


def co_onv_factory():
    """Factory for the CallObject_ObjectNameValue behavior."""

    def custom_set(obj, name, value):
        obj.get_member(name).set_slot(obj, value % 2)

    class SetTest(Atom):
        mi = Int()
        mi.set_setattr_mode(SetAttr.CallObject_ObjectNameValue, custom_set)

    return SetTest


def om_v_factory():
    """Factory for the ObjectMethod_Value behavior."""

    class SetTest(Atom):
        mi = Int()
        mi.set_setattr_mode(SetAttr.ObjectMethod_Value, "custom_set")

        def custom_set(self, value):
            self.get_member("mi").set_slot(self, value % 2)

    return SetTest


def om_nv_factory():
    """Factory for the ObjecMethod_NameValue behavior."""

    class SetTest(Atom):
        mi = Int()
        mi.set_setattr_mode(SetAttr.ObjectMethod_NameValue, "custom_set")

        def custom_set(self, name, value):
            self.get_member(name).set_slot(self, value % 2)

    return SetTest


def mm_ov_factory():
    """Factory for the MemberMethod_ObjectValue behavior."""

    class ModuloInt(Int):
        def __init__(self):
            super(ModuloInt, self).__init__()
            mode = SetAttr.MemberMethod_ObjectValue
            self.set_setattr_mode(mode, "set")

        def set(self, obj, value):
            self.set_slot(obj, value % 2)

    class SetTest(Atom):
        mi = ModuloInt()

    return SetTest


@pytest.mark.parametrize(
    "mode, factory",
    [
        ("CallObject_ObjectValue", co_ov_factory),
        ("CallObject_ObjectNameValue", co_onv_factory),
        ("ObjectMethod_Value", om_v_factory),
        ("ObjectMethod_NameValue", om_nv_factory),
        ("MemberMethod_ObjectValue", mm_ov_factory),
    ],
)
def test_member_set_behaviors(mode, factory):
    """Test defining set in a Member subclass"""
    pvt = factory()()
    mi = pvt.get_member("mi")
    assert mi.setattr_mode[0] == getattr(SetAttr, mode)
    pvt.mi = 2
    assert pvt.mi == 0
    pvt.mi = 3
    assert pvt.mi == 1

    mi.do_setattr(pvt, 2)
    assert pvt.mi == 0
    mi.do_setattr(pvt, 3)
    assert pvt.mi == 1


@pytest.mark.parametrize(
    "mode, msg",
    [
        ("CallObject_ObjectValue", "callable"),
        ("CallObject_ObjectNameValue", "callable"),
        ("ObjectMethod_Value", "str"),
        ("ObjectMethod_NameValue", "str"),
        ("MemberMethod_ObjectValue", "str"),
    ],
)
def test_member_set_behaviors_wrong_args(mode, msg):
    """Test handling bad arguments to set_setattr_mode"""
    m = Int()
    with pytest.raises(TypeError) as excinfo:
        m.set_setattr_mode(getattr(SetAttr, mode), 1)
    assert msg in excinfo.exconly()