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