Skip to content

Commit 09f14d0

Browse files
authored
builtin: Implement builtin sum (#21)
1 parent eaa7d28 commit 09f14d0

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

builtin/builtin.go

+49-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func init() {
5959
py.MustNewMethod("round", builtin_round, 0, round_doc),
6060
py.MustNewMethod("setattr", builtin_setattr, 0, setattr_doc),
6161
// py.MustNewMethod("sorted", builtin_sorted, 0, sorted_doc),
62-
// py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
62+
py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
6363
// py.MustNewMethod("vars", builtin_vars, 0, vars_doc),
6464
}
6565
globals := py.StringDict{
@@ -709,3 +709,51 @@ Update and return a dictionary containing the current scope's local variables.`
709709
const globals_doc = `globals() -> dictionary
710710
711711
Return the dictionary containing the current scope's global variables.`
712+
713+
const sum_doc = `sum($module, iterable, start=0, /)
714+
--
715+
Return the sum of a \'start\' value (default: 0) plus an iterable of numbers
716+
717+
When the iterable is empty, return the start value.
718+
This function is intended specifically for use with numeric values and may
719+
reject non-numeric types.
720+
`
721+
722+
func builtin_sum(self py.Object, args py.Tuple) (py.Object, error) {
723+
var seq py.Object
724+
var start py.Object
725+
err := py.UnpackTuple(args, nil, "sum", 1, 2, &seq, &start)
726+
if err != nil {
727+
return nil, err
728+
}
729+
if start == nil {
730+
start = py.Int(0)
731+
} else {
732+
switch start.(type) {
733+
case py.Bytes:
734+
return nil, py.ExceptionNewf(py.TypeError, "sum() can't sum bytes [use b''.join(seq) instead]")
735+
case py.String:
736+
return nil, py.ExceptionNewf(py.TypeError, "sum() can't sum strings [use ''.join(seq) instead]")
737+
}
738+
}
739+
740+
iter, err := py.Iter(seq)
741+
if err != nil {
742+
return nil, err
743+
}
744+
745+
for {
746+
item, err := py.Next(iter)
747+
if err != nil {
748+
if py.IsException(py.StopIteration, err) {
749+
break
750+
}
751+
return nil, err
752+
}
753+
start, err = py.Add(start, item)
754+
if err != nil {
755+
return nil, err
756+
}
757+
}
758+
return start, nil
759+
}

builtin/tests/builtin.py

+32
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,38 @@ class C: pass
159159
assert getattr(c, "potato") == "spud"
160160
assert c.potato == "spud"
161161

162+
doc="sum"
163+
assert sum([1,2,3]) == 6
164+
assert sum([1,2,3], 3) == 9
165+
assert sum((1,2,3)) == 6
166+
assert sum((1,2,3), 3) == 9
167+
assert sum((1, 2.5, 3)) == 6.5
168+
assert sum((1, 2.5, 3), 3) == 9.5
169+
170+
try:
171+
sum([1,2,3], 'hi')
172+
except TypeError as e:
173+
if e.args[0] != "sum() can't sum strings [use ''.join(seq) instead]":
174+
raise
175+
ok = True
176+
assert ok, "TypeError not raised"
177+
178+
try:
179+
sum([1,2,3], b'hi')
180+
except TypeError as e:
181+
if e.args[0] != "sum() can't sum bytes [use b''.join(seq) instead]":
182+
raise
183+
ok = True
184+
assert ok, "TypeError not raised"
185+
186+
try:
187+
sum(['h', 'i'])
188+
except TypeError as e:
189+
if e.args[0] != "unsupported operand type(s) for +: 'int' and 'str'":
190+
raise
191+
ok = True
192+
assert ok, "TypeError not raised"
193+
162194
doc="__import__"
163195
lib = __import__("lib")
164196
assert lib.libfn() == 42

py/string.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222

2323
type String string
2424

25-
var StringType = ObjectType.NewType("string",
25+
var StringType = ObjectType.NewType("str",
2626
`str(object='') -> str
2727
str(bytes_or_buffer[, encoding[, errors]]) -> str
2828

0 commit comments

Comments
 (0)