Skip to content

builtin: Implement builtin sum #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func init() {
py.MustNewMethod("round", builtin_round, 0, round_doc),
py.MustNewMethod("setattr", builtin_setattr, 0, setattr_doc),
// py.MustNewMethod("sorted", builtin_sorted, 0, sorted_doc),
// py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
// py.MustNewMethod("vars", builtin_vars, 0, vars_doc),
}
globals := py.StringDict{
Expand Down Expand Up @@ -709,3 +709,51 @@ Update and return a dictionary containing the current scope's local variables.`
const globals_doc = `globals() -> dictionary

Return the dictionary containing the current scope's global variables.`

const sum_doc = `sum($module, iterable, start=0, /)
--
Return the sum of a \'start\' value (default: 0) plus an iterable of numbers

When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.
`

func builtin_sum(self py.Object, args py.Tuple) (py.Object, error) {
var seq py.Object
var start py.Object
err := py.UnpackTuple(args, nil, "sum", 1, 2, &seq, &start)
if err != nil {
return nil, err
}
if start == nil {
start = py.Int(0)
} else {
switch start.(type) {
case py.Bytes:
return nil, py.ExceptionNewf(py.TypeError, "sum() can't sum bytes [use b''.join(seq) instead]")
case py.String:
return nil, py.ExceptionNewf(py.TypeError, "sum() can't sum strings [use ''.join(seq) instead]")
}
}

iter, err := py.Iter(seq)
if err != nil {
return nil, err
}

for {
item, err := py.Next(iter)
if err != nil {
if py.IsException(py.StopIteration, err) {
break
}
return nil, err
}
start, err = py.Add(start, item)
if err != nil {
return nil, err
}
}
return start, nil
}
32 changes: 32 additions & 0 deletions builtin/tests/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,38 @@ class C: pass
assert getattr(c, "potato") == "spud"
assert c.potato == "spud"

doc="sum"
assert sum([1,2,3]) == 6
assert sum([1,2,3], 3) == 9
assert sum((1,2,3)) == 6
assert sum((1,2,3), 3) == 9
assert sum((1, 2.5, 3)) == 6.5
assert sum((1, 2.5, 3), 3) == 9.5

try:
sum([1,2,3], 'hi')
except TypeError as e:
if e.args[0] != "sum() can't sum strings [use ''.join(seq) instead]":
raise
ok = True
assert ok, "TypeError not raised"

try:
sum([1,2,3], b'hi')
except TypeError as e:
if e.args[0] != "sum() can't sum bytes [use b''.join(seq) instead]":
raise
ok = True
assert ok, "TypeError not raised"

try:
sum(['h', 'i'])
except TypeError as e:
if e.args[0] != "unsupported operand type(s) for +: 'int' and 'str'":
raise
ok = True
assert ok, "TypeError not raised"

doc="__import__"
lib = __import__("lib")
assert lib.libfn() == 42
Expand Down
2 changes: 1 addition & 1 deletion py/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (

type String string

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

Expand Down