μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_enum.py
Go to the documentation of this file.
1import pytest
2
3from pybind11_tests import enums as m
4
5
6def test_unscoped_enum():
7 assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
8 assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
9 assert str(m.EOne) == "UnscopedEnum.EOne"
10 assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
11 assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
12 assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
13
14 # name property
15 assert m.UnscopedEnum.EOne.name == "EOne"
16 assert m.UnscopedEnum.EOne.value == 1
17 assert m.UnscopedEnum.ETwo.name == "ETwo"
18 assert m.UnscopedEnum.ETwo.value == 2
19 assert m.EOne is m.UnscopedEnum.EOne
20 # name, value readonly
21 with pytest.raises(AttributeError):
22 m.UnscopedEnum.EOne.name = ""
23 with pytest.raises(AttributeError):
24 m.UnscopedEnum.EOne.value = 10
25 # name, value returns a copy
26 # TODO: Neither the name nor value tests actually check against aliasing.
27 # Use a mutable type that has reference semantics.
28 nonaliased_name = m.UnscopedEnum.EOne.name
29 nonaliased_name = "bar" # noqa: F841
30 assert m.UnscopedEnum.EOne.name == "EOne"
31 nonaliased_value = m.UnscopedEnum.EOne.value
32 nonaliased_value = 10 # noqa: F841
33 assert m.UnscopedEnum.EOne.value == 1
34
35 # __members__ property
36 assert m.UnscopedEnum.__members__ == {
37 "EOne": m.UnscopedEnum.EOne,
38 "ETwo": m.UnscopedEnum.ETwo,
39 "EThree": m.UnscopedEnum.EThree,
40 }
41 # __members__ readonly
42 with pytest.raises(AttributeError):
43 m.UnscopedEnum.__members__ = {}
44 # __members__ returns a copy
45 nonaliased_members = m.UnscopedEnum.__members__
46 nonaliased_members["bar"] = "baz"
47 assert m.UnscopedEnum.__members__ == {
48 "EOne": m.UnscopedEnum.EOne,
49 "ETwo": m.UnscopedEnum.ETwo,
50 "EThree": m.UnscopedEnum.EThree,
51 }
52
53 for docstring_line in """An unscoped enumeration
54
55Members:
56
57 EOne : Docstring for EOne
58
59 ETwo : Docstring for ETwo
60
61 EThree : Docstring for EThree""".split(
62 "\n"
63 ):
64 assert docstring_line in m.UnscopedEnum.__doc__
65
66 # Unscoped enums will accept ==/!= int comparisons
67 y = m.UnscopedEnum.ETwo
68 assert y == 2
69 assert 2 == y
70 assert y != 3
71 assert 3 != y
72 # Compare with None
73 assert y != None # noqa: E711
74 assert not (y == None) # noqa: E711
75 # Compare with an object
76 assert y != object()
77 assert not (y == object())
78 # Compare with string
79 assert y != "2"
80 assert "2" != y
81 assert not ("2" == y)
82 assert not (y == "2")
83
84 with pytest.raises(TypeError):
85 y < object() # noqa: B015
86
87 with pytest.raises(TypeError):
88 y <= object() # noqa: B015
89
90 with pytest.raises(TypeError):
91 y > object() # noqa: B015
92
93 with pytest.raises(TypeError):
94 y >= object() # noqa: B015
95
96 with pytest.raises(TypeError):
97 y | object()
98
99 with pytest.raises(TypeError):
100 y & object()
101
102 with pytest.raises(TypeError):
103 y ^ object()
104
105 assert int(m.UnscopedEnum.ETwo) == 2
106 assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
107
108 # order
109 assert m.UnscopedEnum.EOne < m.UnscopedEnum.ETwo
110 assert m.UnscopedEnum.EOne < 2
111 assert m.UnscopedEnum.ETwo > m.UnscopedEnum.EOne
112 assert m.UnscopedEnum.ETwo > 1
113 assert m.UnscopedEnum.ETwo <= 2
114 assert m.UnscopedEnum.ETwo >= 2
115 assert m.UnscopedEnum.EOne <= m.UnscopedEnum.ETwo
116 assert m.UnscopedEnum.EOne <= 2
117 assert m.UnscopedEnum.ETwo >= m.UnscopedEnum.EOne
118 assert m.UnscopedEnum.ETwo >= 1
119 assert not (m.UnscopedEnum.ETwo < m.UnscopedEnum.EOne)
120 assert not (2 < m.UnscopedEnum.EOne)
121
122 # arithmetic
123 assert m.UnscopedEnum.EOne & m.UnscopedEnum.EThree == m.UnscopedEnum.EOne
124 assert m.UnscopedEnum.EOne | m.UnscopedEnum.ETwo == m.UnscopedEnum.EThree
125 assert m.UnscopedEnum.EOne ^ m.UnscopedEnum.EThree == m.UnscopedEnum.ETwo
126
127
128def test_scoped_enum():
129 assert m.test_scoped_enum(m.ScopedEnum.Three) == "ScopedEnum::Three"
130 z = m.ScopedEnum.Two
131 assert m.test_scoped_enum(z) == "ScopedEnum::Two"
132
133 # Scoped enums will *NOT* accept ==/!= int comparisons (Will always return False)
134 assert not z == 3
135 assert not 3 == z
136 assert z != 3
137 assert 3 != z
138 # Compare with None
139 assert z != None # noqa: E711
140 assert not (z == None) # noqa: E711
141 # Compare with an object
142 assert z != object()
143 assert not (z == object())
144 # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
145 with pytest.raises(TypeError):
146 z > 3 # noqa: B015
147 with pytest.raises(TypeError):
148 z < 3 # noqa: B015
149 with pytest.raises(TypeError):
150 z >= 3 # noqa: B015
151 with pytest.raises(TypeError):
152 z <= 3 # noqa: B015
153
154 # order
155 assert m.ScopedEnum.Two < m.ScopedEnum.Three
156 assert m.ScopedEnum.Three > m.ScopedEnum.Two
157 assert m.ScopedEnum.Two <= m.ScopedEnum.Three
158 assert m.ScopedEnum.Two <= m.ScopedEnum.Two
159 assert m.ScopedEnum.Two >= m.ScopedEnum.Two
160 assert m.ScopedEnum.Three >= m.ScopedEnum.Two
161
162
163def test_implicit_conversion():
164 assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
165 assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
166 assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
167 assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
168
169 f = m.ClassWithUnscopedEnum.test_function
170 first = m.ClassWithUnscopedEnum.EFirstMode
171 second = m.ClassWithUnscopedEnum.ESecondMode
172
173 assert f(first) == 1
174
175 assert f(first) == f(first)
176 assert not f(first) != f(first)
177
178 assert f(first) != f(second)
179 assert not f(first) == f(second)
180
181 assert f(first) == int(f(first))
182 assert not f(first) != int(f(first))
183
184 assert f(first) != int(f(second))
185 assert not f(first) == int(f(second))
186
187 # noinspection PyDictCreation
188 x = {f(first): 1, f(second): 2}
189 x[f(first)] = 3
190 x[f(second)] = 4
191 # Hashing test
192 assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
193
194
195def test_binary_operators():
196 assert int(m.Flags.Read) == 4
197 assert int(m.Flags.Write) == 2
198 assert int(m.Flags.Execute) == 1
199 assert int(m.Flags.Read | m.Flags.Write | m.Flags.Execute) == 7
200 assert int(m.Flags.Read | m.Flags.Write) == 6
201 assert int(m.Flags.Read | m.Flags.Execute) == 5
202 assert int(m.Flags.Write | m.Flags.Execute) == 3
203 assert int(m.Flags.Write | 1) == 3
204 assert ~m.Flags.Write == -3
205
206 state = m.Flags.Read | m.Flags.Write
207 assert (state & m.Flags.Read) != 0
208 assert (state & m.Flags.Write) != 0
209 assert (state & m.Flags.Execute) == 0
210 assert (state & 1) == 0
211
212 state2 = ~state
213 assert state2 == -7
214 assert int(state ^ state2) == -1
215
216
217def test_enum_to_int():
218 m.test_enum_to_int(m.Flags.Read)
219 m.test_enum_to_int(m.ClassWithUnscopedEnum.EMode.EFirstMode)
220 m.test_enum_to_int(m.ScopedCharEnum.Positive)
221 m.test_enum_to_int(m.ScopedBoolEnum.TRUE)
222 m.test_enum_to_uint(m.Flags.Read)
223 m.test_enum_to_uint(m.ClassWithUnscopedEnum.EMode.EFirstMode)
224 m.test_enum_to_uint(m.ScopedCharEnum.Positive)
225 m.test_enum_to_uint(m.ScopedBoolEnum.TRUE)
226 m.test_enum_to_long_long(m.Flags.Read)
227 m.test_enum_to_long_long(m.ClassWithUnscopedEnum.EMode.EFirstMode)
228 m.test_enum_to_long_long(m.ScopedCharEnum.Positive)
229 m.test_enum_to_long_long(m.ScopedBoolEnum.TRUE)
230
231
232def test_duplicate_enum_name():
233 with pytest.raises(ValueError) as excinfo:
234 m.register_bad_enum()
235 assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'
236
237
238def test_char_underlying_enum(): # Issue #1331/PR #1334:
239 assert type(m.ScopedCharEnum.Positive.__int__()) is int
240 assert int(m.ScopedChar16Enum.Zero) == 0
241 assert hash(m.ScopedChar32Enum.Positive) == 1
242 assert type(m.ScopedCharEnum.Positive.__getstate__()) is int
243 assert m.ScopedWCharEnum(1) == m.ScopedWCharEnum.Positive
244 with pytest.raises(TypeError):
245 # Even if the underlying type is char, only an int can be used to construct the enum:
246 m.ScopedCharEnum("0")
247
248
249def test_bool_underlying_enum():
250 assert type(m.ScopedBoolEnum.TRUE.__int__()) is int
251 assert int(m.ScopedBoolEnum.FALSE) == 0
252 assert hash(m.ScopedBoolEnum.TRUE) == 1
253 assert type(m.ScopedBoolEnum.TRUE.__getstate__()) is int
254 assert m.ScopedBoolEnum(1) == m.ScopedBoolEnum.TRUE
255 # Enum could construct with a bool
256 # (bool is a strict subclass of int, and False will be converted to 0)
257 assert m.ScopedBoolEnum(False) == m.ScopedBoolEnum.FALSE
258
259
260def test_docstring_signatures():
261 for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
262 for attr in enum_type.__dict__.values():
263 # Issue #2623/PR #2637: Add argument names to enum_ methods
264 assert "arg0" not in (attr.__doc__ or "")
\rst Holds a reference to a Python object (with reference counting)
Definition: pytypes.h:259
Definition: pytypes.h:1200
Definition: pytypes.h:1167
str repr(handle h)
Definition: pytypes.h:2027