cython

Форк
0
/
index.pyx 
366 строк · 9.4 Кб
1
__doc__ = u"""
2
    >>> index_object(100, 100)       # doctest: +ELLIPSIS
3
    Traceback (most recent call last):
4
    ...
5
    TypeError: 'int' object ...
6
"""
7

8
import sys
9
cdef Py_ssize_t maxsize = sys.maxsize
10

11
py_maxsize = maxsize
12

13
import cython
14

15
def index_tuple(tuple t, int i):
16
    """
17
    (minor PyPy error formatting bug here, hence ELLIPSIS)
18

19
    >>> index_tuple((1,1,2,3,5), 0)
20
    1
21
    >>> index_tuple((1,1,2,3,5), 3)
22
    3
23
    >>> index_tuple((1,1,2,3,5), -1)
24
    5
25
    >>> index_tuple((1,1,2,3,5), 100)  # doctest: +ELLIPSIS
26
    Traceback (most recent call last):
27
    IndexError: ... index out of range
28
    >>> index_tuple((1,1,2,3,5), -7)  # doctest: +ELLIPSIS
29
    Traceback (most recent call last):
30
    IndexError: ... index out of range
31
    >>> index_tuple(None, 0)
32
    Traceback (most recent call last):
33
    TypeError: 'NoneType' object is not subscriptable
34
    """
35
    return t[i]
36

37
def index_list(list L, int i):
38
    """
39
    >>> index_list([2,3,5,7,11,13,17,19], 0)
40
    2
41
    >>> index_list([2,3,5,7,11,13,17,19], 5)
42
    13
43
    >>> index_list([2,3,5,7,11,13,17,19], -1)
44
    19
45
    >>> index_list([2,3,5,7,11,13,17,19], 100)  # doctest: +ELLIPSIS
46
    Traceback (most recent call last):
47
    IndexError: ... index out of range
48
    >>> index_list([2,3,5,7,11,13,17,19], -10)  # doctest: +ELLIPSIS
49
    Traceback (most recent call last):
50
    IndexError: ... index out of range
51
    >>> index_list(None, 0)
52
    Traceback (most recent call last):
53
    TypeError: 'NoneType' object is not subscriptable
54
    """
55
    return L[i]
56

57
def index_object(object o, int i):
58
    """
59
    (minor PyPy error formatting bug here, hence ELLIPSIS)
60

61
    >>> index_object([2,3,5,7,11,13,17,19], 1)
62
    3
63
    >>> index_object([2,3,5,7,11,13,17,19], -1)
64
    19
65
    >>> index_object((1,1,2,3,5), 2)
66
    2
67
    >>> index_object((1,1,2,3,5), -2)
68
    3
69
    >>> index_object("abcdef...z", 0)
70
    'a'
71
    >>> index_object("abcdef...z", -1)
72
    'z'
73
    >>> index_object("abcdef...z", 100)
74
    Traceback (most recent call last):
75
    IndexError: string index out of range
76
    >>> try: index_object(None, 0)
77
    ... except TypeError: pass
78
    """
79
    return o[i]
80

81

82
def del_index_list(list L, Py_ssize_t index):
83
    """
84
    >>> del_index_list(list(range(4)), 0)
85
    [1, 2, 3]
86
    >>> del_index_list(list(range(4)), 1)
87
    [0, 2, 3]
88
    >>> del_index_list(list(range(4)), -1)
89
    [0, 1, 2]
90
    >>> del_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
91
    Traceback (most recent call last):
92
    IndexError: list... index out of range
93
    >>> del_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
94
    Traceback (most recent call last):
95
    IndexError: list... index out of range
96
    """
97
    del L[index]
98
    return L
99

100

101
def set_index_list(list L, Py_ssize_t index):
102
    """
103
    >>> set_index_list(list(range(4)), 0)
104
    [5, 1, 2, 3]
105
    >>> set_index_list(list(range(4)), 1)
106
    [0, 5, 2, 3]
107
    >>> set_index_list(list(range(4)), -1)
108
    [0, 1, 2, 5]
109
    >>> set_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
110
    Traceback (most recent call last):
111
    IndexError: list... index out of range
112
    >>> set_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
113
    Traceback (most recent call last):
114
    IndexError: list... index out of range
115
    """
116
    L[index] = 5
117
    return L
118

119

120
# These make sure that our fast indexing works with large and unsigned types.
121

122
def test_unsigned_long():
123
    """
124
    >>> test_unsigned_long()
125
    """
126
    cdef int i
127
    cdef unsigned long ix
128
    cdef D = {}
129
    for i from 0 <= i < <int>sizeof(unsigned long) * 8:
130
        ix = (<unsigned long>1) << i
131
        D[ix] = True
132
    for i from 0 <= i < <int>sizeof(unsigned long) * 8:
133
        ix = (<unsigned long>1) << i
134
        assert D[ix] is True
135
        del D[ix]
136
    assert len(D) == 0
137

138
def test_unsigned_short():
139
    """
140
    >>> test_unsigned_short()
141
    """
142
    cdef int i
143
    cdef unsigned short ix
144
    cdef D = {}
145
    for i from 0 <= i < <int>sizeof(unsigned short) * 8:
146
        ix = (<unsigned short>1) << i
147
        D[ix] = True
148
    for i from 0 <= i < <int>sizeof(unsigned short) * 8:
149
        ix = (<unsigned short>1) << i
150
        assert D[ix] is True
151
        del D[ix]
152
    assert len(D) == 0
153

154
def test_long_long():
155
    """
156
    >>> test_long_long()
157
    """
158
    cdef int i
159
    cdef long long ix
160
    cdef D = {}
161
    for i from 0 <= i < <int>sizeof(long long) * 8:
162
        ix = (<long long>1) << i
163
        D[ix] = True
164
    for i from 0 <= i < <int>sizeof(long long) * 8:
165
        ix = (<long long>1) << i
166
        assert D[ix] is True
167
        del D[ix]
168

169
    L = [1, 2, 3]
170
    try:
171
        ix = py_maxsize + 1
172
    except OverflowError:
173
        pass  # can't test this here
174
    else:
175
        try: L[ix] = 5
176
        except IndexError: pass
177
        else: assert False, "setting large index failed to raise IndexError"
178

179
        try: del L[ix]
180
        except IndexError: pass
181
        else: assert False, "deleting large index failed to raise IndexError"
182

183
    try:
184
        ix = -py_maxsize - 2
185
    except OverflowError:
186
        pass  # can't test this here
187
    else:
188
        try: L[ix] = 5
189
        except IndexError: pass
190
        else: assert False, "setting large index failed to raise IndexError"
191

192
        try: del L[ix]
193
        except IndexError: pass
194
        else: assert False, "deleting large index failed to raise IndexError"
195

196
    assert len(D) == 0
197

198

199
def test_ulong_long():
200
    """
201
    >>> test_ulong_long()
202
    """
203
    cdef unsigned long long ix
204

205
    L = [1, 2, 3]
206
    try:
207
        ix = py_maxsize + 1
208
    except OverflowError:
209
        pass  # can't test this here
210
    else:
211
        try: L[ix] = 5
212
        except IndexError: pass
213
        else: assert False, "setting large index failed to raise IndexError"
214

215
        try: del L[ix]
216
        except IndexError: pass
217
        else: assert False, "deleting large index failed to raise IndexError"
218

219

220
@cython.boundscheck(False)
221
def test_boundscheck_unsigned(list L, tuple t, object o, unsigned long ix):
222
    """
223
    >>> test_boundscheck_unsigned([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
224
    (4, 4, 4)
225
    >>> test_boundscheck_unsigned([1, 2, 4], (1, 2, 4), "", 2)
226
    Traceback (most recent call last):
227
    ...
228
    IndexError: string index out of range
229
    """
230
    return L[ix], t[ix], o[ix]
231

232
@cython.boundscheck(False)
233
def test_boundscheck_signed(list L, tuple t, object o, long ix):
234
    """
235
    >>> test_boundscheck_signed([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
236
    (4, 4, 4)
237
    >>> test_boundscheck_signed([1, 2, 4], (1, 2, 4), "", 2)
238
    Traceback (most recent call last):
239
    ...
240
    IndexError: string index out of range
241
    """
242
    return L[ix], t[ix], o[ix]
243

244
@cython.wraparound(False)
245
def test_wraparound_signed(list L, tuple t, object o, long ix):
246
    """
247
    >>> test_wraparound_signed([1, 2, 4], (1, 2, 4), [1, 2, 4], 2)
248
    (4, 4, 4)
249
    >>> test_wraparound_signed([1, 2, 4], (1, 2, 4), "", 2)
250
    Traceback (most recent call last):
251
    ...
252
    IndexError: string index out of range
253
    """
254
    return L[ix], t[ix], o[ix]
255

256
def large_literal_index(object o):
257
    """
258
    >>> large_literal_index({1000000000000000000000000000000: True})
259
    True
260
    """
261
    return o[1000000000000000000000000000000]
262

263

264
class LargeIndexable(object):
265
    expected = None
266

267
    def __len__(self):
268
        raise OverflowError
269

270
    def __getitem__(self, index):
271
        return index
272

273
    def __setitem__(self, index, value):
274
        assert index == value == self.expected
275
        self.expected = None
276

277
    def __delitem__(self, index):
278
        assert self.expected == index
279
        self.expected = None
280

281

282
def test_large_indexing(obj):
283
    """
284
    >>> obj = LargeIndexable()
285
    >>> zero, pone, none, pmaxsize, nmaxsize = test_large_indexing(obj)
286
    >>> # , p2maxsize, n2maxsize
287
    >>> zero
288
    0
289
    >>> pone
290
    1
291
    >>> none
292
    -1
293
    >>> pmaxsize == py_maxsize
294
    True
295
    >>> nmaxsize == -py_maxsize
296
    True
297

298
    #>>> p2maxsize == py_maxsize*2
299
    #True
300
    #>>> n2maxsize == -py_maxsize*2
301
    #True
302
    """
303
    return (
304
        obj[0], obj[1], obj[-1],
305
        obj[maxsize], obj[-maxsize],
306
        #obj[maxsize*2], obj[-maxsize*2]     # FIXME!
307
    )
308

309

310
def del_large_index(obj, Py_ssize_t index):
311
    """
312
    >>> obj = LargeIndexable()
313
    >>> del_large_index(obj, 0)
314
    >>> del_large_index(obj, 1)
315
    >>> del_large_index(obj, -1)
316
    >>> del_large_index(obj, py_maxsize)
317
    >>> del_large_index(obj, -py_maxsize)
318
    """
319
    obj.expected = index
320
    del obj[index]
321
    assert obj.expected is None
322

323

324
def set_large_index(obj, Py_ssize_t index):
325
    """
326
    >>> obj = LargeIndexable()
327
    >>> set_large_index(obj, 0)
328
    >>> set_large_index(obj, 1)
329
    >>> set_large_index(obj, -1)
330
    >>> set_large_index(obj, py_maxsize)
331
    >>> set_large_index(obj, -py_maxsize)
332
    """
333
    obj.expected = index
334
    obj[index] = index
335
    assert obj.expected is None
336

337

338
class DoesntLikePositiveIndices(object):
339
    def __getitem__(self, idx):
340
        if idx >= 0:
341
            raise RuntimeError("Positive index")
342
        return "Good"
343

344
    def __setitem__(self, idx, value):
345
        if idx >= 0:
346
            raise RuntimeError("Positive index")
347

348
    def __delitem__(self, idx):
349
        if idx >= 0:
350
            raise RuntimeError("Positive index")
351

352
    def __len__(self):
353
        return 500
354

355
def test_call_with_negative_numbers():
356
    """
357
    The key point is that Cython shouldn't default to PySequence_*Item
358
    since that invisibly adjusts negative numbers to be len(o)-idx.
359
    >>> test_call_with_negative_numbers()
360
    'Good'
361
    """
362
    cdef int idx = -5
363
    indexme = DoesntLikePositiveIndices()
364
    del indexme[idx]
365
    indexme[idx] = "something"
366
    return indexme[idx]
367

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.