From 2163105dfb5a107bf693ff93c0408c250d1f9dae Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 22 Mar 2018 15:42:35 +0100 Subject: [PATCH 01/19] all: apply go vet fixes --- go-python.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/go-python.go b/go-python.go index 23394e6..75958fb 100644 --- a/go-python.go +++ b/go-python.go @@ -78,8 +78,5 @@ func pyfmt(v interface{}) (unsafe.Pointer, string) { } - panic(fmt.Errorf( - "python: unknown type (%#T)", - v, - )) + panic(fmt.Errorf("python: unknown type (%T)", v)) } From 2665c25d58b2072d04ab66ef5a2879e4cb626719 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 22 Mar 2018 15:56:28 +0100 Subject: [PATCH 02/19] object: handle nil arguments for topy to match CPython semantics Fixes #61 --- object.go | 3 +++ python_test.go | 10 ++++++++++ sequence.go | 5 +++-- tests/issue61/main.go | 25 +++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/issue61/main.go diff --git a/object.go b/object.go index 7be44fa..274fcfd 100644 --- a/object.go +++ b/object.go @@ -20,6 +20,9 @@ func (self *PyObject) topy() *C.PyObject { } func topy(self *PyObject) *C.PyObject { + if self == nil { + return nil + } return self.ptr } diff --git a/python_test.go b/python_test.go index 3b7e835..0adeb4e 100644 --- a/python_test.go +++ b/python_test.go @@ -130,3 +130,13 @@ ival=1666 `), }) } + +func TestIssue61(t *testing.T) { + t.Parallel() + testPkg(t, pkg{ + path: "tests/issue61", + want: []byte(`['i want this gone'] +[] +`), + }) +} diff --git a/sequence.go b/sequence.go index be66482..54b6a91 100644 --- a/sequence.go +++ b/sequence.go @@ -323,8 +323,9 @@ func PyList_Append(self, item *PyObject) error { // // Changed in version 2.5: This function used an int for low and high. This might require changes in your code for properly supporting 64-bit systems. func PyList_SetSlice(self *PyObject, low, high int, itemlist *PyObject) error { - err := C.PyList_SetSlice(topy(self), C.Py_ssize_t(low), C.Py_ssize_t(high), - topy(itemlist)) + err := C.PyList_SetSlice( + topy(self), C.Py_ssize_t(low), C.Py_ssize_t(high), topy(itemlist), + ) return int2err(err) } diff --git a/tests/issue61/main.go b/tests/issue61/main.go new file mode 100644 index 0000000..ae312b3 --- /dev/null +++ b/tests/issue61/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "log" + + "github.com/sbinet/go-python" +) + +func init() { + err := python.Initialize() + if err != nil { + log.Panic(err) + } +} + +func main() { + + origList := python.PyList_New(0) + python.PyList_Append(origList, python.PyString_FromString("i want this gone")) + fmt.Println(python.PyString_AsString(origList.Str())) + + python.PyList_SetSlice(origList, 0, 1, nil) + fmt.Println(python.PyString_AsString(origList.Str())) +} From 837042dadc934f8e6991cccf0f61f4b0f39576b5 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 22 Mar 2018 16:03:03 +0100 Subject: [PATCH 03/19] travis: bump to go-1.10 --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 597008b..1197a15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,16 @@ language: go go: - - 1.2 + - 1.9.x + - 1.10.x before_install: - sudo apt-get update -qq - sudo apt-get install python-dev -qq - export PATH=$HOME/gopath/bin:$PATH + # temporary workaround for go-python/gopy#83 + - export GODEBUG=cgocheck=0 + notifications: email: From b3bf8f0d95e4d29f2669b8a03143deac554f2ed4 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 22 Mar 2018 16:26:56 +0100 Subject: [PATCH 04/19] travis: remove GODEBUG=cgocheck=0 --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1197a15..678d6f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,6 @@ before_install: - sudo apt-get update -qq - sudo apt-get install python-dev -qq - export PATH=$HOME/gopath/bin:$PATH - # temporary workaround for go-python/gopy#83 - - export GODEBUG=cgocheck=0 - notifications: email: From bd44a9e197ab50782ee8d5d8db0d9a0fe68f934a Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Sun, 25 Mar 2018 19:50:27 +0200 Subject: [PATCH 05/19] implement functions to work with file descriptors * add function to convert os.File to PyObject * helpers to set stdin, stdout, stderr --- file.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 file.go diff --git a/file.go b/file.go new file mode 100644 index 0000000..2dceb13 --- /dev/null +++ b/file.go @@ -0,0 +1,42 @@ +package python + +/* +#include +#include "go-python.h" + +PyObject* +_gopy_PyFile_FromFile(int fd, char *name, char *mode) { + FILE *f = fdopen(fd, mode); + PyObject *py = PyFile_FromFile(f, name, mode, NULL); + PyFile_SetBufSize(py, 0); + return py; +} + +*/ +import "C" + +import ( + "os" +) + +// FromFile converts a Go file to Python file object. +// Calling close from Python will not close a file descriptor. +func FromFile(f *os.File, mode string) *PyObject { + p := C._gopy_PyFile_FromFile(C.int(f.Fd()), C.CString(f.Name()), C.CString(mode)) + return togo(p) +} + +// SetStdin sets a sys.stdin to a specified file descriptor. +func SetStdin(f *os.File) error { + return PySys_SetObject("stdin", FromFile(f, "r")) +} + +// SetStdout sets a sys.stdout to a specified file descriptor. +func SetStdout(f *os.File) error { + return PySys_SetObject("stdout", FromFile(f, "w")) +} + +// SetStderr sets a sys.stderr to a specified file descriptor. +func SetStderr(f *os.File) error { + return PySys_SetObject("stderr", FromFile(f, "w")) +} From f976f61134dc6f5b4920941eb1b0e7cec7e4ef4c Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Mon, 26 Mar 2018 15:41:58 +0200 Subject: [PATCH 06/19] free allocated strings --- file.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/file.go b/file.go index 2dceb13..983ebe8 100644 --- a/file.go +++ b/file.go @@ -17,12 +17,17 @@ import "C" import ( "os" + "unsafe" ) // FromFile converts a Go file to Python file object. // Calling close from Python will not close a file descriptor. func FromFile(f *os.File, mode string) *PyObject { - p := C._gopy_PyFile_FromFile(C.int(f.Fd()), C.CString(f.Name()), C.CString(mode)) + cname := C.CString(f.Name()) + cmode := C.CString(mode) + p := C._gopy_PyFile_FromFile(C.int(f.Fd()), cname, cmode) + C.free(unsafe.Pointer(cname)) + C.free(unsafe.Pointer(cmode)) return togo(p) } From a69309aef4be9a65ba2808acc26989b0530d7fec Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Mon, 6 Aug 2018 11:19:02 +0200 Subject: [PATCH 07/19] python: expose Py_SetProgramName and Py_GetProgramName Fixes sbinet/go-python#71. --- init.go | 43 +++++++++++++++++++++++++++++++++++++++++++ init_test.go | 16 ++++++++++++++++ utilities.go | 13 ------------- 3 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 init.go create mode 100644 init_test.go diff --git a/init.go b/init.go new file mode 100644 index 0000000..be6e399 --- /dev/null +++ b/init.go @@ -0,0 +1,43 @@ +package python + +// #include "go-python.h" +// char *gopy_ProgName = NULL; +import "C" + +import ( + "unsafe" +) + +// Py_SetProgramName should be called before Py_Initialize() is called for +// the first time, if it is called at all. +// It tells the interpreter the value of the argv[0] argument to the main() +// function of the program. This is used by Py_GetPath() and some other +// functions below to find the Python run-time libraries relative to the +// interpreter executable. The default value is 'python'. The argument should +// point to a zero-terminated character string in static storage whose contents +// will not change for the duration of the program’s execution. +// No code in the Python interpreter will change the contents of this storage. +func Py_SetProgramName(name string) { + C.gopy_ProgName = C.CString(name) + C.Py_SetProgramName(C.gopy_ProgName) +} + +// Py_GetProgramName returns the program name set with Py_SetProgramName(), +// or the default. +// The returned string points into static storage; the caller should not +// modify its value. +func Py_GetProgramName() string { + cname := C.Py_GetProgramName() + return C.GoString(cname) +} + +// PySys_SetArgv initializes the 'sys.argv' array in python. +func PySys_SetArgv(argv []string) { + argc := C.int(len(argv)) + cargs := make([]*C.char, len(argv)) + for idx, arg := range argv { + cargs[idx] = C.CString(arg) + defer C.free(unsafe.Pointer(cargs[idx])) + } + C.PySys_SetArgv(argc, &cargs[0]) +} diff --git a/init_test.go b/init_test.go new file mode 100644 index 0000000..9d4a3e4 --- /dev/null +++ b/init_test.go @@ -0,0 +1,16 @@ +package python_test + +import ( + "testing" + + python "github.com/sbinet/go-python" +) + +func TestProgramName(t *testing.T) { + const want = "foo.exe" + python.Py_SetProgramName(want) + name := python.Py_GetProgramName() + if name != want { + t.Fatalf("got=%q. want=%q", name, want) + } +} diff --git a/utilities.go b/utilities.go index ec5d543..8bdaed2 100644 --- a/utilities.go +++ b/utilities.go @@ -468,16 +468,3 @@ func PyEval_GetFuncDesc(fct *PyObject) string { c_name := C.PyEval_GetFuncDesc(topy(fct)) return C.GoString(c_name) } - -// PySys_SetArgv initializes the 'sys.argv' array in python. -func PySys_SetArgv(argv []string) { - argc := C.int(len(argv)) - cargs := make([]*C.char, len(argv)) - for idx, arg := range argv { - cargs[idx] = C.CString(arg) - defer C.free(unsafe.Pointer(cargs[idx])) - } - C.PySys_SetArgv(argc, &cargs[0]) -} - -// EOF From 17c9f530692bb11c325ea8f7d0917ad6cdac88b3 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Tue, 7 Aug 2018 14:21:46 +0200 Subject: [PATCH 08/19] python: expose Py_SetPythonHome and Py_GetPythonHome Fixes sbinet/go-python#71. --- init.go | 17 +++++++++++++++++ init_test.go | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/init.go b/init.go index be6e399..7f1b485 100644 --- a/init.go +++ b/init.go @@ -2,6 +2,7 @@ package python // #include "go-python.h" // char *gopy_ProgName = NULL; +// char *gopy_PythonHome = NULL; import "C" import ( @@ -18,6 +19,7 @@ import ( // will not change for the duration of the program’s execution. // No code in the Python interpreter will change the contents of this storage. func Py_SetProgramName(name string) { + C.free(unsafe.Pointer(C.gopy_ProgName)) C.gopy_ProgName = C.CString(name) C.Py_SetProgramName(C.gopy_ProgName) } @@ -41,3 +43,18 @@ func PySys_SetArgv(argv []string) { } C.PySys_SetArgv(argc, &cargs[0]) } + +// Set the default “home” directory, that is, the location of the standard Python libraries. See PYTHONHOME for the meaning of the argument string. +// +// The argument should point to a zero-terminated character string in static storage whose contents will not change for the duration of the program’s execution. No code in the Python interpreter will change the contents of this storage. +func Py_SetPythonHome(home string) { + C.free(unsafe.Pointer(C.gopy_PythonHome)) + C.gopy_PythonHome = C.CString(home) + C.Py_SetPythonHome(C.gopy_PythonHome) +} + +// Return the default “home”, that is, the value set by a previous call to Py_SetPythonHome(), or the value of the PYTHONHOME environment variable if it is set. +func Py_GetPythonHome() string { + home := C.Py_GetPythonHome() + return C.GoString(home) +} diff --git a/init_test.go b/init_test.go index 9d4a3e4..f1e73ac 100644 --- a/init_test.go +++ b/init_test.go @@ -14,3 +14,12 @@ func TestProgramName(t *testing.T) { t.Fatalf("got=%q. want=%q", name, want) } } + +func TestPythonHome(t *testing.T) { + const want = "/usr/lib/go-python" + python.Py_SetPythonHome(want) + got := python.Py_GetPythonHome() + if got != want { + t.Fatalf("got=%q. want=%q", got, want) + } +} From 53a27e004aa6fc4041327425b3b751a5cd513f0e Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Mon, 4 Jan 2016 10:38:11 +0100 Subject: [PATCH 09/19] cgo: split windows/unix support Split cgo-flags support into Windows and Unix. Windows installations do not usually export a pkg-config installation. Fixes #32. --- cgoflags.go => cgoflags_unix.go | 4 ++-- cgoflags_windows.go | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) rename cgoflags.go => cgoflags_unix.go (81%) create mode 100644 cgoflags_windows.go diff --git a/cgoflags.go b/cgoflags_unix.go similarity index 81% rename from cgoflags.go rename to cgoflags_unix.go index 5f1f0fa..4a38570 100644 --- a/cgoflags.go +++ b/cgoflags_unix.go @@ -1,7 +1,7 @@ +// +build !windows + package python // #cgo pkg-config: python-2.7 // #include "go-python.h" import "C" - -// EOF diff --git a/cgoflags_windows.go b/cgoflags_windows.go new file mode 100644 index 0000000..41aba53 --- /dev/null +++ b/cgoflags_windows.go @@ -0,0 +1,8 @@ +// +build windows + +package python + +// #cgo CFLAGS: -IC:/Python27/include +// #cgo LDFLAGS: -LC:/Python27/libs -lpython27 +// #include "go-python.h" +import "C" From b38845bc194532820d990a07322ca83371ad81e3 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Fri, 18 Jan 2019 12:35:49 +0100 Subject: [PATCH 10/19] all: add Windows CI support Fixes #32. --- README.md | 1 + appveyor.yml | 29 +++++++++ cgoflags_windows.go | 8 ++- gen-cgoflags.go | 141 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 appveyor.yml create mode 100644 gen-cgoflags.go diff --git a/README.md b/README.md index 11e7ac3..d172a44 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ go-python ========= [![Build Status](https://drone.io/github.com/sbinet/go-python/status.png)](https://drone.io/github.com/sbinet/go-python/latest) +[![Build status](https://ci.appveyor.com/api/projects/status/n0ujg8no487a89vo/branch/master?svg=true)](https://ci.appveyor.com/project/sbinet/go-python/branch/master) Naive `go` bindings towards the C-API of CPython-2. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..dbb5016 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,29 @@ +build: off + +clone_folder: c:\gopath\src\github.com\sbinet\go-python + +cache: + - '%LocalAppData%\\go-build' + - '%LocalAppData%\\pip' + +branches: + only: + - master + +environment: + GOPATH: c:\gopath + GOPY_APPVEYOR_CI: '1' + GODEBUG: 'cgocheck=0' + GOTRACEBACK: 'crash' + PYTHONUNBUFFERED: "1" + CPYTHON2DIR: "C:\\Python27-x64" + PATH: '%GOPATH%\bin;%CPYTHON2DIR%;%CPYTHON2DIR%\\Scripts;C:\msys64\mingw64\bin;C:\msys64\usr\bin\;%PATH%' + +stack: go 1.11 + +build_script: + - "%CPYTHON2DIR%\\python --version" + - go get -v -t ./... + +test_script: + - go test ./... diff --git a/cgoflags_windows.go b/cgoflags_windows.go index 41aba53..cb02cf2 100644 --- a/cgoflags_windows.go +++ b/cgoflags_windows.go @@ -2,7 +2,11 @@ package python -// #cgo CFLAGS: -IC:/Python27/include -// #cgo LDFLAGS: -LC:/Python27/libs -lpython27 +// #cgo 386 CFLAGS: -I C:/Python27/include +// #cgo amd64 CFLAGS: -I C:/Python27-x64/include +// #cgo amd64 CFLAGS: -D MS_WIN64 +// #cgo 386 LDFLAGS: -L C:/Python27/libs -lpython27 +// #cgo amd64 LDFLAGS: -L C:/Python27-x64/libs -lpython27 +// // #include "go-python.h" import "C" diff --git a/gen-cgoflags.go b/gen-cgoflags.go new file mode 100644 index 0000000..ce86c5c --- /dev/null +++ b/gen-cgoflags.go @@ -0,0 +1,141 @@ +// +build ignore + +// simple command to generate CGOFLAGS for a given python VM +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "runtime" + "strings" + + "github.com/pkg/errors" +) + +func main() { + vm := flag.String("vm", "python", "path to a python VM") + flag.Parse() + + if *vm == "" { + log.Fatalf("need a python VM") + } + + cfg, err := getPythonConfig(*vm) + if err != nil { + log.Fatalf("could not infer python configuration: %v", err) + } + + oname := "cgoflags_unix.go" + switch runtime.GOOS { + case "windows": + oname = "cgoflags_windows.go" + } + + err = ioutil.WriteFile(oname, []byte(fmt.Sprintf(tmpl, + cfg.cflags, + cfg.ldflags, + runtime.GOOS, + )), 0644) + if err != nil { + log.Fatalf("could not write %q: %v", oname, err) + } +} + +// getPythonConfig returns the needed python configuration for the given +// python VM (python, python2, python3, pypy, etc...) +func getPythonConfig(vm string) (pyconfig, error) { + code := `import sys +import distutils.sysconfig as ds +import json +print(ds.get_config_vars()) +print(ds.get_python_lib()) +print(json.dumps({ + "version": sys.version_info.major, + "prefix": ds.get_config_var("prefix"), + "incdir": ds.get_python_inc(), + "libdir": ds.get_config_var("LIBDIR"), + "libdest": ds.get_config_var("LIBDEST"), + "libpy": ds.get_config_var("LIBRARY"), + "shlibs": ds.get_config_var("SHLIBS"), + "syslibs": ds.get_config_var("SYSLIBS"), + "shlinks": ds.get_config_var("LINKFORSHARED"), + "DLLs": ds.get_config_var("DLLLIBRARY"), +})) +` + + var cfg pyconfig + bin, err := exec.LookPath(vm) + if err != nil { + return cfg, errors.Wrapf(err, "could not locate python vm %q", vm) + } + + buf := new(bytes.Buffer) + cmd := exec.Command(bin, "-c", code) + cmd.Stdin = os.Stdin + cmd.Stdout = buf + cmd.Stderr = os.Stderr + err = cmd.Run() + if err != nil { + return cfg, errors.Wrap(err, "could not run python-config script") + } + + log.Printf("distutils:\n%s", buf.String()) + + var raw struct { + Version int `json:"version"` + IncDir string `json:"incdir"` + LibDir string `json:"libdir"` + LibPy string `json:"libpy"` + ShLibs string `json:"shlibs"` + SysLibs string `json:"syslibs"` + } + err = json.NewDecoder(buf).Decode(&raw) + if err != nil { + return cfg, errors.Wrapf(err, "could not decode JSON script output") + } + + if strings.HasSuffix(raw.LibPy, ".a") { + raw.LibPy = raw.LibPy[:len(raw.LibPy)-len(".a")] + } + if strings.HasPrefix(raw.LibPy, "lib") { + raw.LibPy = raw.LibPy[len("lib"):] + } + + cfg.version = raw.Version + cfg.cflags = strings.Join([]string{ + "-I " + raw.IncDir, + }, " ") + cfg.ldflags = strings.Join([]string{ + "-L " + raw.LibDir, + "-l " + raw.LibPy, + raw.ShLibs, + raw.SysLibs, + }, " ") + + return cfg, nil +} + +type pyconfig struct { + version int + cflags string + ldflags string +} + +const tmpl = `// Automatically generated. Do not edit. + +// +build %[3]s + +package python + +// #cgo %[3]s CFLAGS: %[1]s +// #cgo %[3]s LDFLAGS: %[2]s +// +// #include "go-python.h" +import "C" +` From 5561e0f6d23833c825a57e025596f9bcd3a468d6 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Fri, 18 Jan 2019 14:16:08 +0100 Subject: [PATCH 11/19] doc: add Travis badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d172a44..f79d2e4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ go-python ========= -[![Build Status](https://drone.io/github.com/sbinet/go-python/status.png)](https://drone.io/github.com/sbinet/go-python/latest) +[![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) Naive `go` bindings towards the C-API of CPython-2. From ddccf6692cfa93817bbb8680547c7d7d9a414091 Mon Sep 17 00:00:00 2001 From: Lin Date: Wed, 27 Mar 2019 22:39:13 +0800 Subject: [PATCH 12/19] file: fix "_POSIX_C_SOURCE" redefined warnings --- file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file.go b/file.go index 983ebe8..2d2c5b4 100644 --- a/file.go +++ b/file.go @@ -1,8 +1,8 @@ package python /* -#include #include "go-python.h" +#include PyObject* _gopy_PyFile_FromFile(int fd, char *name, char *mode) { From 092ab27810b5a85d7bf831fc1785683de0fe8666 Mon Sep 17 00:00:00 2001 From: Ilia Choly Date: Fri, 14 Jun 2019 11:08:36 -0400 Subject: [PATCH 13/19] 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 14/19] 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 15/19] 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 16/19] 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 17/19] 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 18/19] 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 19/19] 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) 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