Interpreter lifecycle
parent
f71adb9d2c
commit
e3f8ed64f2
|
@ -10,3 +10,4 @@
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
vendor
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
package python3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include "Python.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The argument for Py_SetProgramName, Py_SetPath and Py_SetPythonHome should point to a zero-terminated wide character string in static storage
|
||||||
|
// whose contents will not change for the duration of the program’s execution
|
||||||
|
var (
|
||||||
|
programName *C.wchar_t
|
||||||
|
pythonPath *C.wchar_t
|
||||||
|
pythonHome *C.wchar_t
|
||||||
|
)
|
||||||
|
|
||||||
|
//Py_Initialize : https://docs.python.org/3/c-api/init.html#c.Py_Initialize
|
||||||
|
func Py_Initialize() {
|
||||||
|
C.Py_Initialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_InitializeEx : https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
|
||||||
|
func Py_InitializeEx(initsigs bool) {
|
||||||
|
if initsigs {
|
||||||
|
C.Py_InitializeEx(1)
|
||||||
|
} else {
|
||||||
|
C.Py_InitializeEx(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_IsInitialized : https://docs.python.org/3/c-api/init.html#c.Py_IsInitialized
|
||||||
|
func Py_IsInitialized() bool {
|
||||||
|
return C.Py_IsInitialized() != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_FinalizeEx : https://docs.python.org/3/c-api/init.html#c.Py_FinalizeEx
|
||||||
|
func Py_FinalizeEx() int {
|
||||||
|
return int(C.Py_FinalizeEx())
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_Finalize : https://docs.python.org/3/c-api/init.html#c.Py_Finalize
|
||||||
|
func Py_Finalize() {
|
||||||
|
C.Py_Finalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_SetStandardStreamEncoding : https://docs.python.org/3/c-api/init.html#c.Py_SetStandardStreamEncoding
|
||||||
|
func Py_SetStandardStreamEncoding(encoding, errors string) int {
|
||||||
|
cencoding := C.CString(encoding)
|
||||||
|
defer C.free(unsafe.Pointer(cencoding))
|
||||||
|
|
||||||
|
cerrors := C.CString(errors)
|
||||||
|
defer C.free(unsafe.Pointer(cerrors))
|
||||||
|
|
||||||
|
return int(C.Py_SetStandardStreamEncoding(cencoding, cerrors))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_SetProgramName : https://docs.python.org/3/c-api/init.html#c.Py_SetProgramName
|
||||||
|
func Py_SetProgramName(name string) error {
|
||||||
|
cname := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
newProgramName := C.Py_DecodeLocale(cname, nil)
|
||||||
|
if newProgramName == nil {
|
||||||
|
return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", name)
|
||||||
|
}
|
||||||
|
C.Py_SetProgramName(newProgramName)
|
||||||
|
|
||||||
|
//no operation is performed if nil
|
||||||
|
C.PyMem_RawFree(unsafe.Pointer(programName))
|
||||||
|
programName = newProgramName
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetProgramName : https://docs.python.org/3/c-api/init.html#c.Py_GetProgramName
|
||||||
|
func Py_GetProgramName() (string, error) {
|
||||||
|
wcname := C.Py_GetProgramName()
|
||||||
|
if wcname == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
cname := C.Py_EncodeLocale(wcname, nil)
|
||||||
|
if cname == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
return C.GoString(cname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetPrefix : https://docs.python.org/3/c-api/init.html#c.Py_GetPrefix
|
||||||
|
func Py_GetPrefix() (string, error) {
|
||||||
|
wcname := C.Py_GetPrefix()
|
||||||
|
if wcname == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
cname := C.Py_EncodeLocale(wcname, nil)
|
||||||
|
if cname == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
return C.GoString(cname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetExecPrefix : https://docs.python.org/3/c-api/init.html#c.Py_GetExecPrefix
|
||||||
|
func Py_GetExecPrefix() (string, error) {
|
||||||
|
wcname := C.Py_GetExecPrefix()
|
||||||
|
if wcname == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
cname := C.Py_EncodeLocale(wcname, nil)
|
||||||
|
if cname == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
return C.GoString(cname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetProgramFullPath : https://docs.python.org/3/c-api/init.html#c.Py_GetProgramFullPath
|
||||||
|
func Py_GetProgramFullPath() (string, error) {
|
||||||
|
wcname := C.Py_GetProgramFullPath()
|
||||||
|
if wcname == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
cname := C.Py_EncodeLocale(wcname, nil)
|
||||||
|
if cname == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
return C.GoString(cname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetPath : https://docs.python.org/3/c-api/init.html#c.Py_GetPath
|
||||||
|
func Py_GetPath() (string, error) {
|
||||||
|
wcname := C.Py_GetPath()
|
||||||
|
if wcname == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
cname := C.Py_EncodeLocale(wcname, nil)
|
||||||
|
if cname == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
|
return C.GoString(cname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_SetPath : https://docs.python.org/3/c-api/init.html#c.Py_SetPath
|
||||||
|
func Py_SetPath(path string) error {
|
||||||
|
cpath := C.CString(path)
|
||||||
|
defer C.free(unsafe.Pointer(cpath))
|
||||||
|
|
||||||
|
newPath := C.Py_DecodeLocale(cpath, nil)
|
||||||
|
if newPath == nil {
|
||||||
|
return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", path)
|
||||||
|
}
|
||||||
|
C.Py_SetPath(newPath)
|
||||||
|
|
||||||
|
C.PyMem_RawFree(unsafe.Pointer(pythonPath))
|
||||||
|
pythonHome = newPath
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetVersion : https://docs.python.org/3/c-api/init.html#c.Py_GetVersion
|
||||||
|
func Py_GetVersion() string {
|
||||||
|
cversion := C.Py_GetVersion()
|
||||||
|
return C.GoString(cversion)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetPlatform : https://docs.python.org/3/c-api/init.html#c.Py_GetPlatform
|
||||||
|
func Py_GetPlatform() string {
|
||||||
|
cplatform := C.Py_GetPlatform()
|
||||||
|
return C.GoString(cplatform)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetCopyright : https://docs.python.org/3/c-api/init.html#c.Py_GetCopyright
|
||||||
|
func Py_GetCopyright() string {
|
||||||
|
ccopyright := C.Py_GetCopyright()
|
||||||
|
return C.GoString(ccopyright)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetCompiler : https://docs.python.org/3/c-api/init.html#c.Py_GetCompiler
|
||||||
|
func Py_GetCompiler() string {
|
||||||
|
ccompiler := C.Py_GetCompiler()
|
||||||
|
return C.GoString(ccompiler)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetBuildInfo : https://docs.python.org/3/c-api/init.html#c.Py_GetBuildInfo
|
||||||
|
func Py_GetBuildInfo() string {
|
||||||
|
cbuildInfo := C.Py_GetBuildInfo()
|
||||||
|
return C.GoString(cbuildInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
//PySys_SetArgvEx : https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
|
||||||
|
func PySys_SetArgvEx(args []string, updatepath bool) error {
|
||||||
|
argc := C.int(len(args))
|
||||||
|
argv := make([]*C.wchar_t, argc, argc)
|
||||||
|
for i, arg := range args {
|
||||||
|
carg := C.CString(arg)
|
||||||
|
defer C.free(unsafe.Pointer(carg))
|
||||||
|
|
||||||
|
warg := C.Py_DecodeLocale(carg, nil)
|
||||||
|
if warg == nil {
|
||||||
|
return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", arg)
|
||||||
|
}
|
||||||
|
// Py_DecodeLocale requires a call to PyMem_RawFree to free the memory
|
||||||
|
defer C.PyMem_RawFree(unsafe.Pointer(warg))
|
||||||
|
|
||||||
|
argv[i] = warg
|
||||||
|
}
|
||||||
|
|
||||||
|
if updatepath {
|
||||||
|
C.PySys_SetArgvEx(argc, (**C.wchar_t)(unsafe.Pointer(&argv[0])), 1)
|
||||||
|
} else {
|
||||||
|
C.PySys_SetArgvEx(argc, (**C.wchar_t)(unsafe.Pointer(&argv[0])), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//PySys_SetArgv : https://docs.python.org/3/c-api/init.html#c.PySys_SetArgv
|
||||||
|
func PySys_SetArgv(args []string) error {
|
||||||
|
argc := C.int(len(args))
|
||||||
|
argv := make([]*C.wchar_t, argc, argc)
|
||||||
|
for i, arg := range args {
|
||||||
|
carg := C.CString(arg)
|
||||||
|
defer C.free(unsafe.Pointer(carg))
|
||||||
|
|
||||||
|
warg := C.Py_DecodeLocale(carg, nil)
|
||||||
|
if warg == nil {
|
||||||
|
return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", arg)
|
||||||
|
}
|
||||||
|
// Py_DecodeLocale requires a call to PyMem_RawFree to free the memory
|
||||||
|
defer C.PyMem_RawFree(unsafe.Pointer(warg))
|
||||||
|
|
||||||
|
argv[i] = warg
|
||||||
|
}
|
||||||
|
C.PySys_SetArgv(argc, (**C.wchar_t)(unsafe.Pointer(&argv[0])))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_SetPythonHome : https://docs.python.org/3/c-api/init.html#c.Py_SetPythonHome
|
||||||
|
func Py_SetPythonHome(home string) error {
|
||||||
|
chome := C.CString(home)
|
||||||
|
defer C.free(unsafe.Pointer(chome))
|
||||||
|
|
||||||
|
newHome := C.Py_DecodeLocale(chome, nil)
|
||||||
|
if newHome == nil {
|
||||||
|
return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", home)
|
||||||
|
}
|
||||||
|
C.Py_SetPythonHome(newHome)
|
||||||
|
|
||||||
|
C.PyMem_RawFree(unsafe.Pointer(pythonHome))
|
||||||
|
pythonHome = newHome
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Py_GetPythonHome : https://docs.python.org/3/c-api/init.html#c.Py_GetPythonHome
|
||||||
|
func Py_GetPythonHome() (string, error) {
|
||||||
|
wchome := C.Py_GetPythonHome()
|
||||||
|
if wchome == nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
chome := C.Py_EncodeLocale(wchome, nil)
|
||||||
|
if chome == nil {
|
||||||
|
return "", fmt.Errorf("fail to call Py_EncodeLocale")
|
||||||
|
}
|
||||||
|
defer C.PyMem_Free(unsafe.Pointer(chome))
|
||||||
|
|
||||||
|
return C.GoString(chome), nil
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
package python3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInitialization(t *testing.T) {
|
||||||
|
|
||||||
|
Py_Initialize()
|
||||||
|
assert.True(t, Py_IsInitialized())
|
||||||
|
Py_Finalize()
|
||||||
|
assert.False(t, Py_IsInitialized())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInitializationEx(t *testing.T) {
|
||||||
|
|
||||||
|
Py_Initialize()
|
||||||
|
assert.True(t, Py_IsInitialized())
|
||||||
|
assert.Zero(t, Py_FinalizeEx())
|
||||||
|
assert.False(t, Py_IsInitialized())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProgramName(t *testing.T) {
|
||||||
|
Py_Finalize()
|
||||||
|
|
||||||
|
defaultName, err := Py_GetProgramName()
|
||||||
|
defer Py_SetProgramName(defaultName)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
name := "py3é"
|
||||||
|
Py_SetProgramName(name)
|
||||||
|
newName, err := Py_GetProgramName()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, name, newName)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrefix(t *testing.T) {
|
||||||
|
prefix, err := Py_GetPrefix()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.IsType(t, "", prefix)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExecPrefix(t *testing.T) {
|
||||||
|
execPrefix, err := Py_GetExecPrefix()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.IsType(t, "", execPrefix)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProgramFullPath(t *testing.T) {
|
||||||
|
programFullPath, err := Py_GetProgramFullPath()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.IsType(t, "", programFullPath)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPath(t *testing.T) {
|
||||||
|
Py_Finalize()
|
||||||
|
|
||||||
|
defaultPath, err := Py_GetPath()
|
||||||
|
defer Py_SetPath(defaultPath)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
name := "påth"
|
||||||
|
Py_SetPath(name)
|
||||||
|
newName, err := Py_GetPath()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, name, newName)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVersion(t *testing.T) {
|
||||||
|
version := Py_GetVersion()
|
||||||
|
assert.IsType(t, "", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlatform(t *testing.T) {
|
||||||
|
platform := Py_GetPlatform()
|
||||||
|
assert.IsType(t, "", platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyright(t *testing.T) {
|
||||||
|
copyright := Py_GetCopyright()
|
||||||
|
assert.IsType(t, "", copyright)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompiler(t *testing.T) {
|
||||||
|
compiler := Py_GetCompiler()
|
||||||
|
assert.IsType(t, "", compiler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildInfo(t *testing.T) {
|
||||||
|
buildInfo := Py_GetBuildInfo()
|
||||||
|
assert.IsType(t, "", buildInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPythonHome(t *testing.T) {
|
||||||
|
name := "høme"
|
||||||
|
|
||||||
|
defaultHome, err := Py_GetPythonHome()
|
||||||
|
defer Py_SetPythonHome(defaultHome)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
Py_SetPythonHome(name)
|
||||||
|
newName, err := Py_GetPythonHome()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, name, newName)
|
||||||
|
}
|
Loading…
Reference in New Issue