Skip to content

Commit 95c8e39

Browse files
committedNov 29, 2023
stdlib/array: add support for 'u' arrays
Signed-off-by: Sebastien Binet <binet@cern.ch>
1 parent 53252dd commit 95c8e39

File tree

3 files changed

+188
-67
lines changed

3 files changed

+188
-67
lines changed
 

‎stdlib/array/array.go

+69-17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import (
1313
"github.com/go-python/gpython/py"
1414
)
1515

16+
// FIXME(sbinet): consider creating an "array handler" type for each of the typecodes
17+
// and make the handler a field of the "array" type.
18+
// or make "array" an interface ?
19+
20+
// array provides efficient manipulation of C-arrays (as Go slices).
1621
type array struct {
1722
descr byte // typecode of elements
1823
esize int // element size in bytes
@@ -197,12 +202,12 @@ func array_new(metatype *py.Type, args py.Tuple, kwargs py.StringDict) (py.Objec
197202
esize: descr2esize[descr[0]],
198203
}
199204

200-
if descr[0] == 'u' {
201-
// FIXME(sbinet)
202-
return nil, py.NotImplementedError
203-
}
204-
205205
switch descr[0] {
206+
case 'u':
207+
var data []rune
208+
arr.data = data
209+
arr.append = arr.appendRune
210+
arr.extend = arr.extendRune
206211
case 'b':
207212
var data []int8
208213
arr.data = data
@@ -300,14 +305,22 @@ func (arr *array) M__repr__() (py.Object, error) {
300305
o := new(strings.Builder)
301306
o.WriteString("array('" + string(arr.descr) + "'")
302307
if data := reflect.ValueOf(arr.data); arr.data != nil && data.Len() > 0 {
303-
o.WriteString(", [")
304-
for i := 0; i < data.Len(); i++ {
305-
if i > 0 {
306-
o.WriteString(", ")
308+
switch arr.descr {
309+
case 'u':
310+
o.WriteString(", '")
311+
o.WriteString(string(arr.data.([]rune)))
312+
o.WriteString("'")
313+
default:
314+
o.WriteString(", [")
315+
for i := 0; i < data.Len(); i++ {
316+
if i > 0 {
317+
o.WriteString(", ")
318+
}
319+
// FIXME(sbinet): we don't get exactly the same display wrt CPython for float32
320+
fmt.Fprintf(o, "%v", data.Index(i))
307321
}
308-
fmt.Fprintf(o, "%v", data.Index(i))
322+
o.WriteString("]")
309323
}
310-
o.WriteString("]")
311324
}
312325
o.WriteString(")")
313326
return py.String(o.String()), nil
@@ -344,8 +357,7 @@ func (arr *array) M__getitem__(k py.Object) (py.Object, error) {
344357
case 'B', 'H', 'I', 'L', 'Q':
345358
return py.Int(sli.Index(i).Uint()), nil
346359
case 'u':
347-
// FIXME(sbinet)
348-
return nil, py.NotImplementedError
360+
return py.String([]rune{rune(sli.Index(i).Int())}), nil
349361
case 'f', 'd':
350362
return py.Float(sli.Index(i).Float()), nil
351363
}
@@ -372,14 +384,23 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) {
372384
}
373385
switch arr.descr {
374386
case 'b', 'h', 'i', 'l', 'q':
375-
vv := v.(py.Int)
387+
vv, ok := v.(py.Int)
388+
if !ok {
389+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
390+
}
376391
sli.Index(i).SetInt(int64(vv))
377392
case 'B', 'H', 'I', 'L', 'Q':
378-
vv := v.(py.Int)
393+
vv, ok := v.(py.Int)
394+
if !ok {
395+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
396+
}
379397
sli.Index(i).SetUint(uint64(vv))
380398
case 'u':
381-
// FIXME(sbinet)
382-
return nil, py.NotImplementedError
399+
vv, ok := v.(py.Int)
400+
if !ok {
401+
return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character")
402+
}
403+
sli.Index(i).SetInt(int64(vv))
383404
case 'f', 'd':
384405
var vv float64
385406
switch v := v.(type) {
@@ -401,6 +422,16 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) {
401422
panic("impossible")
402423
}
403424

425+
func (arr *array) appendRune(v py.Object) (py.Object, error) {
426+
str, ok := v.(py.String)
427+
if !ok {
428+
return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character")
429+
}
430+
431+
arr.data = append(arr.data.([]rune), []rune(str)...)
432+
return py.None, nil
433+
}
434+
404435
func (arr *array) appendI8(v py.Object) (py.Object, error) {
405436
vv, err := asInt(v)
406437
if err != nil {
@@ -491,6 +522,27 @@ func (arr *array) appendF64(v py.Object) (py.Object, error) {
491522
return py.None, nil
492523
}
493524

525+
func (arr *array) extendRune(arg py.Object) (py.Object, error) {
526+
itr, err := py.Iter(arg)
527+
if err != nil {
528+
return nil, err
529+
}
530+
531+
nxt := itr.(py.I__next__)
532+
533+
for {
534+
o, err := nxt.M__next__()
535+
if err == py.StopIteration {
536+
break
537+
}
538+
_, err = arr.appendRune(o)
539+
if err != nil {
540+
return nil, err
541+
}
542+
}
543+
return py.None, nil
544+
}
545+
494546
func (arr *array) extendI8(arg py.Object) (py.Object, error) {
495547
itr, err := py.Iter(arg)
496548
if err != nil {

‎stdlib/array/testdata/test.py

+41-30
Original file line numberDiff line numberDiff line change
@@ -19,87 +19,105 @@ def assertEqual(x, y):
1919
print("")
2020
print("typecode '%s'" % (typ,))
2121
if typ == 'u':
22-
# FIXME(sbinet): implement
23-
print(" SKIP: NotImplemented")
24-
continue
25-
if typ in "bhilqfd":
22+
arr = array.array(typ, "?世界!")
23+
if typ in "bhilq":
2624
arr = array.array(typ, [-1, -2, -3, -4])
2725
if typ in "BHILQ":
2826
arr = array.array(typ, [+1, +2, +3, +4])
29-
print(" array: %s" % (repr(arr),))
27+
if typ in "fd":
28+
arr = array.array(typ, [-1.0, -2.0, -3.0, -4.0])
29+
print(" array: %s ## repr" % (repr(arr),))
30+
print(" array: %s ## str" % (str(arr),))
3031
print(" itemsize: %s" % (arr.itemsize,))
3132
print(" typecode: %s" % (arr.typecode,))
3233
print(" len: %s" % (len(arr),))
3334
print(" arr[0]: %s" % (arr[0],))
3435
print(" arr[-1]: %s" % (arr[-1],))
3536
try:
3637
arr[-10]
37-
print(" ERROR: expected an exception")
38+
print(" ERROR1: expected an exception")
3839
except:
3940
print(" caught an exception [ok]")
4041

4142
try:
4243
arr[10]
43-
print(" ERROR: expected an exception")
44+
print(" ERROR2: expected an exception")
4445
except:
4546
print(" caught an exception [ok]")
4647
arr[-2] = 33
48+
if typ in "fd":
49+
arr[-2] = 0.3
4750
print(" arr[-2]: %s" % (arr[-2],))
4851

4952
try:
5053
arr[-10] = 2
51-
print(" ERROR: expected an exception")
54+
print(" ERROR3: expected an exception")
5255
except:
5356
print(" caught an exception [ok]")
5457

5558
if typ in "bhilqfd":
5659
arr.extend([-5,-6])
5760
if typ in "BHILQ":
5861
arr.extend([5,6])
62+
if typ == 'u':
63+
arr.extend("he")
5964
print(" array: %s" % (repr(arr),))
6065
print(" len: %s" % (len(arr),))
6166

6267
if typ in "bhilqfd":
6368
arr.append(-7)
6469
if typ in "BHILQ":
6570
arr.append(7)
71+
if typ == 'u':
72+
arr.append("l")
6673
print(" array: %s" % (repr(arr),))
6774
print(" len: %s" % (len(arr),))
6875

6976
try:
7077
arr.append()
71-
print(" ERROR: expected an exception")
78+
print(" ERROR4: expected an exception")
7279
except:
7380
print(" caught an exception [ok]")
7481
try:
7582
arr.append([])
76-
print(" ERROR: expected an exception")
83+
print(" ERROR5: expected an exception")
7784
except:
7885
print(" caught an exception [ok]")
7986
try:
8087
arr.append(1, 2)
81-
print(" ERROR: expected an exception")
88+
print(" ERROR6: expected an exception")
8289
except:
8390
print(" caught an exception [ok]")
8491
try:
8592
arr.append(None)
86-
print(" ERROR: expected an exception")
93+
print(" ERROR7: expected an exception")
8794
except:
8895
print(" caught an exception [ok]")
8996

9097
try:
9198
arr.extend()
92-
print(" ERROR: expected an exception")
99+
print(" ERROR8: expected an exception")
93100
except:
94101
print(" caught an exception [ok]")
95102
try:
96103
arr.extend(None)
97-
print(" ERROR: expected an exception")
104+
print(" ERROR9: expected an exception")
98105
except:
99106
print(" caught an exception [ok]")
100107
try:
101108
arr.extend([1,None])
102-
print(" ERROR: expected an exception")
109+
print(" ERROR10: expected an exception")
110+
except:
111+
print(" caught an exception [ok]")
112+
try:
113+
arr.extend(1,None)
114+
print(" ERROR11: expected an exception")
115+
except:
116+
print(" caught an exception [ok]")
117+
118+
try:
119+
arr[0] = object()
120+
print(" ERROR12: expected an exception")
103121
except:
104122
print(" caught an exception [ok]")
105123
pass
@@ -108,55 +126,48 @@ def assertEqual(x, y):
108126
print("## testing array.array(...)")
109127
try:
110128
arr = array.array()
111-
print("ERROR: expected an exception")
129+
print("ERROR1: expected an exception")
112130
except:
113131
print("caught an exception [ok]")
114132

115133
try:
116134
arr = array.array(b"d")
117-
print("ERROR: expected an exception")
135+
print("ERROR2: expected an exception")
118136
except:
119137
print("caught an exception [ok]")
120138

121139
try:
122140
arr = array.array("?")
123-
print("ERROR: expected an exception")
141+
print("ERROR3: expected an exception")
124142
except:
125143
print("caught an exception [ok]")
126144

127145
try:
128146
arr = array.array("dd")
129-
print("ERROR: expected an exception")
147+
print("ERROR4: expected an exception")
130148
except:
131149
print("caught an exception [ok]")
132150

133151
try:
134152
arr = array.array("d", initializer=[1,2])
135-
print("ERROR: expected an exception")
153+
print("ERROR5: expected an exception")
136154
except:
137155
print("caught an exception [ok]")
138156

139157
try:
140158
arr = array.array("d", [1], [])
141-
print("ERROR: expected an exception")
159+
print("ERROR6: expected an exception")
142160
except:
143161
print("caught an exception [ok]")
144162

145163
try:
146164
arr = array.array("d", 1)
147-
print("ERROR: expected an exception")
165+
print("ERROR7: expected an exception")
148166
except:
149167
print("caught an exception [ok]")
150168

151169
try:
152170
arr = array.array("d", ["a","b"])
153-
print("ERROR: expected an exception")
154-
except:
155-
print("caught an exception [ok]")
156-
157-
try:
158-
## FIXME(sbinet): implement it at some point.
159-
arr = array.array("u")
160-
print("ERROR: expected an exception")
171+
print("ERROR8: expected an exception")
161172
except:
162173
print("caught an exception [ok]")

‎stdlib/array/testdata/test_golden.txt

+78-20
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ array.array:
77
<class 'array.array'>
88

99
typecode 'b'
10-
array: array('b', [-1, -2, -3, -4])
10+
array: array('b', [-1, -2, -3, -4]) ## repr
11+
array: array('b', [-1, -2, -3, -4]) ## str
1112
itemsize: 1
1213
typecode: b
1314
len: 4
@@ -28,9 +29,12 @@ typecode 'b'
2829
caught an exception [ok]
2930
caught an exception [ok]
3031
caught an exception [ok]
32+
caught an exception [ok]
33+
caught an exception [ok]
3134

3235
typecode 'B'
33-
array: array('B', [1, 2, 3, 4])
36+
array: array('B', [1, 2, 3, 4]) ## repr
37+
array: array('B', [1, 2, 3, 4]) ## str
3438
itemsize: 1
3539
typecode: B
3640
len: 4
@@ -51,12 +55,38 @@ typecode 'B'
5155
caught an exception [ok]
5256
caught an exception [ok]
5357
caught an exception [ok]
58+
caught an exception [ok]
59+
caught an exception [ok]
5460

5561
typecode 'u'
56-
SKIP: NotImplemented
62+
array: array('u', '?世界!') ## repr
63+
array: array('u', '?世界!') ## str
64+
itemsize: 2
65+
typecode: u
66+
len: 4
67+
arr[0]: ?
68+
arr[-1]: !
69+
caught an exception [ok]
70+
caught an exception [ok]
71+
arr[-2]: !
72+
caught an exception [ok]
73+
array: array('u', '?世!!he')
74+
len: 6
75+
array: array('u', '?世!!hel')
76+
len: 7
77+
caught an exception [ok]
78+
caught an exception [ok]
79+
caught an exception [ok]
80+
caught an exception [ok]
81+
caught an exception [ok]
82+
caught an exception [ok]
83+
caught an exception [ok]
84+
caught an exception [ok]
85+
caught an exception [ok]
5786

5887
typecode 'h'
59-
array: array('h', [-1, -2, -3, -4])
88+
array: array('h', [-1, -2, -3, -4]) ## repr
89+
array: array('h', [-1, -2, -3, -4]) ## str
6090
itemsize: 2
6191
typecode: h
6292
len: 4
@@ -77,9 +107,12 @@ typecode 'h'
77107
caught an exception [ok]
78108
caught an exception [ok]
79109
caught an exception [ok]
110+
caught an exception [ok]
111+
caught an exception [ok]
80112

81113
typecode 'H'
82-
array: array('H', [1, 2, 3, 4])
114+
array: array('H', [1, 2, 3, 4]) ## repr
115+
array: array('H', [1, 2, 3, 4]) ## str
83116
itemsize: 2
84117
typecode: H
85118
len: 4
@@ -100,9 +133,12 @@ typecode 'H'
100133
caught an exception [ok]
101134
caught an exception [ok]
102135
caught an exception [ok]
136+
caught an exception [ok]
137+
caught an exception [ok]
103138

104139
typecode 'i'
105-
array: array('i', [-1, -2, -3, -4])
140+
array: array('i', [-1, -2, -3, -4]) ## repr
141+
array: array('i', [-1, -2, -3, -4]) ## str
106142
itemsize: 2
107143
typecode: i
108144
len: 4
@@ -123,9 +159,12 @@ typecode 'i'
123159
caught an exception [ok]
124160
caught an exception [ok]
125161
caught an exception [ok]
162+
caught an exception [ok]
163+
caught an exception [ok]
126164

127165
typecode 'I'
128-
array: array('I', [1, 2, 3, 4])
166+
array: array('I', [1, 2, 3, 4]) ## repr
167+
array: array('I', [1, 2, 3, 4]) ## str
129168
itemsize: 2
130169
typecode: I
131170
len: 4
@@ -146,9 +185,12 @@ typecode 'I'
146185
caught an exception [ok]
147186
caught an exception [ok]
148187
caught an exception [ok]
188+
caught an exception [ok]
189+
caught an exception [ok]
149190

150191
typecode 'l'
151-
array: array('l', [-1, -2, -3, -4])
192+
array: array('l', [-1, -2, -3, -4]) ## repr
193+
array: array('l', [-1, -2, -3, -4]) ## str
152194
itemsize: 8
153195
typecode: l
154196
len: 4
@@ -169,9 +211,12 @@ typecode 'l'
169211
caught an exception [ok]
170212
caught an exception [ok]
171213
caught an exception [ok]
214+
caught an exception [ok]
215+
caught an exception [ok]
172216

173217
typecode 'L'
174-
array: array('L', [1, 2, 3, 4])
218+
array: array('L', [1, 2, 3, 4]) ## repr
219+
array: array('L', [1, 2, 3, 4]) ## str
175220
itemsize: 8
176221
typecode: L
177222
len: 4
@@ -192,9 +237,12 @@ typecode 'L'
192237
caught an exception [ok]
193238
caught an exception [ok]
194239
caught an exception [ok]
240+
caught an exception [ok]
241+
caught an exception [ok]
195242

196243
typecode 'q'
197-
array: array('q', [-1, -2, -3, -4])
244+
array: array('q', [-1, -2, -3, -4]) ## repr
245+
array: array('q', [-1, -2, -3, -4]) ## str
198246
itemsize: 8
199247
typecode: q
200248
len: 4
@@ -215,9 +263,12 @@ typecode 'q'
215263
caught an exception [ok]
216264
caught an exception [ok]
217265
caught an exception [ok]
266+
caught an exception [ok]
267+
caught an exception [ok]
218268

219269
typecode 'Q'
220-
array: array('Q', [1, 2, 3, 4])
270+
array: array('Q', [1, 2, 3, 4]) ## repr
271+
array: array('Q', [1, 2, 3, 4]) ## str
221272
itemsize: 8
222273
typecode: Q
223274
len: 4
@@ -238,21 +289,24 @@ typecode 'Q'
238289
caught an exception [ok]
239290
caught an exception [ok]
240291
caught an exception [ok]
292+
caught an exception [ok]
293+
caught an exception [ok]
241294

242295
typecode 'f'
243-
array: array('f', [-1, -2, -3, -4])
296+
array: array('f', [-1, -2, -3, -4]) ## repr
297+
array: array('f', [-1, -2, -3, -4]) ## str
244298
itemsize: 4
245299
typecode: f
246300
len: 4
247301
arr[0]: -1
248302
arr[-1]: -4
249303
caught an exception [ok]
250304
caught an exception [ok]
251-
arr[-2]: 33
305+
arr[-2]: 0.30000001192092896
252306
caught an exception [ok]
253-
array: array('f', [-1, -2, 33, -4, -5, -6])
307+
array: array('f', [-1, -2, 0.3, -4, -5, -6])
254308
len: 6
255-
array: array('f', [-1, -2, 33, -4, -5, -6, -7])
309+
array: array('f', [-1, -2, 0.3, -4, -5, -6, -7])
256310
len: 7
257311
caught an exception [ok]
258312
caught an exception [ok]
@@ -261,21 +315,24 @@ typecode 'f'
261315
caught an exception [ok]
262316
caught an exception [ok]
263317
caught an exception [ok]
318+
caught an exception [ok]
319+
caught an exception [ok]
264320

265321
typecode 'd'
266-
array: array('d', [-1, -2, -3, -4])
322+
array: array('d', [-1, -2, -3, -4]) ## repr
323+
array: array('d', [-1, -2, -3, -4]) ## str
267324
itemsize: 8
268325
typecode: d
269326
len: 4
270327
arr[0]: -1
271328
arr[-1]: -4
272329
caught an exception [ok]
273330
caught an exception [ok]
274-
arr[-2]: 33
331+
arr[-2]: 0.3
275332
caught an exception [ok]
276-
array: array('d', [-1, -2, 33, -4, -5, -6])
333+
array: array('d', [-1, -2, 0.3, -4, -5, -6])
277334
len: 6
278-
array: array('d', [-1, -2, 33, -4, -5, -6, -7])
335+
array: array('d', [-1, -2, 0.3, -4, -5, -6, -7])
279336
len: 7
280337
caught an exception [ok]
281338
caught an exception [ok]
@@ -284,6 +341,8 @@ typecode 'd'
284341
caught an exception [ok]
285342
caught an exception [ok]
286343
caught an exception [ok]
344+
caught an exception [ok]
345+
caught an exception [ok]
287346

288347

289348
## testing array.array(...)
@@ -295,4 +354,3 @@ caught an exception [ok]
295354
caught an exception [ok]
296355
caught an exception [ok]
297356
caught an exception [ok]
298-
caught an exception [ok]

0 commit comments

Comments
 (0)
Please sign in to comment.