From e7cff009bf0c83e2ad260af969d60c26675f7a80 Mon Sep 17 00:00:00 2001 From: Adam Boniecki Date: Sun, 19 Mar 2017 00:15:19 +0100 Subject: [PATCH] [WIP] Implement built-in function `next` `next` implemented by trying to call `__next__` method of passed object. Implementation seems to be finished, but this is marked as work in progress for now to investigate why few test cases still fail (possibly due to a bug in new or existing code) --- batavia/builtins/next.js | 29 ++++++++++++++++++++++++++++- tests/builtins/test_next.py | 20 +------------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/batavia/builtins/next.js b/batavia/builtins/next.js index 06795beed..162aa2034 100755 --- a/batavia/builtins/next.js +++ b/batavia/builtins/next.js @@ -1,9 +1,36 @@ var exceptions = require('../core').exceptions +var callables = require('../core').callables +var type_name = require('../core').type_name function next(args, kwargs) { // if its iterable return next thing in iterable // else stop iteration - throw new exceptions.NotImplementedError.$pyclass("Builtin Batavia function 'next' not implemented") + if (arguments.length !== 2) { + throw new exceptions.BataviaError.$pyclass('Batavia calling convention not used.') + } + if (kwargs && Object.keys(kwargs).length > 0) { + throw new exceptions.TypeError.$pyclass('next() takes no keyword arguments') + } + if (!args || args.length === 0) { + throw new exceptions.TypeError.$pyclass('next expected at least 1 arguments, got 0') + } + if (args.length > 2) { + throw new exceptions.TypeError.$pyclass('next expected at most 2 arguments, got ' + args.length) + } + + try { + return callables.call_method(args[0], '__next__', []) + } catch (e) { + if (e instanceof exceptions.StopIteration.$pyclass) { + if (args.length === 2) { + return args[1] + } else { + throw e + } + } else { + throw new exceptions.TypeError.$pyclass("'" + type_name(args[0]) + "' object is not an iterator") + } + } } next.__doc__ = 'next(iterator[, default])\n\nReturn the next item from the iterator. If default is given and the iterator\nis exhausted, it is returned instead of raising StopIteration.' diff --git a/tests/builtins/test_next.py b/tests/builtins/test_next.py index 460b84d2e..802dbc6f3 100644 --- a/tests/builtins/test_next.py +++ b/tests/builtins/test_next.py @@ -4,21 +4,19 @@ class NextTests(TranspileTestCase): - @expectedFailure + def test_next_success(self): self.assertCodeExecution(""" i = iter([1]) print(next(i)) """) - @expectedFailure def test_next_success_with_default(self): self.assertCodeExecution(""" i = iter([1]) print(next(i, 0)) """) - @expectedFailure def test_next_exhausted_with_default(self): self.assertCodeExecution(""" i = iter([]) @@ -37,22 +35,6 @@ class BuiltinNextFunctionTests(BuiltinFunctionTestCase, TranspileTestCase): functions = ["next"] not_implemented = [ - 'test_noargs', - 'test_bool', - 'test_bytearray', - 'test_bytes', - 'test_class', - 'test_complex', - 'test_dict', - 'test_float', 'test_frozenset', - 'test_int', - 'test_list', - 'test_None', - 'test_NotImplemented', - 'test_range', 'test_set', - 'test_slice', - 'test_str', - 'test_tuple', ]