File: cpdef_enums.pyx

package info (click to toggle)
cython 3.0.11%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 19,092 kB
  • sloc: python: 83,539; ansic: 18,831; cpp: 1,402; xml: 1,031; javascript: 511; makefile: 403; sh: 204; sed: 11
file content (245 lines) | stat: -rw-r--r-- 5,883 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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
"""
>>> import sys

>>> ONE, TEN, HUNDRED
(1, 10, 100)
>>> THOUSAND        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'THOUSAND' is not defined

>>> TWO == 2 or TWO
True
>>> THREE == 3 or THREE
True
>>> FIVE == 5 or FIVE
True
>>> ELEVEN == 11 or ELEVEN
True
>>> SEVEN           # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'SEVEN' is not defined

>>> FOUR == 4 or FOUR
True
>>> EIGHT == 8 or EIGHT
True
>>> SIXTEEN        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'SIXTEEN' is not defined

>>> RANK_0 == 11 or RANK_0
True
>>> RANK_1 == 37 or RANK_1
True
>>> RANK_2 == 389 or RANK_2
True
>>> RANK_6 == 159 or RANK_6
True
>>> RANK_7 == 889 or RANK_7
True
>>> RANK_3         # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'RANK_3' is not defined

>>> set(PyxEnum) == {TWO, THREE, FIVE}
True
>>> str(PyxEnum.TWO).split(".")[-1]  if sys.version_info < (3,11) else  "TWO" # Py3.10/11 changed the output here
'TWO'
>>> str(PyxEnum.TWO)  if sys.version_info >= (3,11) else  "2" # Py3.10/11 changed the output here
'2'
>>> PyxEnum.TWO + PyxEnum.THREE == PyxEnum.FIVE
True
>>> PyxEnum(2) is PyxEnum["TWO"] is PyxEnum.TWO
True

# not leaking into module namespace
>>> IntEnum        # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'IntEnum' is not defined
"""

cdef extern from *:
    cpdef enum: # ExternPyx
        ONE "1"
        TEN "10"
        HUNDRED "100"

    cdef enum: # ExternSecretPyx
        THOUSAND "1000"

cpdef enum PyxEnum:
    TWO = 2
    THREE = 3
    FIVE = 5

cpdef enum cpdefPyxDocEnum:
    """Home is where...
    """
    ELEVEN = 11

cpdef enum cpdefPyxDocLineEnum:
    """Home is where..."""
    FOURTEEN = 14

cdef enum SecretPyxEnum:
    SEVEN = 7

cdef enum cdefPyxDocEnum:
    """the heart is.
    """
    FIVE_AND_SEVEN = 5077

cdef extern from *:
    """
    enum ExternHasDuplicates {
        EX_DUP_A,
        EX_DUP_B=EX_DUP_A,
        EX_DUP_C=EX_DUP_A
    };
    """
    # Cython doesn't know about the duplicates though
    cpdef enum ExternHasDuplicates:
        EX_DUP_A
        EX_DUP_B
        EX_DUP_C


cpdef enum CyDefinedHasDuplicates1:
    CY_DUP1_A
    CY_DUP1_B = 0x00000000


cpdef enum CyDefinedHasDuplicates2:
    CY_DUP2_A
    CY_DUP2_B = CY_DUP2_A

cpdef enum CyDefinedHasDuplicates3:
    CY_DUP3_A = 1
    CY_DUP3_B = 0
    CY_DUP3_C  # = 1


def test_as_variable_from_cython():
    """
    >>> test_as_variable_from_cython()
    """
    assert list(PyxEnum) == [TWO, THREE, FIVE], list(PyxEnum)
    assert list(PxdEnum) == [RANK_0, RANK_1, RANK_2], list(PxdEnum)

cdef int verify_pure_c() nogil:
    cdef int x = TWO
    cdef int y = PyxEnum.THREE
    cdef int z = SecretPyxEnum.SEVEN
    return x + y + z

# Use it to suppress warning.
verify_pure_c()

def verify_resolution_GH1533():
    """
    >>> int(verify_resolution_GH1533())
    3
    """
    THREE = 100
    return int(PyxEnum.THREE)


def check_docs():
    """
    >>> PxdEnum.__doc__ not in ("Home is where...\\n    ", "Home is where...")
    True
    >>> PyxEnum.__doc__ not in ("Home is where...\\n    ", "Home is where...")
    True
    >>> cpdefPyxDocEnum.__doc__ == "Home is where...\\n    "
    True
    >>> cpdefPxdDocEnum.__doc__ == "Home is where...\\n    "
    True
    >>> cpdefPyxDocLineEnum.__doc__
    'Home is where...'
    >>> cpdefPxdDocLineEnum.__doc__
    'Home is where...'
    """
    pass


def to_from_py_conversion(PxdEnum val):
    """
    >>> to_from_py_conversion(RANK_1) is PxdEnum.RANK_1
    True

    C enums are commonly enough used as flags that it seems reasonable
    to allow it in Cython
    >>> to_from_py_conversion(RANK_1 | RANK_2) == (RANK_1 | RANK_2)
    True
    """
    return val


def to_from_py_conversion_with_duplicates1(ExternHasDuplicates val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates1(EX_DUP_A) == ExternHasDuplicates.EX_DUP_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates2(CyDefinedHasDuplicates1 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates2(CY_DUP1_A) == CyDefinedHasDuplicates1.CY_DUP1_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates3(CyDefinedHasDuplicates2 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> to_from_py_conversion_with_duplicates3(CY_DUP2_A) == CyDefinedHasDuplicates2.CY_DUP2_A
    True
    """
    return val


def to_from_py_conversion_with_duplicates4(CyDefinedHasDuplicates3 val):
    """
    Mainly a compile-time test - we can't optimize to a switch here
    >>> import sys
    >>> True if sys.version_info < (3, 6, 0) else to_from_py_conversion_with_duplicates4(CY_DUP3_C) == CyDefinedHasDuplicates3.CY_DUP3_C
    True
    """
    return val


def test_pickle():
    """
    >>> from pickle import loads, dumps
    >>> import sys

    Pickling enums won't work without the enum module, so disable the test in Py<3.6.
    (requires 3.6 for IntFlag)
    Python 3.11.4 has a bug that breaks pickling: https://github.com/python/cpython/issues/105332

    >>> if sys.version_info < (3, 6) or sys.version_info[:3] == (3,11,4):
    ...     loads = dumps = lambda x: x

    >>> loads(dumps(PyxEnum.TWO)) == PyxEnum.TWO
    True
    >>> loads(dumps(PxdEnum.RANK_2)) == PxdEnum.RANK_2
    True
    """
    pass

def test_as_default_value(PxdEnum val=PxdEnum.RANK_1):
    """
    In order to work, this requires the utility code to be evaluated
    before the function definition
    >>> test_as_default_value()
    True
    >>> test_as_default_value(PxdEnum.RANK_2)
    False
    >>> test_as_default_value.__defaults__[0] == PxdEnum.RANK_1
    True
    """
    return val == PxdEnum.RANK_1