From 53a27e004aa6fc4041327425b3b751a5cd513f0e Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Mon, 4 Jan 2016 10:38:11 +0100 Subject: [PATCH 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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 10/11] 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 11/11] 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