From 092ab27810b5a85d7bf831fc1785683de0fe8666 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Fri, 14 Jun 2019 11:08:36 -0400 Subject: [PATCH 1/7] object: implement fmt.Stringer --- .gitignore | 1 + object.go | 7 +++++++ python_test.go | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/object.go b/object.go index 274fcfd..a131ef7 100644 --- a/object.go +++ b/object.go @@ -15,6 +15,13 @@ type PyObject struct { ptr *C.PyObject } +// String returns a string representation of the PyObject +func (self *PyObject) String() string { + o := self.Str() + defer o.DecRef() + return PyString_AsString(o) +} + func (self *PyObject) topy() *C.PyObject { return self.ptr } diff --git a/python_test.go b/python_test.go index 0adeb4e..b5f536d 100644 --- a/python_test.go +++ b/python_test.go @@ -112,7 +112,7 @@ func TestErrFetch(t *testing.T) { t.Parallel() testPkg(t, pkg{ path: "tests/errfetch", - want: []byte("exc=&{}\nval=&{}\ntb=&{}\n"), + want: []byte("exc=\nval=\ntb=\n"), }) } From 46d882be3991e1a6166852ddaac0761b2e7ebbe0 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Sat, 15 Jun 2019 05:05:16 -0400 Subject: [PATCH 2/7] object: always return the same value for Py_None, Py_True, and Py_False * tests: add failing test for None check * object: always return the same value for Py_None, Py_True, and Py_False --- none.go | 2 +- numeric.go | 4 ++-- object.go | 12 ++++++++++-- python_test.go | 9 +++++++++ tests/none-check/get_none.py | 5 +++++ tests/none-check/main.go | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 tests/none-check/get_none.py create mode 100644 tests/none-check/main.go diff --git a/none.go b/none.go index 914899e..427c4cf 100644 --- a/none.go +++ b/none.go @@ -6,6 +6,6 @@ import "C" // The Python None object, denoting lack of value. This object has no methods. // It needs to be treated just like any other object with respect to reference // counts. -var Py_None = togo(C._gopy_pynone()) +var Py_None = &PyObject{ptr: C._gopy_pynone()} // EOF diff --git a/numeric.go b/numeric.go index 31a2c2a..97125ad 100644 --- a/numeric.go +++ b/numeric.go @@ -332,13 +332,13 @@ func PyBool_Check(self *PyObject) bool { // The Python False object. This object has no methods. // It needs to be treated just like any other object with respect to // reference counts. -var Py_False = togo(C._gopy_pyfalse()) +var Py_False = &PyObject{ptr: C._gopy_pyfalse()} // PyObject* Py_True // The Python True object. This object has no methods. // It needs to be treated just like any other object with respect to // reference counts. -var Py_True = togo(C._gopy_pytrue()) +var Py_True = &PyObject{ptr: C._gopy_pytrue()} /* Py_RETURN_FALSE diff --git a/object.go b/object.go index a131ef7..2e78c2d 100644 --- a/object.go +++ b/object.go @@ -34,10 +34,18 @@ func topy(self *PyObject) *C.PyObject { } func togo(obj *C.PyObject) *PyObject { - if obj == nil { + switch obj { + case nil: return nil + case Py_None.ptr: + return Py_None + case Py_True.ptr: + return Py_True + case Py_False.ptr: + return Py_False + default: + return &PyObject{ptr: obj} } - return &PyObject{ptr: obj} } // PyObject_FromVoidPtr converts a PyObject from an unsafe.Pointer diff --git a/python_test.go b/python_test.go index b5f536d..564b64e 100644 --- a/python_test.go +++ b/python_test.go @@ -140,3 +140,12 @@ func TestIssue61(t *testing.T) { `), }) } + +func TestCheckNone(t *testing.T) { + t.Parallel() + testPkg(t, pkg{ + path: "tests/none-check", + want: []byte(`type=, str=None, eq_none=true +`), + }) +} diff --git a/tests/none-check/get_none.py b/tests/none-check/get_none.py new file mode 100644 index 0000000..7d27c14 --- /dev/null +++ b/tests/none-check/get_none.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python2 + +def get_none(): + return None + diff --git a/tests/none-check/main.go b/tests/none-check/main.go new file mode 100644 index 0000000..990fec4 --- /dev/null +++ b/tests/none-check/main.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "log" + + "github.com/sbinet/go-python" +) + +func init() { + err := python.Initialize() + if err != nil { + log.Panic(err) + } +} + +func main() { + module := python.PyImport_ImportModule("get_none") + if module == nil { + log.Fatal("could not import 'get_none' module") + } + get_none := module.GetAttrString("get_none") + if get_none == nil { + log.Fatal("could not import 'get_none' function") + } + none := get_none.CallFunction() + fmt.Printf("type=%s, str=%s, eq_none=%t\n", + python.PyString_AsString(none.Type().Str()), + python.PyString_AsString(none.Str()), + none == python.Py_None, + ) +} From e97cf7f9fe1e6ed50c5ecf1c5c61402f2775d3a2 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 26 Mar 2020 13:07:51 +0100 Subject: [PATCH 3/7] all: add Go-module support --- go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 go.mod diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8dc3bb5 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/sbinet/go-python + +go 1.13 From fb007b5b0591c0bdec626386ead9bc6d1bba44a4 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 26 Mar 2020 13:08:24 +0100 Subject: [PATCH 4/7] ci: bump to Go-1.14+1.13 --- .travis.yml | 4 ++-- appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 678d6f3..a13c9f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: go go: - - 1.9.x - - 1.10.x + - 1.14.x + - 1.13.x before_install: - sudo apt-get update -qq diff --git a/appveyor.yml b/appveyor.yml index dbb5016..ad332c1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: CPYTHON2DIR: "C:\\Python27-x64" PATH: '%GOPATH%\bin;%CPYTHON2DIR%;%CPYTHON2DIR%\\Scripts;C:\msys64\mingw64\bin;C:\msys64\usr\bin\;%PATH%' -stack: go 1.11 +stack: go 1.13 build_script: - "%CPYTHON2DIR%\\python --version" From 5167a7b23e1d6ac26f3529a48ae01b9ffb62e1ed Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 26 Mar 2020 15:22:31 +0100 Subject: [PATCH 5/7] capi: prevent from directly wrapping Go functions Fixes #102. --- capi.go | 4 +++- heap.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/capi.go b/capi.go index 2d8d777..deec35f 100644 --- a/capi.go +++ b/capi.go @@ -16,11 +16,13 @@ func Py_BuildValue(format string, args ...interface{}) *PyObject { // ml_doc char * points to the contents of the docstring type PyMethodDef struct { Name string // name of the method - Meth func(self, args *PyObject) *PyObject + Meth PyCFunction Flags MethodDefFlags Doc string } +type PyCFunction C.PyCFunction + type MethodDefFlags int const ( diff --git a/heap.go b/heap.go index d3a00a1..d5f0c27 100644 --- a/heap.go +++ b/heap.go @@ -24,7 +24,7 @@ func cpyMethodDefs(name string, methods []PyMethodDef) *C.PyMethodDef { for i, meth := range methods { cmeth := C.PyMethodDef{ ml_name: C.CString(meth.Name), - ml_meth: (C.PyCFunction)(unsafe.Pointer(&meth.Meth)), + ml_meth: C.PyCFunction(meth.Meth), ml_flags: C.int(meth.Flags), ml_doc: C.CString(meth.Doc), } @@ -43,6 +43,7 @@ func Py_InitModule(name string, methods []PyMethodDef) (*PyObject, error) { obj := togo(C._gopy_InitModule(c_mname, cmeths)) if obj == nil { + PyErr_Print() return nil, errors.New("python: internal error; module creation failed.") } return obj, nil @@ -59,6 +60,7 @@ func Py_InitModule3(name string, methods []PyMethodDef, doc string) (*PyObject, obj := togo(C._gopy_InitModule3(cname, cmeths, cdoc)) if obj == nil { + PyErr_Print() return nil, errors.New("python: internal error; module creation failed.") } return obj, nil From d6ca9f284dab685f42c80cd635ef9169aa5f2afc Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Wed, 14 Apr 2021 10:53:08 +0200 Subject: [PATCH 6/7] doc: update GoDoc badge to point to godocs.io Fixes #113. Signed-off-by: Sebastien Binet --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f79d2e4..956edf6 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ go-python [![Build Status](https://travis-ci.org/sbinet/go-python.svg?branch=master)](https://travis-ci.org/sbinet/go-python) [![Build status](https://ci.appveyor.com/api/projects/status/n0ujg8no487a89vo/branch/master?svg=true)](https://ci.appveyor.com/project/sbinet/go-python/branch/master) +[![GoDocs](https://godocs.io/github.com/sbinet/go-python?status.svg)](https://godocs.io/github.com/sbinet/go-python) Naive `go` bindings towards the C-API of CPython-2. @@ -48,9 +49,9 @@ If ``go get`` + ``pkg-config`` failed: Documentation ------------- -Is available on ``godoc``: +Is available on ``godocs``: - http://godoc.org/github.com/sbinet/go-python + https://godocs.io/github.com/sbinet/go-python Example: From 9a5a20a386a7281f0ef1f7af682c54c7f32a30de Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Mon, 24 Jul 2023 09:11:30 +0200 Subject: [PATCH 7/7] all: archiving sbinet/go-python --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 956edf6..2e82335 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ go-python ========= +**`sbinet/go-python` only supports CPython2. CPython2 isn't supported anymore by [python.org](https://python.org). Thus, `sbinet/go-python` is now archived.** +**A possible alternative may be to use and contribute to [go-python/cpy3](https://github.com/go-python/cpy3) instead.** + [![Build Status](https://travis-ci.org/sbinet/go-python.svg?branch=master)](https://travis-ci.org/sbinet/go-python) [![Build status](https://ci.appveyor.com/api/projects/status/n0ujg8no487a89vo/branch/master?svg=true)](https://ci.appveyor.com/project/sbinet/go-python/branch/master) [![GoDocs](https://godocs.io/github.com/sbinet/go-python?status.svg)](https://godocs.io/github.com/sbinet/go-python)