1
2import sys
3IS_PY3 = sys.version_info[0] >= 3
4
5cimport cython
6
7b_a = bytearray(b'a')
8b_b = bytearray(b'b')
9
10
11'''   # disabled for now, enable when we consider it worth the code overhead
12
13@cython.test_assert_path_exists(
14    "//PythonCapiCallNode")
15@cython.test_fail_if_path_exists(
16    "//SimpleCallNode")
17def bytearray_startswith(bytearray s, sub, start=None, stop=None):
18    """
19    >>> bytearray_startswith(b_a, b_a)
20    True
21    >>> bytearray_startswith(b_a+b_b, b_a)
22    True
23    >>> bytearray_startswith(b_a, b_b)
24    False
25    >>> bytearray_startswith(b_a+b_b, b_b)
26    False
27    >>> bytearray_startswith(b_a, (b_a, b_b))
28    True
29    >>> bytearray_startswith(b_a, b_a, 1)
30    False
31    >>> bytearray_startswith(b_a, b_a, 0, 0)
32    False
33    """
34
35    if start is None:
36      return s.startswith(sub)
37    elif stop is None:
38      return s.startswith(sub, start)
39    else:
40      return s.startswith(sub, start, stop)
41
42
43@cython.test_assert_path_exists(
44    "//PythonCapiCallNode")
45@cython.test_fail_if_path_exists(
46    "//SimpleCallNode")
47def bytearray_endswith(bytearray s, sub, start=None, stop=None):
48    """
49    >>> bytearray_endswith(b_a, b_a)
50    True
51    >>> bytearray_endswith(b_b+b_a, b_a)
52    True
53    >>> bytearray_endswith(b_a, b_b)
54    False
55    >>> bytearray_endswith(b_b+b_a, b_b)
56    False
57    >>> bytearray_endswith(b_a, (b_a, b_b))
58    True
59    >>> bytearray_endswith(b_a, b_a, 1)
60    False
61    >>> bytearray_endswith(b_a, b_a, 0, 0)
62    False
63    """
64
65    if start is None:
66      return s.endswith(sub)
67    elif stop is None:
68      return s.endswith(sub, start)
69    else:
70      return s.endswith(sub, start, stop)
71'''
72
73
74@cython.test_assert_path_exists(
75    "//PythonCapiCallNode")
76@cython.test_fail_if_path_exists(
77    "//SimpleCallNode")
78def bytearray_decode(bytearray s, start=None, stop=None):
79    """
80    >>> s = b_a+b_b+b_a+b_a+b_b
81    >>> print(bytearray_decode(s))
82    abaab
83
84    >>> print(bytearray_decode(s, 2))
85    aab
86    >>> print(bytearray_decode(s, -3))
87    aab
88
89    >>> print(bytearray_decode(s, None, 4))
90    abaa
91    >>> print(bytearray_decode(s, None, 400))
92    abaab
93    >>> print(bytearray_decode(s, None, -2))
94    aba
95    >>> print(bytearray_decode(s, None, -4))
96    a
97    >>> print(bytearray_decode(s, None, -5))
98    <BLANKLINE>
99    >>> print(bytearray_decode(s, None, -200))
100    <BLANKLINE>
101
102    >>> print(bytearray_decode(s, 2, 5))
103    aab
104    >>> print(bytearray_decode(s, 2, 500))
105    aab
106    >>> print(bytearray_decode(s, 2, -1))
107    aa
108    >>> print(bytearray_decode(s, 2, -3))
109    <BLANKLINE>
110    >>> print(bytearray_decode(s, 2, -300))
111    <BLANKLINE>
112    >>> print(bytearray_decode(s, -3, -1))
113    aa
114    >>> print(bytearray_decode(s, -300, 300))
115    abaab
116    >>> print(bytearray_decode(s, -300, -4))
117    a
118    >>> print(bytearray_decode(s, -300, -5))
119    <BLANKLINE>
120    >>> print(bytearray_decode(s, -300, -6))
121    <BLANKLINE>
122    >>> print(bytearray_decode(s, -300, -500))
123    <BLANKLINE>
124
125    >>> s[:'test']                       # doctest: +ELLIPSIS
126    Traceback (most recent call last):
127    TypeError:...
128    >>> print(bytearray_decode(s, 'test'))   # doctest: +ELLIPSIS
129    Traceback (most recent call last):
130    TypeError:...
131    >>> print(bytearray_decode(s, None, 'test'))    # doctest: +ELLIPSIS
132    Traceback (most recent call last):
133    TypeError:...
134    >>> print(bytearray_decode(s, 'test', 'test'))  # doctest: +ELLIPSIS
135    Traceback (most recent call last):
136    TypeError:...
137
138    >>> print(bytearray_decode(None))
139    Traceback (most recent call last):
140    AttributeError: 'NoneType' object has no attribute 'decode'
141    >>> print(bytearray_decode(None, 1))
142    Traceback (most recent call last):
143    TypeError: 'NoneType' object is not subscriptable
144    >>> print(bytearray_decode(None, None, 1))
145    Traceback (most recent call last):
146    TypeError: 'NoneType' object is not subscriptable
147    >>> print(bytearray_decode(None, 0, 1))
148    Traceback (most recent call last):
149    TypeError: 'NoneType' object is not subscriptable
150    """
151    if start is None:
152        if stop is None:
153            return s.decode('utf8')
154        else:
155            return s[:stop].decode('utf8')
156    elif stop is None:
157        return s[start:].decode('utf8')
158    else:
159        return s[start:stop].decode('utf8')
160
161
162@cython.test_assert_path_exists(
163    "//PythonCapiCallNode")
164@cython.test_fail_if_path_exists(
165    "//SimpleCallNode")
166def bytearray_decode_unbound_method(bytearray s, start=None, stop=None):
167    """
168    >>> s = b_a+b_b+b_a+b_a+b_b
169    >>> print(bytearray_decode_unbound_method(s))
170    abaab
171    >>> print(bytearray_decode_unbound_method(s, 1))
172    baab
173    >>> print(bytearray_decode_unbound_method(s, None, 3))
174    aba
175    >>> print(bytearray_decode_unbound_method(s, 1, 4))
176    baa
177
178    >>> print(bytearray_decode_unbound_method(None))
179    Traceback (most recent call last):
180    TypeError: descriptor 'decode' requires a 'bytearray' object but received a 'NoneType'
181    >>> print(bytearray_decode_unbound_method(None, 1))
182    Traceback (most recent call last):
183    TypeError: 'NoneType' object is not subscriptable
184    >>> print(bytearray_decode_unbound_method(None, None, 1))
185    Traceback (most recent call last):
186    TypeError: 'NoneType' object is not subscriptable
187    >>> print(bytearray_decode_unbound_method(None, 0, 1))
188    Traceback (most recent call last):
189    TypeError: 'NoneType' object is not subscriptable
190    """
191    if start is None:
192        if stop is None:
193            return bytearray.decode(s, 'utf8')
194        else:
195            return bytearray.decode(s[:stop], 'utf8')
196    elif stop is None:
197        return bytearray.decode(s[start:], 'utf8')
198    else:
199        return bytearray.decode(s[start:stop], 'utf8')
200
201@cython.test_fail_if_path_exists('//SimpleCallNode')
202@cython.test_assert_path_exists('//PythonCapiCallNode')
203def bytearray_append(bytearray b, signed char c, int i, object o):
204    """
205    >>> b = bytearray(b'abc')
206    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('z'))
207    >>> print(b.decode('ascii'))
208    abcX@xyz
209
210    >>> b = bytearray(b'abc')
211    >>> b = bytearray_append(b, ord('x'), ord('y'), 0)
212    >>> print(b.decode('ascii')[:-1])
213    abcX@xy
214    >>> b[-1]
215    0
216
217    >>> b = bytearray(b'abc')
218    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('z') if IS_PY3 else b'z')
219    >>> print(b.decode('ascii'))
220    abcX@xyz
221
222    >>> b = bytearray(b'abc')
223    >>> b = bytearray_append(b, ord('x'), ord('y'), ord('\\xc3') if IS_PY3 else b'\\xc3')
224    >>> print(b[:-1].decode('ascii'))
225    abcX@xy
226    >>> print('%x' % b[-1])
227    c3
228
229    >>> b = bytearray(b'abc')
230    >>> try:
231    ...     b = bytearray_append(b, ord('x'), ord('y'), b'zz')
232    ... except (TypeError, ValueError): pass  # (Py3, Py2)
233    ... else: print("FAIL")
234    >>> print(b.decode('ascii'))
235    abcX@xy
236
237    >>> b = bytearray(b'abc')
238    >>> b = bytearray_append(b, -1, ord('y'), ord('z'))  # doctest: +ELLIPSIS
239    Traceback (most recent call last):
240    ValueError: ...
241    >>> print(b.decode('ascii'))
242    abcX@
243
244    >>> b = bytearray(b'abc')
245    >>> b = bytearray_append(b, ord('x'), -1, ord('z'))  # doctest: +ELLIPSIS
246    Traceback (most recent call last):
247    ValueError: ...
248    >>> print(b.decode('ascii'))
249    abcX@x
250
251    >>> b = bytearray(b'abc')
252    >>> b = bytearray_append(b, ord('x'), 256, ord('z'))  # doctest: +ELLIPSIS
253    Traceback (most recent call last):
254    ValueError: ...
255    >>> print(b.decode('ascii'))
256    abcX@x
257
258    >>> b = bytearray(b'abc')
259    >>> b = bytearray_append(b, ord('x'), ord('y'), -1)  # doctest: +ELLIPSIS
260    Traceback (most recent call last):
261    ValueError: ...
262    >>> print(b.decode('ascii'))
263    abcX@xy
264
265    >>> b = bytearray(b'abc')
266    >>> b = bytearray_append(b, ord('x'), ord('y'), 256)  # doctest: +ELLIPSIS
267    Traceback (most recent call last):
268    ValueError: ...
269    >>> print(b.decode('ascii'))
270    abcX@xy
271    """
272    assert b.append('X') is None
273    b.append(64)
274    b.append(c)
275    b.append(i)
276    b.append(o)
277    return b
278
279
280cdef class BytearraySubtype(bytearray):
281    """
282    >>> b = BytearraySubtype(b'abc')
283    >>> b._append(ord('x'))
284    >>> b.append(ord('y'))
285    >>> print(b.decode('ascii'))
286    abcxy
287    """
288    def _append(self, x):
289        self.append(x)
290