Skip to content

Commit 61857d0

Browse files
committed
stdlib/array: add support for 'u' arrays
Signed-off-by: Sebastien Binet <binet@cern.ch>
1 parent 53252dd commit 61857d0

File tree

3 files changed

+158
-60
lines changed

3 files changed

+158
-60
lines changed

stdlib/array/array.go

Lines changed: 68 additions & 17 deletions
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,21 @@ 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+
fmt.Fprintf(o, "%v", data.Index(i))
307320
}
308-
fmt.Fprintf(o, "%v", data.Index(i))
321+
o.WriteString("]")
309322
}
310-
o.WriteString("]")
311323
}
312324
o.WriteString(")")
313325
return py.String(o.String()), nil
@@ -344,8 +356,7 @@ func (arr *array) M__getitem__(k py.Object) (py.Object, error) {
344356
case 'B', 'H', 'I', 'L', 'Q':
345357
return py.Int(sli.Index(i).Uint()), nil
346358
case 'u':
347-
// FIXME(sbinet)
348-
return nil, py.NotImplementedError
359+
return py.String([]rune{rune(sli.Index(i).Int())}), nil
349360
case 'f', 'd':
350361
return py.Float(sli.Index(i).Float()), nil
351362
}
@@ -372,14 +383,23 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) {
372383
}
373384
switch arr.descr {
374385
case 'b', 'h', 'i', 'l', 'q':
375-
vv := v.(py.Int)
386+
vv, ok := v.(py.Int)
387+
if !ok {
388+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
389+
}
376390
sli.Index(i).SetInt(int64(vv))
377391
case 'B', 'H', 'I', 'L', 'Q':
378-
vv := v.(py.Int)
392+
vv, ok := v.(py.Int)
393+
if !ok {
394+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
395+
}
379396
sli.Index(i).SetUint(uint64(vv))
380397
case 'u':
381-
// FIXME(sbinet)
382-
return nil, py.NotImplementedError
398+
vv, ok := v.(py.Int)
399+
if !ok {
400+
return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character")
401+
}
402+
sli.Index(i).SetInt(int64(vv))
383403
case 'f', 'd':
384404
var vv float64
385405
switch v := v.(type) {
@@ -401,6 +421,16 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) {
401421
panic("impossible")
402422
}
403423

424+
func (arr *array) appendRune(v py.Object) (py.Object, error) {
425+
str, ok := v.(py.String)
426+
if !ok {
427+
return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character")
428+
}
429+
430+
arr.data = append(arr.data.([]rune), []rune(str)...)
431+
return py.None, nil
432+
}
433+
404434
func (arr *array) appendI8(v py.Object) (py.Object, error) {
405435
vv, err := asInt(v)
406436
if err != nil {
@@ -491,6 +521,27 @@ func (arr *array) appendF64(v py.Object) (py.Object, error) {
491521
return py.None, nil
492522
}
493523

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

stdlib/array/testdata/test.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,87 +19,96 @@ 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
22+
arr = array.array(typ, "?世界!")
2523
if typ in "bhilqfd":
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+
print(" array: %s ## repr" % (repr(arr),))
28+
print(" array: %s ## str" % (str(arr),))
3029
print(" itemsize: %s" % (arr.itemsize,))
3130
print(" typecode: %s" % (arr.typecode,))
3231
print(" len: %s" % (len(arr),))
3332
print(" arr[0]: %s" % (arr[0],))
3433
print(" arr[-1]: %s" % (arr[-1],))
3534
try:
3635
arr[-10]
37-
print(" ERROR: expected an exception")
36+
print(" ERROR1: expected an exception")
3837
except:
3938
print(" caught an exception [ok]")
4039

4140
try:
4241
arr[10]
43-
print(" ERROR: expected an exception")
42+
print(" ERROR2: expected an exception")
4443
except:
4544
print(" caught an exception [ok]")
4645
arr[-2] = 33
4746
print(" arr[-2]: %s" % (arr[-2],))
4847

4948
try:
5049
arr[-10] = 2
51-
print(" ERROR: expected an exception")
50+
print(" ERROR3: expected an exception")
5251
except:
5352
print(" caught an exception [ok]")
5453

5554
if typ in "bhilqfd":
5655
arr.extend([-5,-6])
5756
if typ in "BHILQ":
5857
arr.extend([5,6])
58+
if typ == 'u':
59+
arr.extend("he")
5960
print(" array: %s" % (repr(arr),))
6061
print(" len: %s" % (len(arr),))
6162

6263
if typ in "bhilqfd":
6364
arr.append(-7)
6465
if typ in "BHILQ":
6566
arr.append(7)
67+
if typ == 'u':
68+
arr.append("l")
6669
print(" array: %s" % (repr(arr),))
6770
print(" len: %s" % (len(arr),))
6871

6972
try:
7073
arr.append()
71-
print(" ERROR: expected an exception")
74+
print(" ERROR4: expected an exception")
7275
except:
7376
print(" caught an exception [ok]")
7477
try:
7578
arr.append([])
76-
print(" ERROR: expected an exception")
79+
print(" ERROR5: expected an exception")
7780
except:
7881
print(" caught an exception [ok]")
7982
try:
8083
arr.append(1, 2)
81-
print(" ERROR: expected an exception")
84+
print(" ERROR6: expected an exception")
8285
except:
8386
print(" caught an exception [ok]")
8487
try:
8588
arr.append(None)
86-
print(" ERROR: expected an exception")
89+
print(" ERROR7: expected an exception")
8790
except:
8891
print(" caught an exception [ok]")
8992

9093
try:
9194
arr.extend()
92-
print(" ERROR: expected an exception")
95+
print(" ERROR8: expected an exception")
9396
except:
9497
print(" caught an exception [ok]")
9598
try:
9699
arr.extend(None)
97-
print(" ERROR: expected an exception")
100+
print(" ERROR9: expected an exception")
98101
except:
99102
print(" caught an exception [ok]")
100103
try:
101104
arr.extend([1,None])
102-
print(" ERROR: expected an exception")
105+
print(" ERROR10: expected an exception")
106+
except:
107+
print(" caught an exception [ok]")
108+
109+
try:
110+
arr[0] = object()
111+
print(" ERROR11: expected an exception")
103112
except:
104113
print(" caught an exception [ok]")
105114
pass
@@ -108,55 +117,48 @@ def assertEqual(x, y):
108117
print("## testing array.array(...)")
109118
try:
110119
arr = array.array()
111-
print("ERROR: expected an exception")
120+
print("ERROR1: expected an exception")
112121
except:
113122
print("caught an exception [ok]")
114123

115124
try:
116125
arr = array.array(b"d")
117-
print("ERROR: expected an exception")
126+
print("ERROR2: expected an exception")
118127
except:
119128
print("caught an exception [ok]")
120129

121130
try:
122131
arr = array.array("?")
123-
print("ERROR: expected an exception")
132+
print("ERROR3: expected an exception")
124133
except:
125134
print("caught an exception [ok]")
126135

127136
try:
128137
arr = array.array("dd")
129-
print("ERROR: expected an exception")
138+
print("ERROR4: expected an exception")
130139
except:
131140
print("caught an exception [ok]")
132141

133142
try:
134143
arr = array.array("d", initializer=[1,2])
135-
print("ERROR: expected an exception")
144+
print("ERROR5: expected an exception")
136145
except:
137146
print("caught an exception [ok]")
138147

139148
try:
140149
arr = array.array("d", [1], [])
141-
print("ERROR: expected an exception")
150+
print("ERROR6: expected an exception")
142151
except:
143152
print("caught an exception [ok]")
144153

145154
try:
146155
arr = array.array("d", 1)
147-
print("ERROR: expected an exception")
156+
print("ERROR7: expected an exception")
148157
except:
149158
print("caught an exception [ok]")
150159

151160
try:
152161
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")
162+
print("ERROR8: expected an exception")
161163
except:
162164
print("caught an exception [ok]")

0 commit comments

Comments
 (0)