Skip to content

Commit ec3f125

Browse files
Randall C. O'Reillysbinet
authored andcommitted
should be last fixes before switching over paths and pulling from PR etc: added osfile example test, which uses pkg and imports os -- needed some fixes to get os package to parse, including fixing error conversion from string, and dealing with func literals with no arg names. osfile doesn't actually work b/c python import only working after install -- not worth doing install for test.
1 parent e28bf16 commit ec3f125

File tree

12 files changed

+330
-131
lines changed

12 files changed

+330
-131
lines changed

SUPPORT_MATRIX.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ _examples/consts | yes | yes
1111
_examples/empty | yes | yes
1212
_examples/funcs | yes | yes
1313
_examples/gostrings | yes | yes
14-
_examples/hi | yes | yes
15-
_examples/iface | yes | yes
14+
_examples/hi | no | yes
15+
_examples/iface | no | yes
1616
_examples/lot | yes | yes
1717
_examples/maps | yes | yes
1818
_examples/named | yes | yes
19+
_examples/osfile | yes | yes
1920
_examples/pointers | yes | yes
2021
_examples/pyerrors | yes | yes
2122
_examples/rename | yes | yes

_examples/osfile/osfile.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2019 The go-python Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package osfile
6+
7+
import (
8+
"io"
9+
"log"
10+
"os"
11+
)
12+
13+
// note: the real test is to access os.File, io.Writer etc directly
14+
// these funcs are just dummies to have something here to compile..
15+
16+
func OpenFile(fname string) *os.File {
17+
f, err := os.Create(fname)
18+
if err != nil {
19+
log.Println(err)
20+
return nil
21+
}
22+
return f
23+
}
24+
25+
func WriteToFile(w io.Writer, str string) {
26+
_, err := w.Write([]byte(str))
27+
if err != nil {
28+
log.Println(err)
29+
}
30+
}

_examples/osfile/test.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2019 The go-python Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style
3+
# license that can be found in the LICENSE file.
4+
5+
## py2/py3 compat
6+
from __future__ import print_function
7+
8+
# note: this doesn't work without actually doing "make install" in pkg build dir
9+
# and furthermore, os is also used in python, so probably not very practical
10+
# to include it in the first place -- need to use a wrapper solution.
11+
12+
from osfile import osfile, os, go
13+
14+
try:
15+
f = os.Create("testfile.test")
16+
except Exception as err:
17+
print("os.Create got an error: %s" % (err,))
18+
pass
19+
20+
21+
try:
22+
f.Write("this is a test of python writing to a Go-opened file\n")
23+
except Exception as err:
24+
print("file.Write got an error: %s" % (err,))
25+
pass
26+
27+
f.Close()
28+
29+
try:
30+
os.Remove("testfile.test")
31+
except Exception as err:
32+
print("os.Remove got an error: %s" % (err,))
33+
pass
34+
35+

bind/gen_func.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ func (g *pyGen) genFuncBody(sym *symbol, fsym *Func) {
207207
}
208208
if isMethod {
209209
g.gofile.Printf(
210-
`vifc, err := gopyh.VarFromHandleTry((gopyh.CGoHandle)(_handle), "%s")
211-
if err != nil {
210+
`vifc, __err := gopyh.VarFromHandleTry((gopyh.CGoHandle)(_handle), "%s")
211+
if __err != nil {
212212
`, symNm)
213213
g.gofile.Indent()
214214
if nres > 0 {
@@ -227,7 +227,7 @@ if err != nil {
227227
g.gofile.Outdent()
228228
g.gofile.Printf("}\n")
229229
} else if rvIsErr {
230-
g.gofile.Printf("var err error\n")
230+
g.gofile.Printf("var __err error\n")
231231
}
232232

233233
// pywrap output
@@ -288,9 +288,9 @@ if err != nil {
288288
ret := res[0]
289289
switch {
290290
case rvIsErr:
291-
g.gofile.Printf("err = ")
291+
g.gofile.Printf("__err = ")
292292
case nres == 2:
293-
g.gofile.Printf("cret, err := ")
293+
g.gofile.Printf("cret, __err := ")
294294
case ret.sym.hasHandle() && !ret.sym.isPtrOrIface():
295295
hasAddrOfTmp = true
296296
g.gofile.Printf("cret := ")
@@ -340,9 +340,9 @@ if err != nil {
340340

341341
if rvIsErr || nres == 2 {
342342
g.gofile.Printf("\n")
343-
g.gofile.Printf("if err != nil {\n")
343+
g.gofile.Printf("if __err != nil {\n")
344344
g.gofile.Indent()
345-
g.gofile.Printf("estr := C.CString(err.Error())\n")
345+
g.gofile.Printf("estr := C.CString(__err.Error())\n")
346346
g.gofile.Printf("C.PyErr_SetString(C.PyExc_RuntimeError, estr)\n")
347347
if rvIsErr {
348348
g.gofile.Printf("return estr\n") // NOTE: leaked string

bind/stdtypes.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -339,19 +339,20 @@ func stdBasicTypes() map[string]*symbol {
339339
},
340340

341341
"error": {
342-
gopkg: look("error").Pkg(),
343-
goobj: look("error"),
344-
gotyp: look("error").Type(),
345-
kind: skType | skInterface,
346-
goname: "error",
347-
id: "error",
348-
cpyname: "char*",
349-
cgoname: "*C.char",
350-
pysig: "str",
351-
go2py: "C.CString",
352-
py2go: "C.GoString",
353-
zval: `""`,
354-
pyfmt: "O&",
342+
gopkg: look("error").Pkg(),
343+
goobj: look("error"),
344+
gotyp: look("error").Type(),
345+
kind: skType | skInterface,
346+
goname: "error",
347+
id: "error",
348+
cpyname: "char*",
349+
cgoname: "*C.char",
350+
pysig: "str",
351+
go2py: "C.CString",
352+
py2go: "errors.New(C.GoString",
353+
py2goParenEx: ")",
354+
zval: `""`,
355+
pyfmt: "O&",
355356
},
356357
}
357358

bind/symbols.go

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ func (sym *symtab) buildTuple(tuple *types.Tuple, varnm string, methvar string)
658658
return bstr, nil
659659
}
660660

661-
// pyObjectToGo returns code that will decodes a PyObject variable of name objnm into a basic go type
661+
// pyObjectToGo returns code that decodes a PyObject variable of name objnm into a basic go type
662662
func (sym *symtab) pyObjectToGo(typ types.Type, sy *symbol, objnm string) (string, error) {
663663
bstr := ""
664664
bt, isb := typ.Underlying().(*types.Basic)
@@ -687,6 +687,31 @@ func (sym *symtab) pyObjectToGo(typ types.Type, sy *symbol, objnm string) (strin
687687
return bstr, nil
688688
}
689689

690+
// ZeroToGo returns code for a zero of the given type, e.g., to synthesize a zero return value
691+
func (sym *symtab) ZeroToGo(typ types.Type, sy *symbol) (string, error) {
692+
bstr := ""
693+
bt, isb := typ.Underlying().(*types.Basic)
694+
switch {
695+
// case vsym.goname == "interface{}":
696+
// bstr += fmt.Sprintf("C.PyTuple_SetItem(%s, %d, C.gopy_build_string(%s(%s)%s))\n", varnm, i, vsym.go2py, anm, vsym.go2pyParenEx)
697+
// case vsym.hasHandle(): // note: assuming int64 handles
698+
// bstr += fmt.Sprintf("C.PyTuple_SetItem(%s, %d, C.gopy_build_int64(C.int64_t(%s(%s)%s)))\n", varnm, i, vsym.go2py, anm, vsym.go2pyParenEx)
699+
case isb:
700+
bk := bt.Kind()
701+
switch {
702+
case types.Int <= bk && bk <= types.Float64:
703+
bstr += fmt.Sprintf("%s(0)%s", sy.py2go, sy.py2goParenEx)
704+
case bk == types.String:
705+
bstr += `C.GoString(nil)`
706+
case bk == types.Bool:
707+
bstr += fmt.Sprintf("false")
708+
}
709+
default:
710+
return "", fmt.Errorf("ZeroToGo: type not handled: %s", typ.String())
711+
}
712+
return bstr, nil
713+
}
714+
690715
// typeNamePkg gets the goname and package for a given types.Type -- deals with
691716
// naming for types in other packages, and adds those packages to imports paths.
692717
// Falls back on sym.pkg if no other package info avail.
@@ -990,18 +1015,19 @@ func (sym *symtab) addSignatureType(pkg *types.Package, obj types.Object, t type
9901015
fn := sym.fullTypeString(t)
9911016
kind |= skSignature
9921017

993-
nsig := typeGoName(t.Underlying())
994-
py2g := fmt.Sprintf("%s { ", nsig)
995-
9961018
sig := t.Underlying().(*types.Signature)
9971019
args := sig.Params()
1020+
nargs := args.Len()
9981021
rets := sig.Results()
1022+
nsig := typeGoName(t.Underlying())
1023+
9991024
if rets.Len() > 1 {
10001025
return fmt.Errorf("multiple return values not supported")
10011026
}
10021027
retstr := ""
10031028
var ret *types.Var
10041029
var rsym *symbol
1030+
10051031
if rets.Len() == 1 {
10061032
retstr = "_fcret := "
10071033
ret = rets.At(0)
@@ -1011,14 +1037,36 @@ func (sym *symtab) addSignatureType(pkg *types.Package, obj types.Object, t type
10111037
}
10121038
}
10131039

1040+
if nargs > 0 { // need to deal with unnamed args
1041+
nsig = "func ("
1042+
for i := 0; i < nargs; i++ {
1043+
v := args.At(i)
1044+
typ := v.Type()
1045+
anm := pySafeArg(v.Name(), i)
1046+
if i > 0 {
1047+
nsig += ", "
1048+
}
1049+
nsig += anm + " " + typeGoName(typ)
1050+
}
1051+
nsig += ")"
1052+
if rets.Len() == 1 {
1053+
nsig += " " + typeGoName(ret.Type())
1054+
}
1055+
}
1056+
1057+
py2g := fmt.Sprintf("%s { ", nsig)
1058+
10141059
// TODO: use strings.Builder
10151060
if rets.Len() == 0 {
10161061
py2g += "if C.PyCallable_Check(_fun_arg) == 0 { return }\n"
10171062
} else {
1018-
py2g += fmt.Sprintf("if C.PyCallable_Check(_fun_arg) == 0 { return %s(0)%s }\n", rsym.py2go, rsym.py2goParenEx)
1063+
zstr, err := sym.ZeroToGo(ret.Type(), rsym)
1064+
if err != nil {
1065+
return err
1066+
}
1067+
py2g += fmt.Sprintf("if C.PyCallable_Check(_fun_arg) == 0 { return %s }\n", zstr)
10191068
}
10201069
py2g += "_gstate := C.PyGILState_Ensure()\n"
1021-
nargs := args.Len()
10221070
if nargs > 0 {
10231071
bstr, err := sym.buildTuple(args, "_fcargs", "_fun_arg")
10241072
if err != nil {

cmd_exe.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,13 @@ func gopyRunCmdExe(cmdr *commander.Command, args []string) error {
113113
}
114114

115115
for _, path := range args {
116-
rootdir, err := GoSrcDir(path)
116+
var rootdir string
117+
var err error
118+
if strings.HasPrefix(path, "./") {
119+
rootdir = path
120+
} else {
121+
rootdir, err = GoSrcDir(path)
122+
}
117123
if err != nil {
118124
return err
119125
}

cmd_pkg.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,13 @@ func gopyRunCmdPkg(cmdr *commander.Command, args []string) error {
111111
}
112112

113113
for _, path := range args {
114-
rootdir, err := GoSrcDir(path)
114+
var rootdir string
115+
var err error
116+
if strings.HasPrefix(path, "./") {
117+
rootdir = path
118+
} else {
119+
rootdir, err = GoSrcDir(path)
120+
}
115121
if err != nil {
116122
return err
117123
}
@@ -125,7 +131,7 @@ func buildPkgRecurse(odir, path, rootdir, pathdir string, exmap map[string]struc
125131
gofiles := GoFiles(pathdir)
126132
// fmt.Printf("go files: %s\n", gofiles)
127133
if len(gofiles) == 0 || (len(gofiles) == 1 && gofiles[0] == "doc.go") {
128-
fmt.Printf("\tskipping dir with no go files or only doc.go file: %s\n", pathdir)
134+
fmt.Printf("\tskipping dir with no go files or only doc.go file: %s -- %s\n", pathdir, gofiles)
129135
} else {
130136
if reldir == "" {
131137
newPackage(path)

dirs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func GoSrcDir(dir string) (absDir string, err error) {
2323
return absDir, nil
2424
}
2525
}
26-
return "", fmt.Errorf("kit.GoSrcDir: unable to locate directory (%q) in GOPATH/src/ (%q) or GOROOT/src/pkg/ (%q)", dir, os.Getenv("GOPATH"), os.Getenv("GOROOT"))
26+
return "", fmt.Errorf("GoSrcDir: unable to locate directory (%q) in GOPATH/src/ (%q) or GOROOT/src/pkg/ (%q)", dir, os.Getenv("GOPATH"), os.Getenv("GOROOT"))
2727
}
2828

2929
// Dirs returns a slice of all the directories within a given directory

gopy.gide

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"Run Proj"
2929
],
3030
"Find": {
31-
"Find": "bool",
31+
"Find": "Chdir",
3232
"Replace": "VarFromHandle",
3333
"IgnoreCase": false,
3434
"Langs": [
@@ -37,11 +37,17 @@
3737
],
3838
"Loc": "FindLocAll",
3939
"FindHist": [
40+
"Chdir",
41+
"buildTuple",
42+
"GoSrcDir",
43+
"testPkg",
44+
"run(",
45+
"run",
46+
") run",
4047
"bool",
4148
"genMethod",
4249
"genFuncBody",
4350
"boolPyToGo",
44-
"buildTuple",
4551
"could not find symbol",
4652
"newFuncFrom",
4753
"*ptrFromHandle",
@@ -54,7 +60,6 @@
5460
"C.free",
5561
"c.Free",
5662
"c.free",
57-
"testPkg",
5863
"VarFmHandle",
5964
"sliceptr",
6065
"handle=",
@@ -81,12 +86,7 @@
8186
"Packages",
8287
"thePyGen",
8388
"todo",
84-
"with go",
85-
"for go",
86-
"interface{}",
87-
"types.New",
88-
"C.Raise",
89-
"mutex"
89+
"with go"
9090
],
9191
"ReplHist": [
9292
"VarFromHandle",
@@ -111,13 +111,16 @@
111111
},
112112
"OpenDirs": {
113113
"_examples": true,
114+
"_examples/cgo": true,
115+
"_examples/consts": true,
114116
"_examples/funcs": true,
115117
"_examples/hi": true,
116118
"_examples/hi/gen": false,
117119
"_examples/iface": true,
118120
"_examples/lot": true,
119121
"_examples/maps": true,
120122
"_examples/named": true,
123+
"_examples/osfile": true,
121124
"_examples/pointers": true,
122125
"_examples/rename": true,
123126
"_examples/structs": true,

0 commit comments

Comments
 (0)