Skip to content

Commit 64593f8

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents ee7247e + 4c28217 commit 64593f8

35 files changed

+1360
-328
lines changed

.gometalinter.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"Enable": [
3+
"deadcode",
4+
"errcheck",
5+
"goimports",
6+
"ineffassign",
7+
"structcheck",
8+
"varcheck",
9+
"vet"
10+
],
11+
"EnableGC": true,
12+
"Vendor": true
13+
}

.travis.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ language: go
22
sudo: false
33
dist: trusty
44

5+
go_import_path: github.com/go-python/gpython
6+
57
os:
68
- linux
79

@@ -13,16 +15,13 @@ matrix:
1315
allow_failures:
1416
- go: master
1517
include:
16-
- go: 1.9.x
17-
env:
18-
- TAGS="-tags travis"
19-
- go: 1.10.x
18+
- go: 1.13.x
2019
env:
2120
- TAGS="-tags travis"
22-
- go: 1.11.x
21+
- COVERAGE="-cover"
22+
- go: 1.12.x
2323
env:
2424
- TAGS="-tags travis"
25-
- COVERAGE="-cover"
2625
- go: master
2726
env:
2827
- TAGS="-tags travis"

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ environment:
1212
matrix:
1313
- TARGET: x86_64-pc-windows-gnu
1414

15-
stack: go 1.11
15+
stack: go 1.13
1616

1717
build_script:
1818
- go get -v -t -race ./...

builtin/builtin.go

Lines changed: 147 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package builtin
77

88
import (
9+
"fmt"
10+
"math/big"
911
"unicode/utf8"
1012

1113
"github.com/go-python/gpython/compile"
@@ -25,7 +27,7 @@ func init() {
2527
py.MustNewMethod("all", builtin_all, 0, all_doc),
2628
py.MustNewMethod("any", builtin_any, 0, any_doc),
2729
py.MustNewMethod("ascii", builtin_ascii, 0, ascii_doc),
28-
// py.MustNewMethod("bin", builtin_bin, 0, bin_doc),
30+
py.MustNewMethod("bin", builtin_bin, 0, bin_doc),
2931
// py.MustNewMethod("callable", builtin_callable, 0, callable_doc),
3032
py.MustNewMethod("chr", builtin_chr, 0, chr_doc),
3133
py.MustNewMethod("compile", builtin_compile, 0, compile_doc),
@@ -39,10 +41,10 @@ func init() {
3941
py.MustNewMethod("globals", py.InternalMethodGlobals, 0, globals_doc),
4042
py.MustNewMethod("hasattr", builtin_hasattr, 0, hasattr_doc),
4143
// py.MustNewMethod("hash", builtin_hash, 0, hash_doc),
42-
// py.MustNewMethod("hex", builtin_hex, 0, hex_doc),
44+
py.MustNewMethod("hex", builtin_hex, 0, hex_doc),
4345
// py.MustNewMethod("id", builtin_id, 0, id_doc),
4446
// py.MustNewMethod("input", builtin_input, 0, input_doc),
45-
// py.MustNewMethod("isinstance", builtin_isinstance, 0, isinstance_doc),
47+
py.MustNewMethod("isinstance", builtin_isinstance, 0, isinstance_doc),
4648
// py.MustNewMethod("issubclass", builtin_issubclass, 0, issubclass_doc),
4749
py.MustNewMethod("iter", builtin_iter, 0, iter_doc),
4850
py.MustNewMethod("len", builtin_len, 0, len_doc),
@@ -58,7 +60,7 @@ func init() {
5860
py.MustNewMethod("repr", builtin_repr, 0, repr_doc),
5961
py.MustNewMethod("round", builtin_round, 0, round_doc),
6062
py.MustNewMethod("setattr", builtin_setattr, 0, setattr_doc),
61-
// py.MustNewMethod("sorted", builtin_sorted, 0, sorted_doc),
63+
py.MustNewMethod("sorted", builtin_sorted, 0, sorted_doc),
6264
py.MustNewMethod("sum", builtin_sum, 0, sum_doc),
6365
// py.MustNewMethod("vars", builtin_vars, 0, vars_doc),
6466
}
@@ -85,8 +87,8 @@ func init() {
8587
"object": py.ObjectType,
8688
"range": py.RangeType,
8789
// "reversed": py.ReversedType,
88-
"set": py.SetType,
89-
// "slice": py.SliceType,
90+
"set": py.SetType,
91+
"slice": py.SliceType,
9092
"staticmethod": py.StaticMethodType,
9193
"str": py.StringType,
9294
// "super": py.SuperType,
@@ -309,7 +311,12 @@ func builtin_any(self, seq py.Object) (py.Object, error) {
309311
return py.False, nil
310312
}
311313

312-
const ascii_doc = `
314+
const ascii_doc = `Return an ASCII-only representation of an object.
315+
316+
As repr(), return a string containing a printable representation of an
317+
object, but escape the non-ASCII characters in the string returned by
318+
repr() using \\x, \\u or \\U escapes. This generates a string similar
319+
to that returned by repr() in Python 2.
313320
`
314321

315322
func builtin_ascii(self, o py.Object) (py.Object, error) {
@@ -322,6 +329,29 @@ func builtin_ascii(self, o py.Object) (py.Object, error) {
322329
return py.String(out), err
323330
}
324331

332+
const bin_doc = `Return the binary representation of an integer.
333+
334+
>>> bin(2796202)
335+
'0b1010101010101010101010'
336+
`
337+
338+
func builtin_bin(self, o py.Object) (py.Object, error) {
339+
bigint, ok := py.ConvertToBigInt(o)
340+
if !ok {
341+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", o.Type().Name)
342+
}
343+
344+
value := (*big.Int)(bigint)
345+
var out string
346+
if value.Sign() < 0 {
347+
value = new(big.Int).Abs(value)
348+
out = fmt.Sprintf("-0b%b", value)
349+
} else {
350+
out = fmt.Sprintf("0b%b", value)
351+
}
352+
return py.String(out), nil
353+
}
354+
325355
const round_doc = `round(number[, ndigits]) -> number
326356
327357
Round a number to a given precision in decimal digits (default 0 digits).
@@ -796,6 +826,91 @@ object.
796826
The globals and locals are dictionaries, defaulting to the current
797827
globals and locals. If only globals is given, locals defaults to it.`
798828

829+
const hex_doc = `hex(number) -> string
830+
831+
Return the hexadecimal representation of an integer.
832+
833+
>>> hex(12648430)
834+
'0xc0ffee'
835+
`
836+
837+
func builtin_hex(self, v py.Object) (py.Object, error) {
838+
var (
839+
i int64
840+
err error
841+
)
842+
switch v := v.(type) {
843+
case *py.BigInt:
844+
// test bigint first to make sure we correctly handle the case
845+
// where int64 isn't large enough.
846+
vv := (*big.Int)(v)
847+
format := "%#x"
848+
if vv.Cmp(big.NewInt(0)) == -1 {
849+
format = "%+#x"
850+
}
851+
str := fmt.Sprintf(format, vv)
852+
return py.String(str), nil
853+
case py.IGoInt64:
854+
i, err = v.GoInt64()
855+
case py.IGoInt:
856+
var vv int
857+
vv, err = v.GoInt()
858+
i = int64(vv)
859+
default:
860+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
861+
}
862+
863+
if err != nil {
864+
return nil, err
865+
}
866+
867+
format := "%#x"
868+
if i < 0 {
869+
format = "%+#x"
870+
}
871+
str := fmt.Sprintf(format, i)
872+
return py.String(str), nil
873+
}
874+
875+
const isinstance_doc = `isinstance(obj, class_or_tuple) -> bool
876+
877+
Return whether an object is an instance of a class or of a subclass thereof.
878+
879+
A tuple, as in isinstance(x, (A, B, ...)), may be given as the target to
880+
check against. This is equivalent to isinstance(x, A) or isinstance(x, B)
881+
or ... etc.
882+
`
883+
884+
func isinstance(obj py.Object, classOrTuple py.Object) (py.Bool, error) {
885+
switch classOrTuple.(type) {
886+
case py.Tuple:
887+
var class_tuple = classOrTuple.(py.Tuple)
888+
for idx := range class_tuple {
889+
res, _ := isinstance(obj, class_tuple[idx])
890+
if res {
891+
return res, nil
892+
}
893+
}
894+
return false, nil
895+
default:
896+
if classOrTuple.Type().ObjectType != py.TypeType {
897+
return false, py.ExceptionNewf(py.TypeError, "isinstance() arg 2 must be a type or tuple of types")
898+
}
899+
return obj.Type() == classOrTuple, nil
900+
}
901+
}
902+
903+
func builtin_isinstance(self py.Object, args py.Tuple) (py.Object, error) {
904+
var obj py.Object
905+
var classOrTuple py.Object
906+
err := py.UnpackTuple(args, nil, "isinstance", 2, 2, &obj, &classOrTuple)
907+
if err != nil {
908+
return nil, err
909+
}
910+
911+
return isinstance(obj, classOrTuple)
912+
}
913+
799914
const iter_doc = `iter(iterable) -> iterator
800915
iter(callable, sentinel) -> iterator
801916
@@ -1044,3 +1159,28 @@ func builtin_sum(self py.Object, args py.Tuple) (py.Object, error) {
10441159
}
10451160
return start, nil
10461161
}
1162+
1163+
const sorted_doc = `sorted(iterable, key=None, reverse=False)
1164+
1165+
Return a new list containing all items from the iterable in ascending order.
1166+
1167+
A custom key function can be supplied to customize the sort order, and the
1168+
reverse flag can be set to request the result in descending order.`
1169+
1170+
func builtin_sorted(self py.Object, args py.Tuple, kwargs py.StringDict) (py.Object, error) {
1171+
const funcName = "sorted"
1172+
var iterable py.Object
1173+
err := py.UnpackTuple(args, nil, funcName, 1, 1, &iterable)
1174+
if err != nil {
1175+
return nil, err
1176+
}
1177+
l, err := py.SequenceList(iterable)
1178+
if err != nil {
1179+
return nil, err
1180+
}
1181+
err = py.SortInPlace(l, kwargs, funcName)
1182+
if err != nil {
1183+
return nil, err
1184+
}
1185+
return l, nil
1186+
}

builtin/tests/builtin.py

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
# Copyright 2018 The go-python Authors. All rights reserved.
1+
# Copyright 2019 The go-python Authors. All rights reserved.
22
# Use of this source code is governed by a BSD-style
33
# license that can be found in the LICENSE file.
44

5+
from libtest import assertRaises
6+
57
doc="abs"
68
assert abs(0) == 0
79
assert abs(10) == 10
@@ -25,6 +27,19 @@
2527
assert ascii(chr(0x10001)) == "'\\U00010001'"
2628
assert ascii('안녕 gpython') == "'\\uc548\\ub155 gpython'"
2729

30+
doc="bin"
31+
assert bin(False) == '0b0'
32+
assert bin(True) == '0b1'
33+
assert bin(0) == '0b0'
34+
assert bin(1) == '0b1'
35+
assert bin(-1) == '-0b1'
36+
assert bin(10) == '0b1010'
37+
assert bin(-10) == '-0b1010'
38+
assert bin(2**32) == '0b100000000000000000000000000000000'
39+
assert bin(2**32-1) == '0b11111111111111111111111111111111'
40+
assert bin(-(2**32)) == '-0b100000000000000000000000000000000'
41+
assert bin(-(2**32-1)) == '-0b11111111111111111111111111111111'
42+
2843
doc="chr"
2944
assert chr(65) == "A"
3045
assert chr(163) == "£"
@@ -138,6 +153,29 @@ def func(p):
138153
ok = True
139154
assert ok, "ValueError not raised"
140155

156+
doc="hex"
157+
assert hex( 0)=="0x0", "hex(0)"
158+
assert hex( 1)=="0x1", "hex(1)"
159+
assert hex(42)=="0x2a", "hex(42)"
160+
assert hex( -0)=="0x0", "hex(-0)"
161+
assert hex( -1)=="-0x1", "hex(-1)"
162+
assert hex(-42)=="-0x2a", "hex(-42)"
163+
assert hex( 1<<64) == "0x10000000000000000", "hex(1<<64)"
164+
assert hex(-1<<64) == "-0x10000000000000000", "hex(-1<<64)"
165+
assert hex( 1<<128) == "0x100000000000000000000000000000000", "hex(1<<128)"
166+
assert hex(-1<<128) == "-0x100000000000000000000000000000000", "hex(-1<<128)"
167+
assertRaises(TypeError, hex, 10.0) ## TypeError: 'float' object cannot be interpreted as an integer
168+
assertRaises(TypeError, hex, float(0)) ## TypeError: 'float' object cannot be interpreted as an integer
169+
170+
doc="isinstance"
171+
class A:
172+
pass
173+
a = A()
174+
assert isinstance(1, (str, tuple, int))
175+
assert isinstance(a, (str, (tuple, (A, ))))
176+
assertRaises(TypeError, isinstance, 1, (A, ), "foo")
177+
assertRaises(TypeError, isinstance, 1, [A, "foo"])
178+
141179
doc="iter"
142180
cnt = 0
143181
def f():
@@ -316,6 +354,50 @@ class C: pass
316354
finally:
317355
assert ok
318356

357+
doc="sorted"
358+
a = [3, 1.1, 1, 2]
359+
assert sorted(a) == [1, 1.1, 2, 3]
360+
assert sorted(sorted(a)) == [1, 1.1, 2, 3]
361+
assert sorted(a, reverse=True) == [3, 2, 1.1, 1]
362+
assert sorted(a, key=lambda l: l+1) == [1, 1.1, 2, 3]
363+
s = [2.0, 2, 1, 1.0]
364+
assert sorted(s, key=lambda l: 0) == [2.0, 2, 1, 1.0]
365+
assert [type(t) for t in sorted(s, key=lambda l: 0)] == [float, int, int, float]
366+
assert sorted(s) == [1, 1.0, 2.0, 2]
367+
assert [type(t) for t in sorted(s)] == [int, float, float, int]
368+
369+
try:
370+
sorted([2.0, "abc"])
371+
except TypeError:
372+
pass
373+
else:
374+
assert False
375+
376+
assert sorted([]) == []
377+
assert sorted([0]) == [0]
378+
s = [0, 1]
379+
try:
380+
# Sorting a list of len >= 2 with uncallable key must fail on all Python implementations.
381+
sorted(s, key=1)
382+
except TypeError:
383+
pass
384+
else:
385+
assert False
386+
387+
try:
388+
sorted(1)
389+
except TypeError:
390+
pass
391+
else:
392+
assert False
393+
394+
try:
395+
sorted()
396+
except TypeError:
397+
pass
398+
else:
399+
assert False
400+
319401
doc="sum"
320402
assert sum([1,2,3]) == 6
321403
assert sum([1,2,3], 3) == 9
@@ -356,7 +438,6 @@ class C: pass
356438
try:
357439
zip(1,2,3)
358440
except TypeError as e:
359-
print(e.args[0])
360441
if e.args[0] != "zip argument #1 must support iteration":
361442
raise
362443
ok = True

0 commit comments

Comments
 (0)