diff --git a/stdlib/array/array.go b/stdlib/array/array.go index f28d05ac..b9e682ae 100644 --- a/stdlib/array/array.go +++ b/stdlib/array/array.go @@ -13,6 +13,11 @@ import ( "github.com/go-python/gpython/py" ) +// FIXME(sbinet): consider creating an "array handler" type for each of the typecodes +// and make the handler a field of the "array" type. +// or make "array" an interface ? + +// array provides efficient manipulation of C-arrays (as Go slices). type array struct { descr byte // typecode of elements esize int // element size in bytes @@ -197,12 +202,12 @@ func array_new(metatype *py.Type, args py.Tuple, kwargs py.StringDict) (py.Objec esize: descr2esize[descr[0]], } - if descr[0] == 'u' { - // FIXME(sbinet) - return nil, py.NotImplementedError - } - switch descr[0] { + case 'u': + var data []rune + arr.data = data + arr.append = arr.appendRune + arr.extend = arr.extendRune case 'b': var data []int8 arr.data = data @@ -300,14 +305,22 @@ func (arr *array) M__repr__() (py.Object, error) { o := new(strings.Builder) o.WriteString("array('" + string(arr.descr) + "'") if data := reflect.ValueOf(arr.data); arr.data != nil && data.Len() > 0 { - o.WriteString(", [") - for i := 0; i < data.Len(); i++ { - if i > 0 { - o.WriteString(", ") + switch arr.descr { + case 'u': + o.WriteString(", '") + o.WriteString(string(arr.data.([]rune))) + o.WriteString("'") + default: + o.WriteString(", [") + for i := 0; i < data.Len(); i++ { + if i > 0 { + o.WriteString(", ") + } + // FIXME(sbinet): we don't get exactly the same display wrt CPython for float32 + fmt.Fprintf(o, "%v", data.Index(i)) } - fmt.Fprintf(o, "%v", data.Index(i)) + o.WriteString("]") } - o.WriteString("]") } o.WriteString(")") return py.String(o.String()), nil @@ -344,8 +357,7 @@ func (arr *array) M__getitem__(k py.Object) (py.Object, error) { case 'B', 'H', 'I', 'L', 'Q': return py.Int(sli.Index(i).Uint()), nil case 'u': - // FIXME(sbinet) - return nil, py.NotImplementedError + return py.String([]rune{rune(sli.Index(i).Int())}), nil case 'f', 'd': return py.Float(sli.Index(i).Float()), nil } @@ -372,14 +384,23 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) { } switch arr.descr { case 'b', 'h', 'i', 'l', 'q': - vv := v.(py.Int) + vv, ok := v.(py.Int) + if !ok { + return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name) + } sli.Index(i).SetInt(int64(vv)) case 'B', 'H', 'I', 'L', 'Q': - vv := v.(py.Int) + vv, ok := v.(py.Int) + if !ok { + return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name) + } sli.Index(i).SetUint(uint64(vv)) case 'u': - // FIXME(sbinet) - return nil, py.NotImplementedError + vv, ok := v.(py.Int) + if !ok { + return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character") + } + sli.Index(i).SetInt(int64(vv)) case 'f', 'd': var vv float64 switch v := v.(type) { @@ -401,6 +422,16 @@ func (arr *array) M__setitem__(k, v py.Object) (py.Object, error) { panic("impossible") } +func (arr *array) appendRune(v py.Object) (py.Object, error) { + str, ok := v.(py.String) + if !ok { + return nil, py.ExceptionNewf(py.TypeError, "array item must be unicode character") + } + + arr.data = append(arr.data.([]rune), []rune(str)...) + return py.None, nil +} + func (arr *array) appendI8(v py.Object) (py.Object, error) { vv, err := asInt(v) if err != nil { @@ -491,6 +522,27 @@ func (arr *array) appendF64(v py.Object) (py.Object, error) { return py.None, nil } +func (arr *array) extendRune(arg py.Object) (py.Object, error) { + itr, err := py.Iter(arg) + if err != nil { + return nil, err + } + + nxt := itr.(py.I__next__) + + for { + o, err := nxt.M__next__() + if err == py.StopIteration { + break + } + _, err = arr.appendRune(o) + if err != nil { + return nil, err + } + } + return py.None, nil +} + func (arr *array) extendI8(arg py.Object) (py.Object, error) { itr, err := py.Iter(arg) if err != nil { diff --git a/stdlib/array/testdata/test.py b/stdlib/array/testdata/test.py index 26f26166..906ed898 100644 --- a/stdlib/array/testdata/test.py +++ b/stdlib/array/testdata/test.py @@ -19,14 +19,15 @@ def assertEqual(x, y): print("") print("typecode '%s'" % (typ,)) if typ == 'u': - # FIXME(sbinet): implement - print(" SKIP: NotImplemented") - continue - if typ in "bhilqfd": + arr = array.array(typ, "?世界!") + if typ in "bhilq": arr = array.array(typ, [-1, -2, -3, -4]) if typ in "BHILQ": arr = array.array(typ, [+1, +2, +3, +4]) - print(" array: %s" % (repr(arr),)) + if typ in "fd": + arr = array.array(typ, [-1.0, -2.0, -3.0, -4.0]) + print(" array: %s ## repr" % (repr(arr),)) + print(" array: %s ## str" % (str(arr),)) print(" itemsize: %s" % (arr.itemsize,)) print(" typecode: %s" % (arr.typecode,)) print(" len: %s" % (len(arr),)) @@ -34,21 +35,23 @@ def assertEqual(x, y): print(" arr[-1]: %s" % (arr[-1],)) try: arr[-10] - print(" ERROR: expected an exception") + print(" ERROR1: expected an exception") except: print(" caught an exception [ok]") try: arr[10] - print(" ERROR: expected an exception") + print(" ERROR2: expected an exception") except: print(" caught an exception [ok]") arr[-2] = 33 + if typ in "fd": + arr[-2] = 0.3 print(" arr[-2]: %s" % (arr[-2],)) try: arr[-10] = 2 - print(" ERROR: expected an exception") + print(" ERROR3: expected an exception") except: print(" caught an exception [ok]") @@ -56,6 +59,8 @@ def assertEqual(x, y): arr.extend([-5,-6]) if typ in "BHILQ": arr.extend([5,6]) + if typ == 'u': + arr.extend("he") print(" array: %s" % (repr(arr),)) print(" len: %s" % (len(arr),)) @@ -63,43 +68,56 @@ def assertEqual(x, y): arr.append(-7) if typ in "BHILQ": arr.append(7) + if typ == 'u': + arr.append("l") print(" array: %s" % (repr(arr),)) print(" len: %s" % (len(arr),)) try: arr.append() - print(" ERROR: expected an exception") + print(" ERROR4: expected an exception") except: print(" caught an exception [ok]") try: arr.append([]) - print(" ERROR: expected an exception") + print(" ERROR5: expected an exception") except: print(" caught an exception [ok]") try: arr.append(1, 2) - print(" ERROR: expected an exception") + print(" ERROR6: expected an exception") except: print(" caught an exception [ok]") try: arr.append(None) - print(" ERROR: expected an exception") + print(" ERROR7: expected an exception") except: print(" caught an exception [ok]") try: arr.extend() - print(" ERROR: expected an exception") + print(" ERROR8: expected an exception") except: print(" caught an exception [ok]") try: arr.extend(None) - print(" ERROR: expected an exception") + print(" ERROR9: expected an exception") except: print(" caught an exception [ok]") try: arr.extend([1,None]) - print(" ERROR: expected an exception") + print(" ERROR10: expected an exception") + except: + print(" caught an exception [ok]") + try: + arr.extend(1,None) + print(" ERROR11: expected an exception") + except: + print(" caught an exception [ok]") + + try: + arr[0] = object() + print(" ERROR12: expected an exception") except: print(" caught an exception [ok]") pass @@ -108,55 +126,48 @@ def assertEqual(x, y): print("## testing array.array(...)") try: arr = array.array() - print("ERROR: expected an exception") + print("ERROR1: expected an exception") except: print("caught an exception [ok]") try: arr = array.array(b"d") - print("ERROR: expected an exception") + print("ERROR2: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("?") - print("ERROR: expected an exception") + print("ERROR3: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("dd") - print("ERROR: expected an exception") + print("ERROR4: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("d", initializer=[1,2]) - print("ERROR: expected an exception") + print("ERROR5: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("d", [1], []) - print("ERROR: expected an exception") + print("ERROR6: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("d", 1) - print("ERROR: expected an exception") + print("ERROR7: expected an exception") except: print("caught an exception [ok]") try: arr = array.array("d", ["a","b"]) - print("ERROR: expected an exception") -except: - print("caught an exception [ok]") - -try: - ## FIXME(sbinet): implement it at some point. - arr = array.array("u") - print("ERROR: expected an exception") + print("ERROR8: expected an exception") except: print("caught an exception [ok]") diff --git a/stdlib/array/testdata/test_golden.txt b/stdlib/array/testdata/test_golden.txt index b55665ad..09e9db3d 100644 --- a/stdlib/array/testdata/test_golden.txt +++ b/stdlib/array/testdata/test_golden.txt @@ -7,7 +7,8 @@ array.array: typecode 'b' - array: array('b', [-1, -2, -3, -4]) + array: array('b', [-1, -2, -3, -4]) ## repr + array: array('b', [-1, -2, -3, -4]) ## str itemsize: 1 typecode: b len: 4 @@ -28,9 +29,12 @@ typecode 'b' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'B' - array: array('B', [1, 2, 3, 4]) + array: array('B', [1, 2, 3, 4]) ## repr + array: array('B', [1, 2, 3, 4]) ## str itemsize: 1 typecode: B len: 4 @@ -51,12 +55,38 @@ typecode 'B' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'u' - SKIP: NotImplemented + array: array('u', '?世界!') ## repr + array: array('u', '?世界!') ## str + itemsize: 2 + typecode: u + len: 4 + arr[0]: ? + arr[-1]: ! + caught an exception [ok] + caught an exception [ok] + arr[-2]: ! + caught an exception [ok] + array: array('u', '?世!!he') + len: 6 + array: array('u', '?世!!hel') + len: 7 + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'h' - array: array('h', [-1, -2, -3, -4]) + array: array('h', [-1, -2, -3, -4]) ## repr + array: array('h', [-1, -2, -3, -4]) ## str itemsize: 2 typecode: h len: 4 @@ -77,9 +107,12 @@ typecode 'h' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'H' - array: array('H', [1, 2, 3, 4]) + array: array('H', [1, 2, 3, 4]) ## repr + array: array('H', [1, 2, 3, 4]) ## str itemsize: 2 typecode: H len: 4 @@ -100,9 +133,12 @@ typecode 'H' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'i' - array: array('i', [-1, -2, -3, -4]) + array: array('i', [-1, -2, -3, -4]) ## repr + array: array('i', [-1, -2, -3, -4]) ## str itemsize: 2 typecode: i len: 4 @@ -123,9 +159,12 @@ typecode 'i' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'I' - array: array('I', [1, 2, 3, 4]) + array: array('I', [1, 2, 3, 4]) ## repr + array: array('I', [1, 2, 3, 4]) ## str itemsize: 2 typecode: I len: 4 @@ -146,9 +185,12 @@ typecode 'I' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'l' - array: array('l', [-1, -2, -3, -4]) + array: array('l', [-1, -2, -3, -4]) ## repr + array: array('l', [-1, -2, -3, -4]) ## str itemsize: 8 typecode: l len: 4 @@ -169,9 +211,12 @@ typecode 'l' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'L' - array: array('L', [1, 2, 3, 4]) + array: array('L', [1, 2, 3, 4]) ## repr + array: array('L', [1, 2, 3, 4]) ## str itemsize: 8 typecode: L len: 4 @@ -192,9 +237,12 @@ typecode 'L' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'q' - array: array('q', [-1, -2, -3, -4]) + array: array('q', [-1, -2, -3, -4]) ## repr + array: array('q', [-1, -2, -3, -4]) ## str itemsize: 8 typecode: q len: 4 @@ -215,9 +263,12 @@ typecode 'q' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'Q' - array: array('Q', [1, 2, 3, 4]) + array: array('Q', [1, 2, 3, 4]) ## repr + array: array('Q', [1, 2, 3, 4]) ## str itemsize: 8 typecode: Q len: 4 @@ -238,9 +289,12 @@ typecode 'Q' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'f' - array: array('f', [-1, -2, -3, -4]) + array: array('f', [-1, -2, -3, -4]) ## repr + array: array('f', [-1, -2, -3, -4]) ## str itemsize: 4 typecode: f len: 4 @@ -248,11 +302,11 @@ typecode 'f' arr[-1]: -4 caught an exception [ok] caught an exception [ok] - arr[-2]: 33 + arr[-2]: 0.30000001192092896 caught an exception [ok] - array: array('f', [-1, -2, 33, -4, -5, -6]) + array: array('f', [-1, -2, 0.3, -4, -5, -6]) len: 6 - array: array('f', [-1, -2, 33, -4, -5, -6, -7]) + array: array('f', [-1, -2, 0.3, -4, -5, -6, -7]) len: 7 caught an exception [ok] caught an exception [ok] @@ -261,9 +315,12 @@ typecode 'f' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] typecode 'd' - array: array('d', [-1, -2, -3, -4]) + array: array('d', [-1, -2, -3, -4]) ## repr + array: array('d', [-1, -2, -3, -4]) ## str itemsize: 8 typecode: d len: 4 @@ -271,11 +328,11 @@ typecode 'd' arr[-1]: -4 caught an exception [ok] caught an exception [ok] - arr[-2]: 33 + arr[-2]: 0.3 caught an exception [ok] - array: array('d', [-1, -2, 33, -4, -5, -6]) + array: array('d', [-1, -2, 0.3, -4, -5, -6]) len: 6 - array: array('d', [-1, -2, 33, -4, -5, -6, -7]) + array: array('d', [-1, -2, 0.3, -4, -5, -6, -7]) len: 7 caught an exception [ok] caught an exception [ok] @@ -284,6 +341,8 @@ typecode 'd' caught an exception [ok] caught an exception [ok] caught an exception [ok] + caught an exception [ok] + caught an exception [ok] ## testing array.array(...) @@ -295,4 +354,3 @@ caught an exception [ok] caught an exception [ok] caught an exception [ok] caught an exception [ok] -caught an exception [ok]