From ffb374f6ae4c3e291f1fdefc235bc03f34727bbc Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 10 Sep 2019 19:59:37 +0200 Subject: [PATCH 01/10] Add `sorted` and `list.sort` Mostly finished, needs some argument parsing changes. --- builtin/builtin.go | 27 ++++++++- py/list.go | 133 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) diff --git a/builtin/builtin.go b/builtin/builtin.go index bb4158c4..96e615cc 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -60,7 +60,7 @@ func init() { py.MustNewMethod("repr", builtin_repr, 0, repr_doc), 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("sorted", builtin_sorted, 0, sorted_doc), py.MustNewMethod("sum", builtin_sum, 0, sum_doc), // py.MustNewMethod("vars", builtin_vars, 0, vars_doc), } @@ -1074,3 +1074,28 @@ func builtin_sum(self py.Object, args py.Tuple) (py.Object, error) { } return start, nil } + +const sorted_doc = `sorted(iterable, key=None, reverse=False) +Return a new list containing all items from the iterable in ascending order. + +A custom key function can be supplied to customize the sort order, and the +reverse flag can be set to request the result in descending order.` + +func builtin_sorted(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) { + var iterable py.Object + var keyFunc py.Object = py.None + var reverse py.Object = py.False + err := py.ParseTupleAndKeywords(args, kwargs, "O|Op:sorted", []string{"iterable", "key", "reverse"}, &iterable, &keyFunc, &reverse) + if err != nil { + return nil, err + } + l, err := py.SequenceList(iterable) + if err != nil { + return nil, err + } + err = py.SortInPlace(l, keyFunc, reverse) + if err != nil { + return nil, err + } + return l, nil +} diff --git a/py/list.go b/py/list.go index 9e8e3dca..a338040e 100644 --- a/py/list.go +++ b/py/list.go @@ -6,6 +6,10 @@ package py +import ( + "sort" +) + var ListType = ObjectType.NewType("list", "list() -> new empty list\nlist(iterable) -> new list initialized from iterable's items", ListNew, nil) // FIXME lists are mutable so this should probably be struct { Tuple } then can use the sub methods on Tuple @@ -34,6 +38,29 @@ func init() { return NoneType{}, nil }, 0, "extend([item])") + ListType.Dict["sort"] = MustNewMethod("sort", func(self Object, args Tuple, kwargs StringDict) (Object, error) { + + if len(args) != 0 { + return nil, ExceptionNewf(TypeError, "sort() takes no positional arguments") + } + + var keyFunc Object = None + var reverse Object = False + + err := ParseTupleAndKeywords(nil, kwargs, "|Op:sort", []string{"key", "reverse"}, &keyFunc, &reverse) + if err != nil { + return nil, err + } + + listSelf := self.(*List) + + err = SortInPlace(listSelf, keyFunc, reverse) + if err != nil { + return nil, err + } + return NoneType{}, nil + }, 0, "sort(key=None, reverse=False)") + } // Type of this List object @@ -331,3 +358,109 @@ func (a *List) M__ne__(other Object) (Object, error) { } return False, nil } + +type sortable struct { + l *List + keyFunc Object + reverse bool + firstErr error +} + +type ptrSortable struct { + s *sortable +} + +func (s ptrSortable) Len() int { + return s.s.l.Len() +} + +func (s ptrSortable) Swap(i, j int) { + elemI, err := s.s.l.M__getitem__(Int(i)) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + return + } + elemJ, err := s.s.l.M__getitem__(Int(j)) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + return + } + _, err = s.s.l.M__setitem__(Int(i), elemJ) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + } + _, err = s.s.l.M__setitem__(Int(j), elemI) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + } +} + +func (s ptrSortable) Less(i, j int) bool { + elemI, err := s.s.l.M__getitem__(Int(i)) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + return false + } + elemJ, err := s.s.l.M__getitem__(Int(j)) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + return false + } + + if s.s.keyFunc != None { + elemI, err = Call(s.s.keyFunc, Tuple{elemI}, nil) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + } + elemJ, err = Call(s.s.keyFunc, Tuple{elemJ}, nil) + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + } + } + + var cmpResult Object + if s.s.reverse { + cmpResult, err = Lt(elemJ, elemI) + } else { + cmpResult, err = Lt(elemI, elemJ) + } + + if err != nil { + if s.s.firstErr == nil { + s.s.firstErr = err + } + } + + if boolResult, ok := cmpResult.(Bool); ok { + return bool(boolResult) + } + + return false +} + +func SortInPlace(l *List, keyFunc Object, reverse Object) error { + switch keyFunc.(type) { + case NoneType, I__call__: + default: + return ExceptionNewf(TypeError, "'%s' object is not callable", keyFunc.Type().Name) + } + s := ptrSortable{&sortable{l, keyFunc, ObjectIsTrue(reverse), nil}} + sort.Stable(s) + return s.s.firstErr +} From 7cc1d0bc87c47793402481137185d78769ec4a66 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sun, 15 Sep 2019 12:54:21 +0200 Subject: [PATCH 02/10] Unpacking of args works now for `sorted` and `list.sort` --- builtin/builtin.go | 8 +++---- py/list.go | 58 +++++++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/builtin/builtin.go b/builtin/builtin.go index 96e615cc..27e31965 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -1076,16 +1076,16 @@ func builtin_sum(self py.Object, args py.Tuple) (py.Object, error) { } const sorted_doc = `sorted(iterable, key=None, reverse=False) + Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the reverse flag can be set to request the result in descending order.` func builtin_sorted(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) { + const funcName = "sorted" var iterable py.Object - var keyFunc py.Object = py.None - var reverse py.Object = py.False - err := py.ParseTupleAndKeywords(args, kwargs, "O|Op:sorted", []string{"iterable", "key", "reverse"}, &iterable, &keyFunc, &reverse) + err := py.UnpackTuple(args, nil, funcName, 1, 1, &iterable) if err != nil { return nil, err } @@ -1093,7 +1093,7 @@ func builtin_sorted(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Obj if err != nil { return nil, err } - err = py.SortInPlace(l, keyFunc, reverse) + err = py.SortInPlace(l, kwargs, funcName) if err != nil { return nil, err } diff --git a/py/list.go b/py/list.go index a338040e..1c575f2a 100644 --- a/py/list.go +++ b/py/list.go @@ -39,22 +39,13 @@ func init() { }, 0, "extend([item])") ListType.Dict["sort"] = MustNewMethod("sort", func(self Object, args Tuple, kwargs StringDict) (Object, error) { - - if len(args) != 0 { - return nil, ExceptionNewf(TypeError, "sort() takes no positional arguments") - } - - var keyFunc Object = None - var reverse Object = False - - err := ParseTupleAndKeywords(nil, kwargs, "|Op:sort", []string{"key", "reverse"}, &keyFunc, &reverse) + const funcName = "sort" + err := UnpackTuple(args, nil, funcName, 0, 0) if err != nil { return nil, err } - listSelf := self.(*List) - - err = SortInPlace(listSelf, keyFunc, reverse) + err = SortInPlace(listSelf, kwargs, funcName) if err != nil { return nil, err } @@ -375,27 +366,27 @@ func (s ptrSortable) Len() int { } func (s ptrSortable) Swap(i, j int) { - elemI, err := s.s.l.M__getitem__(Int(i)) + itemI, err := s.s.l.M__getitem__(Int(i)) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } return } - elemJ, err := s.s.l.M__getitem__(Int(j)) + itemJ, err := s.s.l.M__getitem__(Int(j)) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } return } - _, err = s.s.l.M__setitem__(Int(i), elemJ) + _, err = s.s.l.M__setitem__(Int(i), itemJ) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } } - _, err = s.s.l.M__setitem__(Int(j), elemI) + _, err = s.s.l.M__setitem__(Int(j), itemI) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err @@ -404,14 +395,14 @@ func (s ptrSortable) Swap(i, j int) { } func (s ptrSortable) Less(i, j int) bool { - elemI, err := s.s.l.M__getitem__(Int(i)) + itemI, err := s.s.l.M__getitem__(Int(i)) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } return false } - elemJ, err := s.s.l.M__getitem__(Int(j)) + itemJ, err := s.s.l.M__getitem__(Int(j)) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err @@ -420,31 +411,34 @@ func (s ptrSortable) Less(i, j int) bool { } if s.s.keyFunc != None { - elemI, err = Call(s.s.keyFunc, Tuple{elemI}, nil) + itemI, err = Call(s.s.keyFunc, Tuple{itemI}, nil) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } + return false } - elemJ, err = Call(s.s.keyFunc, Tuple{elemJ}, nil) + itemJ, err = Call(s.s.keyFunc, Tuple{itemJ}, nil) if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } + return false } } var cmpResult Object if s.s.reverse { - cmpResult, err = Lt(elemJ, elemI) + cmpResult, err = Lt(itemJ, itemI) } else { - cmpResult, err = Lt(elemI, elemJ) + cmpResult, err = Lt(itemI, itemJ) } if err != nil { if s.s.firstErr == nil { s.s.firstErr = err } + return false } if boolResult, ok := cmpResult.(Bool); ok { @@ -454,12 +448,22 @@ func (s ptrSortable) Less(i, j int) bool { return false } -func SortInPlace(l *List, keyFunc Object, reverse Object) error { - switch keyFunc.(type) { - case NoneType, I__call__: - default: - return ExceptionNewf(TypeError, "'%s' object is not callable", keyFunc.Type().Name) +// SortInPlace sorts the given List in place using a stable sort. +// kwargs can have the keys "key" and "reverse". +func SortInPlace(l *List, kwargs StringDict, funcName string) error { + var keyFunc Object + var reverse Object + err := ParseTupleAndKeywords(nil, kwargs, "|$OO:"+funcName, []string{"key", "reverse"}, &keyFunc, &reverse) + if err != nil { + return err + } + if keyFunc == nil { + keyFunc = None + } + if reverse == nil { + reverse = False } + // FIXME: requires the same bool-check like CPython (or better "|$Op" that doesn't panic on nil). s := ptrSortable{&sortable{l, keyFunc, ObjectIsTrue(reverse), nil}} sort.Stable(s) return s.s.firstErr From d31767d924816d4664f24c4856575dca730a3708 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sun, 15 Sep 2019 15:03:30 +0200 Subject: [PATCH 03/10] add tests --- builtin/tests/sorting.py | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 builtin/tests/sorting.py diff --git a/builtin/tests/sorting.py b/builtin/tests/sorting.py new file mode 100644 index 00000000..24e0619c --- /dev/null +++ b/builtin/tests/sorting.py @@ -0,0 +1,55 @@ +# Copyright 2019 The go-python Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +l = [] +l2 = sorted(l) +assert l == l2 +assert not l is l2 +assert sorted([5, 2, 3, 1, 4]) == [1, 2, 3, 4, 5] +a = [5, 2, 3, 1, 4] +assert a.sort() == None +assert a == [1, 2, 3, 4, 5] +assert sorted({"1": "D", "2": "B", "3": "B", "5": "E", "4": "A"}) == ["1", "2", "3", "4", "5"] + +kwargs = {"key": lambda l: l&1+l, "reverse": True} +l = list(range(10)) +l.sort(**kwargs) +assert l == sorted(range(10), **kwargs) == [8, 9, 6, 4, 5, 2, 0, 1, 3, 7] + +assert sorted([1, 2, 1.1], reverse=1) == [2, 1.1, 1] + +try: + sorted() +except TypeError: + pass +else: + assert False + +try: + sorted([], 1) +except TypeError: + pass +else: + assert False + +try: + sorted(1) +except TypeError: + pass +else: + assert False + +try: + sorted(None) +except TypeError: + pass +else: + assert False + +try: + sorted([1, 2], key=1) +except TypeError: + pass +else: + assert False \ No newline at end of file From cf32df75566dece84ed0138755828f5248a2888c Mon Sep 17 00:00:00 2001 From: Tim S Date: Sun, 15 Sep 2019 15:30:00 +0200 Subject: [PATCH 04/10] new try --- builtin/tests/sorting.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/builtin/tests/sorting.py b/builtin/tests/sorting.py index 24e0619c..398e06df 100644 --- a/builtin/tests/sorting.py +++ b/builtin/tests/sorting.py @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. +doc = "sort: order" l = [] l2 = sorted(l) assert l == l2 @@ -10,15 +11,21 @@ a = [5, 2, 3, 1, 4] assert a.sort() == None assert a == [1, 2, 3, 4, 5] + +doc = "sort: dict-type as iterable" assert sorted({"1": "D", "2": "B", "3": "B", "5": "E", "4": "A"}) == ["1", "2", "3", "4", "5"] + +doc = "sort: complex arguments" kwargs = {"key": lambda l: l&1+l, "reverse": True} l = list(range(10)) l.sort(**kwargs) assert l == sorted(range(10), **kwargs) == [8, 9, 6, 4, 5, 2, 0, 1, 3, 7] +doc = "sort: different types that are comparable" assert sorted([1, 2, 1.1], reverse=1) == [2, 1.1, 1] +doc = "sort: call syntax and types" try: sorted() except TypeError: @@ -52,4 +59,6 @@ except TypeError: pass else: - assert False \ No newline at end of file + assert False + +doc = "finished" \ No newline at end of file From f411862f3a8545ecb0a9b9e75828d367e0a8c680 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sat, 28 Sep 2019 11:27:49 +0200 Subject: [PATCH 05/10] Add tests for `list.sort` --- py/tests/list.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/py/tests/list.py b/py/tests/list.py index 4fb1066c..0e3dfae7 100644 --- a/py/tests/list.py +++ b/py/tests/list.py @@ -1,4 +1,4 @@ -# Copyright 2018 The go-python Authors. All rights reserved. +# Copyright 2019 The go-python Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -39,4 +39,37 @@ assert a * 0 == [] assert a * -1 == [] +doc="sort" +a = [3, 1.1, 1, 2] +s1 = list(a) +s1.sort() +assert s1 == [1, 1.1, 2, 3] +s1.sort() # sort a sorted list +assert s1 == [1, 1.1, 2, 3] +s2 = list(a) +s2.sort(reverse=True) +assert s2 == [3, 2, 1.1, 1] +s2.sort() # sort a reversed list +assert s2 == [1, 1.1, 2, 3] +s3 = list(a) +s3.sort(key=lambda l: l+1) # test lambda key +assert s3 == [1, 1.1, 2, 3] +s4 = [2.0, 2, 1, 1.0] +s4.sort(key=lambda l: 0) # test stability +assert s4 == [2.0, 2, 1, 1.0] +assert [type(t) for t in s4] == [float, int, int, float] +s4 = [2.0, 2, 1, 1.0] +s4.sort() # test stability +assert s4 == [1, 1.0, 2.0, 2] +assert [type(t) for t in s4] == [int, float, float, int] +s5 = [2.0, "abc"] +assertRaises(TypeError, lambda: s5.sort()) +s5 = [] +s5.sort() +assert s5 == [] +s5 = [0] +s5.sort() +assert s5 == [0] +assertRaises(TypeError, lambda: s5.sort(key=1)) + doc="finished" From a432c5463fa4270940915a06ac784952784848c7 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sat, 28 Sep 2019 11:49:04 +0200 Subject: [PATCH 06/10] Update list.py --- py/tests/list.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/tests/list.py b/py/tests/list.py index 0e3dfae7..9b3c1f53 100644 --- a/py/tests/list.py +++ b/py/tests/list.py @@ -70,6 +70,8 @@ s5 = [0] s5.sort() assert s5 == [0] +s5 = [0, 1] +# Sorting a list of len >= 2 with uncallable key must fail on all Python implementations. assertRaises(TypeError, lambda: s5.sort(key=1)) doc="finished" From 6b844622de682397e43725e46058b00165082b86 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sat, 28 Sep 2019 14:07:06 +0200 Subject: [PATCH 07/10] support `list.sort([], **kwargs)` --- py/list.go | 27 ++++++++++++++++++++++----- py/tests/list.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/py/list.go b/py/list.go index 1c575f2a..daf16fbe 100644 --- a/py/list.go +++ b/py/list.go @@ -18,6 +18,7 @@ type List struct { } func init() { + // FIXME: all methods should be callable using list.method([], *args, **kwargs) or [].method(*args, **kwargs) ListType.Dict["append"] = MustNewMethod("append", func(self Object, args Tuple) (Object, error) { listSelf := self.(*List) if len(args) != 1 { @@ -40,12 +41,28 @@ func init() { ListType.Dict["sort"] = MustNewMethod("sort", func(self Object, args Tuple, kwargs StringDict) (Object, error) { const funcName = "sort" - err := UnpackTuple(args, nil, funcName, 0, 0) - if err != nil { - return nil, err + var l *List + if self.Type() == NoneTypeType { + // method called using `list.sort([], **kwargs)` + var o Object + err := UnpackTuple(args, nil, funcName, 1, 1, &o) + if err != nil { + return nil, err + } + var ok bool + l, ok = o.(*List) + if !ok { + return nil, ExceptionNewf(TypeError, "descriptor 'sort' requires a 'list' object but received a '%s'", args[0].Type()) + } + } else { + // method called using `[].sort(**kargs)` + err := UnpackTuple(args, nil, funcName, 0, 0) + if err != nil { + return nil, err + } + l = self.(*List) } - listSelf := self.(*List) - err = SortInPlace(listSelf, kwargs, funcName) + err := SortInPlace(l, kwargs, funcName) if err != nil { return nil, err } diff --git a/py/tests/list.py b/py/tests/list.py index 9b3c1f53..3e8468b0 100644 --- a/py/tests/list.py +++ b/py/tests/list.py @@ -40,6 +40,7 @@ assert a * -1 == [] doc="sort" +# [].sort a = [3, 1.1, 1, 2] s1 = list(a) s1.sort() @@ -74,4 +75,40 @@ # Sorting a list of len >= 2 with uncallable key must fail on all Python implementations. assertRaises(TypeError, lambda: s5.sort(key=1)) +# list.sort([]) +a = [3, 1.1, 1, 2] +s1 = list(a) +assert list.sort(s1) is None +assert s1 == [1, 1.1, 2, 3] +assert list.sort(s1) is None # sort a sorted list +assert s1 == [1, 1.1, 2, 3] +s2 = list(a) +list.sort(s2, reverse=True) +assert s2 == [3, 2, 1.1, 1] +list.sort(s2) # sort a reversed list +assert s2 == [1, 1.1, 2, 3] +s3 = list(a) +list.sort(s3, key=lambda l: l+1) # test lambda key +assert s3 == [1, 1.1, 2, 3] +s4 = [2.0, 2, 1, 1.0] +list.sort(s4, key=lambda l: 0) # test stability +assert s4 == [2.0, 2, 1, 1.0] +assert [type(t) for t in s4] == [float, int, int, float] +s4 = [2.0, 2, 1, 1.0] +list.sort(s4) # test stability +assert s4 == [1, 1.0, 2.0, 2] +assert [type(t) for t in s4] == [int, float, float, int] +s5 = [2.0, "abc"] +assertRaises(TypeError, lambda: list.sort(s5)) +s5 = [] +list.sort(s5) +assert s5 == [] +s5 = [0] +list.sort(s5) +assert s5 == [0] +s5 = [0, 1] +# Sorting a list of len >= 2 with uncallable key must fail on all Python implementations. +assertRaises(TypeError, lambda: list.sort(s5, key=1)) +assertRaises(TypeError, lambda: list.sort(1)) + doc="finished" From af6732df78556e7f94be6b58a38f5c27d8fa762c Mon Sep 17 00:00:00 2001 From: Tim S Date: Sat, 28 Sep 2019 14:09:06 +0200 Subject: [PATCH 08/10] Update list.go --- py/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/list.go b/py/list.go index daf16fbe..ae4878eb 100644 --- a/py/list.go +++ b/py/list.go @@ -52,7 +52,7 @@ func init() { var ok bool l, ok = o.(*List) if !ok { - return nil, ExceptionNewf(TypeError, "descriptor 'sort' requires a 'list' object but received a '%s'", args[0].Type()) + return nil, ExceptionNewf(TypeError, "descriptor 'sort' requires a 'list' object but received a '%s'", o.Type()) } } else { // method called using `[].sort(**kargs)` From c8d35a9130f3b828c36e3d999de14d36aabf2e1a Mon Sep 17 00:00:00 2001 From: Tim S Date: Sat, 28 Sep 2019 17:24:09 +0200 Subject: [PATCH 09/10] better NoneType comparison --- py/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/list.go b/py/list.go index ae4878eb..eee7bf3e 100644 --- a/py/list.go +++ b/py/list.go @@ -42,7 +42,7 @@ func init() { ListType.Dict["sort"] = MustNewMethod("sort", func(self Object, args Tuple, kwargs StringDict) (Object, error) { const funcName = "sort" var l *List - if self.Type() == NoneTypeType { + if self == None { // method called using `list.sort([], **kwargs)` var o Object err := UnpackTuple(args, nil, funcName, 1, 1, &o) From 5f7a289cb2581e35541b49c7b80d03c007462de7 Mon Sep 17 00:00:00 2001 From: Tim S Date: Sun, 29 Sep 2019 10:09:02 +0200 Subject: [PATCH 10/10] put tests for `sorted` in `builtin.py` --- builtin/tests/builtin.py | 46 ++++++++++++++++++++++++++++- builtin/tests/sorting.py | 64 ---------------------------------------- 2 files changed, 45 insertions(+), 65 deletions(-) delete mode 100644 builtin/tests/sorting.py diff --git a/builtin/tests/builtin.py b/builtin/tests/builtin.py index 88cc38c2..9d0bff95 100644 --- a/builtin/tests/builtin.py +++ b/builtin/tests/builtin.py @@ -1,4 +1,4 @@ -# Copyright 2018 The go-python Authors. All rights reserved. +# Copyright 2019 The go-python Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -329,6 +329,50 @@ class C: pass finally: assert ok +doc="sorted" +a = [3, 1.1, 1, 2] +assert sorted(a) == [1, 1.1, 2, 3] +assert sorted(sorted(a)) == [1, 1.1, 2, 3] +assert sorted(a, reverse=True) == [3, 2, 1.1, 1] +assert sorted(a, key=lambda l: l+1) == [1, 1.1, 2, 3] +s = [2.0, 2, 1, 1.0] +assert sorted(s, key=lambda l: 0) == [2.0, 2, 1, 1.0] +assert [type(t) for t in sorted(s, key=lambda l: 0)] == [float, int, int, float] +assert sorted(s) == [1, 1.0, 2.0, 2] +assert [type(t) for t in sorted(s)] == [int, float, float, int] + +try: + sorted([2.0, "abc"]) +except TypeError: + pass +else: + assert False + +assert sorted([]) == [] +assert sorted([0]) == [0] +s = [0, 1] +try: + # Sorting a list of len >= 2 with uncallable key must fail on all Python implementations. + sorted(s, key=1) +except TypeError: + pass +else: + assert False + +try: + sorted(1) +except TypeError: + pass +else: + assert False + +try: + sorted() +except TypeError: + pass +else: + assert False + doc="sum" assert sum([1,2,3]) == 6 assert sum([1,2,3], 3) == 9 diff --git a/builtin/tests/sorting.py b/builtin/tests/sorting.py deleted file mode 100644 index 398e06df..00000000 --- a/builtin/tests/sorting.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2019 The go-python Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -doc = "sort: order" -l = [] -l2 = sorted(l) -assert l == l2 -assert not l is l2 -assert sorted([5, 2, 3, 1, 4]) == [1, 2, 3, 4, 5] -a = [5, 2, 3, 1, 4] -assert a.sort() == None -assert a == [1, 2, 3, 4, 5] - -doc = "sort: dict-type as iterable" -assert sorted({"1": "D", "2": "B", "3": "B", "5": "E", "4": "A"}) == ["1", "2", "3", "4", "5"] - - -doc = "sort: complex arguments" -kwargs = {"key": lambda l: l&1+l, "reverse": True} -l = list(range(10)) -l.sort(**kwargs) -assert l == sorted(range(10), **kwargs) == [8, 9, 6, 4, 5, 2, 0, 1, 3, 7] - -doc = "sort: different types that are comparable" -assert sorted([1, 2, 1.1], reverse=1) == [2, 1.1, 1] - -doc = "sort: call syntax and types" -try: - sorted() -except TypeError: - pass -else: - assert False - -try: - sorted([], 1) -except TypeError: - pass -else: - assert False - -try: - sorted(1) -except TypeError: - pass -else: - assert False - -try: - sorted(None) -except TypeError: - pass -else: - assert False - -try: - sorted([1, 2], key=1) -except TypeError: - pass -else: - assert False - -doc = "finished" \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy