Skip to content

Commit 80d61cf

Browse files
committed
all: support filter builtin feature and fix iterable object
1 parent acd458b commit 80d61cf

File tree

12 files changed

+228
-47
lines changed

12 files changed

+228
-47
lines changed

‎py/arithmetic.go‎

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -147,24 +147,6 @@ func MakeFloat(a Object) (Object, error){
147147
returnnil, ExceptionNewf(TypeError, "unsupported operand type(s) for float: '%s'", a.Type().Name)
148148
}
149149

150-
// Iter the python Object returning an Object
151-
//
152-
// Will raise TypeError if Iter can't be run on this object
153-
funcIter(aObject) (Object, error){
154-
155-
ifA, ok:=a.(I__iter__); ok{
156-
res, err:=A.M__iter__()
157-
iferr!=nil{
158-
returnnil, err
159-
}
160-
ifres!=NotImplemented{
161-
returnres, nil
162-
}
163-
}
164-
165-
returnnil, ExceptionNewf(TypeError, "unsupported operand type(s) for iter: '%s'", a.Type().Name)
166-
}
167-
168150
// Add two python objects together returning an Object
169151
//
170152
// Will raise TypeError if can't be add can't be run on these objects

‎py/dict.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func init(){
3636
returnnil, err
3737
}
3838
sMap:=self.(StringDict)
39-
o:=make([]Object, 0, len(sMap))
39+
o:=make(Tuple, 0, len(sMap))
4040
fork, v:=rangesMap{
4141
o=append(o, Tuple{String(k), v})
4242
}
@@ -49,7 +49,7 @@ func init(){
4949
returnnil, err
5050
}
5151
sMap:=self.(StringDict)
52-
o:=make([]Object, 0, len(sMap))
52+
o:=make(Tuple, 0, len(sMap))
5353
fork:=rangesMap{
5454
o=append(o, String(k))
5555
}
@@ -62,7 +62,7 @@ func init(){
6262
returnnil, err
6363
}
6464
sMap:=self.(StringDict)
65-
o:=make([]Object, 0, len(sMap))
65+
o:=make(Tuple, 0, len(sMap))
6666
for_, v:=rangesMap{
6767
o=append(o, v)
6868
}
@@ -204,7 +204,7 @@ func (a StringDict) M__repr__() (Object, error){
204204

205205
// Returns a list of keys from the dict
206206
func (dStringDict) M__iter__() (Object, error){
207-
o:=make([]Object, 0, len(d))
207+
o:=make(Tuple, 0, len(d))
208208
fork:=ranged{
209209
o=append(o, String(k))
210210
}

‎py/exception.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ func ExceptionGivenMatches(err, exc Object) bool{
336336
funcIsException(exception*Type, rinterface{}) bool{
337337
vart*Type
338338
switchex:=r.(type){
339+
caseExceptionInfo:
340+
t=ex.Type
339341
case*Exception:
340342
t=ex.Type()
341343
case*Type:

‎py/filter.go‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2018 The go-python Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package py
6+
7+
// A python Filter object
8+
typeFilterstruct{
9+
itObject
10+
funObject
11+
}
12+
13+
varFilterType=NewTypeX("filter", `filter(function or None, iterable) --> filter object
14+
15+
Return an iterator yielding those items of iterable for which function(item)
16+
is true. If function is None, return the items that are true.`,
17+
FilterTypeNew, nil)
18+
19+
// Type of this object
20+
func (f*Filter) Type() *Type{
21+
returnFilterType
22+
}
23+
24+
// FilterTypeNew
25+
funcFilterTypeNew(metatype*Type, argsTuple, kwargsStringDict) (resObject, errerror){
26+
varfun, seqObject
27+
varitObject
28+
err=UnpackTuple(args, kwargs, "filter", 2, 2, &fun, &seq)
29+
iferr!=nil{
30+
returnnil, err
31+
}
32+
it, err=Iter(seq)
33+
iferr!=nil{
34+
returnnil, err
35+
}
36+
return&Filter{it: it, fun: fun}, nil
37+
}
38+
39+
func (f*Filter) M__iter__() (Object, error){
40+
returnf, nil
41+
}
42+
43+
func (f*Filter) M__next__() (Object, error){
44+
varokbool
45+
for{
46+
item, err:=Next(f.it)
47+
iferr!=nil{
48+
returnnil, err
49+
}
50+
// if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type)
51+
if_, _ok:=f.fun.(Bool); _ok||f.fun==None{
52+
ok, err=ObjectIsTrue(item)
53+
} else{
54+
vargoodObject
55+
good, err=Call(f.fun, Tuple{item}, nil)
56+
iferr!=nil{
57+
returnnil, err
58+
}
59+
ok, err=ObjectIsTrue(good)
60+
}
61+
ifok{
62+
returnitem, nil
63+
}
64+
iferr!=nil{
65+
returnnil, err
66+
}
67+
}
68+
}
69+
70+
// Check interface is satisfied
71+
var_I__iter__= (*Filter)(nil)
72+
var_I__next__= (*Filter)(nil)

‎py/gen.go‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ var data = Data{
4545
{Name: "complex", Title: "MakeComplex", Operator: "complex", Unary: true, Conversion: "Complex"},
4646
{Name: "int", Title: "MakeInt", Operator: "int", Unary: true, Conversion: "Int"},
4747
{Name: "float", Title: "MakeFloat", Operator: "float", Unary: true, Conversion: "Float"},
48-
{Name: "iter", Title: "Iter", Operator: "iter", Unary: true},
4948
},
5049
BinaryOps: Ops{
5150
{Name: "add", Title: "Add", Operator: "+", Binary: true},

‎py/internal.go‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,20 @@ func ReprAsString(self Object) (string, error){
430430
}
431431
returnstring(str), nil
432432
}
433+
434+
// Returns an iterator object
435+
//
436+
// Call __Iter__ Returns an iterator object
437+
//
438+
// If object is sequence object, create an iterator
439+
funcIter(selfObject) (resObject, errerror){
440+
ifI, ok:=self.(I__iter__); ok{
441+
returnI.M__iter__()
442+
} elseifres, ok, err=TypeCall0(self, "__iter__"); ok{
443+
returnres, err
444+
}
445+
ifObjectIsSequence(self){
446+
returnNewIterator(self), nil
447+
}
448+
returnnil, ExceptionNewf(TypeError, "'%s' object is not iterable", self.Type().Name)
449+
}

‎py/iterator.go‎

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ package py
88

99
// A python Iterator object
1010
typeIteratorstruct{
11-
Posint
12-
Objs []Object
11+
Posint
12+
SeqObject
1313
}
1414

1515
varIteratorType=NewType("iterator", "iterator type")
@@ -20,10 +20,10 @@ func (o *Iterator) Type() *Type{
2020
}
2121

2222
// Define a new iterator
23-
funcNewIterator(Objs []Object) *Iterator{
23+
funcNewIterator(SeqObject) *Iterator{
2424
m:=&Iterator{
25-
Pos: 0,
26-
Objs: Objs,
25+
Pos: 0,
26+
Seq: Seq,
2727
}
2828
returnm
2929
}
@@ -33,13 +33,29 @@ func (it *Iterator) M__iter__() (Object, error){
3333
}
3434

3535
// Get next one from the iteration
36-
func (it*Iterator) M__next__() (Object, error){
37-
ifit.Pos>=len(it.Objs){
38-
returnnil, StopIteration
36+
func (it*Iterator) M__next__() (resObject, errerror){
37+
iftuple, ok:=it.Seq.(Tuple); ok{
38+
ifit.Pos>=len(tuple){
39+
returnnil, StopIteration
40+
}
41+
res=tuple[it.Pos]
42+
it.Pos++
43+
returnres, nil
44+
}
45+
index:=Int(it.Pos)
46+
ifI, ok:=it.Seq.(I__getitem__); ok{
47+
res, err=I.M__getitem__(index)
48+
} elseifres, ok, err=TypeCall1(it.Seq, "__getitem__", index); !ok{
49+
returnnil, ExceptionNewf(TypeError, "'%s' object is not iterable", it.Type().Name)
50+
}
51+
iferr!=nil{
52+
ifIsException(IndexError, err){
53+
returnnil, StopIteration
54+
}
55+
returnnil, err
3956
}
40-
r:=it.Objs[it.Pos]
4157
it.Pos++
42-
returnr, nil
58+
returnres, nil
4359
}
4460

4561
// Check interface is satisfied

‎py/list.go‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func (l *List) M__bool__() (Object, error){
186186
}
187187

188188
func (l*List) M__iter__() (Object, error){
189-
returnNewIterator(l.Items), nil
189+
returnNewIterator(Tuple(l.Items)), nil
190190
}
191191

192192
func (l*List) M__getitem__(keyObject) (Object, error){
@@ -496,7 +496,11 @@ func SortInPlace(l *List, kwargs StringDict, funcName string) error{
496496
reverse=False
497497
}
498498
// FIXME: requires the same bool-check like CPython (or better "|$Op" that doesn't panic on nil).
499-
s:=ptrSortable{&sortable{l, keyFunc, ObjectIsTrue(reverse), nil}}
499+
ok, err:=ObjectIsTrue(reverse)
500+
iferr!=nil{
501+
returnerr
502+
}
503+
s:=ptrSortable{&sortable{l, keyFunc, ok, nil}}
500504
sort.Stable(s)
501505
returns.s.firstErr
502506
}

‎py/object.go‎

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,50 @@ func ObjectRepr(o Object) Object{
2323
}
2424

2525
// Return whether the object is True or not
26-
funcObjectIsTrue(oObject) bool{
26+
funcObjectIsTrue(oObject) (bool, error){
2727
ifo==True{
28-
returntrue
28+
returntrue, nil
2929
}
3030
ifo==False{
31-
returnfalse
31+
returnfalse, nil
3232
}
3333

3434
ifo==None{
35-
returnfalse
35+
returnfalse, nil
3636
}
3737

3838
ifI, ok:=o.(I__bool__); ok{
3939
cmp, err:=I.M__bool__()
40-
iferr==nil&&cmp==True{
40+
iferr!=nil{
41+
returnfalse, err
42+
}
43+
ifcmp==True{
44+
returntrue, nil
45+
} elseifcmp==False{
46+
returnfalse, nil
47+
}
48+
}
49+
ifI, ok:=o.(I__len__); ok{
50+
l, err:=I.M__len__()
51+
iferr!=nil{
52+
returnfalse, err
53+
}
54+
ifl.(Int) >0{
55+
returntrue, nil
56+
} else{
57+
returnfalse, nil
58+
}
59+
}
60+
returnfalse, nil
61+
}
62+
63+
// Return whether the object is True or not
64+
funcObjectIsSequence(oObject) bool{
65+
if_, ok:=o.(I__getitem__); ok{
66+
returntrue
67+
} elseift, ok:=o.(*Type); ok{
68+
ift.GetAttrOrNil("__getitem__") !=nil{
4169
returntrue
42-
} elseiferr==nil&&cmp==False{
43-
returnfalse
4470
}
4571
}
4672
returnfalse

‎py/tests/filter.py‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# test_builtin.py:BuiltinTest.test_filter()
2+
fromlibtestimportassertRaises
3+
4+
doc="filter"
5+
classSquares:
6+
def__init__(self, max):
7+
self.max=max
8+
self.sofar= []
9+
10+
def__len__(self): returnlen(self.sofar)
11+
12+
def__getitem__(self, i):
13+
ifnot0<=i<self.max: raiseIndexError
14+
n=len(self.sofar)
15+
whilen<=i:
16+
self.sofar.append(n*n)
17+
n+=1
18+
returnself.sofar[i]
19+
20+
assertlist(filter(lambdac: 'a'<=c<='z', 'Hello World')) ==list('elloorld')
21+
assertlist(filter(None, [1, 'hello', [], [3], '', None, 9, 0])) == [1, 'hello', [3], 9]
22+
assertlist(filter(lambdax: x>0, [1, -3, 9, 0, 2])) == [1, 9, 2]
23+
assertlist(filter(None, Squares(10))) == [1, 4, 9, 16, 25, 36, 49, 64, 81]
24+
assertlist(filter(lambdax: x%2, Squares(10))) == [1, 9, 25, 49, 81]
25+
defidentity(item):
26+
return1
27+
filter(identity, Squares(5))
28+
assertRaises(TypeError, filter)
29+
classBadSeq(object):
30+
def__getitem__(self, index):
31+
ifindex<4:
32+
return42
33+
raiseValueError
34+
assertRaises(ValueError, list, filter(lambdax: x, BadSeq()))
35+
defbadfunc():
36+
pass
37+
assertRaises(TypeError, list, filter(badfunc, range(5)))
38+
39+
# test bltinmodule.c::filtertuple()
40+
assertlist(filter(None, (1, 2))) == [1, 2]
41+
assertlist(filter(lambdax: x>=3, (1, 2, 3, 4))) == [3, 4]
42+
assertRaises(TypeError, list, filter(42, (1, 2)))
43+
44+
doc="finished"

0 commit comments

Comments
(0)