gopy/bind/utils.go

147 lines
2.6 KiB
Go

// Copyright 2015 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bind
import (
"bufio"
"bytes"
"fmt"
"go/types"
"io"
"os/exec"
"regexp"
"sort"
)
func isErrorType(typ types.Type) bool {
return typ == types.Universe.Lookup("error").Type()
}
func isStringer(obj types.Object) bool {
switch obj := obj.(type) {
case *types.Func:
if obj.Name() != "String" {
return false
}
sig, ok := obj.Type().(*types.Signature)
if !ok {
return false
}
if sig.Recv() == nil {
return false
}
if sig.Params().Len() != 0 {
return false
}
res := sig.Results()
if res.Len() != 1 {
return false
}
ret := res.At(0).Type()
if ret != types.Universe.Lookup("string").Type() {
return false
}
return true
default:
return false
}
}
func hasError(sig *types.Signature) bool {
res := sig.Results()
if res == nil || res.Len() <= 0 {
return false
}
nerr := 0
for i := 0; i < res.Len(); i++ {
ret := res.At(i)
if isErrorType(ret.Type()) {
nerr++
}
}
switch {
case nerr == 0:
return false
case nerr == 1:
return true
default:
panic(fmt.Errorf(
"gopy: invalid number of comma-errors (%d)",
nerr,
))
}
}
func isConstructor(sig *types.Signature) bool {
//TODO(sbinet)
return false
}
// getPkgConfig returns the name of the pkg-config python's pc file
func getPkgConfig(vers int) (string, error) {
bin, err := exec.LookPath("pkg-config")
if err != nil {
return "", fmt.Errorf(
"gopy: could not locate 'pkg-config' executable (err: %v)",
err,
)
}
out, err := exec.Command(bin, "--list-all").Output()
if err != nil {
return "", fmt.Errorf(
"gopy: error retrieving the list of packages known to pkg-config (err: %v)",
err,
)
}
pkgs := []string{}
re := regexp.MustCompile(fmt.Sprintf(`^python(\s|-|\.|)%d.*?`, vers))
s := bufio.NewScanner(bytes.NewReader(out))
for s.Scan() {
err = s.Err()
if err != nil {
if err == io.EOF {
err = nil
}
break
}
line := s.Bytes()
if !bytes.HasPrefix(line, []byte("python")) {
continue
}
if !re.Match(line) {
continue
}
pkg := bytes.Split(line, []byte(" "))
pkgs = append(pkgs, string(pkg[0]))
}
if err != nil {
return "", fmt.Errorf(
"gopy: error scanning pkg-config output (err: %v)",
err,
)
}
if len(pkgs) <= 0 {
return "", fmt.Errorf(
"gopy: could not find pkg-config file (no python.pc installed?)",
)
}
sort.Strings(pkgs)
// FIXME(sbinet): make sure we take the latest version?
pkgcfg := pkgs[0]
return pkgcfg, nil
}