1 import doctest
2 import unittest
3
4 doctests = """
5
6 Setup
7
8 >>> class AClass:
9 ... def __init__(self):
10 ... self._setitem_name = None
11 ... self._setitem_val = None
12 ... self._delitem_name = None
13 ... def __setitem__(self, name, val):
14 ... self._delitem_name = None
15 ... self._setitem_name = name
16 ... self._setitem_val = val
17 ... def __repr__(self):
18 ... if self._setitem_name is not None:
19 ... return f"A[{self._setitem_name}]={self._setitem_val}"
20 ... elif self._delitem_name is not None:
21 ... return f"delA[{self._delitem_name}]"
22 ... def __getitem__(self, name):
23 ... return ParameterisedA(name)
24 ... def __delitem__(self, name):
25 ... self._setitem_name = None
26 ... self._delitem_name = name
27 ...
28 >>> class ParameterisedA:
29 ... def __init__(self, name):
30 ... self._name = name
31 ... def __repr__(self):
32 ... return f"A[{self._name}]"
33 ... def __iter__(self):
34 ... for p in self._name:
35 ... yield p
36 >>> class B:
37 ... def __iter__(self):
38 ... yield StarredB()
39 ... def __repr__(self):
40 ... return "B"
41 >>> class StarredB:
42 ... def __repr__(self):
43 ... return "StarredB"
44 >>> A = AClass()
45 >>> b = B()
46
47 Slices that are supposed to work, starring our custom B class
48
49 >>> A[*b]
50 A[(StarredB,)]
51 >>> A[*b] = 1; A
52 A[(StarredB,)]=1
53 >>> del A[*b]; A
54 delA[(StarredB,)]
55
56 >>> A[*b, *b]
57 A[(StarredB, StarredB)]
58 >>> A[*b, *b] = 1; A
59 A[(StarredB, StarredB)]=1
60 >>> del A[*b, *b]; A
61 delA[(StarredB, StarredB)]
62
63 >>> A[b, *b]
64 A[(B, StarredB)]
65 >>> A[b, *b] = 1; A
66 A[(B, StarredB)]=1
67 >>> del A[b, *b]; A
68 delA[(B, StarredB)]
69
70 >>> A[*b, b]
71 A[(StarredB, B)]
72 >>> A[*b, b] = 1; A
73 A[(StarredB, B)]=1
74 >>> del A[*b, b]; A
75 delA[(StarredB, B)]
76
77 >>> A[b, b, *b]
78 A[(B, B, StarredB)]
79 >>> A[b, b, *b] = 1; A
80 A[(B, B, StarredB)]=1
81 >>> del A[b, b, *b]; A
82 delA[(B, B, StarredB)]
83
84 >>> A[*b, b, b]
85 A[(StarredB, B, B)]
86 >>> A[*b, b, b] = 1; A
87 A[(StarredB, B, B)]=1
88 >>> del A[*b, b, b]; A
89 delA[(StarredB, B, B)]
90
91 >>> A[b, *b, b]
92 A[(B, StarredB, B)]
93 >>> A[b, *b, b] = 1; A
94 A[(B, StarredB, B)]=1
95 >>> del A[b, *b, b]; A
96 delA[(B, StarredB, B)]
97
98 >>> A[b, b, *b, b]
99 A[(B, B, StarredB, B)]
100 >>> A[b, b, *b, b] = 1; A
101 A[(B, B, StarredB, B)]=1
102 >>> del A[b, b, *b, b]; A
103 delA[(B, B, StarredB, B)]
104
105 >>> A[b, *b, b, b]
106 A[(B, StarredB, B, B)]
107 >>> A[b, *b, b, b] = 1; A
108 A[(B, StarredB, B, B)]=1
109 >>> del A[b, *b, b, b]; A
110 delA[(B, StarredB, B, B)]
111
112 >>> A[A[b, *b, b]]
113 A[A[(B, StarredB, B)]]
114 >>> A[A[b, *b, b]] = 1; A
115 A[A[(B, StarredB, B)]]=1
116 >>> del A[A[b, *b, b]]; A
117 delA[A[(B, StarredB, B)]]
118
119 >>> A[*A[b, *b, b]]
120 A[(B, StarredB, B)]
121 >>> A[*A[b, *b, b]] = 1; A
122 A[(B, StarredB, B)]=1
123 >>> del A[*A[b, *b, b]]; A
124 delA[(B, StarredB, B)]
125
126 >>> A[b, ...]
127 A[(B, Ellipsis)]
128 >>> A[b, ...] = 1; A
129 A[(B, Ellipsis)]=1
130 >>> del A[b, ...]; A
131 delA[(B, Ellipsis)]
132
133 >>> A[*A[b, ...]]
134 A[(B, Ellipsis)]
135 >>> A[*A[b, ...]] = 1; A
136 A[(B, Ellipsis)]=1
137 >>> del A[*A[b, ...]]; A
138 delA[(B, Ellipsis)]
139
140 Slices that are supposed to work, starring a list
141
142 >>> l = [1, 2, 3]
143
144 >>> A[*l]
145 A[(1, 2, 3)]
146 >>> A[*l] = 1; A
147 A[(1, 2, 3)]=1
148 >>> del A[*l]; A
149 delA[(1, 2, 3)]
150
151 >>> A[*l, 4]
152 A[(1, 2, 3, 4)]
153 >>> A[*l, 4] = 1; A
154 A[(1, 2, 3, 4)]=1
155 >>> del A[*l, 4]; A
156 delA[(1, 2, 3, 4)]
157
158 >>> A[0, *l]
159 A[(0, 1, 2, 3)]
160 >>> A[0, *l] = 1; A
161 A[(0, 1, 2, 3)]=1
162 >>> del A[0, *l]; A
163 delA[(0, 1, 2, 3)]
164
165 >>> A[1:2, *l]
166 A[(slice(1, 2, None), 1, 2, 3)]
167 >>> A[1:2, *l] = 1; A
168 A[(slice(1, 2, None), 1, 2, 3)]=1
169 >>> del A[1:2, *l]; A
170 delA[(slice(1, 2, None), 1, 2, 3)]
171
172 >>> repr(A[1:2, *l]) == repr(A[1:2, 1, 2, 3])
173 True
174
175 Slices that are supposed to work, starring a tuple
176
177 >>> t = (1, 2, 3)
178
179 >>> A[*t]
180 A[(1, 2, 3)]
181 >>> A[*t] = 1; A
182 A[(1, 2, 3)]=1
183 >>> del A[*t]; A
184 delA[(1, 2, 3)]
185
186 >>> A[*t, 4]
187 A[(1, 2, 3, 4)]
188 >>> A[*t, 4] = 1; A
189 A[(1, 2, 3, 4)]=1
190 >>> del A[*t, 4]; A
191 delA[(1, 2, 3, 4)]
192
193 >>> A[0, *t]
194 A[(0, 1, 2, 3)]
195 >>> A[0, *t] = 1; A
196 A[(0, 1, 2, 3)]=1
197 >>> del A[0, *t]; A
198 delA[(0, 1, 2, 3)]
199
200 >>> A[1:2, *t]
201 A[(slice(1, 2, None), 1, 2, 3)]
202 >>> A[1:2, *t] = 1; A
203 A[(slice(1, 2, None), 1, 2, 3)]=1
204 >>> del A[1:2, *t]; A
205 delA[(slice(1, 2, None), 1, 2, 3)]
206
207 >>> repr(A[1:2, *t]) == repr(A[1:2, 1, 2, 3])
208 True
209
210 Starring an expression (rather than a name) in a slice
211
212 >>> def returns_list():
213 ... return [1, 2, 3]
214
215 >>> A[returns_list()]
216 A[[1, 2, 3]]
217 >>> A[returns_list()] = 1; A
218 A[[1, 2, 3]]=1
219 >>> del A[returns_list()]; A
220 delA[[1, 2, 3]]
221
222 >>> A[returns_list(), 4]
223 A[([1, 2, 3], 4)]
224 >>> A[returns_list(), 4] = 1; A
225 A[([1, 2, 3], 4)]=1
226 >>> del A[returns_list(), 4]; A
227 delA[([1, 2, 3], 4)]
228
229 >>> A[*returns_list()]
230 A[(1, 2, 3)]
231 >>> A[*returns_list()] = 1; A
232 A[(1, 2, 3)]=1
233 >>> del A[*returns_list()]; A
234 delA[(1, 2, 3)]
235
236 >>> A[*returns_list(), 4]
237 A[(1, 2, 3, 4)]
238 >>> A[*returns_list(), 4] = 1; A
239 A[(1, 2, 3, 4)]=1
240 >>> del A[*returns_list(), 4]; A
241 delA[(1, 2, 3, 4)]
242
243 >>> A[0, *returns_list()]
244 A[(0, 1, 2, 3)]
245 >>> A[0, *returns_list()] = 1; A
246 A[(0, 1, 2, 3)]=1
247 >>> del A[0, *returns_list()]; A
248 delA[(0, 1, 2, 3)]
249
250 >>> A[*returns_list(), *returns_list()]
251 A[(1, 2, 3, 1, 2, 3)]
252 >>> A[*returns_list(), *returns_list()] = 1; A
253 A[(1, 2, 3, 1, 2, 3)]=1
254 >>> del A[*returns_list(), *returns_list()]; A
255 delA[(1, 2, 3, 1, 2, 3)]
256
257 Using both a starred object and a start:stop in a slice
258 (See also tests in test_syntax confirming that starring *inside* a start:stop
259 is *not* valid syntax.)
260
261 >>> A[1:2, *b]
262 A[(slice(1, 2, None), StarredB)]
263 >>> A[*b, 1:2]
264 A[(StarredB, slice(1, 2, None))]
265 >>> A[1:2, *b, 1:2]
266 A[(slice(1, 2, None), StarredB, slice(1, 2, None))]
267 >>> A[*b, 1:2, *b]
268 A[(StarredB, slice(1, 2, None), StarredB)]
269
270 >>> A[1:, *b]
271 A[(slice(1, None, None), StarredB)]
272 >>> A[*b, 1:]
273 A[(StarredB, slice(1, None, None))]
274 >>> A[1:, *b, 1:]
275 A[(slice(1, None, None), StarredB, slice(1, None, None))]
276 >>> A[*b, 1:, *b]
277 A[(StarredB, slice(1, None, None), StarredB)]
278
279 >>> A[:1, *b]
280 A[(slice(None, 1, None), StarredB)]
281 >>> A[*b, :1]
282 A[(StarredB, slice(None, 1, None))]
283 >>> A[:1, *b, :1]
284 A[(slice(None, 1, None), StarredB, slice(None, 1, None))]
285 >>> A[*b, :1, *b]
286 A[(StarredB, slice(None, 1, None), StarredB)]
287
288 >>> A[:, *b]
289 A[(slice(None, None, None), StarredB)]
290 >>> A[*b, :]
291 A[(StarredB, slice(None, None, None))]
292 >>> A[:, *b, :]
293 A[(slice(None, None, None), StarredB, slice(None, None, None))]
294 >>> A[*b, :, *b]
295 A[(StarredB, slice(None, None, None), StarredB)]
296
297 *args annotated as starred expression
298
299 >>> def f1(*args: *b): pass
300 >>> f1.__annotations__
301 {'args': StarredB}
302
303 >>> def f2(*args: *b, arg1): pass
304 >>> f2.__annotations__
305 {'args': StarredB}
306
307 >>> def f3(*args: *b, arg1: int): pass
308 >>> f3.__annotations__
309 {'args': StarredB, 'arg1': <class 'int'>}
310
311 >>> def f4(*args: *b, arg1: int = 2): pass
312 >>> f4.__annotations__
313 {'args': StarredB, 'arg1': <class 'int'>}
314
315 >>> def f5(*args: *b = (1,)): pass
316 Traceback (most recent call last):
317 ...
318 SyntaxError: invalid syntax
319 """
320
321 __test__ = {'doctests' : doctests}
322
323 def load_tests(loader, tests, pattern):
324 tests.addTest(doctest.DocTestSuite())
325 return tests
326
327
328 if __name__ == "__main__":
329 unittest.main()